diff --git a/.github/workflows/validate-all.yml b/.github/workflows/validate-all.yml index 26d409d86..e314f00cc 100644 --- a/.github/workflows/validate-all.yml +++ b/.github/workflows/validate-all.yml @@ -8,48 +8,54 @@ on: branches: [main] env: - IOS_PLATFORM: iOS Simulator - IOS_DEVICE: iPhone 15 - IOS_VERSION: 17.4 + XCODE_VERSION: "26.0" jobs: - # TODO: enable when swiftlint supports a linux binary in its artifact bundle - # lint: - # name: Lint - # timeout-minutes: 2 - # runs-on: ubuntu-latest - # defaults: - # run: - # working-directory: ./Vault - # - # steps: - # - uses: actions/checkout@v4 - # - name: Lint Sources - # run: make lint + lint: + name: Lint + timeout-minutes: 2 + runs-on: macos-26 + defaults: + run: + working-directory: ./Vault - # build: - # name: Build - # timeout-minutes: 5 - # runs-on: macos-14 - # - # steps: - # - uses: actions/checkout@v4 - # - run: sudo xcode-select -s /Applications/Xcode_15.3.app/Contents/Developer - # - name: Build App - # run: xcodebuild -workspace Vault.xcworkspace -scheme VaultApp -destination 'platform=${{ env.IOS_PLATFORM }},name=${{ env.IOS_DEVICE }},OS=${{ env.IOS_VERSION }}' -skipMacroValidation -quiet build - # + steps: + - uses: actions/checkout@v4 + - run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer + + - name: Cache SPM Dependencies + uses: actions/cache@v4 + with: + path: | + ~/Library/Caches/org.swift.swiftpm/repositories + Vault/.build + key: ${{ runner.os }}-spm-lint-${{ hashFiles('Vault/Package.resolved') }} + restore-keys: | + ${{ runner.os }}-spm-lint- + + - name: Check Linting & Formatting + run: make lint + + # Don't test for now to save CI time # test: # name: Test - # timeout-minutes: 30 - # runs-on: ubuntu-latest - # # runs-on: macos-14 + # timeout-minutes: 10 + # runs-on: macos-26 # # steps: - # # We currently don't run tests in CI due to cost. - # # This can be re-enabled when the repo is made public! - # - name: Skip Testing - # run: true # - uses: actions/checkout@v4 - # - run: sudo xcode-select -s /Applications/Xcode_15.3.app/Contents/Developer - # - name: Run all Tests - # run: xcodebuild -workspace Vault.xcworkspace -scheme CI_iOS -destination 'platform=${{ env.IOS_PLATFORM }},name=${{ env.IOS_DEVICE }},OS=${{ env.IOS_VERSION }}' -skipMacroValidation -quiet test + # - run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer + # + # - name: Cache SPM Dependencies + # uses: actions/cache@v4 + # with: + # path: ~/Library/Caches/org.swift.swiftpm/repositories + # key: ${{ runner.os }}-spm-${{ hashFiles('Vault/Package.resolved') }} + # restore-keys: | + # ${{ runner.os }}-spm- + # + # - name: Clear SPM Artifacts + # run: rm -rf ~/Library/Caches/org.swift.swiftpm/artifacts + # + # - name: Test CI_macOS + # run: xcodebuild test -workspace Vault.xcworkspace -scheme CI_macOS -skipMacroValidation -skipPackagePluginValidation diff --git a/README.md b/README.md index bd36b4ed9..131787fe6 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ There is purposely no automatic or online backup, so you never need to worry abo There's a few ways that you can use Vault to store your data: 1. Super secret data - - Store data you really don't want to be accessed in encrypted notes, like cryptocurrency private keys. Hide them and add a killcode so, if under duress, you can wipe them with plausible deniability. Restore from a backup when you get home. 2. Store OTP codes diff --git a/Vault/.swiftpm/xcode/xcshareddata/xcschemes/CI_iOS.xcscheme b/Vault/.swiftpm/xcode/xcshareddata/xcschemes/CI_iOS.xcscheme index 90a9c4a1a..22f8cb2e7 100644 --- a/Vault/.swiftpm/xcode/xcshareddata/xcschemes/CI_iOS.xcscheme +++ b/Vault/.swiftpm/xcode/xcshareddata/xcschemes/CI_iOS.xcscheme @@ -28,6 +28,9 @@ reference = "container:TestPlans/CI/iOSAllTests.xctestplan" default = "YES"> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Vault/Makefile b/Vault/Makefile index 913182f13..cd099e389 100644 --- a/Vault/Makefile +++ b/Vault/Makefile @@ -6,10 +6,12 @@ benchmark-keygen: .PHONY: format format: + swift package plugin --allow-writing-to-package-directory swiftlint --fix --quiet ./Sources swift package --allow-writing-to-package-directory format --sources=./ .PHONY: lint lint: + swift package plugin swiftlint --strict --quiet ./Sources swift package --allow-writing-to-package-directory format --lint --sources=./ .PHONY: clean diff --git a/Vault/Package.swift b/Vault/Package.swift index 20f12b68e..c183de1d5 100644 --- a/Vault/Package.swift +++ b/Vault/Package.swift @@ -276,20 +276,18 @@ let package = Package( capability: .command( intent: .custom( verb: "format", - description: "Formats Swift source files using swiftformat and swiftlint" + description: "Formats Swift source files using swiftformat only" ), permissions: [.writeToPackageDirectory(reason: "Format source code")] - ) + ), + dependencies: [ + "swiftformat", + ] ), .binaryTarget( name: "swiftformat", url: "https://github.com/nicklockwood/SwiftFormat/releases/download/\(swiftFormatVersion)/swiftformat.artifactbundle.zip", checksum: swiftFormatChecksum ), - .binaryTarget( - name: "swiftlint", - url: "https://github.com/realm/SwiftLint/releases/download/\(swiftLintVersion)/SwiftLintBinary-macos.artifactbundle.zip", - checksum: swiftLintChecksum - ), ] ) diff --git a/Vault/Plugins/FormatLint/Plugin.swift b/Vault/Plugins/FormatLint/Plugin.swift index 3c2f8a43d..d86f29373 100644 --- a/Vault/Plugins/FormatLint/Plugin.swift +++ b/Vault/Plugins/FormatLint/Plugin.swift @@ -9,8 +9,6 @@ struct FormatLintPlugin: CommandPlugin { let formatLintContext = try makeFormatLintContext(context: context, arguments: arguments) let start = Date() - // Lint before formatting so any formatting that results in lint errors is surfaced and we can address it. - try formatLintContext.runSwiftLint() try formatLintContext.runSwiftFormat() let end = Date() let elapsed = end.timeIntervalSince(start) @@ -32,7 +30,6 @@ struct FormatLintPlugin: CommandPlugin { .format } return try FormatLintContext( - swiftlint: context.tool(named: "swiftlint"), swiftformat: context.tool(named: "swiftformat"), workDirectory: context.pluginWorkDirectoryURL, swiftSourcesDirectory: swiftSources, @@ -42,40 +39,12 @@ struct FormatLintPlugin: CommandPlugin { } struct FormatLintContext { - var swiftlint: PluginContext.Tool var swiftformat: PluginContext.Tool var workDirectory: URL var swiftSourcesDirectory: String var action: Action } -extension FormatLintContext { - func makeSwiftLintArgs() -> [String] { - var swiftLintArguments = [String]() - swiftLintArguments += ["--cache-path", workDirectory.appending(path: "swiftlint.cache").path()] - swiftLintArguments += ["--quiet"] - switch action { - case .format: - swiftLintArguments += ["--fix"] - case .lint: - swiftLintArguments += ["--strict"] - } - swiftLintArguments += [swiftSourcesDirectory] - return swiftLintArguments - } - - func runSwiftLint() throws { - print("🔍 swiftlint: \(action.swiftLintVerb.lowercased())") - try runProcess( - url: swiftlint.url, - arguments: makeSwiftLintArgs(), - exitCodeHandler: swiftLintExitCodeHandler(code:) - ) - } -} - -// MARK: - swiftformat - extension FormatLintContext { func makeSwiftFormatArgs() -> [String] { var swiftFormatArguments = [String]() @@ -110,13 +79,6 @@ enum Action { case .lint: "Checking" } } - - var swiftLintVerb: String { - switch self { - case .format: "Fixing" - case .lint: "Linting" - } - } } enum CommandError: Error { @@ -149,13 +111,3 @@ func swiftFormatExitCodeHandler(code: Int32) throws { throw CommandError.unknownError(exitCode: code) } } - -func swiftLintExitCodeHandler(code: Int32) throws { - switch code { - case 0: - print("☑️ swiftlint done") - default: - print("❌ swiftlint failure") - throw CommandError.exitWithError - } -} diff --git a/Vault/Sources/TestHelpers/PDFDocument+Snapshot.swift b/Vault/Sources/TestHelpers/PDFDocument+Snapshot.swift index c8b2c64a1..4e95883d0 100644 --- a/Vault/Sources/TestHelpers/PDFDocument+Snapshot.swift +++ b/Vault/Sources/TestHelpers/PDFDocument+Snapshot.swift @@ -1,3 +1,4 @@ +#if canImport(UIKit) import Foundation import PDFKit import SnapshotTesting @@ -36,3 +37,5 @@ extension PDFDocument { } } } + +#endif diff --git a/Vault/Sources/TestHelpers/SuspendForever.swift b/Vault/Sources/TestHelpers/SuspendForever.swift index 633031900..01cc5d2c5 100644 --- a/Vault/Sources/TestHelpers/SuspendForever.swift +++ b/Vault/Sources/TestHelpers/SuspendForever.swift @@ -5,10 +5,10 @@ import Foundation /// This is achieved by awaiting on a stream that never yields any values. /// /// - throws: `CancellationError` if the task this is in is cancelled. -public func suspendForever() async throws -> Never { +public func suspendForever() async throws { let stream = AsyncStream { _ in } for await _ in stream { - return fatalError("Unreachable") + fatalError("Unreachable") } // The stream will only exit without a value in the case that it's been cancelled. // Propagate the cancellation. diff --git a/Vault/Sources/VaultFeed/Presentation/Backup/BackupImportFlowViewModel.swift b/Vault/Sources/VaultFeed/Presentation/Backup/BackupImportFlowViewModel.swift index 060912ad9..ceb4b2ef0 100644 --- a/Vault/Sources/VaultFeed/Presentation/Backup/BackupImportFlowViewModel.swift +++ b/Vault/Sources/VaultFeed/Presentation/Backup/BackupImportFlowViewModel.swift @@ -105,7 +105,7 @@ public final class BackupImportFlowViewModel { case let .readyToImport(applicationPayload): payloadState = .ready(applicationPayload, UUID()) } - } catch let error as LocalizedError { + } catch let error as any LocalizedError { payloadState = .error(.init(localizedError: error)) } catch { payloadState = .error(PresentationError( @@ -140,7 +140,7 @@ public final class BackupImportFlowViewModel { try await dataModel.importOverride(payload: payload) } importState = .success - } catch let error as LocalizedError { + } catch let error as any LocalizedError { importState = .error(.init(localizedError: error)) } catch { importState = .error(PresentationError( diff --git a/Vault/Sources/VaultFeed/Presentation/Backup/BackupKeyDecryptorViewModel.swift b/Vault/Sources/VaultFeed/Presentation/Backup/BackupKeyDecryptorViewModel.swift index 347a3c866..b99ed0d17 100644 --- a/Vault/Sources/VaultFeed/Presentation/Backup/BackupKeyDecryptorViewModel.swift +++ b/Vault/Sources/VaultFeed/Presentation/Backup/BackupKeyDecryptorViewModel.swift @@ -91,7 +91,7 @@ public final class BackupKeyDecryptorViewModel { ) decryptionKeyState = .validDecryptionKey decryptedVaultSubject.send(vaultApplicationPayload) - } catch let error as LocalizedError { + } catch let error as any LocalizedError { decryptionKeyState = .error(.init(localizedError: error)) } catch { decryptionKeyState = .error(PresentationError( diff --git a/Vault/Sources/VaultFeed/Presentation/Detail/EncryptedItemDetailViewModel.swift b/Vault/Sources/VaultFeed/Presentation/Detail/EncryptedItemDetailViewModel.swift index fbb3a5430..3da23f946 100644 --- a/Vault/Sources/VaultFeed/Presentation/Detail/EncryptedItemDetailViewModel.swift +++ b/Vault/Sources/VaultFeed/Presentation/Detail/EncryptedItemDetailViewModel.swift @@ -81,7 +81,7 @@ public final class EncryptedItemDetailViewModel { case let .decrypted(item): state = .decrypted(item, generatedPassword) } - } catch let localized as LocalizedError { + } catch let localized as any LocalizedError { state = .decryptionError(PresentationError(localizedError: localized)) } catch { state = .decryptionError(PresentationError( diff --git a/Vault/Sources/VaultFeed/Presentation/OTPCode/OTPCodeTimerUpdater.swift b/Vault/Sources/VaultFeed/Presentation/OTPCode/OTPCodeTimerUpdater.swift index c566e432b..2d6daf757 100644 --- a/Vault/Sources/VaultFeed/Presentation/OTPCode/OTPCodeTimerUpdater.swift +++ b/Vault/Sources/VaultFeed/Presentation/OTPCode/OTPCodeTimerUpdater.swift @@ -14,7 +14,7 @@ public protocol OTPCodeTimerUpdater: AnyObject { /// Controller for producing timers for a given code, according to a clock. @MainActor -public final class OTPCodeTimerUpdaterImpl: OTPCodeTimerUpdater, Sendable { +public final class OTPCodeTimerUpdaterImpl: OTPCodeTimerUpdater { private let timerStateSubject: CurrentValueSubject private let period: UInt64 private let timerTask = SharedMutex?>(nil) diff --git a/Vault/Sources/VaultFeed/Storage/VaultDataModel.swift b/Vault/Sources/VaultFeed/Storage/VaultDataModel.swift index ac60b7866..9d0b3d8eb 100644 --- a/Vault/Sources/VaultFeed/Storage/VaultDataModel.swift +++ b/Vault/Sources/VaultFeed/Storage/VaultDataModel.swift @@ -12,7 +12,7 @@ import VaultKeygen /// This is isolated to the main actor for the purposes of UI interop. @MainActor @Observable -public final class VaultDataModel: Sendable { +public final class VaultDataModel { public enum State { case base, loaded, loading } diff --git a/Vault/Sources/VaultFeed/Storage/VaultStore/SwiftData/PersistedLocalVaultStore.swift b/Vault/Sources/VaultFeed/Storage/VaultStore/SwiftData/PersistedLocalVaultStore.swift index 1f3d7145f..13ca0d282 100644 --- a/Vault/Sources/VaultFeed/Storage/VaultStore/SwiftData/PersistedLocalVaultStore.swift +++ b/Vault/Sources/VaultFeed/Storage/VaultStore/SwiftData/PersistedLocalVaultStore.swift @@ -71,17 +71,14 @@ extension PersistedLocalVaultStore: VaultStoreReader { return .true } else { let searchingTagIds = tags.map(\.id).reducedToSet() - // Returns the number of tags matched by this item. - let tagsMatchingSearch = #Expression { item in - item.tags.filter { tag in - searchingTagIds.contains(tag.id) - }.count - } - // Performs an "AND" query by checking if the number of tags matched equals - // the number of tags we are searching for. - let searchingTagsCount = searchingTagIds.count + // Performs an "AND" query by checking if all searched tags are present in the item's tags. + // We convert the set to an array to use filter, which is supported in SwiftData predicates. + // An item matches if the count of its tags that match our search equals the search count. + let searchingTagsArray = Array(searchingTagIds) return #Predicate { item in - tagsMatchingSearch.evaluate(item) == searchingTagsCount + item.tags.count(where: { tag in + searchingTagsArray.contains(tag.id) + }) == searchingTagsArray.count } } } diff --git a/Vault/Sources/VaultKeygenSpeedtest/Speedtest.swift b/Vault/Sources/VaultKeygenSpeedtest/Speedtest.swift index c3deb8b27..b044d2848 100644 --- a/Vault/Sources/VaultKeygenSpeedtest/Speedtest.swift +++ b/Vault/Sources/VaultKeygenSpeedtest/Speedtest.swift @@ -15,7 +15,7 @@ import VaultKeygen @main struct KeygenSpeedtest { - public static func main() throws { + static func main() throws { print("🚧 Build configuration:", buildConfigString()) try benchmark(keyDeriver: VaultKeyDeriver.Item.Fast.v1, description: "Item Fast") diff --git a/Vault/Sources/VaultiOS/Views/TimerBar/CodeTimerHorizontalBarView.swift b/Vault/Sources/VaultiOS/Views/TimerBar/CodeTimerHorizontalBarView.swift index 0ea13e2e7..b89241a16 100644 --- a/Vault/Sources/VaultiOS/Views/TimerBar/CodeTimerHorizontalBarView.swift +++ b/Vault/Sources/VaultiOS/Views/TimerBar/CodeTimerHorizontalBarView.swift @@ -49,21 +49,19 @@ struct CodeTimerHorizontalBarView: View { resetTimerBarAnimation = .init(qos: .userInteractive) { withAnimation( .linear(duration: animateReset ? 0.15 : 0), - completionCriteria: .removed, - { - currentFractionCompleted = timerState.animationState.initialFraction(currentTime: clock.currentTime) - }, - completion: { - if case let .animate(state) = timerState.animationState { - timerAnimation = .init(qos: .userInteractive) { - withAnimation(.linear(duration: state.remainingTime(at: clock.currentTime))) { - currentFractionCompleted = 0 - } + completionCriteria: .removed + ) { + currentFractionCompleted = timerState.animationState.initialFraction(currentTime: clock.currentTime) + } completion: { + if case let .animate(state) = timerState.animationState { + timerAnimation = .init(qos: .userInteractive) { + withAnimation(.linear(duration: state.remainingTime(at: clock.currentTime))) { + currentFractionCompleted = 0 } - timerAnimation?.perform() } + timerAnimation?.perform() } - ) + } } resetTimerBarAnimation?.perform() } diff --git a/Vault/Sources/VaultiOSAutofill/Views/VaultAutofillConfigurationView.swift b/Vault/Sources/VaultiOSAutofill/Views/VaultAutofillConfigurationView.swift index 09abad973..a8625f753 100644 --- a/Vault/Sources/VaultiOSAutofill/Views/VaultAutofillConfigurationView.swift +++ b/Vault/Sources/VaultiOSAutofill/Views/VaultAutofillConfigurationView.swift @@ -4,11 +4,11 @@ import VaultiOS struct VaultAutofillConfigurationView: View { @State private var viewModel: VaultAutofillConfigurationViewModel - public init(viewModel: VaultAutofillConfigurationViewModel) { + init(viewModel: VaultAutofillConfigurationViewModel) { self.viewModel = viewModel } - public var body: some View { + var body: some View { ScrollView { container .padding(.vertical, 16) diff --git a/Vault/TestPlans/CI/macOS_SupportedTests.xctestplan b/Vault/TestPlans/CI/macOS_SupportedTests.xctestplan new file mode 100644 index 000000000..2051c455c --- /dev/null +++ b/Vault/TestPlans/CI/macOS_SupportedTests.xctestplan @@ -0,0 +1,52 @@ +{ + "configurations" : [ + { + "id" : "D213A255-37DA-4E13-8AB8-3AD0E9C299FE", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "VaultCoreTests", + "name" : "VaultCoreTests" + } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "FoundationExtensionsTests", + "name" : "FoundationExtensionsTests" + } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "CryptoEngineTests", + "name" : "CryptoEngineTests" + } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "VaultKeygenTests", + "name" : "VaultKeygenTests" + } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "VaultKeygenSpeedtestCompileTests", + "name" : "VaultKeygenSpeedtestCompileTests" + } + } + ], + "version" : 1 +} diff --git a/Vault/Tests/CryptoEngineTests/DataHelpersTests.swift b/Vault/Tests/CryptoEngineTests/DataHelpersTests.swift index 6e47f358c..79a64a983 100644 --- a/Vault/Tests/CryptoEngineTests/DataHelpersTests.swift +++ b/Vault/Tests/CryptoEngineTests/DataHelpersTests.swift @@ -28,12 +28,12 @@ struct DataHelpersTests { @Test func int64ToData_interpretsAsLittleEndian() { let number: UInt64 = 1 - #expect(number.data.bytes == [1, 0, 0, 0, 0, 0, 0, 0]) + #expect(Array(number.data) == [1, 0, 0, 0, 0, 0, 0, 0]) } @Test func byteString_interpretsUTF8StringValues() { let value = Data(byteString: "1234") - #expect(value.bytes == [49, 50, 51, 52]) + #expect(Array(value) == [49, 50, 51, 52]) } } diff --git a/Vault/Tests/FoundationExtensionsTests/DefaultsStoredTests.swift b/Vault/Tests/FoundationExtensionsTests/DefaultsStoredTests.swift index 24a31daff..4129a0305 100644 --- a/Vault/Tests/FoundationExtensionsTests/DefaultsStoredTests.swift +++ b/Vault/Tests/FoundationExtensionsTests/DefaultsStoredTests.swift @@ -33,7 +33,7 @@ final class DefaultsStoredTests { } @Test - func test_wrappedValue_setsValueInDefaults() throws { + func wrappedValue_setsValueInDefaults() throws { let key: Key = .init("test3") let coolNumberInitial = 4567 try defaults.set(coolNumberInitial, for: key) diff --git a/Vault/Tests/FoundationExtensionsTests/PendingValueTests.swift b/Vault/Tests/FoundationExtensionsTests/PendingValueTests.swift index 8f8e82fbe..c0566a398 100644 --- a/Vault/Tests/FoundationExtensionsTests/PendingValueTests.swift +++ b/Vault/Tests/FoundationExtensionsTests/PendingValueTests.swift @@ -218,14 +218,14 @@ extension PendingValueTests { /// Without this, you might acidentally call `fulfill`/`reject` before await, and thus the value will be cached. private func awaitValueInBackground( on sut: SUT, - action: () async -> Void + action: @Sendable () async -> Void ) async throws -> Result { let startedWaiting = Pending.signal() let finishedWaiting = Pending.signal() - var result: Result? let task = Task.detached(priority: .high) { await startedWaiting.fulfill() + let result: Result do { let value = try await sut.wait() result = .success(value) @@ -233,6 +233,7 @@ extension PendingValueTests { result = .failure(error) } await finishedWaiting.fulfill() + return result } try await startedWaiting.wait(timeout: .seconds(1)) @@ -242,8 +243,8 @@ extension PendingValueTests { try await finishedWaiting.wait(timeout: .seconds(1)) - task.cancel() - return try #require(result) + defer { task.cancel() } + return await task.value } private func awaitNoValueProduced(on sut: SUT) async { diff --git a/Vault/Tests/VaultCoreTests/OTPAuthDigitsTests.swift b/Vault/Tests/VaultCoreTests/OTPAuthDigitsTests.swift index 1bf20b527..6be417605 100644 --- a/Vault/Tests/VaultCoreTests/OTPAuthDigitsTests.swift +++ b/Vault/Tests/VaultCoreTests/OTPAuthDigitsTests.swift @@ -4,7 +4,7 @@ import VaultCore struct OTPAuthDigitsTests { @Test - func test_description_encodesToSimpleDigits() { + func description_encodesToSimpleDigits() { let digits = OTPAuthDigits(value: 123) #expect("\(digits)" == "123") diff --git a/Vault/Tests/VaultCoreTests/URI/OTPAuthURIEncoderTests.swift b/Vault/Tests/VaultCoreTests/URI/OTPAuthURIEncoderTests.swift index f9038578b..90a9cf2d8 100644 --- a/Vault/Tests/VaultCoreTests/URI/OTPAuthURIEncoderTests.swift +++ b/Vault/Tests/VaultCoreTests/URI/OTPAuthURIEncoderTests.swift @@ -6,7 +6,7 @@ struct OTPAuthURIEncoderTests { let sut = OTPAuthURIEncoder() @Test - func test_encodeScheme_isOtpauth() throws { + func encodeScheme_isOtpauth() throws { let code = makeCode(type: .totp()) let encoded = try sut.encode(code: code) diff --git a/Vault/Tests/VaultFeedTests/CodeScanner/BackupImportScanningHandlerTests.swift b/Vault/Tests/VaultFeedTests/CodeScanner/BackupImportScanningHandlerTests.swift index 008049bfc..db43fffa6 100644 --- a/Vault/Tests/VaultFeedTests/CodeScanner/BackupImportScanningHandlerTests.swift +++ b/Vault/Tests/VaultFeedTests/CodeScanner/BackupImportScanningHandlerTests.swift @@ -94,7 +94,7 @@ struct BackupImportScanningHandlerTests { } @Test - func test_decodeInvalidFullDataEndsWithUnrecoverableError() throws { + func decodeInvalidFullDataEndsWithUnrecoverableError() throws { let result1 = sut.decode(data: """ { "G":{"ID":10,"N":2,"I":0},