Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add macOS support #30

Merged
merged 16 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 36 additions & 25 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#
# This source file is part of the Stanford Spezi open-source project
#
# SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md)
# SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md)
#
# SPDX-License-Identifier: MIT
#
Expand All @@ -16,71 +16,82 @@ on:
workflow_dispatch:

jobs:
buildandtest:
buildandtest_ios:
name: Build and Test Swift Package iOS
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: SpeziViews-Package.xcresult
runsonlabels: '["macOS", "self-hosted"]'
scheme: SpeziViews-Package
buildandtestwatchos:
resultBundle: SpeziViews-iOS.xcresult
artifactname: SpeziViews-iOS.xcresult
buildandtest_watchos:
name: Build and Test Swift Package watchOS
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: SpeziViews-Package-watchOS.xcresult
resultBundle: SpeziViews-Package-watchOS.xcresult
runsonlabels: '["macOS", "self-hosted"]'
scheme: SpeziViews-Package
destination: 'platform=watchOS Simulator,name=Apple Watch Series 9 (45mm)'
buildandtestvisionos:
resultBundle: SpeziViews-watchOS.xcresult
artifactname: SpeziViews-watchOS.xcresult
buildandtest_visionos:
name: Build and Test Swift Package visionOS
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: SpeziViews-Package-visionOS.xcresult
resultBundle: SpeziViews-Package-visionOS.xcresult
runsonlabels: '["macOS", "self-hosted"]'
scheme: SpeziViews-Package
destination: 'platform=visionOS Simulator,name=Apple Vision Pro'
buildandtesttvos:
resultBundle: SpeziViews-visionOS.xcresult
artifactname: SpeziViews-visionOS.xcresult
buildandtest_tvos:
name: Build and Test Swift Package tvOS
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: SpeziViews-Package-tvOS.xcresult
resultBundle: SpeziViews-Package-tvOS.xcresult
runsonlabels: '["macOS", "self-hosted"]'
scheme: SpeziViews-Package
destination: 'platform=tvOS Simulator,name=Apple TV 4K (3rd generation)'
buildandtestuitests:
resultBundle: SpeziViews-tvOS.xcresult
artifactname: SpeziViews-tvOS.xcresult
buildandtest_macos:
name: Build and Test Swift Package macOS
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
runsonlabels: '["macOS", "self-hosted"]'
scheme: SpeziViews-Package
destination: 'platform=macOS,arch=arm64'
resultBundle: SpeziViews-macOS.xcresult
artifactname: SpeziViews-macOS.xcresult
buildandtestuitests_ios:
name: Build and Test UI Tests iOS
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: TestApp.xcresult
runsonlabels: '["macOS", "self-hosted"]'
path: 'Tests/UITests'
path: Tests/UITests
scheme: TestApp
buildandtestuitestsipad:
resultBundle: TestApp-iOS.xcresult
artifactname: TestApp-iOS.xcresult
buildandtestuitests_ipad:
name: Build and Test UI Tests iPadOS
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: TestApp-iPad.xcresult
resultBundle: TestApp-iPad.xcresult
runsonlabels: '["macOS", "self-hosted"]'
path: 'Tests/UITests'
path: Tests/UITests
scheme: TestApp
destination: 'platform=iOS Simulator,name=iPad Air (5th generation)'
buildandtestuitestsvisionos:
resultBundle: TestApp-iPad.xcresult
artifactname: TestApp-iPad.xcresult
buildandtestuitests_visionos:
name: Build and Test UI Tests visionOS
uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: TestApp-visionOS.xcresult
resultBundle: TestApp-visionOS.xcresult
runsonlabels: '["macOS", "self-hosted"]'
path: 'Tests/UITests'
path: Tests/UITests
scheme: TestApp
destination: 'platform=visionOS Simulator,name=Apple Vision Pro'
resultBundle: TestApp-visionOS.xcresult
artifactname: TestApp-visionOS.xcresult
uploadcoveragereport:
name: Upload Coverage Report
needs: [buildandtest, buildandtestwatchos, buildandtestvisionos, buildandtesttvos, buildandtestuitests, buildandtestuitestsipad, buildandtestuitestsvisionos]
needs: [buildandtest_ios, buildandtest_visionos, buildandtest_watchos, buildandtest_tvos, buildandtest_macos, buildandtestuitests_ios, buildandtestuitests_ipad, buildandtestuitests_visionos]
uses: StanfordSpezi/.github/.github/workflows/create-and-upload-coverage-report.yml@v2
with:
coveragereports: SpeziViews-Package.xcresult SpeziViews-Package-watchOS.xcresult SpeziViews-Package-visionOS.xcresult SpeziViews-Package-tvOS.xcresult TestApp.xcresult TestApp-iPad.xcresult TestApp-visionOS.xcresult
coveragereports: SpeziViews-iOS.xcresult SpeziViews-watchOS.xcresult SpeziViews-visionOS.xcresult SpeziViews-tvOS.xcresult TestApp-iOS.xcresult TestApp-iPad.xcresult TestApp-visionOS.xcresult
21 changes: 16 additions & 5 deletions Sources/SpeziPersonalInfo/Fields/NameFieldRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,22 @@


