Skip to content

chore(test-infra): audit Jest unit tests for memory growth #1568

@steilerDev

Description

@steilerDev

Context

During #1564 (auto-itemize redesign), CI Jest workers hit OOM crashes (>4 GB heap) on `LinkedDocumentsSection.test.tsx` and similar. The root cause for that file was a heavy `react-router-dom` mock spread; fixed in PR #1566.

To keep the unit test suite stable as the codebase grows, the test-infra mitigations layered on in the same PR (`--max-old-space-size=6144`, `--maxWorkers=2`, `--workerIdleMemoryLimit=2048MB`) are still in place as defense-in-depth. Without those, similar memory-heavy test patterns elsewhere will start failing again.

Goal

Audit Jest unit tests for memory growth patterns that are likely to OOM as the suite grows. Reduce peak worker heap below 2 GB per test so we can safely drop the heap-bump defenses.

Suspected patterns

  • Mock factories that re-import full modules: `jest.unstable_mockModule(, async () => { const actual = await import(); return { ...actual, X: jest.fn() }; })` is fundamentally leaky for large modules. Should be replaced with minimal factories that only return the symbols actually used by the SUT.
  • Module-scope fixtures: large arrays/objects defined at module scope are retained for the worker lifetime. Move into `beforeEach` so they GC.
  • Missing `afterEach(cleanup)` from React Testing Library: VDOM trees and mock state can accumulate.
  • `jest.fn()` returned from per-render callbacks (e.g., `useNavigate: () => jest.fn()`): each call creates a new mock fn whose `.mock.calls` array is retained.

Files to audit first

  • `client/src/components/documents/LinkedDocumentsSection.test.tsx` (now ~789 lines)
  • `client/src/components/documents/LinkedDocumentsSection.onItemize.test.tsx` (new sibling, 330 lines)
  • Any test that uses `jest.unstable_mockModule` with `...actual` spread (grep for that pattern).
  • Any test that renders 10+ child components in a single `render()` call.

Acceptance criteria

  • Identify the top 3 most memory-hungry test files (per Jest's `--logHeapUsage`).
  • Apply the patterns above. Reduce peak worker heap to <2 GB per test for those files.
  • Once below 2 GB: optionally relax the CI defenses (`--max-old-space-size` back to default, `--maxWorkers` back to default, drop `--workerIdleMemoryLimit`). Or keep them as a safety net — orchestrator's call.

Out of scope

  • E2E test memory profile (separate Playwright runner model).
  • Production code changes (this is purely test infra).

Metadata

Metadata

Assignees

No one assigned

    Labels

    choreMaintenance and refactoring tasks

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions