rsnext/test/development/acceptance-app/ReactRefreshLogBox.test.ts

1412 lines
36 KiB
TypeScript
Raw Normal View History

/* eslint-env jest */
import { sandbox } from './helpers'
import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { check, getSnapshotTestDescribe } from 'next-test-utils'
import path from 'path'
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())
test('should strip whitespace correctly with newline', async () => {
const { session, cleanup } = await sandbox(next)
await session.patch(
'index.js',
`
export default function Page() {
return (
<>
<p>index page</p>
<a onClick={() => {
throw new Error('idk')
}}>
click me
</a>
</>
)
}
`
)
await session.evaluate(() => document.querySelector('a').click())
await session.waitForAndOpenRuntimeError()
expect(await session.getRedboxSource()).toMatchSnapshot()
await cleanup()
})
test('logbox: can recover from a syntax error without losing state', async () => {
const { session, cleanup } = await sandbox(next)
await session.patch(
'index.js',
`
import { useCallback, useState } from 'react'
export default function Index() {
const [count, setCount] = useState(0)
const increment = useCallback(() => setCount(c => c + 1), [setCount])
return (
<main>
<p>{count}</p>
<button onClick={increment}>Increment</button>
</main>
)
}
`
)
await session.evaluate(() => document.querySelector('button').click())
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('1')
await session.patch('index.js', `export default () => <div/`)
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxSource()).toMatchSnapshot()
await session.patch(
'index.js',
`
import { useCallback, useState } from 'react'
export default function Index() {
const [count, setCount] = useState(0)
const increment = useCallback(() => setCount(c => c + 1), [setCount])
return (
<main>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</main>
)
}
`
)
await check(
() => session.evaluate(() => document.querySelector('p').textContent),
/Count: 1/
)
expect(await session.hasRedbox(false)).toBe(false)
await cleanup()
})
test('logbox: can recover from a event handler error', async () => {
const { session, cleanup } = await sandbox(next)
await session.patch(
'index.js',
`
import { useCallback, useState } from 'react'
export default function Index() {
const [count, setCount] = useState(0)
const increment = useCallback(() => {
setCount(c => c + 1)
throw new Error('oops')
}, [setCount])
return (
<main>
<p>{count}</p>
<button onClick={increment}>Increment</button>
</main>
)
}
`
)
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('0')
await session.evaluate(() => document.querySelector('button').click())
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('1')
await session.waitForAndOpenRuntimeError()
if (process.platform === 'win32') {
expect(await session.getRedboxSource()).toMatchSnapshot()
} else {
expect(await session.getRedboxSource()).toMatchSnapshot()
}
await session.patch(
'index.js',
`
import { useCallback, useState } from 'react'
export default function Index() {
const [count, setCount] = useState(0)
const increment = useCallback(() => setCount(c => c + 1), [setCount])
return (
<main>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</main>
)
}
`
)
expect(await session.hasRedbox(false)).toBe(false)
expect(await session.hasErrorToast()).toBe(false)
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('Count: 1')
await session.evaluate(() => document.querySelector('button').click())
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('Count: 2')
expect(await session.hasRedbox(false)).toBe(false)
expect(await session.hasErrorToast()).toBe(false)
await cleanup()
})
test('logbox: can recover from a component error', async () => {
const { session, cleanup } = await sandbox(next)
await session.write(
'child.js',
`
export default function Child() {
return <p>Hello</p>;
}
`
)
await session.patch(
'index.js',
`
import Child from './child'
export default function Index() {
return (
<main>
<Child />
</main>
)
}
`
)
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('Hello')
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()
// TODO-APP: re-enable when error recovery doesn't reload the page.
/* const didNotReload = */ await session.patch(
'child.js',
`
export default function Child() {
return <p>Hello</p>;
}
`
)
// TODO-APP: re-enable when error recovery doesn't reload the page.
// expect(didNotReload).toBe(true)
expect(await session.hasRedbox(false)).toBe(false)
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('Hello')
await cleanup()
})
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() {
return <p>Hello world</p>
}
`,
],
])
)
// Add syntax error
await session.patch(
'app/page.js',
`
export default function Page() {
return <p>Hello world</p>
`
)
expect(await session.hasRedbox(true)).toBe(true)
// Fix syntax error
await session.patch(
'app/page.js',
`
export default function Page() {
return <p>Hello world 2</p>
}
`
)
await check(() => browser.elementByCss('p').text(), 'Hello world 2')
await cleanup()
})
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() {
return <p>Hello world</p>
}
`,
],
])
)
// Add component error
await session.patch(
'app/page.js',
`
export default function Page() {
throw new Error("boom")
return <p>Hello world</p>
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
// Fix component error
await session.patch(
'app/page.js',
`
export default function Page() {
return <p>Hello world 2</p>
}
`
)
expect(await browser.waitForElementByCss('p').text()).toBe(
'Hello world 2'
)
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)
// Starting here:
await session.patch(
'index.js',
`
import * as React from 'react';
class ClassDefault extends React.Component {
render() {
return <h1>Default Export</h1>;
}
}
export default ClassDefault;
`
)
expect(
await session.evaluate(() => document.querySelector('h1').textContent)
).toBe('Default Export')
// Break it with a syntax error:
await session.patch(
'index.js',
`
import * as React from 'react';
class ClassDefault extends React.Component {
render()
return <h1>Default Export</h1>;
}
}
export default ClassDefault;
`
)
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',
`
import * as React from 'react';
class ClassDefault extends React.Component {
render()
throw new Error('nooo');
return <h1>Default Export</h1>;
}
}
export default ClassDefault;
`
)
expect(await session.hasRedbox(true)).toBe(true)
// Now fix the syntax error:
await session.patch(
'index.js',
`
import * as React from 'react';
class ClassDefault extends React.Component {
render() {
throw new Error('nooo');
return <h1>Default Export</h1>;
}
}
export default ClassDefault;
`
)
expect(await session.hasRedbox(true)).toBe(true)
await check(async () => {
const source = await session.getRedboxSource()
return source?.length > 1 ? 'success' : source
}, 'success')
expect(await session.getRedboxSource()).toMatchSnapshot()
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)
// We start here.
await session.patch(
'index.js',
`
import * as React from 'react';
class ClassDefault extends React.Component {
render() {
return <h1>Default Export</h1>;
}
}
export default ClassDefault;
`
)
expect(
await session.evaluate(() => document.querySelector('h1').textContent)
).toBe('Default Export')
// 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')
class ClassDefault extends React.Component {
render() {
return <h1>Default Export</h1>;
}
}
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()
}
await cleanup()
})
// 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',
`
import * as React from 'react';
function FunctionDefault() {
return <h1>Default Export Function</h1>;
}
export default FunctionDefault;
`
)
// 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',
`
import * as React from 'react';
import Foo from './Foo';
function FunctionDefault() {
return <Foo />;
}
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()
// 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(false)).toBe(false)
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)
// Start here.
await session.patch(
'index.js',
`
import * as React from 'react';
export default function FunctionNamed() {
return <div />
}
`
)
// TODO: this acts weird without above step
await session.patch(
'index.js',
`
import * as React from 'react';
let i = 0
setInterval(() => {
i++
throw Error('no ' + i)
}, 1000)
export default function FunctionNamed() {
return <div />
}
`
)
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',
`
import * as React from 'react';
let i = 0
setInterval(() => {
i++
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()
// 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()
})
// 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',
`
export default function FunctionDefault() {
return <h2>hello</h2>
}
`
)
await session.patch(
'index.js',
`
import FunctionDefault from './FunctionDefault.js'
import * as React from 'react'
class ErrorBoundary extends React.Component {
constructor() {
super()
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
return {
hasError: true,
error
};
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}
function App() {
return (
<ErrorBoundary fallback={<h2>error</h2>}>
<FunctionDefault />
</ErrorBoundary>
);
}
export default App;
`
)
expect(
await session.evaluate(() => document.querySelector('h2').textContent)
).toBe('hello')
await session.write(
'FunctionDefault.js',
`export default function FunctionDefault() { throw new Error('no'); }`
)
await session.waitForAndOpenRuntimeError()
expect(await session.getRedboxSource()).toMatchSnapshot()
expect(
await session.evaluate(() => document.querySelector('h2').textContent)
).toBe('error')
await cleanup()
})
// TODO: investigate why this fails when running outside of the Next.js
// monorepo e.g. fails when using yarn create next-app
// https://github.com/vercel/next.js/pull/23203
test.skip('internal package errors', async () => {
const { session, cleanup } = await sandbox(next)
// Make a react build-time error.
await session.patch(
'index.js',
`
export default function FunctionNamed() {
return <div>{{}}</div>
}`
)
expect(await session.hasRedbox(true)).toBe(true)
// We internally only check the script path, not including the line number
// and error message because the error comes from an external library.
// This test ensures that the errored script path is correctly resolved.
expect(await session.getRedboxSource()).toContain(
`../../../../packages/next/dist/pages/_document.js`
)
await cleanup()
})
test('unterminated JSX', async () => {
const { session, cleanup } = await sandbox(next)
await session.patch(
'index.js',
`
export default () => {
return (
<div>
<p>lol</p>
</div>
)
}
`
)
expect(await session.hasRedbox(false)).toBe(false)
await session.patch(
'index.js',
`
export default () => {
return (
<div>
<p>lol</p>
div
)
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
const source = await session.getRedboxSource()
expect(source).toMatchSnapshot()
await cleanup()
})
// Module trace is only available with webpack 5
test('conversion to class component (1)', async () => {
const { session, cleanup } = await sandbox(next)
await session.write(
'Child.js',
`
export default function ClickCount() {
return <p>hello</p>
}
`
)
await session.patch(
'index.js',
`
import Child from './Child';
export default function Home() {
return (
<div>
<Child />
</div>
)
}
`
)
expect(await session.hasRedbox(false)).toBe(false)
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('hello')
await session.patch(
'Child.js',
`
import { Component } from 'react';
export default class ClickCount extends Component {
render() {
throw new Error()
}
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxSource()).toMatchSnapshot()
await session.patch(
'Child.js',
`
import { Component } from 'react';
export default class ClickCount extends Component {
render() {
return <p>hello new</p>
}
}
`
)
expect(await session.hasRedbox(false)).toBe(false)
expect(
await session.evaluate(() => document.querySelector('p').textContent)
).toBe('hello new')
await cleanup()
})
test('css syntax errors', async () => {
const { session, cleanup } = await sandbox(next)
await session.write('index.module.css', `.button {}`)
await session.patch(
'index.js',
`
import './index.module.css';
export default () => {
return (
<div>
<p>lol</p>
</div>
)
}
`
)
expect(await session.hasRedbox(false)).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()
})
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() {
const boom = useCallback(() => {
throw new Error('end http://nextjs.org')
}, [])
return (
<main>
<button onClick={boom}>Boom!</button>
</main>
)
}
`
)
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(
() =>
(
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',
`
import { useCallback } from 'react'
export default function Index() {
const boom = useCallback(() => {
throw new Error('http://nextjs.org start')
}, [])
return (
<main>
<button onClick={boom}>Boom!</button>
</main>
)
}
`
)
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(
() =>
(
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',
`
import { useCallback } from 'react'
export default function Index() {
const boom = useCallback(() => {
throw new Error('middle http://nextjs.org end')
}, [])
return (
<main>
<button onClick={boom}>Boom!</button>
</main>
)
}
`
)
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(
() =>
(
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',
`
import { useCallback } from 'react'
export default function Index() {
const boom = useCallback(() => {
throw new Error('multiple http://nextjs.org links http://example.com')
}, [])
return (
<main>
<button onClick={boom}>Boom!</button>
</main>
)
}
`
)
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(
() =>
(
document
.querySelector('body > nextjs-portal')
.shadowRoot.querySelector(
'#nextjs__container_errors_desc a:nth-of-type(2)'
) as any
).href
)
).toMatchSnapshot()
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)
await session.patch(
'index.js',
`
export default () => {
throw {'a': 1, 'b': 'x'};
return (
<div>hello</div>
)
}
`
)
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',
`
export default () => {
return (
<div>hello</div>
)
}
`
)
expect(await session.hasRedbox(false)).toBe(false)
await session.patch(
'index.js',
`
class Hello {}
export default () => {
throw Hello
return (
<div>hello</div>
)
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxDescription()).toContain(
`Error: class Hello {`
)
// fix previous error
await session.patch(
'index.js',
`
export default () => {
return (
<div>hello</div>
)
}
`
)
expect(await session.hasRedbox(false)).toBe(false)
await session.patch(
'index.js',
`
export default () => {
throw "string error"
return (
<div>hello</div>
)
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: string error"`
)
// fix previous error
await session.patch(
'index.js',
`
export default () => {
return (
<div>hello</div>
)
}
`
)
expect(await session.hasRedbox(false)).toBe(false)
await session.patch(
'index.js',
`
export default () => {
throw null
return (
<div>hello</div>
)
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxDescription()).toContain(
`Error: A null error was thrown`
)
await cleanup()
})
test('Should not show __webpack_exports__ when exporting anonymous arrow function', async () => {
const { session, cleanup } = await sandbox(next)
await session.patch(
'index.js',
`
export default () => {
if (typeof window !== 'undefined') {
throw new Error('test')
}
return null
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxSource()).toMatchSnapshot()
await cleanup()
})
Unhandled errors and rejections opens as minimized in app dir error overlay (#43844) Updated version of the reverted https://github.com/vercel/next.js/pull/43511 Unhandled errors that did not occur during React rendering (those errors are caught in `getDerivedStateFromError` in the Error Overlay) should be opened in the minimized toast state instead of fullscreen. For example if they occur in event handlers or setTimeout. Errors that breaks the app, such as uncaught render errors or build errors, still opens up in fullscreen mode. The added test make sure the errors opens up as minimized, but if there's a breaking error it should "win" and open up in fullscreen. The updated tests either throw errors inside an event handler or a setTimeout, or the error is handled in a custom error boundary - which means the app don't break. Closes NEXT-128 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-12-08 12:30:27 +01:00
test('Unhandled errors and rejections opens up in the minimized state', async () => {
const { session, browser, cleanup } = await sandbox(next)
Unhandled errors and rejections opens as minimized in app dir error overlay (#43844) Updated version of the reverted https://github.com/vercel/next.js/pull/43511 Unhandled errors that did not occur during React rendering (those errors are caught in `getDerivedStateFromError` in the Error Overlay) should be opened in the minimized toast state instead of fullscreen. For example if they occur in event handlers or setTimeout. Errors that breaks the app, such as uncaught render errors or build errors, still opens up in fullscreen mode. The added test make sure the errors opens up as minimized, but if there's a breaking error it should "win" and open up in fullscreen. The updated tests either throw errors inside an event handler or a setTimeout, or the error is handled in a custom error boundary - which means the app don't break. Closes NEXT-128 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-12-08 12:30:27 +01:00
const file = `
Unhandled errors and rejections opens as minimized in app dir error overlay (#43844) Updated version of the reverted https://github.com/vercel/next.js/pull/43511 Unhandled errors that did not occur during React rendering (those errors are caught in `getDerivedStateFromError` in the Error Overlay) should be opened in the minimized toast state instead of fullscreen. For example if they occur in event handlers or setTimeout. Errors that breaks the app, such as uncaught render errors or build errors, still opens up in fullscreen mode. The added test make sure the errors opens up as minimized, but if there's a breaking error it should "win" and open up in fullscreen. The updated tests either throw errors inside an event handler or a setTimeout, or the error is handled in a custom error boundary - which means the app don't break. Closes NEXT-128 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-12-08 12:30:27 +01:00
export default function Index() {
//
setTimeout(() => {
throw new Error('Unhandled error')
}, 0)
setTimeout(() => {
Promise.reject(new Error('Undhandled rejection'))
}, 0)
return (
<>
<button
id="unhandled-error"
onClick={() => {
throw new Error('Unhandled error')
}}
>
Unhandled error
</button>
<button
id="unhandled-rejection"
onClick={() => {
Promise.reject(new Error('Undhandled rejection'))
}}
>
Unhandled rejection
</button>
</>
)
}
`
await session.patch('index.js', file)
Unhandled errors and rejections opens as minimized in app dir error overlay (#43844) Updated version of the reverted https://github.com/vercel/next.js/pull/43511 Unhandled errors that did not occur during React rendering (those errors are caught in `getDerivedStateFromError` in the Error Overlay) should be opened in the minimized toast state instead of fullscreen. For example if they occur in event handlers or setTimeout. Errors that breaks the app, such as uncaught render errors or build errors, still opens up in fullscreen mode. The added test make sure the errors opens up as minimized, but if there's a breaking error it should "win" and open up in fullscreen. The updated tests either throw errors inside an event handler or a setTimeout, or the error is handled in a custom error boundary - which means the app don't break. Closes NEXT-128 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-12-08 12:30:27 +01:00
// Unhandled error and rejection in setTimeout
expect(
await browser.waitForElementByCss('.nextjs-toast-errors').text()
).toBe('2 errors')
Unhandled errors and rejections opens as minimized in app dir error overlay (#43844) Updated version of the reverted https://github.com/vercel/next.js/pull/43511 Unhandled errors that did not occur during React rendering (those errors are caught in `getDerivedStateFromError` in the Error Overlay) should be opened in the minimized toast state instead of fullscreen. For example if they occur in event handlers or setTimeout. Errors that breaks the app, such as uncaught render errors or build errors, still opens up in fullscreen mode. The added test make sure the errors opens up as minimized, but if there's a breaking error it should "win" and open up in fullscreen. The updated tests either throw errors inside an event handler or a setTimeout, or the error is handled in a custom error boundary - which means the app don't break. Closes NEXT-128 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-12-08 12:30:27 +01:00
// Unhandled error in event handler
await browser.elementById('unhandled-error').click()
await check(
() => browser.elementByCss('.nextjs-toast-errors').text(),
/3 errors/
)
Unhandled errors and rejections opens as minimized in app dir error overlay (#43844) Updated version of the reverted https://github.com/vercel/next.js/pull/43511 Unhandled errors that did not occur during React rendering (those errors are caught in `getDerivedStateFromError` in the Error Overlay) should be opened in the minimized toast state instead of fullscreen. For example if they occur in event handlers or setTimeout. Errors that breaks the app, such as uncaught render errors or build errors, still opens up in fullscreen mode. The added test make sure the errors opens up as minimized, but if there's a breaking error it should "win" and open up in fullscreen. The updated tests either throw errors inside an event handler or a setTimeout, or the error is handled in a custom error boundary - which means the app don't break. Closes NEXT-128 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-12-08 12:30:27 +01:00
// Unhandled rejection in event handler
await browser.elementById('unhandled-rejection').click()
await check(
() => browser.elementByCss('.nextjs-toast-errors').text(),
/4 errors/
)
expect(await session.hasRedbox(false)).toBe(false)
// Add Component error
await session.patch(
'index.js',
file.replace(
'//',
"if (typeof window !== 'undefined') throw new Error('Component error')"
)
Unhandled errors and rejections opens as minimized in app dir error overlay (#43844) Updated version of the reverted https://github.com/vercel/next.js/pull/43511 Unhandled errors that did not occur during React rendering (those errors are caught in `getDerivedStateFromError` in the Error Overlay) should be opened in the minimized toast state instead of fullscreen. For example if they occur in event handlers or setTimeout. Errors that breaks the app, such as uncaught render errors or build errors, still opens up in fullscreen mode. The added test make sure the errors opens up as minimized, but if there's a breaking error it should "win" and open up in fullscreen. The updated tests either throw errors inside an event handler or a setTimeout, or the error is handled in a custom error boundary - which means the app don't break. Closes NEXT-128 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-12-08 12:30:27 +01:00
)
// Render error should "win" and show up in fullscreen
expect(await session.hasRedbox(true)).toBe(true)
Unhandled errors and rejections opens as minimized in app dir error overlay (#43844) Updated version of the reverted https://github.com/vercel/next.js/pull/43511 Unhandled errors that did not occur during React rendering (those errors are caught in `getDerivedStateFromError` in the Error Overlay) should be opened in the minimized toast state instead of fullscreen. For example if they occur in event handlers or setTimeout. Errors that breaks the app, such as uncaught render errors or build errors, still opens up in fullscreen mode. The added test make sure the errors opens up as minimized, but if there's a breaking error it should "win" and open up in fullscreen. The updated tests either throw errors inside an event handler or a setTimeout, or the error is handled in a custom error boundary - which means the app don't break. Closes NEXT-128 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-12-08 12:30:27 +01:00
await cleanup()
})
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
test.each([['server'], ['client']])(
'Call stack count is correct for %s error',
async (pageType: string) => {
const fixture =
pageType === 'server'
? new Map([
[
'app/page.js',
`
Collapse sequences of call stack frames from React and Next.js in the error overlay (#44137) Sequences of call stack frames from React or Next.js are collapsed, most of the time these just adds noise to the error overlay. The collapsed stack frames can be expanded though by clicking them. Adds the package of the stack frame to the `'/__nextjs_original-stack-frame'` response, so we can figure out if the stack frame is from React/Next.js in the error overlay. <details> <summary>View before/after</summary> ## Before ![image](https://user-images.githubusercontent.com/25056922/208419557-73af3864-c4e8-4d78-92de-5d2cdf772f33.png) ## After ![image](https://user-images.githubusercontent.com/25056922/208419729-f7f8d0d1-dea9-48cf-8a74-6fca3f0d027b.png) ## Another error, React expanded ![image](https://user-images.githubusercontent.com/25056922/208419977-c608f8ea-ddf9-40b1-ae87-49e6929ee959.png) </details> ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2023-01-03 23:47:58 +01:00
export default function Page() {
throw new Error('Server error')
}
`,
],
])
: new Map([
[
'app/page.js',
`
Collapse sequences of call stack frames from React and Next.js in the error overlay (#44137) Sequences of call stack frames from React or Next.js are collapsed, most of the time these just adds noise to the error overlay. The collapsed stack frames can be expanded though by clicking them. Adds the package of the stack frame to the `'/__nextjs_original-stack-frame'` response, so we can figure out if the stack frame is from React/Next.js in the error overlay. <details> <summary>View before/after</summary> ## Before ![image](https://user-images.githubusercontent.com/25056922/208419557-73af3864-c4e8-4d78-92de-5d2cdf772f33.png) ## After ![image](https://user-images.githubusercontent.com/25056922/208419729-f7f8d0d1-dea9-48cf-8a74-6fca3f0d027b.png) ## Another error, React expanded ![image](https://user-images.githubusercontent.com/25056922/208419977-c608f8ea-ddf9-40b1-ae87-49e6929ee959.png) </details> ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2023-01-03 23:47:58 +01:00
'use client'
export default function Page() {
if (typeof window !== 'undefined') {
throw new Error('Client error')
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
}
Collapse sequences of call stack frames from React and Next.js in the error overlay (#44137) Sequences of call stack frames from React or Next.js are collapsed, most of the time these just adds noise to the error overlay. The collapsed stack frames can be expanded though by clicking them. Adds the package of the stack frame to the `'/__nextjs_original-stack-frame'` response, so we can figure out if the stack frame is from React/Next.js in the error overlay. <details> <summary>View before/after</summary> ## Before ![image](https://user-images.githubusercontent.com/25056922/208419557-73af3864-c4e8-4d78-92de-5d2cdf772f33.png) ## After ![image](https://user-images.githubusercontent.com/25056922/208419729-f7f8d0d1-dea9-48cf-8a74-6fca3f0d027b.png) ## Another error, React expanded ![image](https://user-images.githubusercontent.com/25056922/208419977-c608f8ea-ddf9-40b1-ae87-49e6929ee959.png) </details> ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2023-01-03 23:47:58 +01:00
return null
}
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
`,
],
])
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
const { session, browser, cleanup } = await sandbox(next, fixture)
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
const getCallStackCount = async () =>
(await browser.elementsByCss('[data-nextjs-call-stack-frame]')).length
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
expect(await session.hasRedbox(true)).toBe(true)
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
// Open full Call Stack
await browser
.elementByCss('[data-nextjs-data-runtime-error-collapsed-action]')
.click()
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
const collapsedFrameworkGroups = await browser.elementsByCss(
"[data-nextjs-call-stack-framework-button][data-state='closed']"
Collapse sequences of call stack frames from React and Next.js in the error overlay (#44137) Sequences of call stack frames from React or Next.js are collapsed, most of the time these just adds noise to the error overlay. The collapsed stack frames can be expanded though by clicking them. Adds the package of the stack frame to the `'/__nextjs_original-stack-frame'` response, so we can figure out if the stack frame is from React/Next.js in the error overlay. <details> <summary>View before/after</summary> ## Before ![image](https://user-images.githubusercontent.com/25056922/208419557-73af3864-c4e8-4d78-92de-5d2cdf772f33.png) ## After ![image](https://user-images.githubusercontent.com/25056922/208419729-f7f8d0d1-dea9-48cf-8a74-6fca3f0d027b.png) ## Another error, React expanded ![image](https://user-images.githubusercontent.com/25056922/208419977-c608f8ea-ddf9-40b1-ae87-49e6929ee959.png) </details> ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2023-01-03 23:47:58 +01:00
)
for (const collapsedFrameworkButton of collapsedFrameworkGroups) {
// Open the collapsed framework groups, the callstack count should increase with each opened group
const callStackCountBeforeGroupOpened = await getCallStackCount()
await collapsedFrameworkButton.click()
expect(await getCallStackCount()).toBeGreaterThan(
callStackCountBeforeGroupOpened
)
}
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
// Expect more than the default amount of frames
// The default stackTraceLimit results in max 9 [data-nextjs-call-stack-frame] elements
expect(await getCallStackCount()).toBeGreaterThan(9)
Increase stack trace limit on the server (#43800) Increases `Error.stackTraceLimit` on the server to match the client. Adds `if (typeof window !== 'undefined') {` in `use-error-handler`, otherwise it also affects the server - but only after that file is compiled. Closes NEXT-125 ### Before ![image](https://user-images.githubusercontent.com/25056922/206123948-0c92009a-e5e8-4519-9862-1c1b83d88168.png) ### After ![image](https://user-images.githubusercontent.com/25056922/206124053-ba792463-76d4-457c-ac3b-d3e5b95b7bf9.png) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-12-12 05:35:55 +01:00
await cleanup()
}
)
test('Server component errors should open up in fullscreen', async () => {
const { session, browser, cleanup } = await sandbox(
next,
new Map([
// Start with error
[
'app/page.js',
`
export default function Page() {
throw new Error('Server component error')
return <p id="text">Hello world</p>
}
`,
],
])
)
expect(await session.hasRedbox(true)).toBe(true)
// Remove error
await session.patch(
'app/page.js',
`
export default function Page() {
return <p id="text">Hello world</p>
}
`
)
expect(await browser.waitForElementByCss('#text').text()).toBe(
'Hello world'
)
expect(await session.hasRedbox(false)).toBe(false)
// Re-add error
await session.patch(
'app/page.js',
`
export default function Page() {
throw new Error('Server component error!')
return <p id="text">Hello world</p>
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
await cleanup()
})
2023-01-10 11:33:24 +01:00
test('Import trace when module not found in layout', async () => {
const { session, cleanup } = await sandbox(
next,
new Map([['app/module.js', `import "non-existing-module"`]])
)
await session.patch(
'app/layout.js',
`
import "./module"
export default function RootLayout({ children }) {
return (
<html>
<head></head>
<body>{children}</body>
</html>
)
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxSource()).toMatchSnapshot()
await cleanup()
})
test("Can't resolve @import in CSS file", async () => {
const { session, cleanup } = await sandbox(
next,
new Map([
['app/styles1.css', '@import "./styles2.css"'],
['app/styles2.css', '@import "./boom.css"'],
])
)
await session.patch(
'app/layout.js',
`
import "./styles1.css"
export default function RootLayout({ children }) {
return (
<html>
<head></head>
<body>{children}</body>
</html>
)
}
`
)
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxSource()).toMatchSnapshot()
await cleanup()
})
2023-01-10 11:33:24 +01:00
})
}