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 AccountKeyRequirement.manual #75

Merged
merged 8 commits into from
Sep 15, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@

let keyPathDescription: String

init(_ keyPath: KeyPath<AccountKeys, Key.Type>, type: AccountKeyRequirement) {
init(_ keyPath: KeyPath<AccountKeys, Key.Type>, requirement: AccountKeyRequirement) {
self.key = Key.self
self.requirement = type
self.requirement = requirement
self.keyPathDescription = keyPath.shortDescription
}
}
Expand All @@ -58,6 +58,8 @@
return ".collects(\(keyPathDescription))"
case .supported:
return ".supports(\(keyPathDescription))"
case .manual:
return ".manual(\(keyPathDescription))"

Check warning on line 62 in Sources/SpeziAccount/AccountValue/Configuration/AccountKeyConfigurationImpl.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziAccount/AccountValue/Configuration/AccountKeyConfigurationImpl.swift#L61-L62

Added lines #L61 - L62 were not covered by tests
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ public enum AccountKeyRequirement {
/// The account value is **not** collected at signup. However, it is displayed in the account overview
/// and a user can supply a value by editing their account details.
case supported
/// The associated account value **can** be provided by the user at a later point in time.
///
/// The account value is **not** collected at signup. It is also not displayed in the account overview.
case manual
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,31 @@
/// - Parameter keyPath: The `KeyPath` referencing the ``AccountKey``.
/// - Returns: Returns the ``AccountKey`` configuration.
public static func requires<Key: AccountKey>(_ keyPath: KeyPath<AccountKeys, Key.Type>) -> ConfiguredAccountKey {
.init(configuration: AccountKeyConfigurationImpl(keyPath, type: .required))
.init(configuration: AccountKeyConfigurationImpl(keyPath, requirement: .required))
}

/// Configure an ``AccountKey`` as ``AccountKeyRequirement/collected``.
/// - Parameter keyPath: The `KeyPath` referencing the ``AccountKey``.
/// - Returns: Returns the ``AccountKey`` configuration.
@_disfavoredOverload
public static func collects<Key: AccountKey>(_ keyPath: KeyPath<AccountKeys, Key.Type>) -> ConfiguredAccountKey {
.init(configuration: AccountKeyConfigurationImpl(keyPath, type: .collected))
.init(configuration: AccountKeyConfigurationImpl(keyPath, requirement: .collected))
}

/// Configure an ``AccountKey`` as ``AccountKeyRequirement/supported``.
/// - Parameter keyPath: The `KeyPath` referencing the ``AccountKey``.
/// - Returns: Returns the ``AccountKey`` configuration.
@_disfavoredOverload
public static func supports<Key: AccountKey>(_ keyPath: KeyPath<AccountKeys, Key.Type>) -> ConfiguredAccountKey {
.init(configuration: AccountKeyConfigurationImpl(keyPath, type: .supported))
.init(configuration: AccountKeyConfigurationImpl(keyPath, requirement: .supported))
}

/// Configure an ``AccountKey`` as ``AccountKeyRequirement/manual``.
/// - Parameter keyPath: The `KeyPath` referencing the ``AccountKey``.
/// - Returns: Returns the ``AccountKey`` configuration.
@_disfavoredOverload
Supereg marked this conversation as resolved.
Show resolved Hide resolved
public static func manual<Key: AccountKey>(_ keyPath: KeyPath<AccountKeys, Key.Type>) -> ConfiguredAccountKey {
.init(configuration: AccountKeyConfigurationImpl(keyPath, requirement: .manual))
}

/// Configure an ``AccountKey`` as ``AccountKeyRequirement/required`` as ``RequiredAccountKey`` can only be configured as required.
Expand All @@ -73,6 +81,14 @@
public static func supports<Key: RequiredAccountKey>(_ keyPath: KeyPath<AccountKeys, Key.Type>) -> ConfiguredAccountKey {
requires(keyPath)
}

/// Configure an ``AccountKey`` as ``AccountKeyRequirement/required`` as ``RequiredAccountKey`` can only be configured as required.
/// - Parameter keyPath: The `KeyPath` referencing the ``AccountKey``.
/// - Returns: Returns the ``AccountKey`` configuration.
@available(*, deprecated, renamed: "requires", message: "A 'RequiredAccountKey' must always be supplied as required using requires(_:)")
public static func manual<Key: RequiredAccountKey>(_ keyPath: KeyPath<AccountKeys, Key.Type>) -> ConfiguredAccountKey {
requires(keyPath)
}

Check warning on line 91 in Sources/SpeziAccount/AccountValue/Configuration/ConfiguredAccountKey.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziAccount/AccountValue/Configuration/ConfiguredAccountKey.swift#L89-L91

Added lines #L89 - L91 were not covered by tests
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class AccountOverviewFormViewModel {


init(_ valueConfiguration: AccountValueConfiguration, _ serviceConfiguration: AccountServiceConfiguration) {
self.categorizedAccountKeys = valueConfiguration.allCategorized()
self.categorizedAccountKeys = valueConfiguration.allCategorized(filteredBy: [.required, .collected, .supported])
self.accountServiceConfiguration = serviceConfiguration
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import SwiftUI


private let logger = Logger(subsystem: "edu.stanford.sepzi.SepziAccount", category: "AccountRequiredModifier")
private let logger = Logger(subsystem: "edu.stanford.spezi.SpeziAccount", category: "AccountRequiredModifier")

Check warning on line 13 in Sources/SpeziAccount/ViewModifier/AccountRequiredModifier.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package macOS / Test using xcodebuild or run fastlane

let 'logger' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 13 in Sources/SpeziAccount/ViewModifier/AccountRequiredModifier.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package / Test using xcodebuild or run fastlane

let 'logger' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 13 in Sources/SpeziAccount/ViewModifier/AccountRequiredModifier.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package visionOS / Test using xcodebuild or run fastlane

let 'logger' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 13 in Sources/SpeziAccount/ViewModifier/AccountRequiredModifier.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package visionOS / Test using xcodebuild or run fastlane

let 'logger' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 13 in Sources/SpeziAccount/ViewModifier/AccountRequiredModifier.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

let 'logger' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 13 in Sources/SpeziAccount/ViewModifier/AccountRequiredModifier.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

let 'logger' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 13 in Sources/SpeziAccount/ViewModifier/AccountRequiredModifier.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests visionOS / Test using xcodebuild or run fastlane

let 'logger' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6

Check warning on line 13 in Sources/SpeziAccount/ViewModifier/AccountRequiredModifier.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests visionOS / Test using xcodebuild or run fastlane

let 'logger' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
pauljohanneskraft marked this conversation as resolved.
Show resolved Hide resolved


struct AccountRequiredModifier<SetupSheet: View>: ViewModifier {
Expand Down
5 changes: 5 additions & 0 deletions Tests/UITests/TestApp/AccountTestsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ struct AccountTestsView: View {
} label: {
Text(verbatim: "License Information")
}
if let invitationCode = account.details?.invitationCode {
LabeledContent("Invitation Code") {
Text(invitationCode)
}
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Tests/UITests/TestApp/TestAppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class TestAppDelegate: SpeziAppDelegate {
.collects(\.name),
.collects(\.genderIdentity),
.collects(\.dateOfBirth),
.supports(\.biography)
.supports(\.biography),
.manual(\.invitationCode)
]
case .allRequired:
#if os(visionOS)
Expand Down
19 changes: 19 additions & 0 deletions Tests/UITests/TestApp/Utils/InvitationCodeKey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// This source file is part of the Spezi open-source project
//
// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md)
//
// SPDX-License-Identifier: MIT
//

import SpeziAccount
import SwiftUI

extension AccountDetails {
@AccountKey(name: "Invitation Code", category: .other, as: String.self)
var invitationCode: String?
}


@KeyEntry(\.invitationCode)
extension AccountKeys {}
13 changes: 6 additions & 7 deletions Tests/UITests/TestAppUITests/DocumentationHintsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class DocumentationHintsTests: XCTestCase {
}

@MainActor
func testDocumentationHint(type: ServiceType, button: String, hint: String) {
func testDocumentationHint(type: ServiceType, button: String, hint: String) throws {
let app = XCUIApplication()
app.launch(serviceType: type)

Expand All @@ -37,17 +37,16 @@ final class DocumentationHintsTests: XCTestCase {
sleep(3)
#endif
XCTAssert(safari.wait(for: .runningForeground, timeout: 5))
XCTAssertTrue(safari.staticTexts["Swift Package Index"].waitForExistence(timeout: 10.0))
XCTAssertTrue(safari.staticTexts["Initial Setup"].waitForExistence(timeout: 2.0)) // The initial setup article

safari.terminate()

app.activate()
XCTAssertTrue(app.wait(for: .runningForeground, timeout: 2.0))
}

@MainActor
func testEmptyAccountServices() {
testDocumentationHint(
func testEmptyAccountServices() throws {
try testDocumentationHint(
type: .empty,
button: "Account Setup",
hint: """
Expand All @@ -58,8 +57,8 @@ final class DocumentationHintsTests: XCTestCase {
}

@MainActor
func testMissingAccount() {
testDocumentationHint(
func testMissingAccount() throws {
try testDocumentationHint(
type: .mail,
button: "Account Overview",
hint: """
Expand Down
4 changes: 4 additions & 0 deletions Tests/UITests/UITests.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
2F6D139A28F5F386007C25D6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2F6D139928F5F386007C25D6 /* Assets.xcassets */; };
2FA7382C290ADFAA007ACEB9 /* TestApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA7382B290ADFAA007ACEB9 /* TestApp.swift */; };
2FAD38C02A455FC200E79ED1 /* SpeziAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 2FAD38BF2A455FC200E79ED1 /* SpeziAccount */; };
9B345FB82C94BF470067C977 /* InvitationCodeKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B345FB72C94BF470067C977 /* InvitationCodeKey.swift */; };
A969240F2A9A198800E2128B /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = A969240E2A9A198800E2128B /* ArgumentParser */; };
A98739032C64EE6000E17A42 /* EntryViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98739022C64EE5F00E17A42 /* EntryViewTests.swift */; };
A98739052C64F1BB00E17A42 /* EntryViewsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98739042C64F1B300E17A42 /* EntryViewsTests.swift */; };
Expand Down Expand Up @@ -54,6 +55,7 @@
2FAD38BE2A455F7D00E79ED1 /* SpeziAccount */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = SpeziAccount; path = ../..; sourceTree = "<group>"; };
2FE750C92A8720CE00723EAE /* TestApp.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TestApp.xctestplan; sourceTree = "<group>"; };
636D985F2AF188E00020B8BC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
9B345FB72C94BF470067C977 /* InvitationCodeKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InvitationCodeKey.swift; sourceTree = "<group>"; };
A98739022C64EE5F00E17A42 /* EntryViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryViewTests.swift; sourceTree = "<group>"; };
A98739042C64F1B300E17A42 /* EntryViewsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryViewsTests.swift; sourceTree = "<group>"; };
A9B6E3F62A9B6F5B0008B232 /* AccountSetupTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSetupTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -94,6 +96,7 @@
isa = PBXGroup;
children = (
A9B6E3FC2A9B74830008B232 /* BiographyKey.swift */,
9B345FB72C94BF470067C977 /* InvitationCodeKey.swift */,
A9B6E3FE2A9B795C0008B232 /* TestStandard.swift */,
2F027C7F29D6C29B00234098 /* AccountDetails+Default.swift */,
);
Expand Down Expand Up @@ -284,6 +287,7 @@
2FA7382C290ADFAA007ACEB9 /* TestApp.swift in Sources */,
A98739032C64EE6000E17A42 /* EntryViewTests.swift in Sources */,
A9EE7D2A2A3359E800C2B9A9 /* Features.swift in Sources */,
9B345FB82C94BF470067C977 /* InvitationCodeKey.swift in Sources */,
2F027C9529D6C63100234098 /* TestAppDelegate.swift in Sources */,
2F027C8929D6C2AD00234098 /* AccountDetails+Default.swift in Sources */,
A9B6E3FF2A9B795C0008B232 /* TestStandard.swift in Sources */,
Expand Down
Loading