main
js 98 lines 2.45 KB
Raw
1 let React;
2 let ReactNoop;
3 let Scheduler;
4 let act;
5 let Activity;
6 let useState;
7 let assertLog;
8
9 describe('Activity error handling', () => {
10 beforeEach(() => {
11 jest.resetModules();
12
13 React = require('react');
14 ReactNoop = require('react-noop-renderer');
15 Scheduler = require('scheduler');
16 act = require('internal-test-utils').act;
17 Activity = React.Activity;
18 useState = React.useState;
19
20 const InternalTestUtils = require('internal-test-utils');
21 assertLog = InternalTestUtils.assertLog;
22 });
23
24 function Text({text}) {
25 Scheduler.log(text);
26 return text;
27 }
28
29 it(
30 'errors inside a hidden Activity do not escape in the visible part ' +
31 'of the UI',
32 async () => {
33 class ErrorBoundary extends React.Component {
34 state = {error: null};
35 static getDerivedStateFromError(error) {
36 return {error};
37 }
38 render() {
39 if (this.state.error) {
40 return (
41 <Text text={`Caught an error: ${this.state.error.message}`} />
42 );
43 }
44 return this.props.children;
45 }
46 }
47
48 function Throws() {
49 throw new Error('Oops!');
50 }
51
52 let setShowMore;
53 function App({content, more}) {
54 const [showMore, _setShowMore] = useState(false);
55 setShowMore = _setShowMore;
56 return (
57 <>
58 <div>{content}</div>
59 <div>
60 <ErrorBoundary>
61 <Activity mode={showMore ? 'visible' : 'hidden'}>
62 {more}
63 </Activity>
64 </ErrorBoundary>
65 </div>
66 </>
67 );
68 }
69
70 await act(() =>
71 ReactNoop.render(
72 <App content={<Text text="Visible" />} more={<Throws />} />,
73 ),
74 );
75
76 // Initial render. An error is thrown when prerendering the hidden
77 // Activity boundary, but since it's hidden, the UI doesn't observe it.
78 assertLog(['Visible']);
79 expect(ReactNoop).toMatchRenderedOutput(
80 <>
81 <div>Visible</div>
82 <div />
83 </>,
84 );
85
86 // Once the Activity boundary is revealed, the error is thrown and
87 // captured by the outer ErrorBoundary.
88 await act(() => setShowMore(true));
89 assertLog(['Caught an error: Oops!', 'Caught an error: Oops!']);
90 expect(ReactNoop).toMatchRenderedOutput(
91 <>
92 <div>Visible</div>
93 <div>Caught an error: Oops!</div>
94 </>,
95 );
96 },
97 );
98 });