test: split the Android platform test aggregation and share the scripted adb stub#1103
Conversation
…ted adb stub
AGENTS.md names the platform index.test.ts aggregations as offenders to
shrink opportunistically; this splits the 2,735-line Android one along
its (already well-factored) source modules, every test moved verbatim
(92 tests before and after):
- ui-hierarchy.test.ts (22): parseUiHierarchy/androidUiNodes
- app-lifecycle-install.test.ts (13): install/resolve/infer/launch
component parsing
- app-lifecycle-open.test.ts (19): open/close, deep links, launch args,
TV category, fallback resolve-activity
- input-actions.test.ts (11): type/fill/swipe/scroll/rotate
- settings.test.ts (14): appearance/clear-app-state/fingerprint/
permissions
- notifications.test.ts (2), app-parsers.test.ts (1)
- keyboard state/dismiss tests (10) appended to the existing
device-input-state.test.ts
Consistency fix folded in: the file carried a local withMockedAdb fork
because it needs scripted per-subcommand adb responses, which the shared
arg-recorder helper cannot express. The fork now lives in
src/__tests__/test-utils/mocked-binaries.ts as withScriptedAdb next to
withMockedAdb, and hands each call a fresh copy of the shared
ANDROID_EMULATOR fixture.
The copy matters: the Android TV test mutated the callback's device
(device.target = 'tv'), which the old per-call object literal absorbed
silently. With a shared fixture that mutation leaked into the next test
and flipped its launch to LEANBACK. The helper now clones per call and
the TV test builds { ...device, target: 'tv' } instead of mutating.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqeW8sA2ZnvnftdvpCqFMS
Size Report
Startup median (7 runs, lower is better):
Top changed chunks: no changes in the largest emitted chunks. |
|
Blocking review finding: the split lets the scripted-adb tests run in parallel across files while they still mutate global process state ( Repro from the PR branch: pnpm exec vitest run src/platforms/android/__tests__/app-lifecycle-install.test.ts src/platforms/android/__tests__/app-lifecycle-open.test.ts src/platforms/android/__tests__/app-parsers.test.ts src/platforms/android/__tests__/device-input-state.test.ts src/platforms/android/__tests__/input-actions.test.ts src/platforms/android/__tests__/notifications.test.ts src/platforms/android/__tests__/settings.test.ts src/platforms/android/__tests__/ui-hierarchy.test.tsThat run failed 10 tests with adb exit/timeouts. Running one of the failing files alone passes: pnpm exec vitest run src/platforms/android/__tests__/app-lifecycle-open.test.tsSo the monolith split changed execution semantics: the old single file effectively serialized the env-mutating adb stubs, but the new file split allows concurrent mutation. Please make the scripted-adb helper/tests safe under Vitest's file parallelism, or explicitly serialize this group if that is the intended contract, then rerun the grouped command above. |
Review follow-up for the android index.test.ts split: the monolith implicitly serialized the env-mutating adb-stub tests (PATH, AGENT_DEVICE_TEST_ARGS_FILE) in one worker, and the split let vitest run them across parallel files. Make the contract explicit: - new android-adb vitest project runs the six scripted-adb test files in a single fork (singleFork), keeping the pre-split execution semantics; ui-hierarchy and app-parsers stay in the parallel unit project (pure parsing, no env mutation) - test/test:unit scripts run both projects - the five slow-test ratchet pins that referenced index.test.ts keys now point at the split file names, so the pinned real-time offenders keep their exemption instead of failing at 2x budget under load; the reporter's own pinned-key fixture updated to match Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FqeW8sA2ZnvnftdvpCqFMS
|
Fixed in 5a5dcd8 — the serialization contract is now explicit, plus the split had silently invalidated the slow-test ratchet pins, which is likely what your 10 failures actually were:
Reran your grouped command: 8 files / 94 tests pass, with the six serialized files visibly running under Generated by Claude Code |
|
|
Follow-up after the latest fix: the original grouped-command blocker is resolved for me too, but the new serialization contract is currently expressed through a removed Vitest 4 config path. The grouped run now starts with: This matters because the PR depends on serialization to preserve the old monolithic |
|
Follow-up from the latest review: the Vitest 4 serialization issue is only part of the blocker.
Keeping this as not merge-ready until serialization and isolation/coverage semantics are explicit. |
|
Addressed the remaining review blockers in e54d617. Changes:
Validation:
Remaining risk: none beyond normal CI confirmation. |
|
Follow-up pushed in be8bd77. Changes:
Validation:
|
|
Review pass after be8bd77: no remaining actionable blockers found. The Android ADB split now uses supported Vitest 4 serialization ( Validation reported on the PR covers the grouped Android ADB run, stale-project guard, |
Summary
Companion to #1102, for the Android offender AGENTS.md names directly ("platform
index.test.ts… shrink opportunistically"). The 2,735-linesrc/platforms/android/__tests__/index.test.tssplits along its already well-factored source modules — every test moved verbatim, 92 tests before and after:ui-hierarchy.test.tsui-hierarchy.tsapp-lifecycle-install.test.tsapp-lifecycle.ts(install/resolve/infer/component parsing)app-lifecycle-open.test.tsapp-lifecycle.ts(open/close, deep links, launch args, TV, fallback resolve-activity)input-actions.test.tsinput-actions.ts(type/fill/swipe/scroll/rotate)settings.test.tssettings.tsnotifications.test.ts/app-parsers.test.tsnotifications.ts/app-parsers.tsdevice-input-state.test.tsdevice-input-state.ts(keyboard state/dismiss)adb-mock consistency fix folded in: the monolith carried a local
withMockedAdbfork because it needs scripted per-subcommand adb responses, which the shared arg-recorder helper can't express. That fork now lives insrc/__tests__/test-utils/mocked-binaries.tsaswithScriptedAdb, next to the recorderwithMockedAdb, and hands each callback a fresh copy of the sharedANDROID_EMULATORfixture (which the local fork had duplicated field-for-field).The fresh copy is load-bearing, and the split caught a real latent hazard: the Android TV test mutated the callback's device (
device.target = 'tv'). The old per-call object literal absorbed that silently; with a shared fixture the mutation leaked into the following test and flipped its launch to LEANBACK. The helper now clones per call and the TV test builds{ ...device, target: 'tv' }instead of mutating.Per the discussion: no new e2e scenario — the real-emulator Android workflow (settings replay + snapshot-helper smoke) stays the e2e layer, and these integration tests keep covering install/fill flows against scripted stubs.
Touched files: 10 (1 deleted, 7 created,
device-input-state.test.tsextended,mocked-binaries.ts).Validation
All 92 relocated tests pass in their new homes (including the previously-leaking LEANBACK/fallback pair, which now passes in both orderings), and the full suites are green: 349 test files / 3248 unit tests, smoke 13/13,
check:quick(oxlint + tsgo) clean, fallow audit vsorigin/mainclean. Blocks were moved verbatim except the onewithMockedAdb→withScriptedAdbrename and the TV-test mutation fix described above.🤖 Generated with Claude Code
https://claude.ai/code/session_01FqeW8sA2ZnvnftdvpCqFMS
Generated by Claude Code