From 3e88af428cdb011c450d80e9b70467d08417fe00 Mon Sep 17 00:00:00 2001 From: OJ Kwon <1210596+kwonoj@users.noreply.github.com> Date: Fri, 13 Jan 2023 12:02:44 -0800 Subject: [PATCH] test(snapshot): allow snapshot test not invalidate with --turbo (#43545) --- .../ReactRefreshLogBox-builtins.test.ts | 169 +- .../acceptance-app/ReactRefreshLogBox.test.ts | 1444 +++++++++-------- .../ReactRefreshLogBox-builtins.test.ts.snap | 8 +- .../ReactRefreshLogBox.test.ts.snap | 48 +- .../ReactRefreshLogBox-app-doc.test.ts | 193 +-- .../ReactRefreshLogBox-builtins.test.ts | 167 +- .../acceptance/ReactRefreshLogBox.test.ts | 1086 ++++++------- .../ReactRefreshLogBox-app-doc.test.ts.snap | 4 +- .../ReactRefreshLogBox-builtins.test.ts.snap | 10 +- .../ReactRefreshLogBox.test.ts.snap | 44 +- test/lib/next-test-utils.js | 17 + 11 files changed, 1614 insertions(+), 1576 deletions(-) diff --git a/test/development/acceptance-app/ReactRefreshLogBox-builtins.test.ts b/test/development/acceptance-app/ReactRefreshLogBox-builtins.test.ts index 7d3a39e2a7797..f2f952c682560 100644 --- a/test/development/acceptance-app/ReactRefreshLogBox-builtins.test.ts +++ b/test/development/acceptance-app/ReactRefreshLogBox-builtins.test.ts @@ -2,69 +2,73 @@ import { sandbox } from './helpers' import { createNext, FileRef } from 'e2e-utils' import { NextInstance } from 'test/lib/next-modes/base' import path from 'path' +import { getSnapshotTestDescribe } from 'next-test-utils' // TODO-APP: Investigate snapshot mismatch -describe('ReactRefreshLogBox app', () => { - let next: NextInstance - - beforeAll(async () => { - next = await createNext({ - files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')), - dependencies: { - react: 'latest', - 'react-dom': 'latest', - }, - skipStart: true, +for (const variant of ['default', 'turbo']) { + getSnapshotTestDescribe(variant)(`ReactRefreshLogBox app ${variant}`, () => { + let next: NextInstance + + beforeAll(async () => { + next = await createNext({ + files: new FileRef( + path.join(__dirname, 'fixtures', 'default-template') + ), + dependencies: { + react: 'latest', + 'react-dom': 'latest', + }, + skipStart: true, + }) }) - }) - afterAll(() => next.destroy()) - - // Module trace is only available with webpack 5 - test('Node.js builtins', async () => { - const { session, cleanup } = await sandbox( - next, - new Map([ - [ - 'node_modules/my-package/index.js', - ` + afterAll(() => next.destroy()) + + // Module trace is only available with webpack 5 + test('Node.js builtins', async () => { + const { session, cleanup } = await sandbox( + next, + new Map([ + [ + 'node_modules/my-package/index.js', + ` const dns = require('dns') module.exports = dns `, - ], - [ - 'node_modules/my-package/package.json', - ` + ], + [ + 'node_modules/my-package/package.json', + ` { "name": "my-package", "version": "0.0.1" } `, - ], - ]) - ) + ], + ]) + ) - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` import pkg from 'my-package' export default function Hello() { return (pkg ?
index page
} `, - ], - ]) - ) - expect(await session.hasRedbox(true)).toBe(true) + ], + ]) + ) + expect(await session.hasRedbox(true)).toBe(true) - const source = await session.getRedboxSource() - expect(source).toMatchSnapshot() + const source = await session.getRedboxSource() + expect(source).toMatchSnapshot() - await session.patch( - 'app/page.js', - `'use client' + await session.patch( + 'app/page.js', + `'use client' export default function Page(props) { returnindex page
} ` - ) - expect(await session.hasRedbox(false)).toBe(false) - expect( - await session.evaluate(() => document.documentElement.innerHTML) - ).toContain('index page') + ) + expect(await session.hasRedbox(false)).toBe(false) + expect( + await session.evaluate(() => document.documentElement.innerHTML) + ).toContain('index page') - await cleanup() + await cleanup() + }) }) -}) +} diff --git a/test/development/acceptance-app/ReactRefreshLogBox.test.ts b/test/development/acceptance-app/ReactRefreshLogBox.test.ts index dddf003d1bc39..20f7262256af9 100644 --- a/test/development/acceptance-app/ReactRefreshLogBox.test.ts +++ b/test/development/acceptance-app/ReactRefreshLogBox.test.ts @@ -2,30 +2,33 @@ import { sandbox } from './helpers' import { createNext, FileRef } from 'e2e-utils' import { NextInstance } from 'test/lib/next-modes/base' -import { check } from 'next-test-utils' +import { check, getSnapshotTestDescribe } from 'next-test-utils' import path from 'path' -describe('ReactRefreshLogBox app', () => { - let next: NextInstance - - beforeAll(async () => { - next = await createNext({ - files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')), - dependencies: { - react: 'latest', - 'react-dom': 'latest', - }, - skipStart: true, +for (const variant of ['default', 'turbo']) { + getSnapshotTestDescribe(variant)(`ReactRefreshLogBox app ${variant}`, () => { + let next: NextInstance + + beforeAll(async () => { + next = await createNext({ + files: new FileRef( + path.join(__dirname, 'fixtures', 'default-template') + ), + dependencies: { + react: 'latest', + 'react-dom': 'latest', + }, + skipStart: true, + }) }) - }) - afterAll(() => next.destroy()) + afterAll(() => next.destroy()) - test('should strip whitespace correctly with newline', async () => { - const { session, cleanup } = await sandbox(next) + test('should strip whitespace correctly with newline', async () => { + const { session, cleanup } = await sandbox(next) - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` export default function Page() { return ( <> @@ -41,21 +44,21 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) - await session.evaluate(() => document.querySelector('a').click()) + ) + await session.evaluate(() => document.querySelector('a').click()) - await session.waitForAndOpenRuntimeError() - expect(await session.getRedboxSource()).toMatchSnapshot() + await session.waitForAndOpenRuntimeError() + expect(await session.getRedboxSource()).toMatchSnapshot() - await cleanup() - }) + await cleanup() + }) - test('logbox: can recover from a syntax error without losing state', async () => { - const { session, cleanup } = await sandbox(next) + test('logbox: can recover from a syntax error without losing state', async () => { + const { session, cleanup } = await sandbox(next) - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` import { useCallback, useState } from 'react' export default function Index() { @@ -69,21 +72,21 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) - await session.evaluate(() => document.querySelector('button').click()) - expect( - await session.evaluate(() => document.querySelector('p').textContent) - ).toBe('1') + await session.evaluate(() => document.querySelector('button').click()) + expect( + await session.evaluate(() => document.querySelector('p').textContent) + ).toBe('1') - await session.patch('index.js', `export default () =>Hello
; } ` - ) + ) - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` import Child from './child' export default function Index() { @@ -208,135 +211,139 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) - expect( - await session.evaluate(() => document.querySelector('p').textContent) - ).toBe('Hello') + expect( + await session.evaluate(() => document.querySelector('p').textContent) + ).toBe('Hello') - await session.patch( - 'child.js', - ` + await session.patch( + 'child.js', + ` // hello export default function Child() { throw new Error('oops') } ` - ) + ) - expect(await session.hasRedbox(true)).toBe(true) - expect(await session.getRedboxSource()).toMatchSnapshot() + expect(await session.hasRedbox(true)).toBe(true) + expect(await session.getRedboxSource()).toMatchSnapshot() - // TODO-APP: re-enable when error recovery doesn't reload the page. - /* const didNotReload = */ await session.patch( - 'child.js', - ` + // TODO-APP: re-enable when error recovery doesn't reload the page. + /* const didNotReload = */ await session.patch( + 'child.js', + ` export default function Child() { returnHello
; } ` - ) + ) - // TODO-APP: re-enable when error recovery doesn't reload the page. - // expect(didNotReload).toBe(true) - expect(await session.hasRedbox()).toBe(false) - expect( - await session.evaluate(() => document.querySelector('p').textContent) - ).toBe('Hello') + // TODO-APP: re-enable when error recovery doesn't reload the page. + // expect(didNotReload).toBe(true) + expect(await session.hasRedbox()).toBe(false) + expect( + await session.evaluate(() => document.querySelector('p').textContent) + ).toBe('Hello') - await cleanup() - }) + await cleanup() + }) - test('server component can recover from syntax error', async () => { - const { session, browser, cleanup } = await sandbox( - next, - new Map([ - [ - 'app/page.js', - ` + test('server component can recover from syntax error', async () => { + const { session, browser, cleanup } = await sandbox( + next, + new Map([ + [ + 'app/page.js', + ` export default function Page() { returnHello world
} `, - ], - ]) - ) + ], + ]) + ) - // Add syntax error - await session.patch( - 'app/page.js', - ` + // Add syntax error + await session.patch( + 'app/page.js', + ` export default function Page() { returnHello world
` - ) - expect(await session.hasRedbox(true)).toBe(true) + ) + expect(await session.hasRedbox(true)).toBe(true) - // Fix syntax error - await session.patch( - 'app/page.js', - ` + // Fix syntax error + await session.patch( + 'app/page.js', + ` export default function Page() { returnHello world 2
} ` - ) + ) - expect(await browser.waitForElementByCss('p').text()).toBe('Hello world 2') + expect(await browser.waitForElementByCss('p').text()).toBe( + 'Hello world 2' + ) - await cleanup() - }) + await cleanup() + }) - test('server component can recover from component error', async () => { - const { session, browser, cleanup } = await sandbox( - next, - new Map([ - [ - 'app/page.js', - ` + test('server component can recover from component error', async () => { + const { session, browser, cleanup } = await sandbox( + next, + new Map([ + [ + 'app/page.js', + ` export default function Page() { returnHello world
} `, - ], - ]) - ) + ], + ]) + ) - // Add component error - await session.patch( - 'app/page.js', - ` + // Add component error + await session.patch( + 'app/page.js', + ` export default function Page() { throw new Error("boom") returnHello world
} ` - ) - expect(await session.hasRedbox(true)).toBe(true) + ) + expect(await session.hasRedbox(true)).toBe(true) - // Fix component error - await session.patch( - 'app/page.js', - ` + // Fix component error + await session.patch( + 'app/page.js', + ` export default function Page() { returnHello world 2
} ` - ) + ) - expect(await browser.waitForElementByCss('p').text()).toBe('Hello world 2') + expect(await browser.waitForElementByCss('p').text()).toBe( + 'Hello world 2' + ) - await cleanup() - }) + await cleanup() + }) - // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554137262 - test('render error not shown right after syntax error', async () => { - const { session, cleanup } = await sandbox(next) + // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554137262 + test('render error not shown right after syntax error', async () => { + const { session, cleanup } = await sandbox(next) - // Starting here: - await session.patch( - 'index.js', - ` + // Starting here: + await session.patch( + 'index.js', + ` import * as React from 'react'; class ClassDefault extends React.Component { render() { @@ -346,16 +353,16 @@ describe('ReactRefreshLogBox app', () => { export default ClassDefault; ` - ) + ) - expect( - await session.evaluate(() => document.querySelector('h1').textContent) - ).toBe('Default Export') + expect( + await session.evaluate(() => document.querySelector('h1').textContent) + ).toBe('Default Export') - // Break it with a syntax error: - await session.patch( - 'index.js', - ` + // Break it with a syntax error: + await session.patch( + 'index.js', + ` import * as React from 'react'; class ClassDefault extends React.Component { @@ -366,13 +373,13 @@ describe('ReactRefreshLogBox app', () => { export default ClassDefault; ` - ) - expect(await session.hasRedbox(true)).toBe(true) + ) + expect(await session.hasRedbox(true)).toBe(true) - // Now change the code to introduce a runtime error without fixing the syntax error: - await session.patch( - 'index.js', - ` + // Now change the code to introduce a runtime error without fixing the syntax error: + await session.patch( + 'index.js', + ` import * as React from 'react'; class ClassDefault extends React.Component { @@ -384,13 +391,13 @@ describe('ReactRefreshLogBox app', () => { export default ClassDefault; ` - ) - expect(await session.hasRedbox(true)).toBe(true) + ) + expect(await session.hasRedbox(true)).toBe(true) - // Now fix the syntax error: - await session.patch( - 'index.js', - ` + // Now fix the syntax error: + await session.patch( + 'index.js', + ` import * as React from 'react'; class ClassDefault extends React.Component { @@ -402,28 +409,28 @@ describe('ReactRefreshLogBox app', () => { export default ClassDefault; ` - ) - expect(await session.hasRedbox(true)).toBe(true) + ) + expect(await session.hasRedbox(true)).toBe(true) - await check(async () => { - const source = await session.getRedboxSource() - return source?.length > 1 ? 'success' : source - }, 'success') + await check(async () => { + const source = await session.getRedboxSource() + return source?.length > 1 ? 'success' : source + }, 'success') - expect(await session.getRedboxSource()).toMatchSnapshot() + expect(await session.getRedboxSource()).toMatchSnapshot() - await cleanup() - }) + await cleanup() + }) - // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554137807 - test('module init error not shown', async () => { - // Start here: - const { session, cleanup } = await sandbox(next) + // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554137807 + test('module init error not shown', async () => { + // Start here: + const { session, cleanup } = await sandbox(next) - // We start here. - await session.patch( - 'index.js', - ` + // We start here. + await session.patch( + 'index.js', + ` import * as React from 'react'; class ClassDefault extends React.Component { render() { @@ -432,16 +439,16 @@ describe('ReactRefreshLogBox app', () => { } export default ClassDefault; ` - ) + ) - expect( - await session.evaluate(() => document.querySelector('h1').textContent) - ).toBe('Default Export') + expect( + await session.evaluate(() => document.querySelector('h1').textContent) + ).toBe('Default Export') - // Add a throw in module init phase: - await session.patch( - 'index.js', - ` + // Add a throw in module init phase: + await session.patch( + 'index.js', + ` // top offset for snapshot import * as React from 'react'; throw new Error('no') @@ -452,26 +459,26 @@ describe('ReactRefreshLogBox app', () => { } export default ClassDefault; ` - ) + ) - expect(await session.hasRedbox(true)).toBe(true) - if (process.platform === 'win32') { - expect(await session.getRedboxSource()).toMatchSnapshot() - } else { - expect(await session.getRedboxSource()).toMatchSnapshot() - } + expect(await session.hasRedbox(true)).toBe(true) + if (process.platform === 'win32') { + expect(await session.getRedboxSource()).toMatchSnapshot() + } else { + expect(await session.getRedboxSource()).toMatchSnapshot() + } - await cleanup() - }) + await cleanup() + }) - // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554144016 - test('stuck error', async () => { - const { session, cleanup } = await sandbox(next) + // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554144016 + test('stuck error', async () => { + const { session, cleanup } = await sandbox(next) - // We start here. - await session.patch( - 'index.js', - ` + // We start here. + await session.patch( + 'index.js', + ` import * as React from 'react'; function FunctionDefault() { @@ -480,23 +487,23 @@ describe('ReactRefreshLogBox app', () => { export default FunctionDefault; ` - ) + ) - // We add a new file. Let's call it Foo.js. - await session.write( - 'Foo.js', - ` + // We add a new file. Let's call it Foo.js. + await session.write( + 'Foo.js', + ` // intentionally skips export export default function Foo() { return React.createElement('h1', null, 'Foo'); } ` - ) + ) - // We edit our first file to use it. - await session.patch( - 'index.js', - ` + // We edit our first file to use it. + await session.patch( + 'index.js', + ` import * as React from 'react'; import Foo from './Foo'; function FunctionDefault() { @@ -504,48 +511,48 @@ describe('ReactRefreshLogBox app', () => { } export default FunctionDefault; ` - ) + ) - // We get an error because Foo didn't import React. Fair. - expect(await session.hasRedbox(true)).toBe(true) - expect(await session.getRedboxSource()).toMatchSnapshot() + // We get an error because Foo didn't import React. Fair. + expect(await session.hasRedbox(true)).toBe(true) + expect(await session.getRedboxSource()).toMatchSnapshot() - // Let's add that to Foo. - await session.patch( - 'Foo.js', - ` + // Let's add that to Foo. + await session.patch( + 'Foo.js', + ` import * as React from 'react'; export default function Foo() { return React.createElement('h1', null, 'Foo'); } ` - ) + ) - // Expected: this fixes the problem - expect(await session.hasRedbox()).toBe(false) + // Expected: this fixes the problem + expect(await session.hasRedbox()).toBe(false) - await cleanup() - }) + await cleanup() + }) - // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554150098 - test('syntax > runtime error', async () => { - const { session, cleanup } = await sandbox(next) + // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554150098 + test('syntax > runtime error', async () => { + const { session, cleanup } = await sandbox(next) - // Start here. - await session.patch( - 'index.js', - ` + // Start here. + await session.patch( + 'index.js', + ` import * as React from 'react'; export default function FunctionNamed() { return } ` - ) - // TODO: this acts weird without above step - await session.patch( - 'index.js', - ` + ) + // TODO: this acts weird without above step + await session.patch( + 'index.js', + ` import * as React from 'react'; let i = 0 setInterval(() => { @@ -556,20 +563,20 @@ describe('ReactRefreshLogBox app', () => { return } ` - ) + ) - await new Promise((resolve) => setTimeout(resolve, 1000)) - await session.waitForAndOpenRuntimeError() - if (process.platform === 'win32') { - expect(await session.getRedboxSource()).toMatchSnapshot() - } else { - expect(await session.getRedboxSource()).toMatchSnapshot() - } + await new Promise((resolve) => setTimeout(resolve, 1000)) + await session.waitForAndOpenRuntimeError() + if (process.platform === 'win32') { + expect(await session.getRedboxSource()).toMatchSnapshot() + } else { + expect(await session.getRedboxSource()).toMatchSnapshot() + } - // Make a syntax error. - await session.patch( - 'index.js', - ` + // Make a syntax error. + await session.patch( + 'index.js', + ` import * as React from 'react'; let i = 0 setInterval(() => { @@ -577,35 +584,35 @@ describe('ReactRefreshLogBox app', () => { throw Error('no ' + i) }, 1000) export default function FunctionNamed() {` - ) + ) - await new Promise((resolve) => setTimeout(resolve, 1000)) - expect(await session.hasRedbox(true)).toBe(true) - expect(await session.getRedboxSource()).toMatchSnapshot() + await new Promise((resolve) => setTimeout(resolve, 1000)) + expect(await session.hasRedbox(true)).toBe(true) + expect(await session.getRedboxSource()).toMatchSnapshot() - // Test that runtime error does not take over: - await new Promise((resolve) => setTimeout(resolve, 2000)) - expect(await session.hasRedbox(true)).toBe(true) - expect(await session.getRedboxSource()).toMatchSnapshot() + // Test that runtime error does not take over: + await new Promise((resolve) => setTimeout(resolve, 2000)) + expect(await session.hasRedbox(true)).toBe(true) + expect(await session.getRedboxSource()).toMatchSnapshot() - await cleanup() - }) + await cleanup() + }) - // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554152127 - test('boundaries', async () => { - const { session, cleanup } = await sandbox(next) + // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554152127 + test('boundaries', async () => { + const { session, cleanup } = await sandbox(next) - await session.write( - 'FunctionDefault.js', - ` + await session.write( + 'FunctionDefault.js', + ` export default function FunctionDefault() { returnhello
} ` - ) + ) - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` import Child from './Child'; export default function Home() { @@ -746,16 +753,16 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) - expect(await session.hasRedbox()).toBe(false) - expect( - await session.evaluate(() => document.querySelector('p').textContent) - ).toBe('hello') + expect(await session.hasRedbox()).toBe(false) + expect( + await session.evaluate(() => document.querySelector('p').textContent) + ).toBe('hello') - await session.patch( - 'Child.js', - ` + await session.patch( + 'Child.js', + ` import { Component } from 'react'; export default class ClickCount extends Component { render() { @@ -763,14 +770,14 @@ describe('ReactRefreshLogBox app', () => { } } ` - ) + ) - expect(await session.hasRedbox(true)).toBe(true) - expect(await session.getRedboxSource()).toMatchSnapshot() + expect(await session.hasRedbox(true)).toBe(true) + expect(await session.getRedboxSource()).toMatchSnapshot() - await session.patch( - 'Child.js', - ` + await session.patch( + 'Child.js', + ` import { Component } from 'react'; export default class ClickCount extends Component { render() { @@ -778,23 +785,23 @@ describe('ReactRefreshLogBox app', () => { } } ` - ) + ) - expect(await session.hasRedbox()).toBe(false) - expect( - await session.evaluate(() => document.querySelector('p').textContent) - ).toBe('hello new') + expect(await session.hasRedbox()).toBe(false) + expect( + await session.evaluate(() => document.querySelector('p').textContent) + ).toBe('hello new') - await cleanup() - }) + await cleanup() + }) - test('css syntax errors', async () => { - const { session, cleanup } = await sandbox(next) + test('css syntax errors', async () => { + const { session, cleanup } = await sandbox(next) - await session.write('index.module.css', `.button {}`) - await session.patch( - 'index.js', - ` + await session.write('index.module.css', `.button {}`) + await session.patch( + 'index.js', + ` import './index.module.css'; export default () => { return ( @@ -804,35 +811,35 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) - expect(await session.hasRedbox()).toBe(false) - - // Syntax error - await session.patch('index.module.css', `.button {`) - expect(await session.hasRedbox(true)).toBe(true) - const source = await session.getRedboxSource() - expect(source).toMatch('./index.module.css:1:1') - expect(source).toMatch('Syntax error: ') - expect(source).toMatch('Unclosed block') - expect(source).toMatch('> 1 | .button {') - expect(source).toMatch(' | ^') - - // Not local error - await session.patch('index.module.css', `button {}`) - expect(await session.hasRedbox(true)).toBe(true) - const source2 = await session.getRedboxSource() - expect(source2).toMatchSnapshot() - - await cleanup() - }) + expect(await session.hasRedbox()).toBe(false) - test('logbox: anchors links in error messages', async () => { - const { session, cleanup } = await sandbox(next) + // Syntax error + await session.patch('index.module.css', `.button {`) + expect(await session.hasRedbox(true)).toBe(true) + const source = await session.getRedboxSource() + expect(source).toMatch('./index.module.css:1:1') + expect(source).toMatch('Syntax error: ') + expect(source).toMatch('Unclosed block') + expect(source).toMatch('> 1 | .button {') + expect(source).toMatch(' | ^') + + // Not local error + await session.patch('index.module.css', `button {}`) + expect(await session.hasRedbox(true)).toBe(true) + const source2 = await session.getRedboxSource() + expect(source2).toMatchSnapshot() - await session.patch( - 'index.js', - ` + await cleanup() + }) + + test('logbox: anchors links in error messages', async () => { + const { session, cleanup } = await sandbox(next) + + await session.patch( + 'index.js', + ` import { useCallback } from 'react' export default function Index() { @@ -846,38 +853,38 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) - await session.evaluate(() => document.querySelector('button').click()) - await session.waitForAndOpenRuntimeError() - - const header = await session.getRedboxDescription() - expect(header).toMatchSnapshot() - expect( - await session.evaluate( - () => - document - .querySelector('body > nextjs-portal') - .shadowRoot.querySelectorAll('#nextjs__container_errors_desc a') - .length - ) - ).toBe(1) - expect( - await session.evaluate( - () => - ( + await session.evaluate(() => document.querySelector('button').click()) + await session.waitForAndOpenRuntimeError() + + const header = await session.getRedboxDescription() + expect(header).toMatchSnapshot() + expect( + await session.evaluate( + () => document .querySelector('body > nextjs-portal') - .shadowRoot.querySelector( - '#nextjs__container_errors_desc a:nth-of-type(1)' - ) as any - ).href - ) - ).toMatchSnapshot() + .shadowRoot.querySelectorAll('#nextjs__container_errors_desc a') + .length + ) + ).toBe(1) + expect( + await session.evaluate( + () => + ( + document + .querySelector('body > nextjs-portal') + .shadowRoot.querySelector( + '#nextjs__container_errors_desc a:nth-of-type(1)' + ) as any + ).href + ) + ).toMatchSnapshot() - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` import { useCallback } from 'react' export default function Index() { @@ -891,38 +898,38 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) + + await session.evaluate(() => document.querySelector('button').click()) + await session.waitForAndOpenRuntimeError() - await session.evaluate(() => document.querySelector('button').click()) - await session.waitForAndOpenRuntimeError() - - const header2 = await session.getRedboxDescription() - expect(header2).toMatchSnapshot() - expect( - await session.evaluate( - () => - document - .querySelector('body > nextjs-portal') - .shadowRoot.querySelectorAll('#nextjs__container_errors_desc a') - .length - ) - ).toBe(1) - expect( - await session.evaluate( - () => - ( + const header2 = await session.getRedboxDescription() + expect(header2).toMatchSnapshot() + expect( + await session.evaluate( + () => document .querySelector('body > nextjs-portal') - .shadowRoot.querySelector( - '#nextjs__container_errors_desc a:nth-of-type(1)' - ) as any - ).href - ) - ).toMatchSnapshot() + .shadowRoot.querySelectorAll('#nextjs__container_errors_desc a') + .length + ) + ).toBe(1) + expect( + await session.evaluate( + () => + ( + document + .querySelector('body > nextjs-portal') + .shadowRoot.querySelector( + '#nextjs__container_errors_desc a:nth-of-type(1)' + ) as any + ).href + ) + ).toMatchSnapshot() - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` import { useCallback } from 'react' export default function Index() { @@ -936,38 +943,38 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) + + await session.evaluate(() => document.querySelector('button').click()) + await session.waitForAndOpenRuntimeError() - await session.evaluate(() => document.querySelector('button').click()) - await session.waitForAndOpenRuntimeError() - - const header3 = await session.getRedboxDescription() - expect(header3).toMatchSnapshot() - expect( - await session.evaluate( - () => - document - .querySelector('body > nextjs-portal') - .shadowRoot.querySelectorAll('#nextjs__container_errors_desc a') - .length - ) - ).toBe(1) - expect( - await session.evaluate( - () => - ( + const header3 = await session.getRedboxDescription() + expect(header3).toMatchSnapshot() + expect( + await session.evaluate( + () => document .querySelector('body > nextjs-portal') - .shadowRoot.querySelector( - '#nextjs__container_errors_desc a:nth-of-type(1)' - ) as any - ).href - ) - ).toMatchSnapshot() + .shadowRoot.querySelectorAll('#nextjs__container_errors_desc a') + .length + ) + ).toBe(1) + expect( + await session.evaluate( + () => + ( + document + .querySelector('body > nextjs-portal') + .shadowRoot.querySelector( + '#nextjs__container_errors_desc a:nth-of-type(1)' + ) as any + ).href + ) + ).toMatchSnapshot() - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` import { useCallback } from 'react' export default function Index() { @@ -981,59 +988,59 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) - await session.evaluate(() => document.querySelector('button').click()) - await session.waitForAndOpenRuntimeError() + await session.evaluate(() => document.querySelector('button').click()) + await session.waitForAndOpenRuntimeError() - const header4 = await session.getRedboxDescription() - expect(header4).toMatchInlineSnapshot( - `"Error: multiple http://nextjs.org links http://example.com"` - ) - expect( - await session.evaluate( - () => - document - .querySelector('body > nextjs-portal') - .shadowRoot.querySelectorAll('#nextjs__container_errors_desc a') - .length - ) - ).toBe(2) - expect( - await session.evaluate( - () => - ( - document - .querySelector('body > nextjs-portal') - .shadowRoot.querySelector( - '#nextjs__container_errors_desc a:nth-of-type(1)' - ) as any - ).href - ) - ).toMatchSnapshot() - expect( - await session.evaluate( - () => - ( + const header4 = await session.getRedboxDescription() + expect(header4).toMatchInlineSnapshot( + `"Error: multiple http://nextjs.org links http://example.com"` + ) + expect( + await session.evaluate( + () => document .querySelector('body > nextjs-portal') - .shadowRoot.querySelector( - '#nextjs__container_errors_desc a:nth-of-type(2)' - ) as any - ).href - ) - ).toMatchSnapshot() + .shadowRoot.querySelectorAll('#nextjs__container_errors_desc a') + .length + ) + ).toBe(2) + expect( + await session.evaluate( + () => + ( + document + .querySelector('body > nextjs-portal') + .shadowRoot.querySelector( + '#nextjs__container_errors_desc a:nth-of-type(1)' + ) as any + ).href + ) + ).toMatchSnapshot() + expect( + await session.evaluate( + () => + ( + document + .querySelector('body > nextjs-portal') + .shadowRoot.querySelector( + '#nextjs__container_errors_desc a:nth-of-type(2)' + ) as any + ).href + ) + ).toMatchSnapshot() - await cleanup() - }) + await cleanup() + }) - // TODO-APP: Catch errors that happen before useEffect - test.skip('non-Error errors are handled properly', async () => { - const { session, cleanup } = await sandbox(next) + // TODO-APP: Catch errors that happen before useEffect + test.skip('non-Error errors are handled properly', async () => { + const { session, cleanup } = await sandbox(next) - await session.patch( - 'index.js', - ` + await session.patch( + 'index.js', + ` export default () => { throw {'a': 1, 'b': 'x'}; return ( @@ -1041,28 +1048,28 @@ describe('ReactRefreshLogBox app', () => { ) } ` - ) + ) - expect(await session.hasRedbox(true)).toBe(true) - expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"Error: {\\"a\\":1,\\"b\\":\\"x\\"}"` - ) + expect(await session.hasRedbox(true)).toBe(true) + expect(await session.getRedboxDescription()).toMatchInlineSnapshot( + `"Error: {\\"a\\":1,\\"b\\":\\"x\\"}"` + ) - // fix previous error - await session.patch( - 'index.js', - ` + // fix previous error + await session.patch( + 'index.js', + ` export default () => { return (Hello world
} `, - ], - ]) - ) - expect(await session.hasRedbox(true)).toBe(true) + ], + ]) + ) + expect(await session.hasRedbox(true)).toBe(true) - // Remove error - await session.patch( - 'app/page.js', - ` + // Remove error + await session.patch( + 'app/page.js', + ` export default function Page() { returnHello world
} ` - ) - expect(await browser.waitForElementByCss('#text').text()).toBe( - 'Hello world' - ) - expect(await session.hasRedbox()).toBe(false) + ) + expect(await browser.waitForElementByCss('#text').text()).toBe( + 'Hello world' + ) + expect(await session.hasRedbox()).toBe(false) - // Re-add error - await session.patch( - 'app/page.js', - ` + // Re-add error + await session.patch( + 'app/page.js', + ` export default function Page() { throw new Error('Server component error!') returnHello world
} ` - ) + ) - expect(await session.hasRedbox(true)).toBe(true) + expect(await session.hasRedbox(true)).toBe(true) - await cleanup() - }) + await cleanup() + }) - test('Hydration errors should get error link', async () => { - const { session, browser, cleanup } = await sandbox(next) + test('Hydration errors should get error link', async () => { + const { session, browser, cleanup } = await sandbox(next) - await session.patch( - 'app/page.js', - ` + await session.patch( + 'app/page.js', + ` "use client" export default function Page() { return{typeof window === 'undefined' ? "hello" : "world"}
} ` - ) + ) - await browser.refresh() - await session.waitForAndOpenRuntimeError() - expect(await session.getRedboxDescription()).toMatchSnapshot() + await browser.refresh() + await session.waitForAndOpenRuntimeError() + expect(await session.getRedboxDescription()).toMatchSnapshot() - await cleanup() + await cleanup() + }) }) -}) +} diff --git a/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox-builtins.test.ts.snap b/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox-builtins.test.ts.snap index fc2a1bc5c1e4c..6b6d37ce81914 100644 --- a/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox-builtins.test.ts.snap +++ b/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox-builtins.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ReactRefreshLogBox app Module not found 1`] = ` +exports[`ReactRefreshLogBox app default Module not found 1`] = ` "./index.js:1:0 Module not found: Can't resolve 'b' > 1 | import Comp from 'b' @@ -14,7 +14,7 @@ Import trace for requested module: https://nextjs.org/docs/messages/module-not-found" `; -exports[`ReactRefreshLogBox app Module not found empty import trace 1`] = ` +exports[`ReactRefreshLogBox app default Module not found empty import trace 1`] = ` "./app/page.js:2:6 Module not found: Can't resolve 'b' 1 | 'use client' @@ -27,7 +27,7 @@ Module not found: Can't resolve 'b' https://nextjs.org/docs/messages/module-not-found" `; -exports[`ReactRefreshLogBox app Module not found missing global CSS 1`] = ` +exports[`ReactRefreshLogBox app default Module not found missing global CSS 1`] = ` "./app/page.js:2:10 Module not found: Can't resolve './non-existent.css' 1 | 'use client' @@ -40,7 +40,7 @@ Module not found: Can't resolve './non-existent.css' https://nextjs.org/docs/messages/module-not-found" `; -exports[`ReactRefreshLogBox app Node.js builtins 1`] = ` +exports[`ReactRefreshLogBox app default Node.js builtins 1`] = ` "./node_modules/my-package/index.js:2:0 Module not found: Can't resolve 'dns' diff --git a/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox.test.ts.snap b/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox.test.ts.snap index 4bf8d3b9a83dc..83a71a3365965 100644 --- a/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox.test.ts.snap +++ b/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox.test.ts.snap @@ -1,12 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ReactRefreshLogBox app Hydration errors should get error link 1`] = ` +exports[`ReactRefreshLogBox app default Hydration errors should get error link 1`] = ` "Error: Text content does not match server-rendered HTML. See more info here: https://nextjs.org/docs/messages/react-hydration-error" `; -exports[`ReactRefreshLogBox app Should not show __webpack_exports__ when exporting anonymous arrow function 1`] = ` +exports[`ReactRefreshLogBox app default Should not show __webpack_exports__ when exporting anonymous arrow function 1`] = ` "index.js (4:16) @ default 2 | export default () => { @@ -18,14 +18,14 @@ exports[`ReactRefreshLogBox app Should not show __webpack_exports__ when exporti 7 | return null" `; -exports[`ReactRefreshLogBox app boundaries 1`] = ` +exports[`ReactRefreshLogBox app default boundaries 1`] = ` "FunctionDefault.js (1:50) @ FunctionDefault > 1 | export default function FunctionDefault() { throw new Error('no'); } | ^" `; -exports[`ReactRefreshLogBox app conversion to class component (1) 1`] = ` +exports[`ReactRefreshLogBox app default conversion to class component (1) 1`] = ` "Child.js (5:18) @ ClickCount.render 3 | export default class ClickCount extends Component { @@ -37,7 +37,7 @@ exports[`ReactRefreshLogBox app conversion to class component (1) 1`] = ` 8 | " `; -exports[`ReactRefreshLogBox app css syntax errors 1`] = ` +exports[`ReactRefreshLogBox app default css syntax errors 1`] = ` "./index.module.css:1:1 Syntax error: Selector \\"button\\" is not pure (pure selectors must contain at least one local class or id) @@ -45,23 +45,23 @@ Syntax error: Selector \\"button\\" is not pure (pure selectors must contain at | ^" `; -exports[`ReactRefreshLogBox app logbox: anchors links in error messages 1`] = `"Error: end http://nextjs.org"`; +exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 1`] = `"Error: end http://nextjs.org"`; -exports[`ReactRefreshLogBox app logbox: anchors links in error messages 2`] = `"http://nextjs.org/"`; +exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 2`] = `"http://nextjs.org/"`; -exports[`ReactRefreshLogBox app logbox: anchors links in error messages 3`] = `"Error: http://nextjs.org start"`; +exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 3`] = `"Error: http://nextjs.org start"`; -exports[`ReactRefreshLogBox app logbox: anchors links in error messages 4`] = `"http://nextjs.org/"`; +exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 4`] = `"http://nextjs.org/"`; -exports[`ReactRefreshLogBox app logbox: anchors links in error messages 5`] = `"Error: middle http://nextjs.org end"`; +exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 5`] = `"Error: middle http://nextjs.org end"`; -exports[`ReactRefreshLogBox app logbox: anchors links in error messages 6`] = `"http://nextjs.org/"`; +exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 6`] = `"http://nextjs.org/"`; -exports[`ReactRefreshLogBox app logbox: anchors links in error messages 8`] = `"http://nextjs.org/"`; +exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 8`] = `"http://nextjs.org/"`; -exports[`ReactRefreshLogBox app logbox: anchors links in error messages 9`] = `"http://example.com/"`; +exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 9`] = `"http://example.com/"`; -exports[`ReactRefreshLogBox app logbox: can recover from a component error 1`] = ` +exports[`ReactRefreshLogBox app default logbox: can recover from a component error 1`] = ` "child.js (4:16) @ Child 2 | // hello @@ -72,7 +72,7 @@ exports[`ReactRefreshLogBox app logbox: can recover from a component error 1`] = 6 | " `; -exports[`ReactRefreshLogBox app logbox: can recover from a event handler error 1`] = ` +exports[`ReactRefreshLogBox app default logbox: can recover from a event handler error 1`] = ` "index.js (8:18) @ eval 6 | const increment = useCallback(() => { @@ -84,7 +84,7 @@ exports[`ReactRefreshLogBox app logbox: can recover from a event handler error 1 11 |