Skip to content

Commit

Permalink
Clean up legacy render from ReactTestUtilsAct-test
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack Pope committed Jan 25, 2024
1 parent a41ebfc commit 6e41109
Showing 1 changed file with 77 additions and 135 deletions.
212 changes: 77 additions & 135 deletions packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*/

let React;
let ReactDOM;
let ReactDOMClient;
let ReactTestUtils;
let Scheduler;
Expand All @@ -33,91 +32,57 @@ describe('ReactTestUtils.act()', () => {
jest.restoreAllMocks();
});

// first we run all the tests with concurrent mode
if (__EXPERIMENTAL__) {
let concurrentRoot = null;
const renderConcurrent = (el, dom) => {
concurrentRoot = ReactDOMClient.createRoot(dom);
if (__DEV__) {
act(() => concurrentRoot.render(el));
} else {
concurrentRoot.render(el);
}
};

const unmountConcurrent = _dom => {
if (__DEV__) {
act(() => {
if (concurrentRoot !== null) {
concurrentRoot.unmount();
concurrentRoot = null;
}
});
} else {
if (concurrentRoot !== null) {
concurrentRoot.unmount();
concurrentRoot = null;
let root = null;
const renderConcurrent = (el, dom) => {
root = ReactDOMClient.createRoot(dom);
if (__DEV__) {
act(() => root.render(el));
} else {
root.render(el);
}
};

const unmountConcurrent = _dom => {
if (__DEV__) {
act(() => {
if (root !== null) {
root.unmount();
root = null;
}
});
} else {
if (root !== null) {
root.unmount();
root = null;
}
};

const rerenderConcurrent = el => {
act(() => concurrentRoot.render(el));
};

runActTests(
'concurrent mode',
renderConcurrent,
unmountConcurrent,
rerenderConcurrent,
);
}

// and then in legacy mode

let legacyDom = null;
function renderLegacy(el, dom) {
legacyDom = dom;
ReactDOM.render(el, dom);
}

function unmountLegacy(dom) {
legacyDom = null;
ReactDOM.unmountComponentAtNode(dom);
}
}
};

function rerenderLegacy(el) {
ReactDOM.render(el, legacyDom);
}
const rerenderConcurrent = el => {
act(() => root.render(el));
};

runActTests('legacy mode', renderLegacy, unmountLegacy, rerenderLegacy);
runActTests(renderConcurrent, unmountConcurrent, rerenderConcurrent);

describe('unacted effects', () => {
function App() {
React.useEffect(() => {}, []);
return null;
}

it('does not warn in legacy mode', () => {
expect(() => {
ReactDOM.render(<App />, document.createElement('div'));
}).toErrorDev([]);
});

// @gate __DEV__
it('does not warn in concurrent mode', () => {
it('does not warn', () => {
const root = ReactDOMClient.createRoot(document.createElement('div'));
act(() => root.render(<App />));
});
});
});

function runActTests(label, render, unmount, rerender) {
describe(label, () => {
function runActTests(render, unmount, rerender) {
describe('concurrent render', () => {
beforeEach(() => {
jest.resetModules();
React = require('react');
ReactDOM = require('react-dom');
ReactDOMClient = require('react-dom/client');
ReactTestUtils = require('react-dom/test-utils');
Scheduler = require('scheduler');
Expand Down Expand Up @@ -698,89 +663,66 @@ function runActTests(label, render, unmount, rerender) {
});

describe('suspense', () => {
if (__DEV__ && __EXPERIMENTAL__) {
// todo - remove __DEV__ check once we start using testing builds
it('triggers fallbacks if available', async () => {
let resolved = false;
let resolve;
const promise = new Promise(_resolve => {
resolve = _resolve;
});

// @gate __DEV__
it('triggers fallbacks if available', async () => {
if (label !== 'legacy mode') {
// FIXME: Support for Concurrent Root intentionally removed
// from the public version of `act`. It will be added back in
// a future major version, before the Concurrent Root is released.
// Consider skipping all non-Legacy tests in this suite until then.
return;
function Suspends() {
if (resolved) {
return 'was suspended';
}
throw promise;
}

let resolved = false;
let resolve;
const promise = new Promise(_resolve => {
resolve = _resolve;
});
function App(props) {
return (
<React.Suspense
fallback={<span data-test-id="spinner">loading...</span>}>
{props.suspend ? <Suspends /> : 'content'}
</React.Suspense>
);
}

function Suspends() {
if (resolved) {
return 'was suspended';
}
throw promise;
}
// render something so there's content
act(() => {
render(<App suspend={false} />, container);
});

function App(props) {
return (
<React.Suspense
fallback={<span data-test-id="spinner">loading...</span>}>
{props.suspend ? <Suspends /> : 'content'}
</React.Suspense>
);
}
// trigger a suspendy update
act(() => {
rerender(<App suspend={true} />);
});
expect(document.querySelector('[data-test-id=spinner]')).not.toBeNull();

// render something so there's content
act(() => {
render(<App suspend={false} />, container);
});
// now render regular content again
act(() => {
rerender(<App suspend={false} />);
});
expect(document.querySelector('[data-test-id=spinner]')).toBeNull();

// trigger a suspendy update
// trigger a suspendy update with a delay
React.startTransition(() => {
act(() => {
rerender(<App suspend={true} />);
});
expect(
document.querySelector('[data-test-id=spinner]'),
).not.toBeNull();

// now render regular content again
act(() => {
rerender(<App suspend={false} />);
});
expect(document.querySelector('[data-test-id=spinner]')).toBeNull();

// trigger a suspendy update with a delay
React.startTransition(() => {
act(() => {
rerender(<App suspend={true} />);
});
});

if (label === 'concurrent mode') {
// In Concurrent Mode, refresh transitions delay indefinitely.
expect(document.querySelector('[data-test-id=spinner]')).toBeNull();
} else {
// In Legacy Mode, all fallbacks are forced to display,
// even during a refresh transition.
expect(
document.querySelector('[data-test-id=spinner]'),
).not.toBeNull();
}
});

// resolve the promise
await act(async () => {
resolved = true;
resolve();
});
// In Concurrent Mode, refresh transitions delay indefinitely.
expect(document.querySelector('[data-test-id=spinner]')).toBeNull();

// spinner gone, content showing
expect(document.querySelector('[data-test-id=spinner]')).toBeNull();
expect(container.textContent).toBe('was suspended');
// resolve the promise
await act(async () => {
resolved = true;
resolve();
});
}

// spinner gone, content showing
expect(document.querySelector('[data-test-id=spinner]')).toBeNull();
expect(container.textContent).toBe('was suspended');
});
});
describe('throw in prod mode', () => {
// @gate !__DEV__
Expand Down

0 comments on commit 6e41109

Please sign in to comment.