Skip to content

[internal] Fix failing React 18 unit tests#22846

Merged
brijeshb42 merged 15 commits into
mui:masterfrom
brijeshb42:fix-usedisposable-react18-strictmode
Jun 17, 2026
Merged

[internal] Fix failing React 18 unit tests#22846
brijeshb42 merged 15 commits into
mui:masterfrom
brijeshb42:fix-usedisposable-react18-strictmode

Conversation

@brijeshb42

@brijeshb42 brijeshb42 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Makes the unit and browser test suites pass under React 18 (the test_*_react_18 CI jobs), plus a couple of fixes to genuinely flaky/infra failures surfaced along the way. React 18 differs from React 19 in ways several tests implicitly relied on:

  • StrictMode resets a render-mutated ref between its double-render passes.
  • Render-throws and "ref on a function component" cases reach console.error, which vitest-fail-on-console turns into failures.
  • React 18 still emits the missing-key dev warning for unkeyed array children (React 19 dropped it).

Changes

React 18 test compatibility

  • useDisposable: guard the StrictMode-sensitive assertions by React major version.
  • x-chat / x-chat-headless: mock console.error for the render-throw test and adjust the slot probes so they work under React 18 browser mode.
  • BasePopper (x-data-grid/material): wrap in forwardRef so the ref is forwarded instead of read off props.ref (avoids the React 18 ref-on-function-component warning). (only non-test source change)

Missing-key warnings in actions-cell tests

  • Add key props to every action element passed to getActions across rows, keyboard, events, and exportExcel tests. Fixed at the call sites; no production code change.