public var body: some View {
DescriptionGridRow {
description
} content: {
NameTextField(name: $name, for: component) {
label
#if os(macOS)
let isMacOS = true
#else
let isMacOS = false
#endif
if isMacOS, let label = label as? Text {
NameTextField(name: $name, for: component, prompt: label) {
description
}

Check warning on line 60 in Sources/SpeziPersonalInfo/Fields/NameFieldRow.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziPersonalInfo/Fields/NameFieldRow.swift#L58-L60

Added lines #L58 - L60 were not covered by tests
} else {
DescriptionGridRow {
description
} content: {
NameTextField(name: $name, for: component) {
label
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/SpeziViews/Views/Layout/DescriptionGridRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
}
}
.padding(32)
#if os(iOS)
.background(Color(.systemGroupedBackground))
#endif

Check warning on line 89 in Sources/SpeziViews/Views/Layout/DescriptionGridRow.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziViews/Views/Layout/DescriptionGridRow.swift#L87-L89

Added lines #L87 - L89 were not covered by tests
}
}
#endif
1 change: 1 addition & 0 deletions Tests/SpeziViewsTests/SnapshotTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ final class SnapshotTests: XCTestCase {
}
}


let largeRow = row
.dynamicTypeSize(.accessibility3)

Expand Down
2 changes: 2 additions & 0 deletions Tests/UITests/TestApp/Examples/NameFieldsExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ struct NameFieldsExample: View {
}
}
.navigationTitle("Enter your details")
#if !os(macOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.navigationBarBackButtonHidden(hideBackButton)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Expand Down
4 changes: 4 additions & 0 deletions Tests/UITests/TestApp/Examples/ValidationExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ struct ValidationExample: View {
VerifiableTextField("Password", text: $password, type: .secure)
.validate(input: password, rules: .minimalPassword)
}
#if !os(macOS)
.textInputAutocapitalization(.never)
#endif
.autocorrectionDisabled(true)

Section {
Expand All @@ -40,7 +42,9 @@ struct ValidationExample: View {
}
}
.navigationTitle("Signup")
#if !os(macOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.navigationBarBackButtonHidden(backButtonHidden)
.receiveValidation(in: $validation)
.toolbar {
Expand Down
6 changes: 5 additions & 1 deletion Tests/UITests/TestApp/Examples/ViewStateExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ struct ViewStateExample: View {
.padding()
}
.navigationTitle("Reset Password")
#if !os(macOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.viewStateAlert(state: $viewState)
.frame(maxWidth: .infinity, minHeight: proxy.size.height)
}
Expand All @@ -54,9 +56,11 @@ struct ViewStateExample: View {
.validate(input: emailAddress, rules: .minimalEmail)
.textFieldStyle(.roundedBorder)
.autocorrectionDisabled(true)
#if !os(macOS)
.textInputAutocapitalization(.never)
.textContentType(.username)
.keyboardType(.emailAddress)
#endif
.textContentType(.username)
.font(.title3)

Spacer()
Expand Down
16 changes: 16 additions & 0 deletions Tests/UITests/TestApp/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@
},
"Action executed" : {

},
"Canvas Size: none" : {

},
"Canvas Size: width %lf, height %lf" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Canvas Size: width %1$lf, height %2$lf"
}
}
}
},
"CanvasTest" : {

},
"Credentials" : {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ struct NameFieldsTestView: View {
nameFields
}
}
#if !os(macOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}


