Skip to content

test(react): drain stubbed animation frames in the remaining UI harnesses - #3890

Merged
kojiwakayama merged 1 commit into
mainfrom
test/drain-raf-stubs
Aug 20, 2026
Merged

kojiwakayama merged 1 commit into
mainfrom
test/drain-raf-stubs

Conversation

@kojiwakayama

Copy link
Copy Markdown
Contributor

Description

Eleven UI test files stub requestAnimationFrame with a real timer and never drain it:

g.requestAnimationFrame = (cb) => setTimeout(() => cb(0), 0);
g.cancelAnimationFrame = (id) => clearTimeout(id);

cancelAnimationFrame only helps a caller holding the id. A frame still queued at teardown is a pending timer, which the Deno op sanitizer reports as "a timer was started in this test, but never completed". React can schedule a frame right up to unmount, so whether it has run by teardown is a matter of load.

Because the sanitizer reports at suite level, the resulting failure names a suite rather than a step and lands on whatever branch happens to be pushing — the misattribution pattern already recorded in #594 and #612.

Fix

Track outstanding frames and clear them in the teardown that already restores globals and closes the DOM. The stub and its teardown were byte-identical across every file, so the change is identical in each — a mechanical, exact-match patch rather than eleven judgement calls.

Scope and honesty

None of these was observed failing. This closes a latent hole; it is not a live defect. I am not claiming it fixes a specific flake.

navigation-menu.test.tsx is excluded — it is fixed on the pre-push-gate branch, and patching it here would only create a conflict.

Deliberately not bundled: each of these files hand-rolls the same JSDOM globals harness. Extracting one shared helper would remove the next copy of this bug before it is written, and is the better long-term answer. But that is a refactor across twelve files with subtly different surroundings, and it deserves its own review rather than riding along with a mechanical fix. Worth doing next.

Evidence

src/react/ under --parallel --trace-leaks, three consecutive runs:

ok | 241 passed (1839 steps) | 0 failed
ok | 241 passed (1839 steps) | 0 failed
ok | 241 passed (1839 steps) | 0 failed

No production code changed.

Related Issue(s)

Tracked internally.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • Test update

Checklist

  • Identical, exact-match change in every file
  • No production code changed
  • Remaining refactor named rather than silently skipped

…sses

Eleven UI test files stub requestAnimationFrame with a real timer:

    g.requestAnimationFrame = (cb) => setTimeout(() => cb(0), 0);

and nothing drains it. cancelAnimationFrame only helps a caller holding the id;
a frame still queued at teardown is a pending timer, which the Deno op sanitizer
reports as "a timer was started in this test, but never completed". React can
schedule a frame right up to unmount, so whether it has run is a matter of load.

Because the sanitizer reports at suite level, the resulting failure names a
suite rather than a step and lands on whatever branch happens to be pushing.

Track outstanding frames and clear them in the teardown that already restores
the globals and closes the DOM. The stub and its teardown were byte-identical
across every file, so the change is the same in each.

None of these was observed failing -- this is closing a latent hole, not a live
defect. navigation-menu is excluded because it is fixed on the pre-push-gate
branch; patching it here would only create a conflict.

Left as a follow-up rather than bundled here: each of these files hand-rolls the
same JSDOM globals harness, and extracting one shared helper would remove the
next copy of this bug before it is written. That is a refactor across twelve
files and deserves its own review rather than riding along with a mechanical fix.
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 3 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 13d9fa3d-2414-43af-b4a1-7ce74e0562d0

📥 Commits

Reviewing files that changed from the base of the PR and between f16c1c4 and f62c7e7.

📒 Files selected for processing (11)
  • src/react/components/ui/adapter/drawer.conformance.test.tsx
  • src/react/components/ui/alert-dialog.test.tsx
  • src/react/components/ui/breadcrumb.test.tsx
  • src/react/components/ui/calendar.test.tsx
  • src/react/components/ui/conformance.test.tsx
  • src/react/components/ui/date-picker.test.tsx
  • src/react/components/ui/field.test.tsx
  • src/react/components/ui/input-otp.test.tsx
  • src/react/components/ui/meter.test.tsx
  • src/react/components/ui/pagination.test.tsx
  • src/react/components/ui/scroll-area.test.tsx

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.

@github-actions

Copy link
Copy Markdown

📦 Client bundle boundary

Entrypoint Modules Source size Server leaks
src/index.client.ts 326 1947 KiB ✅ 0

A server module in a client graph aborts hydration in the browser. New leaks fail CI; known leaks are tracked in scripts/lint/client-bundle-baseline.json to burn down.

@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 20, 2026
Merged via the queue into main with commit fa93044 Aug 20, 2026
34 checks passed
@kojiwakayama
kojiwakayama deleted the test/drain-raf-stubs branch August 20, 2026 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant