LogInteraction.test.tsx exhausts V8 heap during full-suite vitest run #123
Labels
No labels
blocked:depends-p1
blocked:gate-research
blocked:lint-failed
blocked:needs-decision
blocked:needs-human
blocked:verify-failed
bug
data-loss
documentation
enhancement
feature-request
in-progress
needs-decompose
needs-triage
pwa
quickfix
security
security/high
security/medium
test
test-coverage
triage-approved
vault
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/kimi_agent_kin_app_sync#123
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The test suite is over-engineered for what the app actually does, and that over-engineering is what tips the runner into a 3-hour OOM on every full-suite verify.
This was filed first as a "config split" problem (#122) and a "LogInteraction heap" problem (#123). Both frames assume the test suite is the right size and we just need to slim a few files. It is not the right size. The numbers:
src/lib/. We have more test code than source under test, and most of the suite is re-implementation, not coverage.src/lib/utils.test.ts— 849 lines, 95 testssrc/lib/store.test.ts— 718 lines, 68 testssrc/lib/db.test.ts— 706 lines, 64 testssrc/lib/metrics-engine.test.ts— 630 lines, 41 testssrc/lib/schemas.test.ts— 587 linessrc/lib/native/__tests__/plugin-wrappers.test.ts— 537 linesLogInteraction.test.tsxthat mocks framer-motion via a Proxy, mocks the store via a globalmockState, mocks the router, and pulls in the global Capacitor/IndexedDB/MSW setup fromsrc/test/setup.ts.vitest runclocks 10,838s and OOMs V8 inside theLogInteraction.test.tsxworker. Targeted single-file runs: ~3s. That is not a flaky test. It is the cumulative retention cost of a suite that mocks the world.The framing changed because the original gate-budget issue (#122) and the OOM issue (#123) were both pointing at the same root cause: the tests are stupid. They re-mock components, re-implement utilities against themselves, and stack fixture chains that don't reflect how the app is used. LogInteraction is just the leaf where V8 finally says no.
Evidence
From a manual full-suite verify run on 2026-06-30 (started 13:27 UTC, ran ~3h 0m 38s before crashing):
Specifically about the over-mock pattern (from the existing test, not fabricated):
That Proxy exists because the test renders the page. The page shouldn't need to render framer-motion primitives in a unit test. If the test is testing LogInteraction's behavior, it should render the page with the real motion library, or it should target a smaller surface.
Scope
src/lib/*.test.tstop-heavies (utils,store,db,metrics-engine,schemas,plugin-wrappers). For each, ask:src/pages/__tests__/LogInteraction.test.tsx: stop rendering the full page. Pull the page apart. Cover the actual behavior (form state, submission, navigation) without mounting the whole component graph under a framer-motion Proxy. The framer-motion mock alone is a sign the test is testing how the test feels, not how the app behaves.src/test/setup.ts: review the global imports offake-indexeddb, Capacitor mocks, MSW server. Decide which ones need to be global vs per-file. Most of the suite doesn't need all three wired in front of every test.vitest.config.*,package.jsonscripts): once the suite is lean, set the gate to the actualnpm testagain. Do not split intotest:unitand a separate full run — that hides the problem. The whole suite should be fast enough to gate on.Out of scope
src/lib/native/__tests__/beyond deleting the over-mocked ones; native bridge tests are deliberately low-level and most of them should stay.Reproduction
Suggested approach
src/pages/__tests__/LogInteraction.test.tsx. Refactor it to not render the page; cover behavior at a smaller surface. This should drop full-suite heap pressure immediately.src/lib/utils.test.ts,src/lib/store.test.ts,src/lib/db.test.ts,src/lib/metrics-engine.test.ts,src/lib/schemas.test.ts,src/lib/native/__tests__/plugin-wrappers.test.ts— for each, delete tests that don't answer the three questions in Scope item 1.src/test/setup.tsso it only mocks what the suite that actually runs needs.vitest rununder 180s with no OOM. Then full-suitenpm testis the gate, no split.Constraints
test:unit/test:fullsplit. One suite, fast enough to gate.Verification
time npx vitest runfinishes under 180s, exits 0, no V8 OOMnpm test(gate) clears on the first kilo-gsd verify for any dispatched issue