Skip to content

Commit 5bb4ad7

Browse files
authored
Added ErrorBoundary tests for useEffect and useLayoutEffect (#14401)
1 parent 98eb5ae commit 5bb4ad7

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

packages/react-dom/src/__tests__/ReactErrorBoundaries-test.internal.js

+87
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,20 @@ describe('ReactErrorBoundaries', () => {
2828
let BrokenComponentWillMountErrorBoundary;
2929
let BrokenComponentDidMountErrorBoundary;
3030
let BrokenRender;
31+
let BrokenUseEffect;
32+
let BrokenUseLayoutEffect;
3133
let ErrorBoundary;
3234
let ErrorMessage;
3335
let NoopErrorBoundary;
3436
let RetryErrorBoundary;
3537
let Normal;
3638

3739
beforeEach(() => {
40+
jest.useFakeTimers();
3841
jest.resetModules();
3942
PropTypes = require('prop-types');
4043
ReactFeatureFlags = require('shared/ReactFeatureFlags');
44+
ReactFeatureFlags.enableHooks = true;
4145
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
4246
ReactDOM = require('react-dom');
4347
React = require('react');
@@ -386,6 +390,28 @@ describe('ReactErrorBoundaries', () => {
386390
}
387391
};
388392

393+
BrokenUseEffect = props => {
394+
log.push('BrokenUseEffect render');
395+
396+
React.useEffect(() => {
397+
log.push('BrokenUseEffect useEffect [!]');
398+
throw new Error('Hello');
399+
});
400+
401+
return props.children;
402+
};
403+
404+
BrokenUseLayoutEffect = props => {
405+
log.push('BrokenUseLayoutEffect render');
406+
407+
React.useLayoutEffect(() => {
408+
log.push('BrokenUseLayoutEffect useLayoutEffect [!]');
409+
throw new Error('Hello');
410+
});
411+
412+
return props.children;
413+
};
414+
389415
NoopErrorBoundary = class extends React.Component {
390416
constructor(props) {
391417
super(props);
@@ -1795,6 +1821,67 @@ describe('ReactErrorBoundaries', () => {
17951821
expect(log).toEqual(['ErrorBoundary componentWillUnmount']);
17961822
});
17971823

1824+
it('catches errors in useEffect', () => {
1825+
const container = document.createElement('div');
1826+
ReactDOM.render(
1827+
<ErrorBoundary>
1828+
<BrokenUseEffect>Initial value</BrokenUseEffect>
1829+
</ErrorBoundary>,
1830+
container,
1831+
);
1832+
expect(log).toEqual([
1833+
'ErrorBoundary constructor',
1834+
'ErrorBoundary componentWillMount',
1835+
'ErrorBoundary render success',
1836+
'BrokenUseEffect render',
1837+
'ErrorBoundary componentDidMount',
1838+
]);
1839+
1840+
expect(container.firstChild.textContent).toBe('Initial value');
1841+
log.length = 0;
1842+
1843+
jest.runAllTimers();
1844+
1845+
// Flush passive effects and handle the error
1846+
expect(log).toEqual([
1847+
'BrokenUseEffect useEffect [!]',
1848+
// Handle the error
1849+
'ErrorBoundary static getDerivedStateFromError',
1850+
'ErrorBoundary componentWillUpdate',
1851+
'ErrorBoundary render error',
1852+
'ErrorBoundary componentDidUpdate',
1853+
]);
1854+
1855+
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
1856+
});
1857+
1858+
it('catches errors in useLayoutEffect', () => {
1859+
const container = document.createElement('div');
1860+
ReactDOM.render(
1861+
<ErrorBoundary>
1862+
<BrokenUseLayoutEffect>Initial value</BrokenUseLayoutEffect>
1863+
</ErrorBoundary>,
1864+
container,
1865+
);
1866+
expect(log).toEqual([
1867+
'ErrorBoundary constructor',
1868+
'ErrorBoundary componentWillMount',
1869+
'ErrorBoundary render success',
1870+
'BrokenUseLayoutEffect render',
1871+
'BrokenUseLayoutEffect useLayoutEffect [!]',
1872+
// Fiber proceeds with the hooks
1873+
'ErrorBoundary componentDidMount',
1874+
// The error propagates to the higher boundary
1875+
'ErrorBoundary static getDerivedStateFromError',
1876+
// Fiber retries from the root
1877+
'ErrorBoundary componentWillUpdate',
1878+
'ErrorBoundary render error',
1879+
'ErrorBoundary componentDidUpdate',
1880+
]);
1881+
1882+
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
1883+
});
1884+
17981885
it('propagates errors inside boundary during componentDidMount', () => {
17991886
const container = document.createElement('div');
18001887
ReactDOM.render(

0 commit comments

Comments
 (0)