import Foundation import Testing @testable import LocalData private struct MockKey: StorageKey { typealias Value = String let name: String let domain: StorageDomain let security: SecurityPolicy = .none let serializer: Serializer = .json let owner: String = "ErrorTests" let description: String = "Test key" let availability: PlatformAvailability = .all let syncPolicy: SyncPolicy = .never } private struct PartialCatalog: StorageKeyCatalog { var allKeys: [AnyStorageKey] { [.key(MockKey(name: "registered.key", domain: .userDefaults(suite: nil)))] } } @Suite(.serialized) struct RouterErrorTests { private let router: StorageRouter init() { let testBaseURL = FileManager.default.temporaryDirectory.appending(path: "RouterErrorTests-\(UUID().uuidString)") router = StorageRouter( keychain: MockKeychainHelper(), encryption: EncryptionHelper(keychain: MockKeychainHelper()), file: FileStorageHelper(configuration: FileStorageConfiguration(baseURL: testBaseURL)), defaults: UserDefaultsHelper(defaults: UserDefaults(suiteName: "RouterErrorTests-\(UUID().uuidString)")!) ) } @Test func unregisteredKeyThrows() async throws { try await router.registerCatalog(PartialCatalog()) let badKey = MockKey(name: "unregistered.key", domain: .userDefaults(suite: nil)) await #expect(throws: StorageError.unregisteredKey("unregistered.key")) { try await router.set("value", for: badKey) } } @Test func resolveIdentifierThrowsIfNoDefault() async { // Clear default app group ID await router.updateStorageConfiguration(StorageConfiguration( defaultKeychainService: "test", defaultAppGroupIdentifier: nil )) let appGroupKey = MockKey(name: "appgroup.key", domain: .appGroupUserDefaults(identifier: nil)) await #expect(throws: StorageError.invalidAppGroupIdentifier("none")) { try await router.set("value", for: appGroupKey) } } @Test func resolveServiceThrowsIfNoDefault() async { // Clear default keychain service await router.updateStorageConfiguration(StorageConfiguration( defaultKeychainService: nil, defaultAppGroupIdentifier: "test" )) let _ = MockKey(name: "keychain.key", domain: .keychain(service: nil)) // Note: Keychain security policy must match keychain domain in descriptor // but descriptor is usually created from key. // MockKey by default has .none security, which might cause applySecurity to return early // BUT the store() method for .keychain domain checks security. } }