From 820865c2908bcd56f5765367bd4ea6c90e056a04 Mon Sep 17 00:00:00 2001 From: Matt Czech Date: Fri, 21 Nov 2025 11:38:32 -0600 Subject: [PATCH] [PM-27143] Add default bundle for APITestData in each framework (#2156) --- .../Support/BitwardenTestCase.swift | 7 +- .../Fixtures/APITestData+Authenticator.swift | 12 ++++ .../AuthenticatorSharedBundleFinder.swift | 10 +++ .../Support/BitwardenTestCase.swift | 2 - .../Fixtures/APITestData+Account.swift | 65 ++++--------------- .../APITestData+BitwardenKitMocks.swift | 12 ++++ .../API/Fixtures/APITestData+Config.swift | 5 +- .../API/Fixtures/APITestData+Error.swift | 5 +- .../BitwardenKitMocksBundleFinder.swift | 5 ++ .../APITestData+BitwardenShared.swift | 12 ++++ .../BitwardenSharedBundleFinder.swift | 10 +++ .../Services/Fixtures/CXF+Fixtures.swift | 5 +- .../Support/BitwardenTestCase.swift | 2 - .../Support/BitwardenTestCase.swift | 2 - TestHelpers/API/APITestData.swift | 4 +- TestHelpers/API/TestDataHelpers.swift | 19 ++---- 16 files changed, 88 insertions(+), 89 deletions(-) create mode 100644 AuthenticatorShared/Core/Platform/Services/API/Fixtures/APITestData+Authenticator.swift create mode 100644 AuthenticatorShared/Core/Platform/Services/API/Fixtures/AuthenticatorSharedBundleFinder.swift create mode 100644 BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+BitwardenKitMocks.swift create mode 100644 BitwardenShared/Core/Platform/Services/API/Fixtures/APITestData+BitwardenShared.swift create mode 100644 BitwardenShared/Core/Platform/Services/API/Fixtures/BitwardenSharedBundleFinder.swift diff --git a/AuthenticatorBridgeKit/Tests/TestHelpers/Support/BitwardenTestCase.swift b/AuthenticatorBridgeKit/Tests/TestHelpers/Support/BitwardenTestCase.swift index b6d5e7829..3a2861080 100644 --- a/AuthenticatorBridgeKit/Tests/TestHelpers/Support/BitwardenTestCase.swift +++ b/AuthenticatorBridgeKit/Tests/TestHelpers/Support/BitwardenTestCase.swift @@ -1,9 +1,4 @@ import TestHelpers import XCTest -open class BitwardenTestCase: BaseBitwardenTestCase { - @MainActor - override open class func setUp() { - TestDataHelpers.defaultBundle = Bundle(for: Self.self) - } -} +open class BitwardenTestCase: BaseBitwardenTestCase {} diff --git a/AuthenticatorShared/Core/Platform/Services/API/Fixtures/APITestData+Authenticator.swift b/AuthenticatorShared/Core/Platform/Services/API/Fixtures/APITestData+Authenticator.swift new file mode 100644 index 000000000..b8424d21b --- /dev/null +++ b/AuthenticatorShared/Core/Platform/Services/API/Fixtures/APITestData+Authenticator.swift @@ -0,0 +1,12 @@ +import TestHelpers + +/// `APITestData` helpers that load the resource from the `AuthenticatorShared` bundle. +extension APITestData { + static func loadFromBundle(resource: String, extension: String) -> APITestData { + loadFromBundle(resource: resource, extension: `extension`, bundle: .authenticatorShared) + } + + static func loadFromJsonBundle(resource: String) -> APITestData { + loadFromJsonBundle(resource: resource, bundle: .authenticatorShared) + } +} diff --git a/AuthenticatorShared/Core/Platform/Services/API/Fixtures/AuthenticatorSharedBundleFinder.swift b/AuthenticatorShared/Core/Platform/Services/API/Fixtures/AuthenticatorSharedBundleFinder.swift new file mode 100644 index 000000000..2d3789813 --- /dev/null +++ b/AuthenticatorShared/Core/Platform/Services/API/Fixtures/AuthenticatorSharedBundleFinder.swift @@ -0,0 +1,10 @@ +import Foundation + +class AuthenticatorSharedBundleFinder { + static let bundle = Bundle(for: AuthenticatorSharedBundleFinder.self) +} + +public extension Bundle { + /// The bundle for the `AuthenticatorShared` target. + static let authenticatorShared = AuthenticatorSharedBundleFinder.bundle +} diff --git a/BitwardenKit/Application/TestHelpers/Support/BitwardenTestCase.swift b/BitwardenKit/Application/TestHelpers/Support/BitwardenTestCase.swift index 89274d5cd..999dad5c9 100644 --- a/BitwardenKit/Application/TestHelpers/Support/BitwardenTestCase.swift +++ b/BitwardenKit/Application/TestHelpers/Support/BitwardenTestCase.swift @@ -7,8 +7,6 @@ open class BitwardenTestCase: BaseBitwardenTestCase { override open class func setUp() { // Apply default appearances for snapshot tests. UI.applyDefaultAppearances() - - TestDataHelpers.defaultBundle = Bundle(for: Self.self) } /// Executes any logic that should be applied before each test runs. diff --git a/BitwardenKit/Core/Auth/Services/API/Account/Fixtures/APITestData+Account.swift b/BitwardenKit/Core/Auth/Services/API/Account/Fixtures/APITestData+Account.swift index 855d8b1b1..f63bd6bde 100644 --- a/BitwardenKit/Core/Auth/Services/API/Account/Fixtures/APITestData+Account.swift +++ b/BitwardenKit/Core/Auth/Services/API/Account/Fixtures/APITestData+Account.swift @@ -14,111 +14,70 @@ public extension APITestData { // MARK: Create Account /// Test data of an invalid model state with no validation errors. - static let createAccountNilValidationErrors = loadFromJsonBundle( - resource: "CreateAccountNilValidationErrors", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let createAccountNilValidationErrors = loadFromJsonBundle(resource: "CreateAccountNilValidationErrors") /// Test data with a validation error of "User verification failed." - static let deleteAccountRequestFailure = loadFromJsonBundle( - resource: "DeleteAccountRequestFailure", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let deleteAccountRequestFailure = loadFromJsonBundle(resource: "DeleteAccountRequestFailure") /// Test data with several leaked passwords. - static let hibpLeakedPasswords = loadFromBundle( - resource: "hibpLeakedPasswords", - extension: "txt", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let hibpLeakedPasswords = loadFromBundle(resource: "hibpLeakedPasswords", extension: "txt") /// Test data with an invalid username/password error. - static let responseValidationError = loadFromJsonBundle( - resource: "ResponseValidationError", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let responseValidationError = loadFromJsonBundle(resource: "ResponseValidationError") // MARK: Pre-Login /// Test data for prelogin success. - static let preLoginSuccess = loadFromJsonBundle( - resource: "PreLoginSuccess", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let preLoginSuccess = loadFromJsonBundle(resource: "PreLoginSuccess") // MARK: Register Finish /// Test data with a validation error of "Email 'j@a.com' is already taken." - static let registerFinishAccountAlreadyExists = loadFromJsonBundle( - resource: "RegisterFinishAccountAlreadyExists", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let registerFinishAccountAlreadyExists = loadFromJsonBundle(resource: "RegisterFinishAccountAlreadyExists") /// Test data with a validation error of /// "The field MasterPasswordHint must be a string with a maximum length of 50." - static let registerFinishHintTooLong = loadFromJsonBundle( - resource: "RegisterFinishHintTooLong", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let registerFinishHintTooLong = loadFromJsonBundle(resource: "RegisterFinishHintTooLong") /// Test data with a validation error of "The Email field is not a supported e-mail address format." - static let registerFinishInvalidEmailFormat = loadFromJsonBundle( - resource: "RegisterFinishInvalidEmailFormat", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let registerFinishInvalidEmailFormat = loadFromJsonBundle(resource: "RegisterFinishInvalidEmailFormat") /// Test data of a request to create an account for `example@email.com` - static let registerFinishRequest = loadFromJsonBundle( - resource: "RegisterFinishRequest", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let registerFinishRequest = loadFromJsonBundle(resource: "RegisterFinishRequest") /// Test data of a successful account creation. - static let registerFinishSuccess = loadFromJsonBundle( - resource: "RegisterFinishSuccess", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let registerFinishSuccess = loadFromJsonBundle(resource: "RegisterFinishSuccess") // MARK: Request Password Hint /// Test data for a failure for password hint. - static let passwordHintFailure = loadFromJsonBundle( - resource: "PasswordHintFailure", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let passwordHintFailure = loadFromJsonBundle(resource: "PasswordHintFailure") // MARK: Start Registration /// Test data with a validation error of "Email 'j@a.com' is already taken." static let startRegistrationEmailAlreadyExists = loadFromJsonBundle( resource: "StartRegistrationEmailAlreadyExists", - bundle: BitwardenKitMocksBundleFinder.bundle, ) /// Test data with a validation error of "The field Email must be a string with a maximum length of 256." static let startRegistrationEmailExceedsMaxLength = loadFromJsonBundle( resource: "StartRegistrationEmailExceedsMaxLength", - bundle: BitwardenKitMocksBundleFinder.bundle, ) /// Test data with a validation error of static let startRegistrationInvalidEmailFormat = loadFromJsonBundle( resource: "StartRegistrationInvalidEmailFormat", - bundle: BitwardenKitMocksBundleFinder.bundle, ) /// Test data for success with a registration start. static let startRegistrationSuccess = loadFromBundle( resource: "StartRegistrationSuccess", extension: "txt", - bundle: BitwardenKitMocksBundleFinder.bundle, ) // MARK: Verify Email Token /// Test data indicating that the verify email token link has expired. - static let verifyEmailTokenExpiredLink = loadFromJsonBundle( - resource: "VerifyEmailTokenExpiredLink", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let verifyEmailTokenExpiredLink = loadFromJsonBundle(resource: "VerifyEmailTokenExpiredLink") } diff --git a/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+BitwardenKitMocks.swift b/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+BitwardenKitMocks.swift new file mode 100644 index 000000000..a6290d78c --- /dev/null +++ b/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+BitwardenKitMocks.swift @@ -0,0 +1,12 @@ +import TestHelpers + +/// `APITestData` helpers that load the resource from the `BitwardenKitMocks` bundle. +extension APITestData { + static func loadFromBundle(resource: String, extension: String) -> APITestData { + loadFromBundle(resource: resource, extension: `extension`, bundle: .bitwardenKitMocks) + } + + static func loadFromJsonBundle(resource: String) -> APITestData { + loadFromJsonBundle(resource: resource, bundle: .bitwardenKitMocks) + } +} diff --git a/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+Config.swift b/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+Config.swift index db864c1b4..3631c5403 100644 --- a/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+Config.swift +++ b/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+Config.swift @@ -3,8 +3,5 @@ import TestHelpers public extension APITestData { /// A valid server configuration to produce a `ConfigResponseModel`. - static let validServerConfig = loadFromJsonBundle( - resource: "ValidServerConfig", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let validServerConfig = loadFromJsonBundle(resource: "ValidServerConfig") } diff --git a/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+Error.swift b/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+Error.swift index e0ec5ed85..572edb261 100644 --- a/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+Error.swift +++ b/BitwardenKit/Core/Platform/Services/API/Fixtures/APITestData+Error.swift @@ -3,8 +3,5 @@ import TestHelpers public extension APITestData { /// A standard Bitwarden error message of "You do not have permissions to edit this." - static let bitwardenErrorMessage = loadFromJsonBundle( - resource: "BitwardenErrorMessage", - bundle: BitwardenKitMocksBundleFinder.bundle, - ) + static let bitwardenErrorMessage = loadFromJsonBundle(resource: "BitwardenErrorMessage") } diff --git a/BitwardenKit/Core/Platform/Services/API/Fixtures/BitwardenKitMocksBundleFinder.swift b/BitwardenKit/Core/Platform/Services/API/Fixtures/BitwardenKitMocksBundleFinder.swift index de8b9a5bf..79429ab67 100644 --- a/BitwardenKit/Core/Platform/Services/API/Fixtures/BitwardenKitMocksBundleFinder.swift +++ b/BitwardenKit/Core/Platform/Services/API/Fixtures/BitwardenKitMocksBundleFinder.swift @@ -3,3 +3,8 @@ import Foundation class BitwardenKitMocksBundleFinder { static let bundle = Bundle(for: BitwardenKitMocksBundleFinder.self) } + +public extension Bundle { + /// The bundle for the `BitwardenKitMocks` target. + static let bitwardenKitMocks = BitwardenKitMocksBundleFinder.bundle +} diff --git a/BitwardenShared/Core/Platform/Services/API/Fixtures/APITestData+BitwardenShared.swift b/BitwardenShared/Core/Platform/Services/API/Fixtures/APITestData+BitwardenShared.swift new file mode 100644 index 000000000..d73c72bde --- /dev/null +++ b/BitwardenShared/Core/Platform/Services/API/Fixtures/APITestData+BitwardenShared.swift @@ -0,0 +1,12 @@ +import TestHelpers + +/// `APITestData` helpers that load the resource from the `BitwardenShared` bundle. +extension APITestData { + static func loadFromBundle(resource: String, extension: String) -> APITestData { + loadFromBundle(resource: resource, extension: `extension`, bundle: .bitwardenShared) + } + + static func loadFromJsonBundle(resource: String) -> APITestData { + loadFromJsonBundle(resource: resource, bundle: .bitwardenShared) + } +} diff --git a/BitwardenShared/Core/Platform/Services/API/Fixtures/BitwardenSharedBundleFinder.swift b/BitwardenShared/Core/Platform/Services/API/Fixtures/BitwardenSharedBundleFinder.swift new file mode 100644 index 000000000..082e742f2 --- /dev/null +++ b/BitwardenShared/Core/Platform/Services/API/Fixtures/BitwardenSharedBundleFinder.swift @@ -0,0 +1,10 @@ +import Foundation + +class BitwardenSharedBundleFinder { + static let bundle = Bundle(for: BitwardenSharedBundleFinder.self) +} + +public extension Bundle { + /// The bundle for the `BitwardenShared` target. + static let bitwardenShared = BitwardenSharedBundleFinder.bundle +} diff --git a/BitwardenShared/Core/Vault/Services/Fixtures/CXF+Fixtures.swift b/BitwardenShared/Core/Vault/Services/Fixtures/CXF+Fixtures.swift index 362cdba98..349a57864 100644 --- a/BitwardenShared/Core/Vault/Services/Fixtures/CXF+Fixtures.swift +++ b/BitwardenShared/Core/Vault/Services/Fixtures/CXF+Fixtures.swift @@ -5,5 +5,8 @@ import TestHelpers /// Fixtures for Credential Exchange flows. enum CXFFixtures { /// Fixture to be used on export flow with two basic-auth ciphers. - static let twoBasicAuthCiphers = TestDataHelpers.loadUTFStringFromJsonBundle(resource: "cxfTwoBasicAuthCiphers") + static let twoBasicAuthCiphers = TestDataHelpers.loadUTFStringFromJsonBundle( + resource: "cxfTwoBasicAuthCiphers", + bundle: .bitwardenShared, + ) } diff --git a/GlobalTestHelpers-bwa/Support/BitwardenTestCase.swift b/GlobalTestHelpers-bwa/Support/BitwardenTestCase.swift index c7088072d..e320b94de 100644 --- a/GlobalTestHelpers-bwa/Support/BitwardenTestCase.swift +++ b/GlobalTestHelpers-bwa/Support/BitwardenTestCase.swift @@ -10,8 +10,6 @@ open class BitwardenTestCase: BaseBitwardenTestCase { override open class func setUp() { // Apply default appearances for snapshot tests. UI.applyDefaultAppearances() - - TestDataHelpers.defaultBundle = Bundle(for: Self.self) } /// Executes any logic that should be applied before each test runs. diff --git a/GlobalTestHelpers/Support/BitwardenTestCase.swift b/GlobalTestHelpers/Support/BitwardenTestCase.swift index 0caa45100..ce068e7e1 100644 --- a/GlobalTestHelpers/Support/BitwardenTestCase.swift +++ b/GlobalTestHelpers/Support/BitwardenTestCase.swift @@ -8,8 +8,6 @@ open class BitwardenTestCase: BaseBitwardenTestCase { override open class func setUp() { // Apply default appearances for snapshot tests. UI.applyDefaultAppearances() - - TestDataHelpers.defaultBundle = Bundle(for: Self.self) } /// Executes any logic that should be applied before each test runs. diff --git a/TestHelpers/API/APITestData.swift b/TestHelpers/API/APITestData.swift index ea2f14490..ce97b8edd 100644 --- a/TestHelpers/API/APITestData.swift +++ b/TestHelpers/API/APITestData.swift @@ -12,13 +12,13 @@ public struct APITestData { } /// Loads test data from a provided file in the test class's bundle. - public static func loadFromBundle(resource: String, extension: String, bundle: Bundle? = nil) -> APITestData { + public static func loadFromBundle(resource: String, extension: String, bundle: Bundle) -> APITestData { let data = TestDataHelpers.loadFromBundle(resource: resource, extension: `extension`, bundle: bundle) return APITestData(data: data) } /// Loads test data from a provided JSON file in the test class's bundle. - public static func loadFromJsonBundle(resource: String, bundle: Bundle? = nil) -> APITestData { + public static func loadFromJsonBundle(resource: String, bundle: Bundle) -> APITestData { loadFromBundle(resource: resource, extension: "json", bundle: bundle) } } diff --git a/TestHelpers/API/TestDataHelpers.swift b/TestHelpers/API/TestDataHelpers.swift index 523b1aabf..3d9c2818b 100644 --- a/TestHelpers/API/TestDataHelpers.swift +++ b/TestHelpers/API/TestDataHelpers.swift @@ -3,34 +3,27 @@ import Foundation /// A type that wraps fixture data for use in mocking responses during tests. /// public enum TestDataHelpers { - /// The default bundle to try loading files from. - public static var defaultBundle: Bundle? - /// Loads the data from the provided file. - public static func loadFromBundle(resource: String, extension: String, bundle: Bundle? = nil) -> Data { - let resolvedBundle = bundle ?? defaultBundle - guard let resolvedBundle else { - fatalError("Default test data bundle from not set properly in the test case.") - } - guard let url = resolvedBundle.url(forResource: resource, withExtension: `extension`) else { + public static func loadFromBundle(resource: String, extension: String, bundle: Bundle) -> Data { + guard let url = bundle.url(forResource: resource, withExtension: `extension`) else { // swiftlint:disable:next line_length - fatalError("Unable to locate file \(resource).\(`extension`) in the bundle \(resolvedBundle.bundleURL.lastPathComponent).") + fatalError("Unable to locate file \(resource).\(`extension`) in the bundle \(bundle.bundleURL.lastPathComponent).") } do { return try Data(contentsOf: url) } catch { // swiftlint:disable:next line_length - fatalError("Unable to load data from \(resource).\(`extension`) in the bundle \(resolvedBundle.bundleURL.lastPathComponent). Error: \(error)") + fatalError("Unable to load data from \(resource).\(`extension`) in the bundle \(bundle.bundleURL.lastPathComponent). Error: \(error)") } } /// Convenience function for loading data from a JSON file. - public static func loadFromJsonBundle(resource: String, bundle: Bundle? = nil) -> Data { + public static func loadFromJsonBundle(resource: String, bundle: Bundle) -> Data { loadFromBundle(resource: resource, extension: "json", bundle: bundle) } /// Convenience function for loading a JSON file into a UTF-8 string. - public static func loadUTFStringFromJsonBundle(resource: String, bundle: Bundle? = nil) -> String? { + public static func loadUTFStringFromJsonBundle(resource: String, bundle: Bundle) -> String? { let data = loadFromJsonBundle(resource: resource, bundle: bundle) return String(data: data, encoding: .utf8) }