mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
1826b2e68b
* refactor(ios): integrate runner with snapshot engine * fix(ios): preserve macOS runner snapshots * refactor(ios): keep runner presentation device-aware * fix(ios): validate runner scroll presentation * fix(ios): close presenter package boundaries * fix(ios): preserve snapshot source lineage * test(ios): colocate snapshot engine coverage * fix(ios): settle post-merge audit checks * test(ios): fix manifest parity lint * refactor(ios): simplify runner source walk * test(ios): cover shared package source fixture * fix(ios): close post-merge audit gaps * perf(ios): avoid bundling acquired snapshot path
69 lines
2.0 KiB
Swift
69 lines
2.0 KiB
Swift
import Foundation
|
|
import AgentDeviceSnapshotPresentation
|
|
|
|
#if AGENT_DEVICE_RUNNER_UNIT_TESTS
|
|
private struct SnapshotScopeFixture: Decodable {
|
|
struct Node: Decodable {
|
|
let depth: Int
|
|
let label: String?
|
|
let identifier: String?
|
|
let value: String?
|
|
let presented: Bool?
|
|
}
|
|
|
|
let name: String
|
|
let scope: String
|
|
let nodes: [Node]
|
|
let expectedSubtreeIndexes: [Int]
|
|
}
|
|
|
|
extension RunnerTests {
|
|
func testSnapshotScopePolicyMatchesGoldenParityTable() throws {
|
|
// Non-vacuity: label-only semantic values fail the identifier-only and value-only fixtures.
|
|
let fixtureURL = URL(fileURLWithPath: #filePath)
|
|
.deletingLastPathComponent() // UnitTests
|
|
.deletingLastPathComponent() // AgentDeviceRunnerUITests
|
|
.deletingLastPathComponent() // AgentDeviceRunner
|
|
.deletingLastPathComponent() // runner
|
|
.deletingLastPathComponent() // apple
|
|
.deletingLastPathComponent() // repo root
|
|
.appendingPathComponent("contracts")
|
|
.appendingPathComponent("fixtures")
|
|
.appendingPathComponent("snapshot-scope-policy.json")
|
|
let cases = try JSONDecoder().decode(
|
|
[SnapshotScopeFixture].self,
|
|
from: Data(contentsOf: fixtureURL)
|
|
)
|
|
XCTAssertFalse(cases.isEmpty, "parity table must not be empty")
|
|
|
|
for fixture in cases {
|
|
let selected = SnapshotScopePolicy.select(
|
|
fromPreorder: fixture.nodes,
|
|
scope: fixture.scope,
|
|
depth: \.depth,
|
|
semanticValues: { [$0.label, $0.identifier, $0.value] },
|
|
subtreeContributes: { range in
|
|
range.contains { fixture.nodes[$0].presented != false }
|
|
}
|
|
)
|
|
let actual: [Int]
|
|
switch selected {
|
|
case .unscoped:
|
|
actual = Array(fixture.nodes.indices)
|
|
case .missing:
|
|
actual = []
|
|
case .matched(let start):
|
|
actual = Array(
|
|
SnapshotScopePolicy.subtreeRange(
|
|
from: start,
|
|
in: fixture.nodes,
|
|
depth: \.depth
|
|
)
|
|
)
|
|
}
|
|
XCTAssertEqual(actual, fixture.expectedSubtreeIndexes, fixture.name)
|
|
}
|
|
}
|
|
}
|
|
#endif
|