perf: reduce frontend unit test time (Tamagui extraction, pointer-events check) - #789
Open
gaidheal1 wants to merge 3 commits into
Open
perf: reduce frontend unit test time (Tamagui extraction, pointer-events check)#789gaidheal1 wants to merge 3 commits into
gaidheal1 wants to merge 3 commits into
Conversation
The 'unit' project (happy-dom) never observes Tamagui's compiled-CSS output - it asserts on rendered DOM, not shipped bundle size - but paid the extraction plugin's full per-file AST walk anyway, across all ~70 test files regardless of whether they touch Tamagui. Disabling it only for that project (detected via argv, not a global toggle) cut its measured transform time roughly 4x (~43s -> ~9-10s) with an identical pass/fail test count. Production build and the 'storybook' project keep the optimization untouched (verified npm run build:production still runs ~1800+ tamagui-extract transforms). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iu8KPSj96K2guMzMRzeN3
Profiled the remaining ~43s unit-test run after the Tamagui-extraction fix (this PR): Map.test.tsx alone is 17.3s/44 tests (~40% of total file-time) and, being one file, can't be split across Vitest's per-file worker parallelism. maxWorkers=1 vs 4 (96s vs 38s, ~2.5x not ~4x) is consistent with it forming a long serial tail. Also verified adding pointerEventsCheck:0 to userEvent.setup() cuts that file's time 17.3s -> 14.2s with zero test changes; 149 call sites across 34 files still pay the stricter default. Plan covers splitting Map.test.tsx along its existing describe boundaries and centralizing a shared userEvent helper - implementation not started. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iu8KPSj96K2guMzMRzeN3
Adds frontend/src/testUtils/setupUser.ts (userEvent.setup() defaulting to pointerEventsCheck: 0) and migrates all 35 test files / ~150 userEvent.setup() call sites onto it, replacing an inline workaround already used ad hoc in a few places (TasksPanel.test.tsx). Verified via audit that no test in the codebase relies on the strict check itself - every toBeDisabled()/pointer-events reference is either a static assertion or clicks a different element that causes disabling, never a click on the disabled element expecting it to be blocked. Cut Map.test.tsx's isolated run time ~18% (17.3s -> 14.2s) with zero test changes; full suite pass/fail count is unchanged (561 passed, 1 pre-existing unrelated failure). Also implemented and then reverted a Map.test.tsx file split (the other opportunity from the linked plan): measured no wall-clock benefit on a clean A/B, since Vitest's default scheduler already duration-aware-prioritizes slow files, so splitting the one big file didn't relieve a bottleneck that didn't exist in practice. Recorded in the plan doc for future reference. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014iu8KPSj96K2guMzMRzeN3
gaidheal1
marked this pull request as ready for review
August 16, 2026 16:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Investigated the frontend Vitest suite for speed opportunities. Two changes landed here; a third was implemented, measured, and reverted (see below) since it didn't pay for itself.
1. Skip Tamagui's static extraction for the
unitvitest project.npm run test(happy-dom) paid@tamagui/vite-plugin's full static-extraction AST walk on every one of ~70 test files, even though only a handful (ProgressBar,ToastManager,Map) import fromtamagui. That plugin's job — compiling styles to CSS ahead of time — is a bundle-size/runtime-perf optimization unit tests never observe. Disabled specifically for theunitproject (detected viaprocess.argv/process.env.VITEST), left untouched for the real app build and thestorybookproject.2. Centralize a
pointerEventsCheck: 0userEvent helper.userEvent.setup()defaults to the strictest pointer-events check (re-validating computed style on every interaction) — real, measured cost across files with many clicks. Addedfrontend/src/testUtils/setupUser.tsand migrated all 35 files / ~150 call sites onto it, replacing an inline workaround a couple of files already used ad hoc. Audited first: no test in the codebase relies on the strict check itself (everytoBeDisabled()/pointer-events reference is a static assertion, or clicks a different element that causes disabling — never a click on the disabled element expecting it to be blocked).Investigated and reverted: splitting
Map.test.tsx. At 1533 lines/44 tests/17.3s, it's ~40% of total file-time and, being one file, can't be split across Vitest's per-file worker parallelism —maxWorkers=1vs4showed only ~2.5x speedup instead of ~4x, consistent with it forming a long serial tail. Implemented the full split (shared helpers module + 3 test files, all 44 tests passing), then measured a clean A/B: unsplit ~42.7s/44.1s vs split ~44.6s/43.9s — no benefit, slightly worse. Root cause: Vitest's default sequencer already schedules known-slow files first, so the single big file was already getting its own worker from the start. Reverted; recorded in.claude/plans/frontend-test-speed-restructuring-plan.mdfor future reference.Measured impact (local, this sandbox — absolute numbers will vary by machine)
npm run testwall timeMap.test.tsxisolated runTest pass/fail counts identical throughout (561 passed, one pre-existing unrelated failure in
UnifiedTimerHome.test.tsx, not touched by this PR).Verification
npm run test: same pass/fail results before and after each changenpx tsc --noEmit: cleannpm run lint: cleannpm run build:production: succeeds; build output confirmstamagui-extract transformstill runs (~1845 calls) — production optimization untouchednpm run test:storybook— needs a browser binary revision not available in this sandbox (pre-existing environment limitation, unrelated to these changes)🤖 Generated with Claude Code
Generated by Claude Code