Skip to content

Commit fb1e51a

Browse files
committed
fix(runner): discard the settle window when the target binding is dropped for any reason but an announced relaunch
A dropped binding with a leftover deadline must mean the announced external relaunch, so a skipped activation can keep that deadline safely. Error invalidations and the host-app rebind now clear it and the next activation stamps a fresh window as before.
1 parent fd11348 commit fb1e51a

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

‎apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ extension RunnerTests {
196196
mainOwned.bundleId = nil
197197
mainOwned.processIdentifier = nil
198198
resetTargetBoundState()
199+
firstInteractionReadyUptime = nil
199200
}
200201

201202
/// State that belongs to the currently bound target and must not outlive it: the text-entry tap
@@ -217,6 +218,9 @@ extension RunnerTests {
217218
mainOwned.bundleId = nil
218219
mainOwned.processIdentifier = nil
219220
resetTargetBoundState()
221+
// Only the announced relaunch below leaves a deadline behind a dropped binding, which is what
222+
// lets a skipped activation keep it. Any other invalidation starts the next activation fresh.
223+
firstInteractionReadyUptime = nil
220224
}
221225

222226
@MainActor

‎apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerTests+LifecycleCacheTests.swift‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,26 @@ extension RunnerTests {
118118
}
119119
}
120120

121+
@MainActor
122+
func testInvalidationForErrorDiscardsTheWindowSoTheNextSkippedActivationStampsFresh() {
123+
withStubbedTargetActivation {
124+
mainOwned.needsPostSnapshotInteractionDelay = false
125+
RunnerTargetActivationSpy.state = .runningForeground
126+
mainOwned.app = app
127+
mainOwned.bundleId = "com.example.app"
128+
firstInteractionReadyUptime = ProcessInfo.processInfo.systemUptime - 1
129+
130+
invalidateCachedTarget(reason: "target_terminated")
131+
_ = activateTarget(bundleId: "com.example.app", reason: "bundle_changed")
132+
133+
XCTAssertEqual(RunnerTargetActivationSpy.activationCount, 0)
134+
XCTAssertGreaterThanOrEqual(
135+
measureStabilizationDuration(),
136+
firstInteractionAfterActivateDelay * 0.8
137+
)
138+
}
139+
}
140+
121141
@MainActor
122142
func testSkippedActivationWithoutADeadlineStampsTheWindow() {
123143
withStubbedTargetActivation {

0 commit comments

Comments
 (0)