Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions Tests/DomainTests/Shared/AffordanceRegistryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,45 @@ struct AffordanceRegistryTests {
#expect(link.method == "POST")
#expect(link.href.contains("simulators"))
}

// MARK: - Plugin affordances merged into a real domain model
//
// These live here, not in SimulatorTests, on purpose. AffordanceRegistry is
// process-global mutable state, and `.serialized` only orders tests *within*
// a suite — separate suites still run concurrently. Any test that registers a
// provider must therefore share this one serialized suite, or `init()`'s reset
// will wipe its registration mid-test. Register from anywhere else and you
// reintroduce a flake that only shows up under parallel scheduling.

@Test func `booted simulator affordances include plugin stream when registered`() {
AffordanceRegistry.register(Simulator.self) { id, props in
guard props["isBooted"] == "true" else { return [] }
return [Affordance(key: "stream", command: "simulators", action: "stream", params: ["udid": id])]
}
let sim = MockRepositoryFactory.makeSimulator(id: "SIM-1", state: .booted)
// Plugin affordance should be merged into the model's own affordances
#expect(sim.affordances["stream"] == "asc simulators stream --udid SIM-1")
// Model's own affordances still present
#expect(sim.affordances["shutdown"] == "asc simulators shutdown --udid SIM-1")
}

@Test func `shutdown simulator does not get stream affordance from plugin`() {
AffordanceRegistry.register(Simulator.self) { id, props in
guard props["isBooted"] == "true" else { return [] }
return [Affordance(key: "stream", command: "simulators", action: "stream", params: ["udid": id])]
}
let sim = MockRepositoryFactory.makeSimulator(id: "SIM-2", state: .shutdown)
#expect(sim.affordances["stream"] == nil)
}

@Test func `booted simulator apiLinks include plugin stream when registered`() {
AffordanceRegistry.register(Simulator.self) { id, props in
guard props["isBooted"] == "true" else { return [] }
return [Affordance(key: "stream", command: "simulators", action: "stream", params: ["udid": id])]
}
let sim = MockRepositoryFactory.makeSimulator(id: "SIM-1", state: .booted)
// Plugin affordance should appear in REST links too
#expect(sim.apiLinks["stream"] != nil)
#expect(sim.apiLinks["stream"]?.method == "POST")
}
}
40 changes: 3 additions & 37 deletions Tests/DomainTests/Simulators/SimulatorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,41 +151,7 @@ struct SimulatorTests {
#expect(sim.registryProperties["isBooted"] == "false")
}

@Test(.serialized) func `booted simulator affordances include plugin stream when registered`() {
AffordanceRegistry.reset()
AffordanceRegistry.register(Simulator.self) { id, props in
guard props["isBooted"] == "true" else { return [] }
return [Affordance(key: "stream", command: "simulators", action: "stream", params: ["udid": id])]
}
let sim = MockRepositoryFactory.makeSimulator(id: "SIM-1", state: .booted)
// Plugin affordance should be merged into the model's own affordances
#expect(sim.affordances["stream"] == "asc simulators stream --udid SIM-1")
// Model's own affordances still present
#expect(sim.affordances["shutdown"] == "asc simulators shutdown --udid SIM-1")
AffordanceRegistry.reset()
}

@Test(.serialized) func `shutdown simulator does not get stream affordance from plugin`() {
AffordanceRegistry.reset()
AffordanceRegistry.register(Simulator.self) { id, props in
guard props["isBooted"] == "true" else { return [] }
return [Affordance(key: "stream", command: "simulators", action: "stream", params: ["udid": id])]
}
let sim = MockRepositoryFactory.makeSimulator(id: "SIM-2", state: .shutdown)
#expect(sim.affordances["stream"] == nil)
AffordanceRegistry.reset()
}

@Test(.serialized) func `booted simulator apiLinks include plugin stream when registered`() {
AffordanceRegistry.reset()
AffordanceRegistry.register(Simulator.self) { id, props in
guard props["isBooted"] == "true" else { return [] }
return [Affordance(key: "stream", command: "simulators", action: "stream", params: ["udid": id])]
}
let sim = MockRepositoryFactory.makeSimulator(id: "SIM-1", state: .booted)
// Plugin affordance should appear in REST links too
#expect(sim.apiLinks["stream"] != nil)
#expect(sim.apiLinks["stream"]?.method == "POST")
AffordanceRegistry.reset()
}
// Tests that register plugin providers for Simulator live in
// AffordanceRegistryTests — they need that suite's serialized scope because
// AffordanceRegistry is process-global. See the note there before adding more.
}
Loading