Expand Down
38 changes: 35 additions & 3 deletions Tests/UITests/TestApp/SpeziViewsTargetsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@ struct SpeziViewsTargetsTests: View {
@State var presentingSpeziPersonalInfo = false
@State var presentingSpeziValidation = false

#if os(macOS)
@MainActor
private var idealWidth: CGFloat {
guard let width = NSApp.keyWindow?.contentView?.bounds.width else {
return 500
}
return max(width - 100, 300)
}

@MainActor
private var idealHeight: CGFloat {
guard let height = NSApp.keyWindow?.contentView?.bounds.height else {
return 400
}
return max(height - 50, 250)
}
#endif


var body: some View {
NavigationStack {
Expand All @@ -28,6 +46,11 @@ struct SpeziViewsTargetsTests: View {
Button("SpeziValidation") {
presentingSpeziValidation = true
}
#if canImport(PencilKit) && !os(macOS)
NavigationLink("CanvasTest") {
CanvasTestView()
}
#endif

Section {
NavigationLink("ViewState") {
Expand All @@ -48,13 +71,22 @@ struct SpeziViewsTargetsTests: View {
.navigationTitle("Targets")
}
.sheet(isPresented: $presentingSpeziViews) {
TestAppTestsView<SpeziViewsTests>()
TestAppTestsView<SpeziViewsTests>(showCloseButton: true)
#if os(macOS)
.frame(minWidth: idealWidth, minHeight: idealHeight)
#endif
}
.sheet(isPresented: $presentingSpeziPersonalInfo) {
TestAppTestsView<SpeziPersonalInfoTests>()
TestAppTestsView<SpeziPersonalInfoTests>(showCloseButton: true)
#if os(macOS)
.frame(minWidth: idealWidth, minHeight: idealHeight)
#endif
}
.sheet(isPresented: $presentingSpeziValidation) {
TestAppTestsView<SpeziValidationTests>()
TestAppTestsView<SpeziValidationTests>(showCloseButton: true)
#if os(macOS)
.frame(minWidth: idealWidth, minHeight: idealHeight)
#endif
}
}
}
Expand Down
10 changes: 0 additions & 10 deletions Tests/UITests/TestApp/TestApp.entitlements

This file was deleted.

38 changes: 25 additions & 13 deletions Tests/UITests/TestApp/ViewsTests/CanvasTestView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// SPDX-License-Identifier: MIT
//

#if canImport(PencilKit) && !os(macOS)
import PencilKit
import SpeziViews
import SwiftUI
Expand All @@ -16,28 +17,38 @@ struct CanvasTestView: View {
@State var didDrawAnything = false
@State var showToolPicker = false
@State var drawing = PKDrawing()

@State var receivedSize: CGSize?

var body: some View {
VStack {
Text("Did Draw Anything: \(didDrawAnything.description)")
Button("Show Tool Picker") {
showToolPicker.toggle()
ZStack {
VStack {
Text("Did Draw Anything: \(didDrawAnything.description)")
if let receivedSize {
Text("Canvas Size: width \(receivedSize.width), height \(receivedSize.height)")
} else {
Text("Canvas Size: none")
}
Button("Show Tool Picker") {
showToolPicker.toggle()
}
CanvasView(
drawing: $drawing,
isDrawing: $isDrawing,
tool: .init(.pencil, color: .red, width: 10),
drawingPolicy: .anyInput,
showToolPicker: $showToolPicker
)
}
CanvasView(
drawing: $drawing,
isDrawing: $isDrawing,
tool: .init(.pencil, color: .red, width: 10),
drawingPolicy: .anyInput,
showToolPicker: $showToolPicker
)
}
.onChange(of: isDrawing) {
if isDrawing {
didDrawAnything = true
}
}
.navigationBarTitleDisplayMode(.inline)
.onPreferenceChange(CanvasView.CanvasSizePreferenceKey.self) { size in
self.receivedSize = size
}
}
}

Expand All @@ -49,3 +60,4 @@ struct CanvasTestView_Previews: PreviewProvider {
}
}
#endif
#endif
2 changes: 2 additions & 0 deletions Tests/UITests/TestApp/ViewsTests/GeometryReaderTestView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ struct GeometryReaderTestView: View {
.frame(width: 300)
.border(.blue)
}
#if !os(macOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}
}

Expand Down
Loading
Loading