Flaky / infra fixes

  • ChatCodeBlock clipboard-failure test: skipped on jsdom since it doesn't execCommand.
  • DataGridPro column-resize test: flush the rowsSet requestAnimationFrame (which refreshes the resize hook's cell refs) before resizing again, removing a race with the pointer move.

@brijeshb42
brijeshb42 requested a review from romgrk as a code owner June 17, 2026 05:08
@brijeshb42 brijeshb42 added internal Behind-the-scenes enhancement. Formerly called “core”. type: bug It doesn't behave as expected. labels Jun 17, 2026
@brijeshb42
brijeshb42 requested a review from a team June 17, 2026 05:10
@code-infra-dashboard

code-infra-dashboard Bot commented Jun 17, 2026

Copy link
Copy Markdown

Deploy preview

https://deploy-preview-22846--material-ui-x.netlify.app/

Bundle size

Bundle Parsed size Gzip size
@mui/x-data-grid 🔺+6B(0.00%) 🔺+7B(+0.01%)
@mui/x-data-grid-pro 🔺+6B(0.00%) 🔺+3B(0.00%)
@mui/x-data-grid-premium 🔺+14B(0.00%) 🔺+14B(+0.01%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 0B(0.00%) 0B(0.00%)
@mui/x-charts-premium 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)
@mui/x-license 0B(0.00%) 0B(0.00%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@brijeshb42 brijeshb42 changed the title [internal] Fix useDisposable test under React 18 StrictMode [internal] Fix React 18 unit test failures Jun 17, 2026
@brijeshb42
brijeshb42 force-pushed the fix-usedisposable-react18-strictmode branch from ff836c9 to 3c5a74d Compare June 17, 2026 05:21
@brijeshb42 brijeshb42 changed the title [internal] Fix React 18 unit test failures [internal] Fix failing React 18 unit tests Jun 17, 2026
@brijeshb42
brijeshb42 force-pushed the fix-usedisposable-react18-strictmode branch 4 times, most recently from 7b77bc8 to 13f9577 Compare June 17, 2026 07:24
@brijeshb42
brijeshb42 requested a review from a team June 17, 2026 07:24
@brijeshb42
brijeshb42 force-pushed the fix-usedisposable-react18-strictmode branch 2 times, most recently from 7f51561 to 43f2986 Compare June 17, 2026 07:29
Comment thread packages/x-internals/src/useDisposable/useDisposable.ts Outdated
@brijeshb42
brijeshb42 force-pushed the fix-usedisposable-react18-strictmode branch from d974734 to d6b3500 Compare June 17, 2026 08:27
Comment thread packages/x-chat/src/ChatCodeBlock/ChatCodeBlock.test.tsx Outdated
Comment thread docs/next.config.ts Outdated
@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jun 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@rita-codes

rita-codes commented Jun 17, 2026

Copy link
Copy Markdown
Member

Heyy @brijeshb42 👋 I've been looking into this with Claude because I wanted to understand why our useDisposable tests passed when we merged #22532 but fail under React 18 now. This is just a theory, is this what you found too?

Main idea: the test_unit_react_18 job was actually running React 19, not React 18, until June 16. It only started running real React 18 that afternoon.

What I saw:

  • In useDisposable.test.tsx, the test only runs on React 19 (it skips when React.Activity is missing). On older commits it ran and passed in the react_18 job. On master now it is skipped. So the job was React 19 before, and real React 18 now. (I only use this test to tell which React version is running — it is not one of the failing tests.)
  • The change happens between 5455d9c (react_18 job at 13:38, still React 19) and 9441bbb (15:34, now React 18). Neither commit changes pnpm-lock, package.json, the CircleCI config, or the pinned orb.
  • The React override does not come from the pinned orb. It comes from pnpm dlx @mui/internal-code-infra@canary set-version-overrides, and canary is a moving tag. canary.63 was published at 15:17:35, right in that window.
  • The fix in canary.63 looks like mui-public e08081fbb ("Write version overrides to pnpm-workspace.yaml"). Before, cmdSetVersionOverrides wrote the override to package.json resolutions — a Yarn field that pnpm does not read — so react@^18 did nothing and React 19 stayed. The fix writes it to pnpm-workspace.yaml, so React 18 is finally installed.

So while the override was broken, the react_18 job was green but wrong for the whole repo, so there may be more React 18 failures hidden somewhere. Does this match what you saw?

@brijeshb42
brijeshb42 force-pushed the fix-usedisposable-react18-strictmode branch from d6b3500 to 0aa830e Compare June 17, 2026 09:20
@Janpot

Janpot commented Jun 17, 2026

Copy link
Copy Markdown
Member

Main idea: the test_unit_react_18 job was actually running React 19, not React 18, until June 16. It only started running real React 18 that afternoon.

👍 Correct, but with the addition that this problem was only recent. It got introduced by pnpm 11 migration (cc @LukasTy) 2 weeks ago and fixed yesterday by mui/mui-public#1549. So there could be other issues, but likely only in code that was introduced over the last two weeks.

React 18 StrictMode resets a render-mutated ref between double-render passes, so the useDisposable factory runs twice. Guard the affected assertions by React major version.
React 18 logs render-throws and ref-on-function-component warnings via console.error, tripping vitest-fail-on-console. Mock console.error for the throw test and forwardRef the slot probe.
BasePopper read ref from props but was not a forwardRef component, so React 18 warned "Function components cannot be given refs" when the multiSelect edit Modal passed a ref, tripping vitest-fail-on-console and cascading into a teardown crash. Wrap it in forwardRef like the sibling Base* components.
Passing the unkeyed getActions array as children triggered React 18's missing-key warning, tripping vitest-fail-on-console in the actions cell tests.
@brijeshb42
brijeshb42 force-pushed the fix-usedisposable-react18-strictmode branch from 0aa830e to 323b611 Compare June 17, 2026 09:25
@github-actions github-actions Bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jun 17, 2026
@brijeshb42
brijeshb42 force-pushed the fix-usedisposable-react18-strictmode branch from 323b611 to ae821ae Compare June 17, 2026 09:25
@brijeshb42
brijeshb42 enabled auto-merge (squash) June 17, 2026 10:08

@LukasTy LukasTy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. 👍
Thanks for addressing this. 🙏

Comment thread packages/x-chat/src/ChatCodeBlock/ChatCodeBlock.test.tsx Outdated
@brijeshb42
brijeshb42 merged commit 984e20f into mui:master Jun 17, 2026
21 checks passed
@brijeshb42
brijeshb42 deleted the fix-usedisposable-react18-strictmode branch June 17, 2026 10:37
@cherniavskii

Copy link
Copy Markdown
Member

Should be cherry-picked to v8? Noticed React 18 tests failing in #22860

it('throws outside a ChatProvider when called without the optional flag', () => {
// React 18 logs the render-time throw via `console.error`, which trips
// `vitest-fail-on-console` in the browser runner; silence it for this case.
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To not that this silences all console errors, even unintended ones.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. But there's not much to silence in this particular test.

mbrookes pushed a commit to mbrookes/mui-x that referenced this pull request Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Behind-the-scenes enhancement. Formerly called “core”. type: bug It doesn't behave as expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants