TeraScopedAddTests.swift (8952B)
1 @testable import TeraApp 2 import XCTest 3 4 @MainActor 5 final class TeraScopedAddTests: XCTestCase { 6 func testServiceProbeCompletionCannotChangeReplacementScopeOrClearItsProbe() async throws { 7 for fails in [false, true] { 8 let backend = try TeraScopeBackend() 9 let client = try await TeraScopeFixtures.client(backend) 10 let store = TeraAddStore(runtimeClient: client) 11 store.configure(snapshot: TeraScopeFixtures.snapshot()) 12 let first = await backend.pause(.probe, fails: fails) 13 let old = Task { await store.checkPhotoService() } 14 await first.entered.wait() 15 let updated = TeraScopeFixtures.snapshot(account: "b", relay: "second") 16 await backend.configure(updated) 17 store.configure(snapshot: updated) 18 let second = await backend.pause(.probe) 19 let current = Task { await store.checkPhotoService() } 20 await second.entered.wait() 21 await first.resume.open() 22 await old.value 23 XCTAssertTrue(store.isCheckingBlossom) 24 XCTAssertNil(store.blossomEvidence) 25 XCTAssertNil(store.message) 26 await second.resume.open() 27 await current.value 28 XCTAssertEqual(store.blossomEvidence?.configFingerprint, "second") 29 XCTAssertFalse(store.isCheckingBlossom) 30 _ = try await client.stop() 31 } 32 } 33 34 func testLateDraftStartupCannotPopulateAReplacementAccount() async throws { 35 let backend = try TeraScopeBackend() 36 let client = try await TeraScopeFixtures.client(backend) 37 let store = TeraAddStore(runtimeClient: client) 38 store.configure(snapshot: TeraScopeFixtures.snapshot()) 39 let pause = await backend.pause(.drafts) 40 let old = Task { await store.start() } 41 await pause.entered.wait() 42 store.configure(snapshot: TeraScopeFixtures.snapshot(account: "b")) 43 await backend.setDrafts([TeraScopeFixtures.draft("new")]) 44 await store.start() 45 await pause.resume.open() 46 await old.value 47 XCTAssertEqual(store.drafts.first?.form?.content, "new") 48 XCTAssertEqual(store.state, .ready) 49 store.stop() 50 _ = try await client.stop() 51 } 52 53 func testLegacyFormEditDuringSubmitKeepsTheNewFormAndRetainsDurableOldReceipt() async throws { 54 let backend = try TeraScopeBackend() 55 let client = try await TeraScopeFixtures.client(backend) 56 let store = TeraAddStore(runtimeClient: client) 57 store.configure(snapshot: TeraScopeFixtures.snapshot()) 58 await store.start() 59 store.reopen(TeraScopeFixtures.draft("legacy source")) 60 await TeraScopeFixtures.eventually { !store.protection.isWorking } 61 store.updateForm(\.content, "saved version") 62 let pause = await backend.pause(.save) 63 let old = Task { await store.submit() } 64 await pause.entered.wait() 65 store.updateForm(\.content, "new edit") 66 await pause.resume.open() 67 await old.value 68 XCTAssertEqual(store.form.content, "new edit") 69 XCTAssertEqual(store.activeDraft?.form?.content, "legacy source") 70 XCTAssertNil(store.message) 71 XCTAssertFalse(store.isWorking) 72 let durable = try await client.draftHeads(limit: 100) 73 XCTAssertEqual(durable.first?.form?.content, "saved version") 74 await store.submit() 75 XCTAssertEqual(store.activeDraft?.form?.content, "new edit") 76 store.stop() 77 _ = try await client.stop() 78 } 79 80 func testLegacyLateFailureSnapshotCannotWriteItsMessageOrClearANewerOperation() async throws { 81 let backend = try TeraScopeBackend() 82 let client = try await TeraScopeFixtures.client(backend) 83 let store = TeraAddStore(runtimeClient: client) 84 store.configure(snapshot: TeraScopeFixtures.snapshot()) 85 await store.start() 86 store.reopen(TeraScopeFixtures.draft("legacy source")) 87 await TeraScopeFixtures.eventually { !store.protection.isWorking } 88 let save = await backend.pause(.save, fails: true) 89 let old = Task { await store.submit() } 90 await save.entered.wait() 91 let snapshot = await backend.pause(.snapshot) 92 await save.resume.open() 93 await snapshot.entered.wait() 94 let updated = TeraScopeFixtures.snapshot(account: "b") 95 await backend.configure(updated) 96 store.configure(snapshot: updated) 97 await store.start() 98 store.reopen(TeraScopeFixtures.draft("legacy replacement")) 99 await TeraScopeFixtures.eventually { !store.protection.isWorking } 100 store.updateForm(\.content, "new account") 101 let next = await backend.pause(.save) 102 let current = Task { await store.submit() } 103 await next.entered.wait() 104 await snapshot.resume.open() 105 await old.value 106 XCTAssertTrue(store.isWorking) 107 XCTAssertNil(store.message) 108 XCTAssertNil(store.lastFailureCode) 109 await next.resume.open() 110 await current.value 111 XCTAssertEqual(store.activeDraft?.form?.content, "new account") 112 store.stop() 113 _ = try await client.stop() 114 } 115 116 func testOldDraftObserverCannotOverwriteOrReportFailureInNewAccount() async throws { 117 for fails in [false, true] { 118 let backend = try TeraScopeBackend() 119 let client = try await TeraScopeFixtures.client(backend) 120 let store = TeraAddStore(runtimeClient: client) 121 store.configure(snapshot: TeraScopeFixtures.snapshot()) 122 await store.start() 123 await TeraScopeFixtures.eventually { store.observationState == .active } 124 let tokens = await backend.tokens 125 let oldToken = try XCTUnwrap(tokens.first) 126 let pause = await backend.pause(.drafts, fails: fails) 127 await backend.emit(.drafts) 128 await pause.entered.wait() 129 store.configure(snapshot: TeraScopeFixtures.snapshot(account: "b")) 130 await backend.setDrafts([TeraScopeFixtures.draft("new account")]) 131 await store.start() 132 await pause.resume.open() 133 await oldToken.cancelled.wait() 134 XCTAssertEqual(store.drafts.first?.form?.content, "new account") 135 XCTAssertNil(store.message) 136 store.stop() 137 _ = try await client.stop() 138 } 139 } 140 141 func testLateStartupInventoryCannotOverwriteANewerObserverSnapshot() async throws { 142 let backend = try TeraScopeBackend() 143 let client = try await TeraScopeFixtures.client(backend) 144 let store = TeraAddStore(runtimeClient: client) 145 store.configure(snapshot: TeraScopeFixtures.snapshot()) 146 let schemas = await backend.pause(.schemas) 147 let startup = Task { await store.start() } 148 await schemas.entered.wait() 149 await TeraScopeFixtures.eventually { store.observationState == .active } 150 await TeraScopeFixtures.eventually { store.drafts.first?.revision == 1 } 151 let pause = await backend.pause(.drafts) 152 await schemas.resume.open() 153 await pause.entered.wait() 154 await backend.setDrafts([TeraScopeFixtures.draft("new revision", revision: 2)]) 155 await backend.emit(.drafts) 156 await TeraScopeFixtures.eventually { store.drafts.first?.revision == 2 } 157 await pause.resume.open() 158 await startup.value 159 XCTAssertEqual(store.drafts.first?.revision, 2) 160 XCTAssertEqual(store.state, .ready) 161 store.stop() 162 _ = try await client.stop() 163 } 164 165 func testLateProbeCannotOverwriteNewerServiceSnapshotInTheSameScope() async throws { 166 let backend = try TeraScopeBackend() 167 let client = try await TeraScopeFixtures.client(backend) 168 let store = TeraAddStore(runtimeClient: client) 169 store.configure(snapshot: TeraScopeFixtures.snapshot()) 170 await store.start() 171 await TeraScopeFixtures.eventually { store.observationState == .active } 172 let pause = await backend.pause(.probe) 173 let old = Task { await store.checkPhotoService() } 174 await pause.entered.wait() 175 let evidence = TeraScopeFixtures.evidence(observedAt: 2) 176 await backend.configure(TeraScopeFixtures.snapshot(evidence: evidence)) 177 await backend.emit(.settings) 178 await TeraScopeFixtures.eventually { store.blossomEvidence == evidence } 179 await pause.resume.open() 180 await old.value 181 XCTAssertEqual(store.blossomEvidence, evidence) 182 XCTAssertFalse(store.isCheckingBlossom) 183 store.stop() 184 _ = try await client.stop() 185 } 186 187 func testLegacyLateFailureSnapshotCannotOverwriteEditedFormMessage() async throws { 188 let backend = try TeraScopeBackend() 189 let client = try await TeraScopeFixtures.client(backend) 190 let store = TeraAddStore(runtimeClient: client) 191 store.configure(snapshot: TeraScopeFixtures.snapshot()) 192 await store.start() 193 store.reopen(TeraScopeFixtures.draft("legacy source")) 194 await TeraScopeFixtures.eventually { !store.protection.isWorking } 195 let save = await backend.pause(.save, fails: true) 196 let old = Task { await store.submit() } 197 await save.entered.wait() 198 let snapshot = await backend.pause(.snapshot) 199 await save.resume.open() 200 await snapshot.entered.wait() 201 store.updateForm(\.content, "New edit while error recovery waits") 202 await snapshot.resume.open() 203 await old.value 204 XCTAssertNil(store.message) 205 XCTAssertNil(store.lastFailureCode) 206 XCTAssertEqual(store.form.content, "New edit while error recovery waits") 207 XCTAssertFalse(store.isWorking) 208 store.stop() 209 _ = try await client.stop() 210 } 211 }