62 lines
2.1 KiB
Swift
62 lines
2.1 KiB
Swift
import Foundation
|
|
@testable import Closer
|
|
|
|
/// Deterministic test fake for `FirestoreInvitesProtocol`.
|
|
///
|
|
/// Simulates the server-side invite create/accept flow in memory:
|
|
/// - `createInvite` stores the E2EE fields keyed by the invite code.
|
|
/// - `acceptInvite` returns those fields plus deterministic `coupleId` and
|
|
/// `inviterUserId`, mirroring `acceptInviteCallable`.
|
|
///
|
|
/// No Firebase network is exercised.
|
|
public final class MockFirestoreInvites: @unchecked Sendable, FirestoreInvitesProtocol {
|
|
private var invites: [String: InvitePayload] = [:]
|
|
private let lock = NSLock()
|
|
|
|
public var lastAcceptedCode: String?
|
|
public var nextCoupleId = "couple-mock-123"
|
|
public var inviterUserId = "inviter-mock-uid"
|
|
|
|
public init() {}
|
|
|
|
public func createInvite(uid: String, code: String, recoveryPhrase: String) async throws -> InvitePayload {
|
|
lock.lock()
|
|
defer { lock.unlock() }
|
|
|
|
// Simulate server-side code collision if the same code is used twice.
|
|
guard invites[code] == nil else {
|
|
struct DuplicateCode: Error {}
|
|
throw DuplicateCode()
|
|
}
|
|
|
|
let payload = InvitePayload(
|
|
code: code,
|
|
wrappedCoupleKey: "wrapped-mock-\(code)",
|
|
kdfSalt: "salt-mock-\(code)",
|
|
kdfParams: CoupleEncryptionManager.kdfParamsTag,
|
|
encryptedRecoveryPhrase: "phrase-mock-\(code)"
|
|
)
|
|
invites[code] = payload
|
|
return payload
|
|
}
|
|
|
|
public func acceptInvite(code: String, inviterUserId: String, recoveryPhrase: String) async throws -> AcceptResult {
|
|
lock.lock()
|
|
defer { lock.unlock() }
|
|
|
|
lastAcceptedCode = code
|
|
guard let payload = invites[code] else {
|
|
struct NotFound: Error {}
|
|
throw NotFound()
|
|
}
|
|
return AcceptResult(
|
|
coupleId: nextCoupleId,
|
|
inviterUserId: self.inviterUserId,
|
|
wrappedCoupleKey: payload.wrappedCoupleKey,
|
|
kdfSalt: payload.kdfSalt,
|
|
kdfParams: payload.kdfParams,
|
|
encryptedRecoveryPhrase: payload.encryptedRecoveryPhrase
|
|
)
|
|
}
|
|
}
|