Skip to content

Picker/page test suites are pathologically slow under real timers; testTimeout: 60000 is masking it #2078

Description

@steilerDev

Summary

@testing-library/user-event tests that drive a debounced component under real timers have become extremely slow, to the point of exceeding a 60s per-test limit. The current mitigation is a global testTimeout: 60000 in jest.config.ts (line 67), which hides the problem rather than fixing it — and the margin is now thin enough that unrelated PRs fail intermittently.

How this was found

While processing Dependabot PRs #2072 and #2073, both went red on Jest shards 5 and 6 with 60s timeouts (not assertion failures) in the SearchPicker / HouseholdItemPicker suites.

The dependency bumps were not the cause:

  • chore(deps-dev): bump the dev-dependencies group with 3 updates #2072 contains no i18next/react-i18next/fastify change at all — only a lockfile repair plus eslint/stylelint — and it failed the identical tests.
  • react-i18next 17.0.13 has zero runtime JS changes vs 17.0.12 (registry tarball diff: only index.d.ts + changelog).
  • i18next 26.4.2's sole runtime change is a one-line $-escape in nest(), unreachable here (no $t( nesting anywhere in client/src/i18n/**).

Root cause

The regression entered beta in 038a9431 (PR #2070, "dev-dependencies group across 1 directory with 20 updates"), which bumped:

  • @testing-library/user-event 14.6.1 → 14.6.7
  • @testing-library/react 16.3.2 → 16.3.3
  • jest 30.4.2 → 30.5.1
  • jest-environment-jsdom 30.4.1 → 30.5.1

That commit's own message records the symptom and the workaround: "SearchPicker-family test timing (global testTimeout raise + a real assertion-ordering race fix)". #2070 passed CI; every PR branched from it has been failing.

Measured impact (from CI, untreated baseline on #2072)

Suite Wall time Failing tests
SearchPicker.test.tsx 2377 s (~40 min) 10
HouseholdItemPicker.test.tsx 498 s 2
HouseholdItemPicker.breadcrumb.test.tsx 537 s 2

Note HouseholdItemPicker.test.tsx spends ~357s across its passing tests (~30s each) — the whole file is slow, not just the tests that trip the ceiling.

Already fixed (on PR #2073 only)

Three commits convert those suites to jest.useFakeTimers() + userEvent.setup({ advanceTimers: jest.advanceTimersByTime.bind(jest) }), hoisted into each describe's beforeEach, with act(() => jest.advanceTimersByTime(300)) after each type/clear to clear the 300 ms useDebouncedCallback. No assertions were changed and no timeouts were raised. This also uncovered a latent bug: the Floating UI portal (#1708) describe block had no jest.useRealTimers() cleanup.

Remaining work

  1. Sweep the rest of the client suite. There are 587 bare userEvent.setup() occurrences across client/src/**/*.test.tsx, and only 14 files currently use advanceTimers. Any suite combining a bare setup with a debounced component has the same latent slowness, currently hidden by the 60s ceiling. Largest concentrations:

    Occurrences File
    73 client/src/pages/ReportWizardPage/ReportWizardPage.test.tsx
    52 client/src/pages/SubsidyProgramsPage/SubsidyProgramsPage.test.tsx
    48 client/src/pages/BudgetSourcesPage/BudgetSourcesPage.test.tsx
    43 client/src/pages/ManagePage/ManagePage.test.tsx
    39 client/src/pages/VendorDetailPage/VendorDetailPage.test.tsx
    36 client/src/pages/ReportWizardPage/ReportWizardPage.aiGeneration.test.tsx
    22 client/src/pages/HouseholdItemDetailPage/HouseholdItemDetailPage.test.tsx
  2. Lower testTimeout back down (jest.config.ts:67) once the sweep lands. At 60000 the next suite to regress hides for a full minute per test instead of failing fast — which is exactly how this reached beta unnoticed.

  3. Investigate the upstream cause. Worth confirming whether user-event 14.6.7 or jest/jsdom 30.5.x is responsible, and whether an upstream issue already exists. If the slowdown is a genuine upstream regression, pinning back may be preferable to converting hundreds of tests.

References

🤖 Filed by /dependabot

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions