field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

TeraNativeRepairPreviewTests.swift (4359B)


      1 import Foundation
      2 @testable import TeraApp
      3 import XCTest
      4 
      5 @MainActor
      6 final class TeraNativeRepairPreviewTests: XCTestCase {
      7   func testLaterPageCannotHideEarlierRepairAndDurableResolutionClearsIt() async throws {
      8     let backend = try TeraScopeBackend()
      9     let client = try await TeraScopeFixtures.client(backend)
     10     let issue = Self.issue(1)
     11     let pages = NativeRepairPages([
     12       .init(visited: 64, remaining: 100, needsAttention: true, issues: [issue]),
     13       .init(visited: 1, remaining: 0, needsAttention: false),
     14     ])
     15     let store = TeraNativeRepairStore(client: client, media: pages)
     16     store.configure(author: "first")
     17     await store.reconcile()
     18     await store.reconcile()
     19     XCTAssertEqual(store.issues, [issue])
     20     XCTAssertNotNil(store.message)
     21     await backend.setNativeRepairValue(.init(key: issue.key, reason: .resolved, revision: 2, firstObservedUnixMS: 1, updatedAtUnixMS: 2))
     22     await store.reconcile()
     23     XCTAssertTrue(store.issues.isEmpty)
     24     XCTAssertNil(store.message)
     25     store.configure(author: "second")
     26     XCTAssertNil(store.progress)
     27     store.stop()
     28     _ = try await client.stop()
     29   }
     30 
     31   func testRepairPreviewRemainsBoundedAcrossFullPages() async throws {
     32     let backend = try TeraScopeBackend()
     33     let client = try await TeraScopeFixtures.client(backend)
     34     let pages = NativeRepairPages([
     35       .init(visited: 64, remaining: 64, needsAttention: true, issues: (1 ... 64).map(Self.issue)),
     36       .init(visited: 64, remaining: 0, needsAttention: true, issues: (65 ... 128).map(Self.issue)),
     37     ])
     38     let store = TeraNativeRepairStore(client: client, media: pages)
     39     await store.reconcile()
     40     await store.reconcile()
     41     XCTAssertEqual(store.issues.count, 64)
     42     XCTAssertEqual(Set(store.issues.map(\.key)), Set((1 ... 64).map { Self.issue($0).key }))
     43     store.stop()
     44     _ = try await client.stop()
     45   }
     46 
     47   func testSelectedCheckClearsOnlyAcknowledgedKeyAndRetainsOtherNotice() async throws {
     48     let backend = try TeraScopeBackend()
     49     let client = try await TeraScopeFixtures.client(backend)
     50     let first = Self.issue(1), second = Self.issue(2)
     51     let pages = NativeRepairPages([.init(visited: 0, remaining: 12, needsAttention: true, issues: [first, second], pause: .protectedData)])
     52     let store = TeraNativeRepairStore(client: client, media: pages)
     53     await store.reconcile()
     54     store.check(Self.issue(3))
     55     XCTAssertFalse(store.isRunning, "Unretained keys cannot be admitted by a stale UI action")
     56     store.check(first)
     57     await TeraScopeFixtures.eventually { !store.isRunning }
     58     let keys = await pages.selectedKeys
     59     XCTAssertEqual(keys, [first.key])
     60     XCTAssertEqual(store.issues, [second])
     61     XCTAssertEqual(store.progress?.remaining, 12, "Selected check preserves the unvisited sweep positions")
     62     XCTAssertNotNil(store.message)
     63     store.stop()
     64     _ = try await client.stop()
     65   }
     66 
     67   private static func issue(_ index: Int) -> TeraNativeRecoveryIssue {
     68     .init(key: String(format: "%064x", index), reason: .missingParent, status: nil)
     69   }
     70 }
     71 
     72 extension TeraScopeBackend {
     73   func nativeRecoveryStatus(key: String) -> TeraNativeRecoveryStatus? {
     74     nativeRepairValues[key]
     75   }
     76 
     77   func setNativeRepairValue(_ value: TeraNativeRecoveryStatus) {
     78     nativeRepairValues[value.key] = value
     79   }
     80 }
     81 
     82 private actor NativeRepairPages: TeraAddMediaHandling {
     83   var pages: [TeraNativeRecoveryProgress]
     84   private(set) var selectedKeys: [String] = []
     85   init(_ pages: [TeraNativeRecoveryProgress]) {
     86     self.pages = pages
     87   }
     88 
     89   func support() -> TeraAddMediaSupport {
     90     .unavailable
     91   }
     92 
     93   func recoverNativeUploads(client _: TeraRuntimeClient) -> TeraNativeRecoveryProgress {
     94     pages.isEmpty ? .init(visited: 0, remaining: 0, needsAttention: false) : pages.removeFirst()
     95   }
     96 
     97   func recoverNativeUpload(key: String, client _: TeraRuntimeClient) -> TeraNativeRecoveryProgress {
     98     selectedKeys.append(key)
     99     return .init(visited: 1, remaining: 0, needsAttention: false, issues: [.init(key: key, reason: .resolved, status: nil)])
    100   }
    101 
    102   func importImages(limit _: Int) throws -> [TeraPreparedMedia] {
    103     throw TeraComposerAcknowledgment.unconfirmed
    104   }
    105 
    106   func captureImage() throws -> TeraPreparedMedia {
    107     throw TeraComposerAcknowledgment.unconfirmed
    108   }
    109 
    110   func open(_: [TeraPreparedMedia]) throws -> TeraOpenedMedia {
    111     throw TeraComposerAcknowledgment.unconfirmed
    112   }
    113 }