RadrootsBackgroundTransferTesting.swift (5533B)
1 import Foundation 2 import RadrootsKit 3 4 public actor RadrootsInMemoryBackgroundTransferStore: RadrootsBackgroundTransferStore { 5 private var snapshotsByIdentifier: [RadrootsBackgroundTransferIdentifier: RadrootsBackgroundTransferSnapshot] 6 7 public init(snapshots: [RadrootsBackgroundTransferSnapshot] = []) { 8 self.snapshotsByIdentifier = Dictionary(uniqueKeysWithValues: snapshots.map { ($0.identifier, $0) }) 9 } 10 11 public func loadSnapshots() async throws -> [RadrootsBackgroundTransferSnapshot] { 12 snapshotsByIdentifier.values.sorted { left, right in 13 left.identifier < right.identifier 14 } 15 } 16 17 public func saveSnapshot(_ snapshot: RadrootsBackgroundTransferSnapshot) async throws { 18 snapshotsByIdentifier[snapshot.identifier] = snapshot 19 } 20 21 public func removeSnapshot(for identifier: RadrootsBackgroundTransferIdentifier) async throws { 22 snapshotsByIdentifier.removeValue(forKey: identifier) 23 } 24 25 public func removeAllSnapshots() async throws { 26 snapshotsByIdentifier.removeAll() 27 } 28 } 29 30 public actor RadrootsFakeBackgroundTransfer: RadrootsBackgroundTransfer { 31 private let store: any RadrootsBackgroundTransferStore 32 private var enqueueOutcome: Result<Void, RadrootsBackgroundTransferError> 33 private var enqueuedRequestsValue: [RadrootsBackgroundTransferRequest] 34 private var cancelledIdentifiersValue: [RadrootsBackgroundTransferIdentifier] 35 private var handledBackgroundEventIdentifiersValue: [String] 36 private let updatedAt: Date 37 38 public init( 39 store: any RadrootsBackgroundTransferStore = RadrootsInMemoryBackgroundTransferStore(), 40 enqueueOutcome: Result<Void, RadrootsBackgroundTransferError> = .success(()), 41 updatedAt: Date = Date(timeIntervalSince1970: 0) 42 ) { 43 self.store = store 44 self.enqueueOutcome = enqueueOutcome 45 self.enqueuedRequestsValue = [] 46 self.cancelledIdentifiersValue = [] 47 self.handledBackgroundEventIdentifiersValue = [] 48 self.updatedAt = updatedAt 49 } 50 51 public func setEnqueueOutcome(_ outcome: Result<Void, RadrootsBackgroundTransferError>) { 52 enqueueOutcome = outcome 53 } 54 55 public func enqueue(_ request: RadrootsBackgroundTransferRequest) async throws -> RadrootsBackgroundTransferHandle { 56 enqueuedRequestsValue.append(request) 57 switch enqueueOutcome { 58 case .success: 59 let snapshot = try RadrootsBackgroundTransferSnapshot( 60 request: request, 61 state: .queued, 62 updatedAt: updatedAt 63 ) 64 try await store.saveSnapshot(snapshot) 65 return RadrootsBackgroundTransferHandle(request: request) 66 case .failure(let error): 67 throw error 68 } 69 } 70 71 public func cancel(_ identifier: RadrootsBackgroundTransferIdentifier) async throws { 72 cancelledIdentifiersValue.append(identifier) 73 if let existing = try await store.loadSnapshots().first(where: { $0.identifier == identifier }) { 74 let snapshot = try RadrootsBackgroundTransferSnapshot( 75 request: existing.request, 76 state: .cancelled, 77 progress: existing.progress, 78 updatedAt: updatedAt 79 ) 80 try await store.saveSnapshot(snapshot) 81 } 82 } 83 84 public func complete(_ identifier: RadrootsBackgroundTransferIdentifier) async throws { 85 guard let existing = try await store.loadSnapshots().first(where: { $0.identifier == identifier }) else { 86 throw RadrootsBackgroundTransferError.transferFailure("background transfer snapshot not found") 87 } 88 let snapshot = try RadrootsBackgroundTransferSnapshot( 89 request: existing.request, 90 state: .completed, 91 progress: existing.progress, 92 updatedAt: updatedAt 93 ) 94 try await store.saveSnapshot(snapshot) 95 } 96 97 public func fail(_ identifier: RadrootsBackgroundTransferIdentifier, message: String) async throws { 98 guard let existing = try await store.loadSnapshots().first(where: { $0.identifier == identifier }) else { 99 throw RadrootsBackgroundTransferError.transferFailure("background transfer snapshot not found") 100 } 101 let snapshot = try RadrootsBackgroundTransferSnapshot( 102 request: existing.request, 103 state: .failed, 104 progress: existing.progress, 105 errorMessage: message, 106 updatedAt: updatedAt 107 ) 108 try await store.saveSnapshot(snapshot) 109 } 110 111 public func snapshot(for identifier: RadrootsBackgroundTransferIdentifier) async throws -> RadrootsBackgroundTransferSnapshot? { 112 try await store.loadSnapshots().first { $0.identifier == identifier } 113 } 114 115 public func snapshots() async throws -> [RadrootsBackgroundTransferSnapshot] { 116 try await store.loadSnapshots() 117 } 118 119 public func handleEventsForBackgroundURLSession( 120 identifier: String, 121 completionHandler: @escaping @Sendable () -> Void 122 ) async { 123 handledBackgroundEventIdentifiersValue.append(identifier) 124 completionHandler() 125 } 126 127 public var enqueuedRequests: [RadrootsBackgroundTransferRequest] { 128 enqueuedRequestsValue 129 } 130 131 public var cancelledIdentifiers: [RadrootsBackgroundTransferIdentifier] { 132 cancelledIdentifiersValue 133 } 134 135 public var handledBackgroundEventIdentifiers: [String] { 136 handledBackgroundEventIdentifiersValue 137 } 138 }