refactor(daemon): relocate the session-lifecycle tests by what they assert

Merged
TH
20h ago
+2107-2632

Summary

Batch session-lifecycle (plus the device, replay-suite and replay-target leftovers) of the daemon test redesign (no test exports of any kind). 13 root tests under src/__tests__/daemon-composition/{session-lifecycle,device,replay-suite,replay-target}/ are placed by what they assert; the directories are gone. Stacked on #3666 (and through it #3652).

Daemon halves (a) run against the package fakes and a new lifecycle-operations-spy.ts (the canned lifecycle port with finalizeApplicationClose as a spy). Assertions about what the real platform adapters or command code do (c) moved beside that code. The device-ready mocks and the patch of platform-runtime-apple-application-tools.ts are gone.

a / c split and test-count parity

Before = exact count at the old path (vitest JSON reporter on a clean tree); after = run count per destination on this head.

Source (before)Daemon half (a)Adapter / command half (c)
session-close-error-precedence (2)session-lifecycle/internal/__tests__/session-close-error-precedence.test.ts (3 → 5)packages/platform-apple/src/lifecycle-physical-close.test.ts (runner stop before a physical-device close)
session-close-save-script (1).../session-close-save-script.test.ts (1 → 2)covered by platform-apple/lifecycle.test.ts
session-close-shutdown-platform (2).../session-close-shutdown-platform.test.ts (5 → 7)platform-apple/lifecycle-physical-close.test.ts, platform-android/lifecycle.test.ts (+1): close --shutdown gating
session-teardown-resources (2).../session-teardown-resources.test.ts (7 → 9)retention policy: src/platform-runtime-resource-cleanup-retention.test.ts in #3666
session-close-runtime-hints (4).../session-close-lifecycle-runtime.test.ts (5 → 9)src/platform-runtime-android-application-tools.test.ts (2)
session-open-surface (1), session-open-target (4)nonesrc/platform-runtime-open-target.test.ts (18)
session-open-existing (8).../session-open-existing.test.ts (2 → 10)platform-runtime-open-target.test.ts; src/platform-runtime-apple-application-tools.test.ts (3, macOS frontmost)
session-open-post-open-observation (3).../session-open-execution-runtime.test.ts (14 → 24, shared)platform-runtime-apple-application-tools.test.ts (runner prewarm forwarding)
session-open-url-prewarm (16)session-open-execution-runtime.test.ts (6 prewarm), sessions/handlers/__tests__/session-prepare.test.ts (3 → 8)platform-runtime-open-target.test.ts (5 URL identity), packages/platform-apple/src/lifecycle-open-prewarm.test.ts (5: cold-boot cache prewarm, Maestro simulator reset, blocking prewarm failure, no-bundle-id skip), apple tools prepareRunner
device/device-ready (5)core/device/device-ready.test.ts (6; +1: an unhandled device is not cached)src/platform-runtime-device-ready.test.ts (4)
replay-suite/session-test-suite-command-flag-policy (6)nonesrc/commands/replay/index.test.ts (19 → 20, schema parity); packages/replay-port/src/daemon-port/test-command-flag-policy.test.ts (5, raw-wire rejections, no daemon)
replay-target/session-replay-target-guard (7)nonegit mv to src/commands/interaction/runtime/replay-target-guard.test.ts (5); replay-port/.../__tests__/target-classification.test.ts (17 → 19)

61 tests before; 229 pass across the destinations including pre-existing tests in the extended twins. The old session-open-url-prewarm URL-identity cases map one to one: web URL on a simulator with a stale app id → platform-runtime-open-target.test.ts "a web URL on an iOS simulator targets Safari whatever the active app is" plus the session-open-existing.test.ts row "a web URL on an iOS simulator session with a stale app bundle id"; URL on a macOS session clears the stale id → "a URL on a macOS session clears the stale app bundle id"; URL on an iOS device keeps the app → "a web URL on an iOS device keeps the active app context"; custom URL on an existing simulator → "a custom URL on %s keeps the active app bundle id"; custom URL on a fresh simulator infers from the scheme → "a custom URL on a fresh iOS simulator infers the app bundle id from the URL scheme". No case disappeared 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)

  • platform-runtime-android-application-tools.test.ts, ./platform-runtime-runtime-hints.ts: runtimeHints.evaluated is false after building the tools and true after clearRuntimeHints; clearRuntimeHintValues is called once with the device and app.
  • platform-runtime-apple-application-tools.test.ts, platform-apple/macos: the frontmost-app case returns the mocked { appBundleId: 'com.apple.TextEdit', appName: 'TextEdit' }.
  • same file, platform-apple/runner/operations: prewarmIosRunnerSession called with propagateError: false and the request id; prepareIosRunner called with the cleanStaleBundles and timeout fields.
  • platform-runtime-open-target.test.ts, platform-android/mechanics resolveAndroidPackageForOpen, platform-apple/app-resolution resolveIosApp and resolveIosSimulatorDeepLinkBundleId: each result is read through the returned id.
  • platform-runtime-device-ready.test.ts: host-kit/command (runCmd called once; its written JSON consumed), platform-apple/simulator (ensureBootedSimulator called with the device), platform-android/mechanics (waitForAndroidBoot called with the id).
  • Existing twin mocks are untouched; the root device-ready mocks (×3) are gone.

Subpath exports

PackageBefore (#3666)After
daemon8985

Deleted: __tests__/application-lifecycle-runtime-harness, __tests__/device-selection-stub, handlers/session-replay-command, session-lifecycle/internal/__tests__/*. No other package changed; no new subpath, barrel or export *.

Notes

  • packages/platform-apple/src/lifecycle.test.ts is back to its merge-base size (968 lines): the cases this batch adds live in two new files beside lifecycle.ts (lifecycle-open-prewarm.test.ts, lifecycle-physical-close.test.ts), because the test-file size ratchet fails a file over 1,000 lines that grows (46 + 5 + 2 = 53 tests, all passing).
  • Edits beyond packages/daemon and the daemon-composition tree are additive tests in platform-apple, platform-android, replay-port and src/commands/**, plus new src/platform-runtime-*.test.ts files; they carry rules the root fixture only wrapped. Say if any belongs to another worker.
  • The agent's own platform-runtime-resource-cleanup.test.ts retention tests were dropped in favor of #3666's equivalent -retention file (same rules).

Validation

check:quick, check:layering, check:fallow and check:gate-manifest pass on this head; check:affected --run fails only test-file-size-ratchet on the pre-split head (fixed by the split above); test-file-size-ratchet passes after it.

🤖 Generated with Claude Code