TeraAddObservationStartupTests.swift (3412B)
1 @testable import TeraApp 2 import XCTest 3 4 @MainActor 5 final class TeraAddObservationStartupTests: XCTestCase { 6 func testPendingObserverCannotDiscardUsableStartupInventory() async throws { 7 let backend = try TeraScopeBackend() 8 let client = try await TeraScopeFixtures.client(backend) 9 let media = ObservationStartupMedia() 10 let subscription = await backend.pause(.subscribe) 11 let initialDrafts = await backend.pause(.drafts) 12 let store = TeraAddStore(runtimeClient: client, media: media) 13 store.configure(snapshot: TeraScopeFixtures.snapshot()) 14 let startup = Task { await store.start() } 15 await initialDrafts.entered.wait() 16 await media.supportPause.entered.wait() 17 let observerDrafts = await backend.pause(.drafts) 18 await initialDrafts.resume.open() 19 await subscription.resume.open() 20 await observerDrafts.entered.wait() 21 await media.supportPause.resume.open() 22 await startup.value 23 XCTAssertEqual(store.drafts.first?.form?.content, "old") 24 XCTAssertEqual(store.mediaSupport, .init(library: true, camera: true)) 25 XCTAssertEqual(store.state, .ready) 26 let recoveryPasses = await media.recoveryPasses 27 XCTAssertEqual(recoveryPasses, 1) 28 await observerDrafts.resume.open() 29 store.stop() 30 _ = try await client.stop() 31 } 32 33 func testStartupRecoversIndependentlyOfAppliedObserverInventoryAndKeepsMediaSupport() async throws { 34 let backend = try TeraScopeBackend() 35 let client = try await TeraScopeFixtures.client(backend) 36 let media = ObservationStartupMedia() 37 let subscription = await backend.pause(.subscribe) 38 let initialDrafts = await backend.pause(.drafts) 39 let store = TeraAddStore(runtimeClient: client, media: media) 40 store.configure(snapshot: TeraScopeFixtures.snapshot()) 41 let startup = Task { await store.start() } 42 await initialDrafts.entered.wait() 43 await media.supportPause.entered.wait() 44 await initialDrafts.resume.open() 45 await backend.setDrafts([TeraScopeFixtures.draft("new", revision: 2)]) 46 await backend.configure(TeraScopeFixtures.snapshot(evidence: TeraScopeFixtures.evidence(observedAt: 2))) 47 await subscription.resume.open() 48 await TeraScopeFixtures.eventually { 49 store.drafts.first?.revision == 2 && store.blossomEvidence?.observedAtUnixMilliseconds == 2 50 } 51 await media.supportPause.resume.open() 52 await startup.value 53 XCTAssertEqual(store.drafts.first?.revision, 2) 54 XCTAssertEqual(store.mediaSupport, .init(library: true, camera: true)) 55 let recoveryPasses = await media.recoveryPasses 56 XCTAssertEqual(recoveryPasses, 1) 57 store.stop() 58 _ = try await client.stop() 59 } 60 } 61 62 private actor ObservationStartupMedia: TeraAddMediaHandling { 63 let supportPause = ResourceTestPause() 64 private(set) var recoveryPasses = 0 65 66 func support() async -> TeraAddMediaSupport { 67 await supportPause.wait() 68 return .init(library: true, camera: true) 69 } 70 71 func recoverNativeUploads(client _: TeraRuntimeClient) -> TeraNativeRecoveryProgress { 72 recoveryPasses += 1 73 return .init(visited: 0, remaining: 0, needsAttention: false) 74 } 75 76 func importImages(limit _: Int) throws -> [TeraPreparedMedia] { 77 throw TeraScopeFixtures.failure() 78 } 79 80 func captureImage() throws -> TeraPreparedMedia { 81 throw TeraScopeFixtures.failure() 82 } 83 84 func open(_: [TeraPreparedMedia]) throws -> TeraOpenedMedia { 85 throw TeraScopeFixtures.failure() 86 } 87 }