From cce00bcd855612e164bcb10aa633edda8763c72f Mon Sep 17 00:00:00 2001
From: Sebastian Silbermann
Date: Wed, 31 Jan 2024 22:36:48 +0100
Subject: [PATCH 1/6] Convert ReactFresh to createRoot
---
.../src/__tests__/ReactFresh-test.js | 881 +++++++++---------
1 file changed, 466 insertions(+), 415 deletions(-)
diff --git a/packages/react-refresh/src/__tests__/ReactFresh-test.js b/packages/react-refresh/src/__tests__/ReactFresh-test.js
index 94e170e3346e6..2f0f51851f663 100644
--- a/packages/react-refresh/src/__tests__/ReactFresh-test.js
+++ b/packages/react-refresh/src/__tests__/ReactFresh-test.js
@@ -17,25 +17,25 @@ let ReactDOMClient;
let ReactFreshRuntime;
let Scheduler;
let act;
-let internalAct;
let createReactClass;
let waitFor;
let assertLog;
describe('ReactFresh', () => {
let container;
+ let root;
beforeEach(() => {
if (__DEV__) {
jest.resetModules();
+ global.IS_REACT_ACT_ENVIRONMENT = true;
React = require('react');
ReactFreshRuntime = require('react-refresh/runtime');
ReactFreshRuntime.injectIntoGlobalHook(global);
ReactDOM = require('react-dom');
ReactDOMClient = require('react-dom/client');
Scheduler = require('scheduler');
- act = React.act;
- internalAct = require('internal-test-utils').act;
+ act = require('internal-test-utils').act;
const InternalTestUtils = require('internal-test-utils');
waitFor = InternalTestUtils.waitFor;
@@ -47,6 +47,7 @@ describe('ReactFresh', () => {
new React.Component().updater,
);
container = document.createElement('div');
+ root = ReactDOMClient.createRoot(container);
document.body.appendChild(container);
}
});
@@ -63,17 +64,19 @@ describe('ReactFresh', () => {
return Component;
}
- function render(version, props) {
+ async function render(version, props) {
const Component = version();
- act(() => {
- ReactDOM.render(, container);
+ await act(() => {
+ root.render();
});
return Component;
}
- function patch(version) {
+ async function patch(version) {
const Component = version();
- ReactFreshRuntime.performReactRefresh();
+ await act(() => {
+ ReactFreshRuntime.performReactRefresh();
+ });
return Component;
}
@@ -99,9 +102,9 @@ describe('ReactFresh', () => {
);
}
- it('can preserve state for compatible types', () => {
+ it('can preserve state for compatible types', async () => {
if (__DEV__) {
- const HelloV1 = render(() => {
+ const HelloV1 = await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -118,13 +121,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- const HelloV2 = patch(() => {
+ const HelloV2 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -143,7 +146,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump the state again.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -153,15 +156,15 @@ describe('ReactFresh', () => {
// Perform top-down renders with both fresh and stale types.
// Neither should change the state or color.
// They should always resolve to the latest version.
- render(() => HelloV1);
- render(() => HelloV2);
- render(() => HelloV1);
+ await render(() => HelloV1);
+ await render(() => HelloV2);
+ await render(() => HelloV1);
expect(container.firstChild).toBe(el);
expect(el.textContent).toBe('2');
expect(el.style.color).toBe('red');
// Bump the state again.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -169,7 +172,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Finally, a render with incompatible type should reset it.
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -189,9 +192,9 @@ describe('ReactFresh', () => {
}
});
- it('can preserve state for forwardRef', () => {
+ it('can preserve state for forwardRef', async () => {
if (__DEV__) {
- const OuterV1 = render(() => {
+ const OuterV1 = await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -211,13 +214,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- const OuterV2 = patch(() => {
+ const OuterV2 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -239,7 +242,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump the state again.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -249,15 +252,15 @@ describe('ReactFresh', () => {
// Perform top-down renders with both fresh and stale types.
// Neither should change the state or color.
// They should always resolve to the latest version.
- render(() => OuterV1);
- render(() => OuterV2);
- render(() => OuterV1);
+ await render(() => OuterV1);
+ await render(() => OuterV2);
+ await render(() => OuterV1);
expect(container.firstChild).toBe(el);
expect(el.textContent).toBe('2');
expect(el.style.color).toBe('red');
// Finally, a render with incompatible type should reset it.
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -279,9 +282,9 @@ describe('ReactFresh', () => {
}
});
- it('should not consider two forwardRefs around the same type to be equivalent', () => {
+ it('should not consider two forwardRefs around the same type to be equivalent', async () => {
if (__DEV__) {
- const ParentV1 = render(
+ const ParentV1 = await render(
() => {
function Hello() {
const [val, setVal] = React.useState(0);
@@ -317,38 +320,38 @@ describe('ReactFresh', () => {
let el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Switching up the inner types should reset the state.
- render(() => ParentV1, {cond: false});
+ await render(() => ParentV1, {cond: false});
expect(el).not.toBe(container.firstChild);
el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Switch them up back again.
- render(() => ParentV1, {cond: true});
+ await render(() => ParentV1, {cond: true});
expect(el).not.toBe(container.firstChild);
el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
// Now bump up the state to prepare for patching.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Patch to change the color.
- const ParentV2 = patch(() => {
+ const ParentV2 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -383,14 +386,14 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Switching up the condition should still reset the state.
- render(() => ParentV2, {cond: false});
+ await render(() => ParentV2, {cond: false});
expect(el).not.toBe(container.firstChild);
el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('red');
// Now bump up the state to prepare for top-level renders.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el).toBe(container.firstChild);
@@ -398,18 +401,18 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Finally, verify using top-level render with stale type keeps state.
- render(() => ParentV1);
- render(() => ParentV2);
- render(() => ParentV1);
+ await render(() => ParentV1);
+ await render(() => ParentV2);
+ await render(() => ParentV1);
expect(container.firstChild).toBe(el);
expect(el.textContent).toBe('1');
expect(el.style.color).toBe('red');
}
});
- it('can update forwardRef render function with its wrapper', () => {
+ it('can update forwardRef render function with its wrapper', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Hello({color}) {
const [val, setVal] = React.useState(0);
return (
@@ -429,13 +432,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function Hello({color}) {
const [val, setVal] = React.useState(0);
return (
@@ -458,9 +461,9 @@ describe('ReactFresh', () => {
}
});
- it('can update forwardRef render function in isolation', () => {
+ it('can update forwardRef render function in isolation', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Hello({color}) {
const [val, setVal] = React.useState(0);
return (
@@ -483,13 +486,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update of just the rendering function.
- patch(() => {
+ await patch(() => {
function Hello({color}) {
const [val, setVal] = React.useState(0);
return (
@@ -515,9 +518,9 @@ describe('ReactFresh', () => {
}
});
- it('can preserve state for simple memo', () => {
+ it('can preserve state for simple memo', async () => {
if (__DEV__) {
- const OuterV1 = render(() => {
+ const OuterV1 = await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -537,13 +540,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- const OuterV2 = patch(() => {
+ const OuterV2 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -565,7 +568,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump the state again.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -575,15 +578,15 @@ describe('ReactFresh', () => {
// Perform top-down renders with both fresh and stale types.
// Neither should change the state or color.
// They should always resolve to the latest version.
- render(() => OuterV1);
- render(() => OuterV2);
- render(() => OuterV1);
+ await render(() => OuterV1);
+ await render(() => OuterV2);
+ await render(() => OuterV1);
expect(container.firstChild).toBe(el);
expect(el.textContent).toBe('2');
expect(el.style.color).toBe('red');
// Finally, a render with incompatible type should reset it.
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -605,9 +608,9 @@ describe('ReactFresh', () => {
}
});
- it('can preserve state for memo with custom comparison', () => {
+ it('can preserve state for memo with custom comparison', async () => {
if (__DEV__) {
- const OuterV1 = render(() => {
+ const OuterV1 = await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -626,13 +629,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- const OuterV2 = patch(() => {
+ const OuterV2 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -653,7 +656,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump the state again.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -663,15 +666,15 @@ describe('ReactFresh', () => {
// Perform top-down renders with both fresh and stale types.
// Neither should change the state or color.
// They should always resolve to the latest version.
- render(() => OuterV1);
- render(() => OuterV2);
- render(() => OuterV1);
+ await render(() => OuterV1);
+ await render(() => OuterV2);
+ await render(() => OuterV1);
expect(container.firstChild).toBe(el);
expect(el.textContent).toBe('2');
expect(el.style.color).toBe('red');
// Finally, a render with incompatible type should reset it.
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -693,9 +696,9 @@ describe('ReactFresh', () => {
}
});
- it('can update simple memo function in isolation', () => {
+ it('can update simple memo function in isolation', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -713,13 +716,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update of just the rendering function.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -740,9 +743,9 @@ describe('ReactFresh', () => {
}
});
- it('can preserve state for memo(forwardRef)', () => {
+ it('can preserve state for memo(forwardRef)', async () => {
if (__DEV__) {
- const OuterV1 = render(() => {
+ const OuterV1 = await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -762,13 +765,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- const OuterV2 = patch(() => {
+ const OuterV2 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -790,7 +793,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump the state again.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -800,15 +803,15 @@ describe('ReactFresh', () => {
// Perform top-down renders with both fresh and stale types.
// Neither should change the state or color.
// They should always resolve to the latest version.
- render(() => OuterV1);
- render(() => OuterV2);
- render(() => OuterV1);
+ await render(() => OuterV1);
+ await render(() => OuterV2);
+ await render(() => OuterV1);
expect(container.firstChild).toBe(el);
expect(el.textContent).toBe('2');
expect(el.style.color).toBe('red');
// Finally, a render with incompatible type should reset it.
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -832,7 +835,8 @@ describe('ReactFresh', () => {
it('can preserve state for lazy after resolution', async () => {
if (__DEV__) {
- const AppV1 = render(() => {
+ let resolve;
+ const AppV1 = await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -845,8 +849,8 @@ describe('ReactFresh', () => {
const Outer = React.lazy(
() =>
- new Promise(resolve => {
- setTimeout(() => resolve({default: Hello}), 100);
+ new Promise(_resolve => {
+ resolve = () => _resolve({default: Hello});
}),
);
$RefreshReg$(Outer, 'Outer');
@@ -865,7 +869,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
await act(() => {
- jest.runAllTimers();
+ resolve();
});
expect(container.textContent).toBe('0');
@@ -873,13 +877,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- const AppV2 = patch(() => {
+ const AppV2 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -892,8 +896,8 @@ describe('ReactFresh', () => {
const Outer = React.lazy(
() =>
- new Promise(resolve => {
- setTimeout(() => resolve({default: Hello}), 100);
+ new Promise(_resolve => {
+ resolve = () => _resolve({default: Hello});
}),
);
$RefreshReg$(Outer, 'Outer');
@@ -916,7 +920,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump the state again.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -926,15 +930,15 @@ describe('ReactFresh', () => {
// Perform top-down renders with both fresh and stale types.
// Neither should change the state or color.
// They should always resolve to the latest version.
- render(() => AppV1);
- render(() => AppV2);
- render(() => AppV1);
+ await render(() => AppV1);
+ await render(() => AppV2);
+ await render(() => AppV1);
expect(container.firstChild).toBe(el);
expect(el.textContent).toBe('2');
expect(el.style.color).toBe('red');
// Finally, a render with incompatible type should reset it.
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -968,7 +972,8 @@ describe('ReactFresh', () => {
it('can patch lazy before resolution', async () => {
if (__DEV__) {
- render(() => {
+ let resolve;
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -981,8 +986,8 @@ describe('ReactFresh', () => {
const Outer = React.lazy(
() =>
- new Promise(resolve => {
- setTimeout(() => resolve({default: Hello}), 100);
+ new Promise(_resolve => {
+ resolve = () => _resolve({default: Hello});
}),
);
$RefreshReg$(Outer, 'Outer');
@@ -1001,7 +1006,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1014,7 +1019,7 @@ describe('ReactFresh', () => {
});
await act(() => {
- jest.runAllTimers();
+ resolve();
});
// Expect different color on initial mount.
@@ -1023,7 +1028,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump state.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -1031,7 +1036,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Test another reload.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1050,7 +1055,8 @@ describe('ReactFresh', () => {
it('can patch lazy(forwardRef) before resolution', async () => {
if (__DEV__) {
- render(() => {
+ let resolve;
+ await render(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1064,8 +1070,8 @@ describe('ReactFresh', () => {
const Outer = React.lazy(
() =>
- new Promise(resolve => {
- setTimeout(() => resolve({default: Hello}), 100);
+ new Promise(_resolve => {
+ resolve = () => _resolve({default: Hello});
}),
);
$RefreshReg$(Outer, 'Outer');
@@ -1084,7 +1090,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1098,7 +1104,7 @@ describe('ReactFresh', () => {
});
await act(() => {
- jest.runAllTimers();
+ resolve();
});
// Expect different color on initial mount.
@@ -1107,7 +1113,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump state.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -1115,7 +1121,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Test another reload.
- patch(() => {
+ await patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1135,7 +1141,8 @@ describe('ReactFresh', () => {
it('can patch lazy(memo) before resolution', async () => {
if (__DEV__) {
- render(() => {
+ let resolve;
+ await render(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1149,8 +1156,8 @@ describe('ReactFresh', () => {
const Outer = React.lazy(
() =>
- new Promise(resolve => {
- setTimeout(() => resolve({default: Hello}), 100);
+ new Promise(_resolve => {
+ resolve = () => _resolve({default: Hello});
}),
);
$RefreshReg$(Outer, 'Outer');
@@ -1169,7 +1176,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1183,7 +1190,7 @@ describe('ReactFresh', () => {
});
await act(() => {
- jest.runAllTimers();
+ resolve();
});
// Expect different color on initial mount.
@@ -1192,7 +1199,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump state.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -1200,7 +1207,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Test another reload.
- patch(() => {
+ await patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1220,7 +1227,8 @@ describe('ReactFresh', () => {
it('can patch lazy(memo(forwardRef)) before resolution', async () => {
if (__DEV__) {
- render(() => {
+ let resolve;
+ await render(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1234,8 +1242,8 @@ describe('ReactFresh', () => {
const Outer = React.lazy(
() =>
- new Promise(resolve => {
- setTimeout(() => resolve({default: Hello}), 100);
+ new Promise(_resolve => {
+ resolve = () => _resolve({default: Hello});
}),
);
$RefreshReg$(Outer, 'Outer');
@@ -1254,7 +1262,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1268,7 +1276,7 @@ describe('ReactFresh', () => {
});
await act(() => {
- jest.runAllTimers();
+ resolve();
});
// Expect different color on initial mount.
@@ -1277,7 +1285,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Bump state.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.firstChild).toBe(el);
@@ -1285,7 +1293,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Test another reload.
- patch(() => {
+ await patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1305,7 +1313,7 @@ describe('ReactFresh', () => {
it('can patch both trees while suspense is displaying the fallback', async () => {
if (__DEV__) {
- const AppV1 = render(
+ const AppV1 = await render(
() => {
function Hello({children}) {
const [val, setVal] = React.useState(0);
@@ -1343,7 +1351,7 @@ describe('ReactFresh', () => {
expect(primaryChild.style.display).toBe('');
// Bump primary content state.
- act(() => {
+ await act(() => {
primaryChild.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.childNodes.length).toBe(1);
@@ -1353,7 +1361,7 @@ describe('ReactFresh', () => {
expect(primaryChild.style.display).toBe('');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function Hello({children}) {
const [val, setVal] = React.useState(0);
return (
@@ -1371,7 +1379,7 @@ describe('ReactFresh', () => {
expect(primaryChild.style.display).toBe('');
// Now force the tree to suspend.
- render(() => AppV1, {shouldSuspend: true});
+ await render(() => AppV1, {shouldSuspend: true});
// Expect to see two trees, one of them is hidden.
expect(container.childNodes.length).toBe(2);
@@ -1385,7 +1393,7 @@ describe('ReactFresh', () => {
expect(fallbackChild.style.display).toBe('');
// Bump fallback state.
- act(() => {
+ await act(() => {
fallbackChild.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(container.childNodes.length).toBe(2);
@@ -1399,7 +1407,7 @@ describe('ReactFresh', () => {
expect(fallbackChild.style.display).toBe('');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function Hello({children}) {
const [val, setVal] = React.useState(0);
return (
@@ -1423,7 +1431,7 @@ describe('ReactFresh', () => {
expect(fallbackChild.style.display).toBe('');
// Only primary tree should exist now:
- render(() => AppV1, {shouldSuspend: false});
+ await render(() => AppV1, {shouldSuspend: false});
expect(container.childNodes.length).toBe(1);
expect(container.childNodes[0]).toBe(primaryChild);
expect(primaryChild.textContent).toBe('Content 1');
@@ -1431,7 +1439,7 @@ describe('ReactFresh', () => {
expect(primaryChild.style.display).toBe('');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function Hello({children}) {
const [val, setVal] = React.useState(0);
return (
@@ -1450,11 +1458,11 @@ describe('ReactFresh', () => {
}
});
- it('does not re-render ancestor components unnecessarily during a hot update', () => {
+ it('does not re-render ancestor components unnecessarily during a hot update', async () => {
if (__DEV__) {
let appRenders = 0;
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1478,7 +1486,7 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
@@ -1487,7 +1495,7 @@ describe('ReactFresh', () => {
expect(appRenders).toBe(1);
// Perform a hot update for Hello only.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1508,7 +1516,7 @@ describe('ReactFresh', () => {
expect(appRenders).toBe(1);
// Bump the state.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('2');
@@ -1518,11 +1526,11 @@ describe('ReactFresh', () => {
}
});
- it('batches re-renders during a hot update', () => {
+ it('batches re-renders during a hot update', async () => {
if (__DEV__) {
let helloRenders = 0;
- render(() => {
+ await render(() => {
function Hello({children}) {
helloRenders++;
return X{children}X
;
@@ -1547,7 +1555,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('XXXXXXXXXX');
helloRenders = 0;
- patch(() => {
+ await patch(() => {
function Hello({children}) {
helloRenders++;
return O{children}O
;
@@ -1559,9 +1567,9 @@ describe('ReactFresh', () => {
}
});
- it('does not leak state between components', () => {
+ it('does not leak state between components', async () => {
if (__DEV__) {
- const AppV1 = render(
+ const AppV1 = await render(
() => {
function Hello1() {
const [val, setVal] = React.useState(0);
@@ -1594,27 +1602,27 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Switch the condition, flipping inner content.
// This should reset the state.
- render(() => AppV1, {cond: true});
+ await render(() => AppV1, {cond: true});
const el2 = container.firstChild;
expect(el2).not.toBe(el);
expect(el2.textContent).toBe('0');
expect(el2.style.color).toBe('blue');
// Bump it again.
- act(() => {
+ await act(() => {
el2.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el2.textContent).toBe('1');
// Perform a hot update for both inner components.
- patch(() => {
+ await patch(() => {
function Hello1() {
const [val, setVal] = React.useState(0);
return (
@@ -1641,7 +1649,7 @@ describe('ReactFresh', () => {
expect(el2.style.color).toBe('red');
// Flip the condition again.
- render(() => AppV1, {cond: false});
+ await render(() => AppV1, {cond: false});
const el3 = container.firstChild;
expect(el3).not.toBe(el2);
expect(el3.textContent).toBe('0');
@@ -1649,9 +1657,9 @@ describe('ReactFresh', () => {
}
});
- it('can force remount by changing signature', () => {
+ it('can force remount by changing signature', async () => {
if (__DEV__) {
- const HelloV1 = render(() => {
+ const HelloV1 = await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1670,13 +1678,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- const HelloV2 = patch(() => {
+ const HelloV2 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1697,7 +1705,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Perform a hot update.
- const HelloV3 = patch(() => {
+ const HelloV3 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1719,7 +1727,7 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('yellow');
// Bump state again.
- act(() => {
+ await act(() => {
newEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(newEl.textContent).toBe('1');
@@ -1728,17 +1736,17 @@ describe('ReactFresh', () => {
// Perform top-down renders with both fresh and stale types.
// Neither should change the state or color.
// They should always resolve to the latest version.
- render(() => HelloV1);
- render(() => HelloV2);
- render(() => HelloV3);
- render(() => HelloV2);
- render(() => HelloV1);
+ await render(() => HelloV1);
+ await render(() => HelloV2);
+ await render(() => HelloV3);
+ await render(() => HelloV2);
+ await render(() => HelloV1);
expect(container.firstChild).toBe(newEl);
expect(newEl.textContent).toBe('1');
expect(newEl.style.color).toBe('yellow');
// Verify we can patch again while preserving the signature.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1758,7 +1766,7 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('purple');
// Check removing the signature also causes a remount.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1780,7 +1788,7 @@ describe('ReactFresh', () => {
}
});
- it('keeps a valid tree when forcing remount', () => {
+ it('keeps a valid tree when forcing remount', async () => {
if (__DEV__) {
const HelloV1 = prepare(() => {
function Hello() {
@@ -1910,27 +1918,32 @@ describe('ReactFresh', () => {
,
];
- // First, check that each tree handles remounts in isolation.
- ReactDOM.render(null, container);
+ await act(() => {
+ root.render(null);
+ });
+
for (let i = 0; i < trees.length; i++) {
- runRemountingStressTest(trees[i]);
+ await runRemountingStressTest(trees[i]);
}
// Then check that each tree is resilient to updates from another tree.
for (let i = 0; i < trees.length; i++) {
for (let j = 0; j < trees.length; j++) {
- ReactDOM.render(null, container);
+ await act(() => {
+ root.render(null);
+ });
+
// Intentionally don't clean up between the tests:
- runRemountingStressTest(trees[i]);
- runRemountingStressTest(trees[j]);
- runRemountingStressTest(trees[i]);
+ await runRemountingStressTest(trees[i]);
+ await runRemountingStressTest(trees[j]);
+ await runRemountingStressTest(trees[i]);
}
}
}
});
- function runRemountingStressTest(tree) {
- patch(() => {
+ async function runRemountingStressTest(tree) {
+ await patch(() => {
function Hello({children}) {
return ;
}
@@ -1939,7 +1952,10 @@ describe('ReactFresh', () => {
return Hello;
});
- ReactDOM.render(tree, container);
+ await act(() => {
+ root.render(tree);
+ });
+
const elements = container.querySelectorAll('section');
// Each tree above produces exactly three elements:
expect(elements.length).toBe(3);
@@ -1948,7 +1964,7 @@ describe('ReactFresh', () => {
});
// Patch color without changing the signature.
- patch(() => {
+ await patch(() => {
function Hello({children}) {
return ;
}
@@ -1967,7 +1983,7 @@ describe('ReactFresh', () => {
});
// Patch color *and* change the signature.
- patch(() => {
+ await patch(() => {
function Hello({children}) {
return ;
}
@@ -1986,7 +2002,7 @@ describe('ReactFresh', () => {
});
// Now patch color but *don't* change the signature.
- patch(() => {
+ await patch(() => {
function Hello({children}) {
return ;
}
@@ -2003,8 +2019,10 @@ describe('ReactFresh', () => {
expect(el.dataset.color).toBe('black');
});
- // Do another render just in case.
- ReactDOM.render(tree, container);
+ await act(() => {
+ root.render(tree);
+ });
+
expect(container.querySelectorAll('section').length).toBe(3);
container.querySelectorAll('section').forEach((el, index) => {
expect(el).toBe(elementsAfterRemount[index]);
@@ -2012,21 +2030,21 @@ describe('ReactFresh', () => {
});
}
- it('can remount on signature change within a wrapper', () => {
+ it('can remount on signature change within a wrapper', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => Hello);
+ await testRemountingWithWrapper(Hello => Hello);
}
});
- it('can remount on signature change within a simple memo wrapper', () => {
+ it('can remount on signature change within a simple memo wrapper', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => React.memo(Hello));
+ await testRemountingWithWrapper(Hello => React.memo(Hello));
}
});
- it('can remount on signature change within a lazy simple memo wrapper', () => {
+ it('can remount on signature change within a lazy simple memo wrapper', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello =>
+ await testRemountingWithWrapper(Hello =>
React.lazy(() => ({
then(cb) {
cb({default: React.memo(Hello)});
@@ -2036,35 +2054,37 @@ describe('ReactFresh', () => {
}
});
- it('can remount on signature change within forwardRef', () => {
+ it('can remount on signature change within forwardRef', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => React.forwardRef(Hello));
+ await testRemountingWithWrapper(Hello => React.forwardRef(Hello));
}
});
- it('can remount on signature change within forwardRef render function', () => {
+ it('can remount on signature change within forwardRef render function', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => React.forwardRef(() => ));
+ await testRemountingWithWrapper(Hello =>
+ React.forwardRef(() => ),
+ );
}
});
- it('can remount on signature change within nested memo', () => {
+ it('can remount on signature change within nested memo', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello =>
+ await testRemountingWithWrapper(Hello =>
React.memo(React.memo(React.memo(Hello))),
);
}
});
- it('can remount on signature change within a memo wrapper and custom comparison', () => {
+ it('can remount on signature change within a memo wrapper and custom comparison', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => React.memo(Hello, () => true));
+ await testRemountingWithWrapper(Hello => React.memo(Hello, () => true));
}
});
- it('can remount on signature change within a class', () => {
+ it('can remount on signature change within a class', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => {
+ await testRemountingWithWrapper(Hello => {
const child = ;
return class Wrapper extends React.PureComponent {
render() {
@@ -2075,9 +2095,9 @@ describe('ReactFresh', () => {
}
});
- it('can remount on signature change within a context provider', () => {
+ it('can remount on signature change within a context provider', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => {
+ await testRemountingWithWrapper(Hello => {
const Context = React.createContext();
const child = (
@@ -2091,9 +2111,9 @@ describe('ReactFresh', () => {
}
});
- it('can remount on signature change within a context consumer', () => {
+ it('can remount on signature change within a context consumer', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => {
+ await testRemountingWithWrapper(Hello => {
const Context = React.createContext();
const child = {() => };
return function Wrapper() {
@@ -2103,9 +2123,9 @@ describe('ReactFresh', () => {
}
});
- it('can remount on signature change within a suspense node', () => {
+ it('can remount on signature change within a suspense node', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => {
+ await testRemountingWithWrapper(Hello => {
// TODO: we'll probably want to test fallback trees too.
const child = (
@@ -2119,9 +2139,9 @@ describe('ReactFresh', () => {
}
});
- it('can remount on signature change within a mode node', () => {
+ it('can remount on signature change within a mode node', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => {
+ await testRemountingWithWrapper(Hello => {
const child = (
@@ -2134,9 +2154,9 @@ describe('ReactFresh', () => {
}
});
- it('can remount on signature change within a fragment node', () => {
+ it('can remount on signature change within a fragment node', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => {
+ await testRemountingWithWrapper(Hello => {
const child = (
<>
@@ -2149,9 +2169,9 @@ describe('ReactFresh', () => {
}
});
- it('can remount on signature change within multiple siblings', () => {
+ it('can remount on signature change within multiple siblings', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => {
+ await testRemountingWithWrapper(Hello => {
const child = (
<>
<>
@@ -2168,9 +2188,9 @@ describe('ReactFresh', () => {
}
});
- it('can remount on signature change within a profiler node', () => {
+ it('can remount on signature change within a profiler node', async () => {
if (__DEV__) {
- testRemountingWithWrapper(Hello => {
+ await testRemountingWithWrapper(Hello => {
const child = ;
return function Wrapper() {
return (
@@ -2183,8 +2203,8 @@ describe('ReactFresh', () => {
}
});
- function testRemountingWithWrapper(wrap) {
- render(() => {
+ async function testRemountingWithWrapper(wrap) {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2206,13 +2226,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update that doesn't remount.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2233,7 +2253,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Perform a hot update that remounts.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2255,14 +2275,14 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('yellow');
// Bump state again.
- act(() => {
+ await act(() => {
newEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(newEl.textContent).toBe('1');
expect(newEl.style.color).toBe('yellow');
// Verify we can patch again while preserving the signature.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2282,7 +2302,7 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('purple');
// Check removing the signature also causes a remount.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2303,11 +2323,11 @@ describe('ReactFresh', () => {
expect(finalEl.style.color).toBe('orange');
}
- it('resets hooks with dependencies on hot reload', () => {
+ it('resets hooks with dependencies on hot reload', async () => {
if (__DEV__) {
let useEffectWithEmptyArrayCalls = 0;
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
const tranformed = React.useMemo(() => val * 2, [val]);
@@ -2332,33 +2352,31 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
expect(useEffectWithEmptyArrayCalls).toBe(1); // useEffect ran
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('2'); // val * 2
expect(useEffectWithEmptyArrayCalls).toBe(1); // useEffect didn't re-run
// Perform a hot update.
- act(() => {
- patch(() => {
- function Hello() {
- const [val, setVal] = React.useState(0);
- const tranformed = React.useMemo(() => val * 10, [val]);
- const handleClick = React.useCallback(() => setVal(v => v - 1), []);
+ await patch(() => {
+ function Hello() {
+ const [val, setVal] = React.useState(0);
+ const tranformed = React.useMemo(() => val * 10, [val]);
+ const handleClick = React.useCallback(() => setVal(v => v - 1), []);
- React.useEffect(() => {
- useEffectWithEmptyArrayCalls++;
- }, []);
+ React.useEffect(() => {
+ useEffectWithEmptyArrayCalls++;
+ }, []);
- return (
-
- {tranformed}
-
- );
- }
- $RefreshReg$(Hello, 'Hello');
- return Hello;
- });
+ return (
+
+ {tranformed}
+
+ );
+ }
+ $RefreshReg$(Hello, 'Hello');
+ return Hello;
});
// Assert the state was preserved but memo was evicted.
@@ -2368,7 +2386,7 @@ describe('ReactFresh', () => {
expect(useEffectWithEmptyArrayCalls).toBe(2); // useEffect re-ran
// This should fire the new callback which decreases the counter.
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('0');
@@ -2378,9 +2396,9 @@ describe('ReactFresh', () => {
});
// This pattern is inspired by useSubscription and similar mechanisms.
- it('does not get into infinite loops during render phase updates', () => {
+ it('does not get into infinite loops during render phase updates', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Hello() {
const source = React.useMemo(() => ({value: 10}), []);
const [state, setState] = React.useState({value: null});
@@ -2398,20 +2416,18 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('blue');
// Perform a hot update.
- act(() => {
- patch(() => {
- function Hello() {
- const source = React.useMemo(() => ({value: 20}), []);
- const [state, setState] = React.useState({value: null});
- if (state !== source) {
- // This should perform a single render-phase update.
- setState(source);
- }
- return {state.value}
;
+ await patch(() => {
+ function Hello() {
+ const source = React.useMemo(() => ({value: 20}), []);
+ const [state, setState] = React.useState({value: null});
+ if (state !== source) {
+ // This should perform a single render-phase update.
+ setState(source);
}
- $RefreshReg$(Hello, 'Hello');
- return Hello;
- });
+ return {state.value}
;
+ }
+ $RefreshReg$(Hello, 'Hello');
+ return Hello;
});
expect(container.firstChild).toBe(el);
@@ -2448,7 +2464,6 @@ describe('ReactFresh', () => {
};
});
- const root = ReactDOMClient.createRoot(container);
root.render();
await waitFor(['App#layout']);
const el = container.firstChild;
@@ -2456,8 +2471,8 @@ describe('ReactFresh', () => {
expect(el.firstChild).toBe(null); // Offscreen content not flushed yet.
// Perform a hot update.
- patch(() => {
- function Hello() {
+ {
+ const Hello = () => {
React.useLayoutEffect(() => {
Scheduler.log('Hello#layout');
});
@@ -2467,9 +2482,10 @@ describe('ReactFresh', () => {
{val}
);
- }
+ };
$RefreshReg$(Hello, 'Hello');
- });
+ ReactFreshRuntime.performReactRefresh();
+ }
// It's still offscreen so we don't see anything.
expect(container.firstChild).toBe(el);
@@ -2482,7 +2498,7 @@ describe('ReactFresh', () => {
expect(el.firstChild.textContent).toBe('0');
expect(el.firstChild.style.color).toBe('red');
- await internalAct(() => {
+ await act(() => {
el.firstChild.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
@@ -2495,8 +2511,8 @@ describe('ReactFresh', () => {
expect(el.firstChild.style.color).toBe('red');
// Hot reload while we're offscreen.
- patch(() => {
- function Hello() {
+ {
+ const Hello = () => {
React.useLayoutEffect(() => {
Scheduler.log('Hello#layout');
});
@@ -2506,9 +2522,10 @@ describe('ReactFresh', () => {
{val}
);
- }
+ };
$RefreshReg$(Hello, 'Hello');
- });
+ ReactFreshRuntime.performReactRefresh();
+ }
// It's still offscreen so we don't see the updates.
expect(container.firstChild).toBe(el);
@@ -2522,9 +2539,9 @@ describe('ReactFresh', () => {
expect(el.firstChild.style.color).toBe('orange');
});
- it('remounts failed error boundaries (componentDidCatch)', () => {
+ it('remounts failed error boundaries (componentDidCatch)', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Hello() {
return Hi
;
}
@@ -2563,7 +2580,7 @@ describe('ReactFresh', () => {
const secondP = firstP.nextSibling.nextSibling;
// Perform a hot update that fails.
- patch(() => {
+ await patch(() => {
function Hello() {
throw new Error('No');
}
@@ -2575,7 +2592,7 @@ describe('ReactFresh', () => {
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
// Perform a hot update that fixes the error.
- patch(() => {
+ await patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2589,7 +2606,7 @@ describe('ReactFresh', () => {
// Verify next hot reload doesn't remount anything.
const helloNode = container.firstChild.nextSibling;
- patch(() => {
+ await patch(() => {
function Hello() {
return Nice.
;
}
@@ -2600,9 +2617,9 @@ describe('ReactFresh', () => {
}
});
- it('remounts failed error boundaries (getDerivedStateFromError)', () => {
+ it('remounts failed error boundaries (getDerivedStateFromError)', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Hello() {
return Hi
;
}
@@ -2641,7 +2658,7 @@ describe('ReactFresh', () => {
const secondP = firstP.nextSibling.nextSibling;
// Perform a hot update that fails.
- patch(() => {
+ await patch(() => {
function Hello() {
throw new Error('No');
}
@@ -2653,7 +2670,7 @@ describe('ReactFresh', () => {
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
// Perform a hot update that fixes the error.
- patch(() => {
+ await patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2667,7 +2684,7 @@ describe('ReactFresh', () => {
// Verify next hot reload doesn't remount anything.
const helloNode = container.firstChild.nextSibling;
- patch(() => {
+ await patch(() => {
function Hello() {
return Nice.
;
}
@@ -2678,9 +2695,9 @@ describe('ReactFresh', () => {
}
});
- it('remounts error boundaries that failed asynchronously after hot update', () => {
+ it('remounts error boundaries that failed asynchronously after hot update', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Hello() {
const [x] = React.useState('');
React.useEffect(() => {}, []);
@@ -2722,26 +2739,25 @@ describe('ReactFresh', () => {
const secondP = firstP.nextSibling.nextSibling;
// Perform a hot update that fails.
- act(() => {
- patch(() => {
- function Hello() {
- const [x, setX] = React.useState('');
- React.useEffect(() => {
- setTimeout(() => {
- setX(42); // This will crash next render.
- }, 1);
- }, []);
- x.slice();
- return Hi
;
- }
- $RefreshReg$(Hello, 'Hello');
- });
+ let crash;
+ await patch(() => {
+ function Hello() {
+ const [x, setX] = React.useState('');
+ React.useEffect(() => {
+ crash = () => {
+ setX(42); // This will crash next render.
+ };
+ }, []);
+ x.slice();
+ return Hi
;
+ }
+ $RefreshReg$(Hello, 'Hello');
});
expect(container.innerHTML).toBe('A
Hi
B
');
// Run timeout inside effect:
- act(() => {
- jest.runAllTimers();
+ await act(() => {
+ crash();
});
expect(container.innerHTML).toBe(
'A
Oops: x.slice is not a function
B
',
@@ -2750,16 +2766,14 @@ describe('ReactFresh', () => {
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
// Perform a hot update that fixes the error.
- act(() => {
- patch(() => {
- function Hello() {
- const [x] = React.useState('');
- React.useEffect(() => {}, []); // Removes the bad effect code.
- x.slice(); // Doesn't throw initially.
- return Fixed!
;
- }
- $RefreshReg$(Hello, 'Hello');
- });
+ await patch(() => {
+ function Hello() {
+ const [x] = React.useState('');
+ React.useEffect(() => {}, []); // Removes the bad effect code.
+ x.slice(); // Doesn't throw initially.
+ return Fixed!
;
+ }
+ $RefreshReg$(Hello, 'Hello');
});
// This should remount the error boundary (but not anything above it).
@@ -2769,16 +2783,14 @@ describe('ReactFresh', () => {
// Verify next hot reload doesn't remount anything.
const helloNode = container.firstChild.nextSibling;
- act(() => {
- patch(() => {
- function Hello() {
- const [x] = React.useState('');
- React.useEffect(() => {}, []);
- x.slice();
- return Nice.
;
- }
- $RefreshReg$(Hello, 'Hello');
- });
+ await patch(() => {
+ function Hello() {
+ const [x] = React.useState('');
+ React.useEffect(() => {}, []);
+ x.slice();
+ return Nice.
;
+ }
+ $RefreshReg$(Hello, 'Hello');
});
expect(container.firstChild.nextSibling).toBe(helloNode);
@@ -2786,9 +2798,9 @@ describe('ReactFresh', () => {
}
});
- it('remounts a failed root on mount', () => {
+ it('remounts a failed root on mount', async () => {
if (__DEV__) {
- expect(() => {
+ await expect(
render(() => {
function Hello() {
throw new Error('No');
@@ -2796,23 +2808,23 @@ describe('ReactFresh', () => {
$RefreshReg$(Hello, 'Hello');
return Hello;
- });
- }).toThrow('No');
+ }),
+ ).rejects.toThrow('No');
expect(container.innerHTML).toBe('');
// A bad retry
- expect(() => {
+ await expect(
patch(() => {
function Hello() {
throw new Error('Not yet');
}
$RefreshReg$(Hello, 'Hello');
- });
- }).toThrow('Not yet');
+ }),
+ ).rejects.toThrow('Not yet');
expect(container.innerHTML).toBe('');
// Perform a hot update that fixes the error.
- patch(() => {
+ await patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2822,25 +2834,25 @@ describe('ReactFresh', () => {
expect(container.innerHTML).toBe('Fixed!
');
// Ensure we can keep failing and recovering later.
- expect(() => {
+ await expect(
patch(() => {
function Hello() {
throw new Error('No 2');
}
$RefreshReg$(Hello, 'Hello');
- });
- }).toThrow('No 2');
+ }),
+ ).rejects.toThrow('No 2');
expect(container.innerHTML).toBe('');
- expect(() => {
+ await expect(
patch(() => {
function Hello() {
throw new Error('Not yet 2');
}
$RefreshReg$(Hello, 'Hello');
- });
- }).toThrow('Not yet 2');
+ }),
+ ).rejects.toThrow('Not yet 2');
expect(container.innerHTML).toBe('');
- patch(() => {
+ await patch(() => {
function Hello() {
return Fixed 2!
;
}
@@ -2849,15 +2861,17 @@ describe('ReactFresh', () => {
expect(container.innerHTML).toBe('Fixed 2!
');
// Updates after intentional unmount are ignored.
- ReactDOM.unmountComponentAtNode(container);
- patch(() => {
+ await act(() => {
+ root.unmount();
+ });
+ await patch(() => {
function Hello() {
throw new Error('Ignored');
}
$RefreshReg$(Hello, 'Hello');
});
expect(container.innerHTML).toBe('');
- patch(() => {
+ await patch(() => {
function Hello() {
return Ignored
;
}
@@ -2867,9 +2881,9 @@ describe('ReactFresh', () => {
}
});
- it('does not retry an intentionally unmounted failed root', () => {
+ it('does not retry an intentionally unmounted failed root', async () => {
if (__DEV__) {
- expect(() => {
+ await expect(
render(() => {
function Hello() {
throw new Error('No');
@@ -2877,15 +2891,17 @@ describe('ReactFresh', () => {
$RefreshReg$(Hello, 'Hello');
return Hello;
- });
- }).toThrow('No');
+ }),
+ ).rejects.toThrow('No');
expect(container.innerHTML).toBe('');
// Intentional unmount.
- ReactDOM.unmountComponentAtNode(container);
+ await act(() => {
+ root.unmount();
+ });
// Perform a hot update that fixes the error.
- patch(() => {
+ await patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2896,9 +2912,9 @@ describe('ReactFresh', () => {
}
});
- it('remounts a failed root on update', () => {
+ it('remounts a failed root on update', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Hello() {
return Hi
;
}
@@ -2910,29 +2926,29 @@ describe('ReactFresh', () => {
// Perform a hot update that fails.
// This removes the root.
- expect(() => {
+ await expect(
patch(() => {
function Hello() {
throw new Error('No');
}
$RefreshReg$(Hello, 'Hello');
- });
- }).toThrow('No');
+ }),
+ ).rejects.toThrow('No');
expect(container.innerHTML).toBe('');
// A bad retry
- expect(() => {
+ await expect(
patch(() => {
function Hello() {
throw new Error('Not yet');
}
$RefreshReg$(Hello, 'Hello');
- });
- }).toThrow('Not yet');
+ }),
+ ).rejects.toThrow('Not yet');
expect(container.innerHTML).toBe('');
// Perform a hot update that fixes the error.
- patch(() => {
+ await patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2943,7 +2959,7 @@ describe('ReactFresh', () => {
// Verify next hot reload doesn't remount anything.
const helloNode = container.firstChild;
- patch(() => {
+ await patch(() => {
function Hello() {
return Nice.
;
}
@@ -2953,18 +2969,18 @@ describe('ReactFresh', () => {
expect(helloNode.textContent).toBe('Nice.');
// Break again.
- expect(() => {
+ await expect(
patch(() => {
function Hello() {
throw new Error('Oops');
}
$RefreshReg$(Hello, 'Hello');
- });
- }).toThrow('Oops');
+ }),
+ ).rejects.toThrow('Oops');
expect(container.innerHTML).toBe('');
// Perform a hot update that fixes the error.
- patch(() => {
+ await patch(() => {
function Hello() {
return At last.
;
}
@@ -2974,9 +2990,11 @@ describe('ReactFresh', () => {
expect(container.innerHTML).toBe('At last.
');
// Check we don't attempt to reverse an intentional unmount.
- ReactDOM.unmountComponentAtNode(container);
+ await act(() => {
+ root.unmount();
+ });
expect(container.innerHTML).toBe('');
- patch(() => {
+ await patch(() => {
function Hello() {
return Never mind me!
;
}
@@ -2985,7 +3003,8 @@ describe('ReactFresh', () => {
expect(container.innerHTML).toBe('');
// Mount a new container.
- render(() => {
+ root = ReactDOMClient.createRoot(container);
+ await render(() => {
function Hello() {
return Hi
;
}
@@ -2996,20 +3015,22 @@ describe('ReactFresh', () => {
expect(container.innerHTML).toBe('Hi
');
// Break again.
- expect(() => {
+ await expect(
patch(() => {
function Hello() {
throw new Error('Oops');
}
$RefreshReg$(Hello, 'Hello');
- });
- }).toThrow('Oops');
+ }),
+ ).rejects.toThrow('Oops');
expect(container.innerHTML).toBe('');
// Check we don't attempt to reverse an intentional unmount, even after an error.
- ReactDOM.unmountComponentAtNode(container);
+ await act(() => {
+ root.unmount();
+ });
expect(container.innerHTML).toBe('');
- patch(() => {
+ await patch(() => {
function Hello() {
return Never mind me!
;
}
@@ -3019,10 +3040,12 @@ describe('ReactFresh', () => {
}
});
- it('regression test: does not get into an infinite loop', () => {
+ it('regression test: does not get into an infinite loop', async () => {
if (__DEV__) {
const containerA = document.createElement('div');
const containerB = document.createElement('div');
+ const rootA = ReactDOMClient.createRoot(containerA);
+ const rootB = ReactDOMClient.createRoot(containerB);
// Initially, nothing interesting.
const RootAV1 = () => {
@@ -3034,9 +3057,9 @@ describe('ReactFresh', () => {
};
$RefreshReg$(RootBV1, 'RootB');
- act(() => {
- ReactDOM.render(, containerA);
- ReactDOM.render(, containerB);
+ await act(() => {
+ rootA.render();
+ rootB.render();
});
expect(containerA.innerHTML).toBe('A1');
expect(containerB.innerHTML).toBe('B1');
@@ -3046,7 +3069,11 @@ describe('ReactFresh', () => {
throw new Error('A2!');
};
$RefreshReg$(RootAV2, 'RootA');
- expect(() => ReactFreshRuntime.performReactRefresh()).toThrow('A2!');
+ await expect(
+ act(() => {
+ ReactFreshRuntime.performReactRefresh();
+ }),
+ ).rejects.toThrow('A2!');
expect(containerA.innerHTML).toBe('');
expect(containerB.innerHTML).toBe('B1');
@@ -3060,7 +3087,11 @@ describe('ReactFresh', () => {
return 'A3';
};
$RefreshReg$(RootAV3, 'RootA');
- expect(() => ReactFreshRuntime.performReactRefresh()).toThrow('A3!');
+ await expect(
+ act(() => {
+ ReactFreshRuntime.performReactRefresh();
+ }),
+ ).rejects.toThrow('A3!');
expect(containerA.innerHTML).toBe('');
expect(containerB.innerHTML).toBe('B1');
@@ -3068,15 +3099,17 @@ describe('ReactFresh', () => {
return 'A4';
};
$RefreshReg$(RootAV4, 'RootA');
- ReactFreshRuntime.performReactRefresh();
+ await act(() => {
+ ReactFreshRuntime.performReactRefresh();
+ });
expect(containerA.innerHTML).toBe('A4');
expect(containerB.innerHTML).toBe('B1');
}
});
- it('remounts classes on every edit', () => {
+ it('remounts classes on every edit', async () => {
if (__DEV__) {
- const HelloV1 = render(() => {
+ const HelloV1 = await render(() => {
class Hello extends React.Component {
state = {count: 0};
handleClick = () => {
@@ -3105,13 +3138,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- const HelloV2 = patch(() => {
+ const HelloV2 = await patch(() => {
class Hello extends React.Component {
state = {count: 0};
handleClick = () => {
@@ -3136,19 +3169,19 @@ describe('ReactFresh', () => {
const newEl = container.firstChild;
expect(newEl.textContent).toBe('0');
expect(newEl.style.color).toBe('red');
- act(() => {
+ await act(() => {
newEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(newEl.textContent).toBe('1');
// Now top-level renders of both types resolve to latest.
- render(() => HelloV1);
- render(() => HelloV2);
+ await render(() => HelloV1);
+ await render(() => HelloV2);
expect(container.firstChild).toBe(newEl);
expect(newEl.style.color).toBe('red');
expect(newEl.textContent).toBe('1');
- const HelloV3 = patch(() => {
+ const HelloV3 = await patch(() => {
class Hello extends React.Component {
state = {count: 0};
handleClick = () => {
@@ -3173,24 +3206,24 @@ describe('ReactFresh', () => {
const finalEl = container.firstChild;
expect(finalEl.textContent).toBe('0');
expect(finalEl.style.color).toBe('orange');
- act(() => {
+ await act(() => {
finalEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(finalEl.textContent).toBe('1');
- render(() => HelloV3);
- render(() => HelloV2);
- render(() => HelloV1);
+ await render(() => HelloV3);
+ await render(() => HelloV2);
+ await render(() => HelloV1);
expect(container.firstChild).toBe(finalEl);
expect(finalEl.style.color).toBe('orange');
expect(finalEl.textContent).toBe('1');
}
});
- it('updates refs when remounting', () => {
+ it('updates refs when remounting', async () => {
if (__DEV__) {
const testRef = React.createRef();
- render(
+ await render(
() => {
class Hello extends React.Component {
getColor() {
@@ -3207,7 +3240,7 @@ describe('ReactFresh', () => {
);
expect(testRef.current.getColor()).toBe('green');
- patch(() => {
+ await patch(() => {
class Hello extends React.Component {
getColor() {
return 'orange';
@@ -3220,7 +3253,7 @@ describe('ReactFresh', () => {
});
expect(testRef.current.getColor()).toBe('orange');
- patch(() => {
+ await patch(() => {
const Hello = React.forwardRef((props, ref) => {
React.useImperativeHandle(ref, () => ({
getColor() {
@@ -3233,7 +3266,7 @@ describe('ReactFresh', () => {
});
expect(testRef.current.getColor()).toBe('pink');
- patch(() => {
+ await patch(() => {
const Hello = React.forwardRef((props, ref) => {
React.useImperativeHandle(ref, () => ({
getColor() {
@@ -3246,7 +3279,7 @@ describe('ReactFresh', () => {
});
expect(testRef.current.getColor()).toBe('yellow');
- patch(() => {
+ await patch(() => {
const Hello = React.forwardRef((props, ref) => {
React.useImperativeHandle(ref, () => ({
getColor() {
@@ -3261,9 +3294,9 @@ describe('ReactFresh', () => {
}
});
- it('remounts on conversion from class to function and back', () => {
+ it('remounts on conversion from class to function and back', async () => {
if (__DEV__) {
- const HelloV1 = render(() => {
+ const HelloV1 = await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -3280,13 +3313,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update that turns it into a class.
- const HelloV2 = patch(() => {
+ const HelloV2 = await patch(() => {
class Hello extends React.Component {
state = {count: 0};
handleClick = () => {
@@ -3311,20 +3344,20 @@ describe('ReactFresh', () => {
const newEl = container.firstChild;
expect(newEl.textContent).toBe('0');
expect(newEl.style.color).toBe('red');
- act(() => {
+ await act(() => {
newEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(newEl.textContent).toBe('1');
// Now top-level renders of both types resolve to latest.
- render(() => HelloV1);
- render(() => HelloV2);
+ await render(() => HelloV1);
+ await render(() => HelloV2);
expect(container.firstChild).toBe(newEl);
expect(newEl.style.color).toBe('red');
expect(newEl.textContent).toBe('1');
// Now convert it back to a function.
- const HelloV3 = patch(() => {
+ const HelloV3 = await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -3342,20 +3375,20 @@ describe('ReactFresh', () => {
const finalEl = container.firstChild;
expect(finalEl.textContent).toBe('0');
expect(finalEl.style.color).toBe('orange');
- act(() => {
+ await act(() => {
finalEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(finalEl.textContent).toBe('1');
- render(() => HelloV3);
- render(() => HelloV2);
- render(() => HelloV1);
+ await render(() => HelloV3);
+ await render(() => HelloV2);
+ await render(() => HelloV1);
expect(container.firstChild).toBe(finalEl);
expect(finalEl.style.color).toBe('orange');
expect(finalEl.textContent).toBe('1');
// Now that it's a function, verify edits keep state.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -3373,9 +3406,9 @@ describe('ReactFresh', () => {
}
});
- it('can find host instances for a family', () => {
+ it('can find host instances for a family', async () => {
if (__DEV__) {
- render(() => {
+ await render(() => {
function Child({children}) {
return {children}
;
}
@@ -3481,7 +3514,7 @@ describe('ReactFresh', () => {
});
}
- it('can update multiple roots independently', () => {
+ it('can update multiple roots independently', async () => {
if (__DEV__) {
// Declare the first version.
const HelloV1 = () => {
@@ -3504,7 +3537,9 @@ describe('ReactFresh', () => {
);
};
$RefreshReg$(HelloV2, 'Hello');
- ReactFreshRuntime.performReactRefresh();
+ await act(() => {
+ ReactFreshRuntime.performReactRefresh();
+ });
// Mount three roots.
const cont1 = document.createElement('div');
@@ -3513,10 +3548,19 @@ describe('ReactFresh', () => {
document.body.appendChild(cont1);
document.body.appendChild(cont2);
document.body.appendChild(cont3);
+ const root1 = ReactDOMClient.createRoot(cont1);
+ const root2 = ReactDOMClient.createRoot(cont2);
+ const root3 = ReactDOMClient.createRoot(cont3);
try {
- ReactDOM.render(, cont1);
- ReactDOM.render(, cont2);
- ReactDOM.render(, cont3);
+ await act(() => {
+ root1.render();
+ });
+ await act(() => {
+ root2.render();
+ });
+ await act(() => {
+ root3.render();
+ });
// Expect we see the V2 color.
expect(cont1.firstChild.style.color).toBe('red');
@@ -3527,7 +3571,7 @@ describe('ReactFresh', () => {
expect(cont3.firstChild.textContent).toBe('0');
// Bump the state for each of them.
- act(() => {
+ await act(() => {
cont1.firstChild.dispatchEvent(
new MouseEvent('click', {bubbles: true}),
);
@@ -3555,7 +3599,9 @@ describe('ReactFresh', () => {
);
};
$RefreshReg$(HelloV3, 'Hello');
- ReactFreshRuntime.performReactRefresh();
+ await act(() => {
+ ReactFreshRuntime.performReactRefresh();
+ });
// It should affect all roots.
expect(cont1.firstChild.style.color).toBe('green');
@@ -3566,7 +3612,9 @@ describe('ReactFresh', () => {
expect(cont3.firstChild.textContent).toBe('1');
// Unmount the second root.
- ReactDOM.unmountComponentAtNode(cont2);
+ await act(() => {
+ root2.unmount();
+ });
// Make the first root throw and unmount on hot update.
const HelloV4 = ({id}) => {
if (id === 1) {
@@ -3580,9 +3628,11 @@ describe('ReactFresh', () => {
);
};
$RefreshReg$(HelloV4, 'Hello');
- expect(() => {
- ReactFreshRuntime.performReactRefresh();
- }).toThrow('Oops.');
+ await expect(
+ act(() => {
+ ReactFreshRuntime.performReactRefresh();
+ }),
+ ).rejects.toThrow('Oops.');
// Still, we expect the last root to be updated.
expect(cont1.innerHTML).toBe('');
@@ -3791,18 +3841,20 @@ describe('ReactFresh', () => {
jest.resetModules();
React = require('react');
ReactDOM = require('react-dom');
+ ReactDOMClient = require('react-dom/client');
Scheduler = require('scheduler');
- act = React.act;
- internalAct = require('internal-test-utils').act;
+ act = require('internal-test-utils').act;
// Important! Inject into the global hook *after* ReactDOM runs:
ReactFreshRuntime = require('react-refresh/runtime');
ReactFreshRuntime.injectIntoGlobalHook(global);
+ root = ReactDOMClient.createRoot(container);
+
// We're verifying that we're able to track roots mounted after this point.
// The rest of this test is taken from the simplest first test case.
- render(() => {
+ await render(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -3819,13 +3871,13 @@ describe('ReactFresh', () => {
const el = container.firstChild;
expect(el.textContent).toBe('0');
expect(el.style.color).toBe('blue');
- act(() => {
+ await act(() => {
el.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(el.textContent).toBe('1');
// Perform a hot update.
- patch(() => {
+ await patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -3846,7 +3898,7 @@ describe('ReactFresh', () => {
});
// This simulates the scenario in https://github.com/facebook/react/issues/20100
- it('does not block DevTools when an unsupported renderer is injected', () => {
+ it('does not block DevTools when an unsupported legacy renderer is injected', () => {
if (__DEV__) {
initFauxDevToolsHook();
@@ -3872,13 +3924,12 @@ describe('ReactFresh', () => {
ReactFreshRuntime = require('react-refresh/runtime');
ReactFreshRuntime.injectIntoGlobalHook(global);
- render(() => {
- function Hello() {
- return Hi!
;
- }
- $RefreshReg$(Hello, 'Hello');
- return Hello;
- });
+ const Hello = () => {
+ return Hi!
;
+ };
+ $RefreshReg$(Hello, 'Hello');
+ const Component = Hello;
+ ReactDOM.render(, container);
expect(onCommitFiberRoot).toHaveBeenCalled();
}
From 39f95f45a0daf993aebe163ed20dc383fe899565 Mon Sep 17 00:00:00 2001
From: Sebastian Silbermann
Date: Fri, 2 Feb 2024 19:18:24 +0100
Subject: [PATCH 2/6] Amend assertions
---
packages/react-refresh/src/__tests__/ReactFresh-test.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/react-refresh/src/__tests__/ReactFresh-test.js b/packages/react-refresh/src/__tests__/ReactFresh-test.js
index 2f0f51851f663..47cf32f9e64d0 100644
--- a/packages/react-refresh/src/__tests__/ReactFresh-test.js
+++ b/packages/react-refresh/src/__tests__/ReactFresh-test.js
@@ -1419,12 +1419,12 @@ describe('ReactFresh', () => {
$RefreshReg$(Hello, 'Hello');
});
- // Colors inside both trees should change:
+ // Only update color in the visible child
expect(container.childNodes.length).toBe(2);
expect(container.childNodes[0]).toBe(primaryChild);
expect(container.childNodes[1]).toBe(fallbackChild);
expect(primaryChild.textContent).toBe('Content 1');
- expect(primaryChild.style.color).toBe('red');
+ expect(primaryChild.style.color).toBe('green');
expect(primaryChild.style.display).toBe('none');
expect(fallbackChild.textContent).toBe('Fallback 1');
expect(fallbackChild.style.color).toBe('red');
From c52fc26c5fd15da72aa2dd0491d62f1bb38d66d2 Mon Sep 17 00:00:00 2001
From: Sebastian Silbermann
Date: Fri, 2 Feb 2024 19:18:43 +0100
Subject: [PATCH 3/6] Silly mistake
---
packages/react-refresh/src/__tests__/ReactFresh-test.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/packages/react-refresh/src/__tests__/ReactFresh-test.js b/packages/react-refresh/src/__tests__/ReactFresh-test.js
index 47cf32f9e64d0..0e344756ce621 100644
--- a/packages/react-refresh/src/__tests__/ReactFresh-test.js
+++ b/packages/react-refresh/src/__tests__/ReactFresh-test.js
@@ -28,7 +28,6 @@ describe('ReactFresh', () => {
beforeEach(() => {
if (__DEV__) {
jest.resetModules();
- global.IS_REACT_ACT_ENVIRONMENT = true;
React = require('react');
ReactFreshRuntime = require('react-refresh/runtime');
ReactFreshRuntime.injectIntoGlobalHook(global);
From 6462aaf53c8c514ae339deed9c0a2bf24151cf2a Mon Sep 17 00:00:00 2001
From: Sebastian Silbermann
Date: Fri, 2 Feb 2024 19:27:54 +0100
Subject: [PATCH 4/6] Don't need to wrap performReactRefresh in act
---
.../src/__tests__/ReactFresh-test.js | 200 +++++++++---------
1 file changed, 98 insertions(+), 102 deletions(-)
diff --git a/packages/react-refresh/src/__tests__/ReactFresh-test.js b/packages/react-refresh/src/__tests__/ReactFresh-test.js
index 0e344756ce621..50e72cae5ae3c 100644
--- a/packages/react-refresh/src/__tests__/ReactFresh-test.js
+++ b/packages/react-refresh/src/__tests__/ReactFresh-test.js
@@ -71,11 +71,9 @@ describe('ReactFresh', () => {
return Component;
}
- async function patch(version) {
+ function patch(version) {
const Component = version();
- await act(() => {
- ReactFreshRuntime.performReactRefresh();
- });
+ ReactFreshRuntime.performReactRefresh();
return Component;
}
@@ -126,7 +124,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- const HelloV2 = await patch(() => {
+ const HelloV2 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -219,7 +217,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- const OuterV2 = await patch(() => {
+ const OuterV2 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -350,7 +348,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Patch to change the color.
- const ParentV2 = await patch(() => {
+ const ParentV2 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -437,7 +435,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function Hello({color}) {
const [val, setVal] = React.useState(0);
return (
@@ -491,7 +489,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update of just the rendering function.
- await patch(() => {
+ patch(() => {
function Hello({color}) {
const [val, setVal] = React.useState(0);
return (
@@ -545,7 +543,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- const OuterV2 = await patch(() => {
+ const OuterV2 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -634,7 +632,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- const OuterV2 = await patch(() => {
+ const OuterV2 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -721,7 +719,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update of just the rendering function.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -770,7 +768,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- const OuterV2 = await patch(() => {
+ const OuterV2 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -882,7 +880,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- const AppV2 = await patch(() => {
+ const AppV2 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1005,7 +1003,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1035,7 +1033,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Test another reload.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1089,7 +1087,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1120,7 +1118,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Test another reload.
- await patch(() => {
+ patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1175,7 +1173,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1206,7 +1204,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Test another reload.
- await patch(() => {
+ patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1261,7 +1259,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('Loading');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1292,7 +1290,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Test another reload.
- await patch(() => {
+ patch(() => {
function renderHello() {
const [val, setVal] = React.useState(0);
return (
@@ -1360,7 +1358,7 @@ describe('ReactFresh', () => {
expect(primaryChild.style.display).toBe('');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function Hello({children}) {
const [val, setVal] = React.useState(0);
return (
@@ -1406,7 +1404,7 @@ describe('ReactFresh', () => {
expect(fallbackChild.style.display).toBe('');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function Hello({children}) {
const [val, setVal] = React.useState(0);
return (
@@ -1438,7 +1436,7 @@ describe('ReactFresh', () => {
expect(primaryChild.style.display).toBe('');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function Hello({children}) {
const [val, setVal] = React.useState(0);
return (
@@ -1494,7 +1492,7 @@ describe('ReactFresh', () => {
expect(appRenders).toBe(1);
// Perform a hot update for Hello only.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1554,7 +1552,7 @@ describe('ReactFresh', () => {
expect(container.textContent).toBe('XXXXXXXXXX');
helloRenders = 0;
- await patch(() => {
+ patch(() => {
function Hello({children}) {
helloRenders++;
return O{children}O
;
@@ -1621,7 +1619,7 @@ describe('ReactFresh', () => {
expect(el2.textContent).toBe('1');
// Perform a hot update for both inner components.
- await patch(() => {
+ patch(() => {
function Hello1() {
const [val, setVal] = React.useState(0);
return (
@@ -1683,7 +1681,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- const HelloV2 = await patch(() => {
+ const HelloV2 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1704,7 +1702,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Perform a hot update.
- const HelloV3 = await patch(() => {
+ const HelloV3 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1745,7 +1743,7 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('yellow');
// Verify we can patch again while preserving the signature.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1765,7 +1763,7 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('purple');
// Check removing the signature also causes a remount.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -1942,7 +1940,7 @@ describe('ReactFresh', () => {
});
async function runRemountingStressTest(tree) {
- await patch(() => {
+ patch(() => {
function Hello({children}) {
return ;
}
@@ -1963,7 +1961,7 @@ describe('ReactFresh', () => {
});
// Patch color without changing the signature.
- await patch(() => {
+ patch(() => {
function Hello({children}) {
return ;
}
@@ -1982,7 +1980,7 @@ describe('ReactFresh', () => {
});
// Patch color *and* change the signature.
- await patch(() => {
+ patch(() => {
function Hello({children}) {
return ;
}
@@ -2001,7 +1999,7 @@ describe('ReactFresh', () => {
});
// Now patch color but *don't* change the signature.
- await patch(() => {
+ patch(() => {
function Hello({children}) {
return ;
}
@@ -2231,7 +2229,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update that doesn't remount.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2252,7 +2250,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('red');
// Perform a hot update that remounts.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2281,7 +2279,7 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('yellow');
// Verify we can patch again while preserving the signature.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2301,7 +2299,7 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('purple');
// Check removing the signature also causes a remount.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -2358,7 +2356,7 @@ describe('ReactFresh', () => {
expect(useEffectWithEmptyArrayCalls).toBe(1); // useEffect didn't re-run
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
const tranformed = React.useMemo(() => val * 10, [val]);
@@ -2415,7 +2413,7 @@ describe('ReactFresh', () => {
expect(el.style.color).toBe('blue');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function Hello() {
const source = React.useMemo(() => ({value: 20}), []);
const [state, setState] = React.useState({value: null});
@@ -2470,8 +2468,8 @@ describe('ReactFresh', () => {
expect(el.firstChild).toBe(null); // Offscreen content not flushed yet.
// Perform a hot update.
- {
- const Hello = () => {
+ patch(() => {
+ function Hello() {
React.useLayoutEffect(() => {
Scheduler.log('Hello#layout');
});
@@ -2481,10 +2479,9 @@ describe('ReactFresh', () => {
{val}
);
- };
+ }
$RefreshReg$(Hello, 'Hello');
- ReactFreshRuntime.performReactRefresh();
- }
+ });
// It's still offscreen so we don't see anything.
expect(container.firstChild).toBe(el);
@@ -2510,8 +2507,8 @@ describe('ReactFresh', () => {
expect(el.firstChild.style.color).toBe('red');
// Hot reload while we're offscreen.
- {
- const Hello = () => {
+ patch(() => {
+ function Hello() {
React.useLayoutEffect(() => {
Scheduler.log('Hello#layout');
});
@@ -2521,10 +2518,9 @@ describe('ReactFresh', () => {
{val}
);
- };
+ }
$RefreshReg$(Hello, 'Hello');
- ReactFreshRuntime.performReactRefresh();
- }
+ });
// It's still offscreen so we don't see the updates.
expect(container.firstChild).toBe(el);
@@ -2579,7 +2575,7 @@ describe('ReactFresh', () => {
const secondP = firstP.nextSibling.nextSibling;
// Perform a hot update that fails.
- await patch(() => {
+ patch(() => {
function Hello() {
throw new Error('No');
}
@@ -2591,7 +2587,7 @@ describe('ReactFresh', () => {
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
// Perform a hot update that fixes the error.
- await patch(() => {
+ patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2605,7 +2601,7 @@ describe('ReactFresh', () => {
// Verify next hot reload doesn't remount anything.
const helloNode = container.firstChild.nextSibling;
- await patch(() => {
+ patch(() => {
function Hello() {
return Nice.
;
}
@@ -2657,7 +2653,7 @@ describe('ReactFresh', () => {
const secondP = firstP.nextSibling.nextSibling;
// Perform a hot update that fails.
- await patch(() => {
+ patch(() => {
function Hello() {
throw new Error('No');
}
@@ -2669,7 +2665,7 @@ describe('ReactFresh', () => {
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
// Perform a hot update that fixes the error.
- await patch(() => {
+ patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2683,7 +2679,7 @@ describe('ReactFresh', () => {
// Verify next hot reload doesn't remount anything.
const helloNode = container.firstChild.nextSibling;
- await patch(() => {
+ patch(() => {
function Hello() {
return Nice.
;
}
@@ -2739,7 +2735,7 @@ describe('ReactFresh', () => {
// Perform a hot update that fails.
let crash;
- await patch(() => {
+ patch(() => {
function Hello() {
const [x, setX] = React.useState('');
React.useEffect(() => {
@@ -2765,7 +2761,7 @@ describe('ReactFresh', () => {
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
// Perform a hot update that fixes the error.
- await patch(() => {
+ patch(() => {
function Hello() {
const [x] = React.useState('');
React.useEffect(() => {}, []); // Removes the bad effect code.
@@ -2782,7 +2778,7 @@ describe('ReactFresh', () => {
// Verify next hot reload doesn't remount anything.
const helloNode = container.firstChild.nextSibling;
- await patch(() => {
+ patch(() => {
function Hello() {
const [x] = React.useState('');
React.useEffect(() => {}, []);
@@ -2812,18 +2808,18 @@ describe('ReactFresh', () => {
expect(container.innerHTML).toBe('');
// A bad retry
- await expect(
+ expect(() => {
patch(() => {
function Hello() {
throw new Error('Not yet');
}
$RefreshReg$(Hello, 'Hello');
- }),
- ).rejects.toThrow('Not yet');
+ });
+ }).toThrow('Not yet');
expect(container.innerHTML).toBe('');
// Perform a hot update that fixes the error.
- await patch(() => {
+ patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2833,25 +2829,25 @@ describe('ReactFresh', () => {
expect(container.innerHTML).toBe('Fixed!
');
// Ensure we can keep failing and recovering later.
- await expect(
+ expect(() => {
patch(() => {
function Hello() {
throw new Error('No 2');
}
$RefreshReg$(Hello, 'Hello');
- }),
- ).rejects.toThrow('No 2');
+ });
+ }).toThrow('No 2');
expect(container.innerHTML).toBe('');
- await expect(
+ expect(() => {
patch(() => {
function Hello() {
throw new Error('Not yet 2');
}
$RefreshReg$(Hello, 'Hello');
- }),
- ).rejects.toThrow('Not yet 2');
+ });
+ }).toThrow('Not yet 2');
expect(container.innerHTML).toBe('');
- await patch(() => {
+ patch(() => {
function Hello() {
return Fixed 2!
;
}
@@ -2863,14 +2859,14 @@ describe('ReactFresh', () => {
await act(() => {
root.unmount();
});
- await patch(() => {
+ patch(() => {
function Hello() {
throw new Error('Ignored');
}
$RefreshReg$(Hello, 'Hello');
});
expect(container.innerHTML).toBe('');
- await patch(() => {
+ patch(() => {
function Hello() {
return Ignored
;
}
@@ -2900,7 +2896,7 @@ describe('ReactFresh', () => {
});
// Perform a hot update that fixes the error.
- await patch(() => {
+ patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2925,29 +2921,29 @@ describe('ReactFresh', () => {
// Perform a hot update that fails.
// This removes the root.
- await expect(
+ expect(() => {
patch(() => {
function Hello() {
throw new Error('No');
}
$RefreshReg$(Hello, 'Hello');
- }),
- ).rejects.toThrow('No');
+ });
+ }).toThrow('No');
expect(container.innerHTML).toBe('');
// A bad retry
- await expect(
+ expect(() => {
patch(() => {
function Hello() {
throw new Error('Not yet');
}
$RefreshReg$(Hello, 'Hello');
- }),
- ).rejects.toThrow('Not yet');
+ });
+ }).toThrow('Not yet');
expect(container.innerHTML).toBe('');
// Perform a hot update that fixes the error.
- await patch(() => {
+ patch(() => {
function Hello() {
return Fixed!
;
}
@@ -2958,7 +2954,7 @@ describe('ReactFresh', () => {
// Verify next hot reload doesn't remount anything.
const helloNode = container.firstChild;
- await patch(() => {
+ patch(() => {
function Hello() {
return Nice.
;
}
@@ -2968,18 +2964,18 @@ describe('ReactFresh', () => {
expect(helloNode.textContent).toBe('Nice.');
// Break again.
- await expect(
+ expect(() => {
patch(() => {
function Hello() {
throw new Error('Oops');
}
$RefreshReg$(Hello, 'Hello');
- }),
- ).rejects.toThrow('Oops');
+ });
+ }).toThrow('Oops');
expect(container.innerHTML).toBe('');
// Perform a hot update that fixes the error.
- await patch(() => {
+ patch(() => {
function Hello() {
return At last.
;
}
@@ -2993,7 +2989,7 @@ describe('ReactFresh', () => {
root.unmount();
});
expect(container.innerHTML).toBe('');
- await patch(() => {
+ patch(() => {
function Hello() {
return Never mind me!
;
}
@@ -3014,14 +3010,14 @@ describe('ReactFresh', () => {
expect(container.innerHTML).toBe('Hi
');
// Break again.
- await expect(
+ expect(() => {
patch(() => {
function Hello() {
throw new Error('Oops');
}
$RefreshReg$(Hello, 'Hello');
- }),
- ).rejects.toThrow('Oops');
+ });
+ }).toThrow('Oops');
expect(container.innerHTML).toBe('');
// Check we don't attempt to reverse an intentional unmount, even after an error.
@@ -3029,7 +3025,7 @@ describe('ReactFresh', () => {
root.unmount();
});
expect(container.innerHTML).toBe('');
- await patch(() => {
+ patch(() => {
function Hello() {
return Never mind me!
;
}
@@ -3143,7 +3139,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- const HelloV2 = await patch(() => {
+ const HelloV2 = patch(() => {
class Hello extends React.Component {
state = {count: 0};
handleClick = () => {
@@ -3180,7 +3176,7 @@ describe('ReactFresh', () => {
expect(newEl.style.color).toBe('red');
expect(newEl.textContent).toBe('1');
- const HelloV3 = await patch(() => {
+ const HelloV3 = patch(() => {
class Hello extends React.Component {
state = {count: 0};
handleClick = () => {
@@ -3239,7 +3235,7 @@ describe('ReactFresh', () => {
);
expect(testRef.current.getColor()).toBe('green');
- await patch(() => {
+ patch(() => {
class Hello extends React.Component {
getColor() {
return 'orange';
@@ -3252,7 +3248,7 @@ describe('ReactFresh', () => {
});
expect(testRef.current.getColor()).toBe('orange');
- await patch(() => {
+ patch(() => {
const Hello = React.forwardRef((props, ref) => {
React.useImperativeHandle(ref, () => ({
getColor() {
@@ -3265,7 +3261,7 @@ describe('ReactFresh', () => {
});
expect(testRef.current.getColor()).toBe('pink');
- await patch(() => {
+ patch(() => {
const Hello = React.forwardRef((props, ref) => {
React.useImperativeHandle(ref, () => ({
getColor() {
@@ -3278,7 +3274,7 @@ describe('ReactFresh', () => {
});
expect(testRef.current.getColor()).toBe('yellow');
- await patch(() => {
+ patch(() => {
const Hello = React.forwardRef((props, ref) => {
React.useImperativeHandle(ref, () => ({
getColor() {
@@ -3318,7 +3314,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update that turns it into a class.
- const HelloV2 = await patch(() => {
+ const HelloV2 = patch(() => {
class Hello extends React.Component {
state = {count: 0};
handleClick = () => {
@@ -3356,7 +3352,7 @@ describe('ReactFresh', () => {
expect(newEl.textContent).toBe('1');
// Now convert it back to a function.
- const HelloV3 = await patch(() => {
+ const HelloV3 = patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -3387,7 +3383,7 @@ describe('ReactFresh', () => {
expect(finalEl.textContent).toBe('1');
// Now that it's a function, verify edits keep state.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
@@ -3876,7 +3872,7 @@ describe('ReactFresh', () => {
expect(el.textContent).toBe('1');
// Perform a hot update.
- await patch(() => {
+ patch(() => {
function Hello() {
const [val, setVal] = React.useState(0);
return (
From caac07853f3c906d4a903e685c3efc9b67c92ca7 Mon Sep 17 00:00:00 2001
From: Sebastian Silbermann
Date: Fri, 2 Feb 2024 19:48:39 +0100
Subject: [PATCH 5/6] Update test name to reflect new behavior
---
packages/react-refresh/src/__tests__/ReactFresh-test.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/react-refresh/src/__tests__/ReactFresh-test.js b/packages/react-refresh/src/__tests__/ReactFresh-test.js
index 50e72cae5ae3c..b3464765c5529 100644
--- a/packages/react-refresh/src/__tests__/ReactFresh-test.js
+++ b/packages/react-refresh/src/__tests__/ReactFresh-test.js
@@ -1308,7 +1308,7 @@ describe('ReactFresh', () => {
}
});
- it('can patch both trees while suspense is displaying the fallback', async () => {
+ it('only patches the fallback tree while suspended', async () => {
if (__DEV__) {
const AppV1 = await render(
() => {
From 6aea7f81fe7ce8590f348bc1d3b085ce42590b08 Mon Sep 17 00:00:00 2001
From: Sebastian Silbermann
Date: Fri, 2 Feb 2024 20:04:45 +0100
Subject: [PATCH 6/6] Increase timeout for slow tests
---
packages/react-refresh/src/__tests__/ReactFresh-test.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/react-refresh/src/__tests__/ReactFresh-test.js b/packages/react-refresh/src/__tests__/ReactFresh-test.js
index b3464765c5529..38b74563c30a7 100644
--- a/packages/react-refresh/src/__tests__/ReactFresh-test.js
+++ b/packages/react-refresh/src/__tests__/ReactFresh-test.js
@@ -1937,7 +1937,7 @@ describe('ReactFresh', () => {
}
}
}
- });
+ }, 10000);
async function runRemountingStressTest(tree) {
patch(() => {