Skip to content

fix(frontend): isolate test data dirs and remove load-sensitive sleeps (fix parallel test flakes)#416

Open
OBenner wants to merge 2 commits into
developfrom
fix/frontend-parallel-test-flakes
Open

fix(frontend): isolate test data dirs and remove load-sensitive sleeps (fix parallel test flakes)#416
OBenner wants to merge 2 commits into
developfrom
fix/frontend-parallel-test-flakes

Conversation

@OBenner

@OBenner OBenner commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Problem

A full npm run test in apps/frontend failed 1–10 random tests per run under local parallel vitest workers (window-security.test.ts, security-export-e2e.spec.ts, security-level-presets-e2e.spec.ts and others); the failing set changed every run and every test passed in isolation.

Root causes (three independent races)

1. src/__tests__/setup.ts deleted a shared directory while parallel workers were using it.
The beforeEach hook rm -rf'd the shared /tmp/auto-code-ui-tests on every test and recreated it. It even computed a unique per-test testId subdirectory — but never used it (_testDir was dead code).

2. The five security-*-e2e.spec.ts files shared process.cwd()/test-data.
Each spec's beforeAll/afterAll unlinked .auto-claude-security.json / audit-log fixtures and rmdir'd the directory — clobbering sibling specs scheduled into other workers. This is what actually broke the named security-* failures.

3. Fixed sleeps that lose under 16-worker load.

  • project-store.test.ts: waitForStoreInit() slept a flat 50 ms hoping ProjectStore's fire-and-forget initializeAsync() had finished; under load it hadn't, so addProject minted a random UUID instead of finding the pre-seeded project.
  • window-security.test.ts: three tests slept a flat 100 ms after importing the main module before asserting on captured BrowserWindow options.

Fix

  • setup.ts: TEST_DATA_DIR is now a unique per-test directory under a per-worker base — os.tmpdir()/auto-code-ui-tests/worker-<pid>-<VITEST_POOL_ID> (pid covers the forks pool, pool id covers threads). afterEach removes only that test's directory; the shared parent is never deleted.
  • security e2e specs: each file gets its own os.tmpdir()/auto-code-ui-tests/security-<name>-<pid> directory.
  • ProjectStore: new whenReady() method exposing the init promise (additive, no behavior change); the test helper awaits it deterministically (all 17 call sites updated).
  • window-security.test.ts: polls until the BrowserWindow constructor has fired (5 s cap) instead of sleeping 100 ms.

Verification

  • 3 consecutive full npm run test runs in apps/frontend: all green (161/161 files, 3898 passed / 6 skipped each; before the fix, the first run reproduced a flake).
  • tsc --noEmit clean; biome reports no new issues on touched files.

🤖 Generated with Claude Code

Full parallel vitest runs failed 1-10 random tests per run (the failing
set changed every run; each test passed in isolation). Three independent
race sources:

1. setup.ts rm -rf'd the shared /tmp/auto-code-ui-tests in beforeEach
   while parallel workers were using it; the computed per-test testId
   subdir was dead code. TEST_DATA_DIR is now a unique per-test dir
   under a per-worker base (pid + VITEST_POOL_ID), and afterEach cleans
   only that dir - the shared parent is never deleted.

2. The five security-*-e2e specs all shared cwd/test-data and unlinked
   each other's fixture files in beforeAll/afterAll when scheduled into
   different workers. Each spec now uses its own tmpdir-scoped dir.

3. Fixed sleeps lost under 16-worker load: project-store.test.ts waited
   a flat 50ms for ProjectStore's fire-and-forget initializeAsync(), so
   addProject minted a fresh UUID instead of loading the pre-seeded
   project; window-security.test.ts waited a flat 100ms for
   app.whenReady() before reading captured BrowserWindow options.
   ProjectStore now exposes whenReady() (the init promise) which the
   tests await, and window-security polls until options are captured.

Verified: 3 consecutive full npm run test runs green (161 files,
3898 passed / 6 skipped each).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
@github-actions github-actions Bot added area/frontend bug Something isn't working size/M labels Jul 12, 2026
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@OBenner, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 43 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7236c648-8943-474e-a9e4-aba95b10ed93

📥 Commits

Reviewing files that changed from the base of the PR and between 4aa2449 and a718d3b.

📒 Files selected for processing (9)
  • apps/frontend/src/__tests__/setup.ts
  • apps/frontend/src/main/__tests__/project-store.test.ts
  • apps/frontend/src/main/__tests__/window-security.test.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/security-allowlist-e2e.spec.ts
  • apps/frontend/src/security-audit-log-e2e.spec.ts
  • apps/frontend/src/security-export-e2e.spec.ts
  • apps/frontend/src/security-level-presets-e2e.spec.ts
  • apps/frontend/src/security-warnings-e2e.spec.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/frontend-parallel-test-flakes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…porary-file)

Predictable names under the shared os.tmpdir() triggered 61 CWE-377
alerts: another local user could pre-create or symlink the path.
mkdtempSync creates an unpredictable directory with 0700 permissions,
which also keeps the per-worker/per-file isolation this PR introduced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
@sonarqubecloud

Copy link
Copy Markdown

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

Labels

area/frontend bug Something isn't working size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant