refactor(daemon): relocate the interaction touch tests by what they assert
Summary
Batch interaction-touch of the daemon test redesign (no test exports of any kind). The 16 root tests (plus the interaction-touch-runner.ts helper and the root-level interaction-touch-android-readiness-spawns sibling) that drove handleInteractionCommands with the real command surface are placed by what they assert. Daemon halves (a) now run against package fakes; assertions about what the real src/commands/interaction/** code does (c) moved to tests beside that code. snapshot-interactor-capture mocks are gone: captures go through installInteractorSnapshotResolution() (the InteractorResolution seam). Stacked on #3670.
New package fixtures, all unexported: interactor-resolution-fixture.ts, touch-command-surface-fake.ts, touch-interaction-runner.ts.
a / c split and test-count parity
Before = exact count at the old path (vitest JSON reporter); after = run count per destination (all under packages/daemon/src/execution/ unless noted).
| Source (before) | Daemon half (a) | Command half (c), src/commands/interaction/runtime/ |
|---|---|---|
interaction-touch (12) | interaction/internal/interaction-touch-routing.test.ts (12) | none |
interaction-touch-press-admission (13) | .../interaction-touch-press-admission.test.ts (12) | interactions-preresolved-target.test.ts (the #1654 provenance-mismatch case) |
interaction-touch-press (9) | .../interaction-touch-press.test.ts (5) | interactions-target-promotion.test.ts (4), interactions-preresolved-target.test.ts (5, shared) |
interaction-touch-fill (6) | .../interaction-touch-fill.test.ts (4; +1 dispatch-and-record) | interactions-ref-frame-evidence.test.ts (off-screen and invalid bounds), interactions-target-promotion.test.ts (editable node) |
interaction-touch-runtime (7) | .../interaction-touch-runtime.test.ts (3) | interactions-ref-frame-evidence.test.ts (5, shared); the missing-rect refusal is already pinned by ref-target-resolution.test.ts |
interaction-touch-response (6) | .../interaction-touch-response-evidence.test.ts (6) | digest/changed-from-before stays in interactions.test.ts |
interaction-touch-payload (7) | .../interaction-touch-payload.test.ts (7) | none |
interaction-touch-prepare (5) | .../interaction-touch-prepare.test.ts (5) | none |
interaction-touch-android-freshness (4) | .../interaction-touch-android-freshness.test.ts (4) | none |
interaction-touch-android-readiness (7) | .../interaction-touch-android-readiness.test.ts (7) | none |
root interaction-touch-android-readiness-spawns (1) | .../interaction-touch-android-readiness-spawns.test.ts (1; real createAndroidObservationAdapter over a counting runAdb host port: six dumpsys calls for three taps) | none |
interaction-touch-direct-ios-eligibility (4) | .../interaction-touch-direct-ios-eligibility.test.ts (4) | none |
interaction-touch-direct-ios (6) | .../interaction-touch-direct-ios.test.ts (6, incl. the maestro-direct disclosure row loop) | none |
interaction-ios-tap-outcome (22) | .../interaction-ios-tap-outcome.test.ts (22) | none |
interaction-gesture-drag (2) | .../interaction-gesture-drag.test.ts (2) | drag endpoint disclosure already pinned by gestures.test.ts |
interaction-get (16) | execution/selector-runtime-get-reads.test.ts (9), execution/selector-runtime-is-reads.test.ts (5) | selector-is-visibility.test.ts (2), selector-read-disambiguation.test.ts (1) |
127 tests before; 131 after (the added ones are the fill dispatch-and-record case, the disambiguation case, and splits). The interaction-touch.test.ts original was deleted with its package copy (12 = 12); nothing was dropped without a named owner.
Selection
All destinations match packages/*/src/**/*.test.ts or src/**/*.test.ts, so unit-core selects them (pnpm test:unit, test:coverage); the sources were already in unit-core. check:affected --run runs the vitest related leg over them.
vi.mock (each reads what its mock provided or recorded)
interaction-touch-android-readiness.test.ts,platform-android/mechanics: the mockedgetAndroidAppStateresult is read by "tap likely escaped the app", "foregrounded com.android.settings" and the permission-dialog warning.- same file,
../../android-system-dialog.ts: its spy drives "a ref action aborts with the shared ref_frame_expired rejection after Android dialog recovery mutates" (details.reason === 'ref_frame_expired',mockTapPointnot called). interaction-touch-payload.test.ts,platform-android/mechanics:getAndroidScreenSizeis read bytoHaveBeenCalledTimes(1),not.toHaveBeenCalled()and the 1344Ć2992 reference-size assertions.interaction-touch-android-freshness.test.ts,platform-android/mechanics: a benign default that keeps the readiness check from spawning adb; theresponse.okassertions depend on it. No assertion reads its recordings.selector-runtime-is-reads.test.ts,platform-android/mechanics:mockGetAndroidAppStateis read by the permission-dialog blocker test (foregroundPackagein details).selector-runtime-get-reads.test.ts,platform-apple/runner/operations: a negative guard.expect(mockRunAppleRunnerCommand).not.toHaveBeenCalled()and thequerySelectornot.toHaveBeenCalledWithfail if the daemon starts reaching the runner for a get again, instead of silently running it. It passes today because the daemon no longer queries the runner.
Subpath exports
| Package | Before (#3670) | After |
|---|---|---|
daemon | 85 | 81 |
Deleted: __tests__/ios-comparison-key-fixture, __tests__/replay-runtime/replay-command-fixture, interaction/internal/interaction-ios-tap-outcome, interaction/internal/interaction-touch-android-readiness. No other package changed; no new subpath, barrel or export *.
Notes
- The touch fake's target resolution is a deliberate minimum (points resolve to themselves; a
@refis the centre of its node inrefFrameSnapshot/snapshot; a selector is the first matching node of one fresh capture;preresolvedTargetis honored). It has no promotion, occlusion, off-screen, bounds, label-recovery or verify-evidence logic. Those are asserted as (c) tests against the real runtime, so its default answers do not stand in for command behavior. - Real-surface composition legs removed from the daemon tests are covered by
test/integration/interaction-contract/*andprovider-scenarios/press-selector-resolution.test.ts; I have not confirmed those assert the same cases one for one. - One-line path repoints for registries that named moved tests:
packages/contracts/src/dispatch-disclosure.fixtures.ts(maestro-direct.owner) andpackages/test-kit/src/boundary-fault-matrix.ts. - (c) tests are additive files in
src/commands/interaction/runtime/, outsidepackages/daemon; say if any belongs to another worker.
Validation
check:quick, check:layering, check:fallow and check:gate-manifest pass on this head; check:affected --run passes (including test-file-size-ratchet and the eager-closure suite).
š¤ Generated with Claude Code