@samitouri / QOS-React-2 / commits / 3c7d52c3d6

Give unresolved lazy() a name in component stack (#16104)

* Give unresolved lazy() a name in component stack * Normalize stack in tests Co-authored-by: Sebastian Markbage <sema@fb.com>

Moti Zilberman committed May 2, 2020 at 00:41 UTC 3c7d52c3d6d316d09d5c2479c6851acecccc6325
1 file changed +90
packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js
+90
@@ -6,6 +6,15 @@ let ReactFeatureFlags;
6 let Suspense;
7 let lazy;
8
9 +function normalizeCodeLocInfo(str) {
10 + return (
11 + str &&
12 + str.replace(/\n +(?:at|in) ([\S]+)[^\n]*/g, function(m, name) {
13 + return '\n in ' + name + ' (at **)';
14 + })
15 + );
16 +}
17 +
18 describe('ReactLazy', () => {
19 beforeEach(() => {
20 jest.resetModules();
@@ -1183,4 +1192,85 @@ describe('ReactLazy', () => {
1192 expect(Scheduler).toFlushAndYield([]);
1193 }).toErrorDev('Function components cannot be given refs');
1194 });
1195 +
1196 + it('should error with a component stack naming the resolved component', async () => {
1197 + let componentStackMessage;
1198 +
1199 + const LazyText = lazy(() =>
1200 + fakeImport(function ResolvedText() {
1201 + throw new Error('oh no');
1202 + }),
1203 + );
1204 +
1205 + class ErrorBoundary extends React.Component {
1206 + state = {error: null};
1207 +
1208 + componentDidCatch(error, errMessage) {
1209 + componentStackMessage = normalizeCodeLocInfo(errMessage.componentStack);
1210 + this.setState({
1211 + error,
1212 + });
1213 + }
1214 +
1215 + render() {
1216 + return this.state.error ? null : this.props.children;
1217 + }
1218 + }
1219 +
1220 + ReactTestRenderer.create(
1221 + <ErrorBoundary>
1222 + <Suspense fallback={<Text text="Loading..." />}>
1223 + <LazyText text="Hi" />
1224 + </Suspense>
1225 + </ErrorBoundary>,
1226 + {unstable_isConcurrent: true},
1227 + );
1228 +
1229 + expect(Scheduler).toFlushAndYield(['Loading...']);
1230 +
1231 + try {
1232 + await Promise.resolve();
1233 + } catch (e) {}
1234 +
1235 + expect(Scheduler).toFlushAndYield([]);
1236 +
1237 + expect(componentStackMessage).toContain('in ResolvedText');
1238 + });
1239 +
1240 + it('should error with a component stack containing Lazy if unresolved', () => {
1241 + let componentStackMessage;
1242 +
1243 + const LazyText = lazy(() => ({
1244 + then(resolve, reject) {
1245 + reject(new Error('oh no'));
1246 + },
1247 + }));
1248 +
1249 + class ErrorBoundary extends React.Component {
1250 + state = {error: null};
1251 +
1252 + componentDidCatch(error, errMessage) {
1253 + componentStackMessage = normalizeCodeLocInfo(errMessage.componentStack);
1254 + this.setState({
1255 + error,
1256 + });
1257 + }
1258 +
1259 + render() {
1260 + return this.state.error ? null : this.props.children;
1261 + }
1262 + }
1263 +
1264 + ReactTestRenderer.create(
1265 + <ErrorBoundary>
1266 + <Suspense fallback={<Text text="Loading..." />}>
1267 + <LazyText text="Hi" />
1268 + </Suspense>
1269 + </ErrorBoundary>,
1270 + );
1271 +
1272 + expect(Scheduler).toHaveYielded([]);
1273 +
1274 + expect(componentStackMessage).toContain('in Lazy');
1275 + });
1276 });