Replace hasRedbox() (#67025)

...with `assertHasRedbox` and `assertNoRedbox`.

`hasRedbox()` has a hardcoded timeout of 5s that is only required for
the negative assertion.
Instead, we now have dedicated assertions for the positive
(`assertHasRedbox`) and negative case (`assertNoRedbox`).
The negative assertion still has the hardcoded timeout.
But the positive assertion just retries until we find the Redbox.

This speeds up tests using the positive assertion.
Removing `hasRedbox` also uncovered some unused expressions e.g. `await
hasRedbox(browser)`.
These expressions probably wanted to use `expect(await
hasRedbox(browser)).toBe(true)
This commit is contained in:
Sebastian Silbermann 2024-06-20 10:37:32 +02:00 committed by GitHub
parent 503fa921ab
commit fe8d953e2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
87 changed files with 608 additions and 555 deletions

View file

@ -45,7 +45,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
expect(await session.getRedboxSource()).toMatchInlineSnapshot(` expect(await session.getRedboxSource()).toMatchInlineSnapshot(`
"./node_modules/my-package/index.js:1:13 "./node_modules/my-package/index.js:1:13
@ -92,7 +92,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
@ -145,7 +145,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
@ -195,7 +195,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
], ],
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
@ -234,7 +234,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.documentElement.innerHTML) await session.evaluate(() => document.documentElement.innerHTML)
).toContain('index page') ).toContain('index page')

View file

@ -33,17 +33,17 @@ describe.skip('ReactRefreshLogBox scss app', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
// Syntax error // Syntax error
await session.patch('index.module.scss', `.button { font-size: :5px; }`) await session.patch('index.module.scss', `.button { font-size: :5px; }`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
expect(source).toMatchSnapshot() expect(source).toMatchSnapshot()
// Fix syntax error // Fix syntax error
await session.patch('index.module.scss', `.button { font-size: 5px; }`) await session.patch('index.module.scss', `.button { font-size: 5px; }`)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -69,7 +69,7 @@ describe.skip('ReactRefreshLogBox scss app', () => {
// Checks for selectors that can't be prefixed. // Checks for selectors that can't be prefixed.
// Selector "button" is not pure (pure selectors must contain at least one local class or id) // Selector "button" is not pure (pure selectors must contain at least one local class or id)
await session.patch('index.module.scss', `button { font-size: 5px; }`) await session.patch('index.module.scss', `button { font-size: 5px; }`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source2 = await session.getRedboxSource() const source2 = await session.getRedboxSource()
expect(source2).toMatchSnapshot() expect(source2).toMatchSnapshot()

View file

@ -5,14 +5,13 @@ import {
check, check,
describeVariants as describe, describeVariants as describe,
expandCallStack, expandCallStack,
retry,
} from 'next-test-utils' } from 'next-test-utils'
import path from 'path' import path from 'path'
import { outdent } from 'outdent' import { outdent } from 'outdent'
const IS_TURBOPACK = Boolean(process.env.TURBOPACK)
describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => { describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
const { next } = nextTestSetup({ const { next, isTurbopack } = nextTestSetup({
files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')), files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
skipStart: true, skipStart: true,
}) })
@ -85,7 +84,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (process.platform === 'win32') { if (process.platform === 'win32') {
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
} else { } else {
@ -175,7 +174,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// We internally only check the script path, not including the line number // We internally only check the script path, not including the line number
// and error message because the error comes from an external library. // and error message because the error comes from an external library.
// This test ensures that the errored script path is correctly resolved. // This test ensures that the errored script path is correctly resolved.
@ -202,7 +201,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -217,23 +216,24 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
console.log({ isTurbopack })
const source = next.normalizeTestDirContent(await session.getRedboxSource()) const source = next.normalizeTestDirContent(await session.getRedboxSource())
if (IS_TURBOPACK) { if (isTurbopack) {
expect(source).toMatchInlineSnapshot(` expect(source).toEqual(outdent`
"./index.js:7:1 ./index.js:7:1
Parsing ecmascript source code failed Parsing ecmascript source code failed
5 | div 5 | div
6 | ) 6 | )
> 7 | } > 7 | }
| ^ | ^
Unexpected token. Did you mean \`{'}'}\` or \`}\`?" Unexpected token. Did you mean \`{'}'}\` or \`}\`?
`) `)
} else { } else {
expect(source).toMatchInlineSnapshot(` expect(source).toEqual(outdent`
"./index.js ./index.js
Error: Error:
x Unexpected token. Did you mean \`{'}'}\` or \`}\`? x Unexpected token. Did you mean \`{'}'}\` or \`}\`?
,-[TEST_DIR/index.js:4:1] ,-[TEST_DIR/index.js:4:1]
@ -257,7 +257,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
Import trace for requested module: Import trace for requested module:
./index.js ./index.js
./app/page.js" ./app/page.js
`) `)
} }
@ -292,7 +292,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('hello') ).toBe('hello')
@ -309,7 +309,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
await session.patch( await session.patch(
@ -324,7 +324,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('hello new') ).toBe('hello new')
@ -350,26 +350,26 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
// Syntax error // Syntax error
await session.patch('index.module.css', `.button`) await session.patch('index.module.css', `.button`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
expect(source).toMatch( expect(source).toMatch(
IS_TURBOPACK ? './index.module.css:1:9' : './index.module.css:1:1' isTurbopack ? './index.module.css:1:9' : './index.module.css:1:1'
) )
if (!IS_TURBOPACK) { if (!isTurbopack) {
expect(source).toMatch('Syntax error: ') expect(source).toMatch('Syntax error: ')
expect(source).toMatch('Unknown word') expect(source).toMatch('Unknown word')
} }
expect(source).toMatch('> 1 | .button') expect(source).toMatch('> 1 | .button')
expect(source).toMatch(IS_TURBOPACK ? ' | ^' : ' | ^') expect(source).toMatch(isTurbopack ? ' | ^' : ' | ^')
// Checks for selectors that can't be prefixed. // Checks for selectors that can't be prefixed.
// Selector "button" is not pure (pure selectors must contain at least one local class or id) // Selector "button" is not pure (pure selectors must contain at least one local class or id)
await session.patch('index.module.css', `button {}`) await session.patch('index.module.css', `button {}`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source2 = await session.getRedboxSource() const source2 = await session.getRedboxSource()
expect(source2).toMatchSnapshot() expect(source2).toMatchSnapshot()
@ -536,8 +536,8 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
await session.waitForAndOpenRuntimeError() await session.waitForAndOpenRuntimeError()
const header4 = await session.getRedboxDescription() const header4 = await session.getRedboxDescription()
expect(header4).toMatchInlineSnapshot( expect(header4).toEqual(
`"Error: multiple https://nextjs.org links http://example.com"` `Error: multiple https://nextjs.org links http://example.com`
) )
// Do not highlight example.com but do highlight nextjs.org // Do not highlight example.com but do highlight nextjs.org
expect( expect(
@ -593,9 +593,9 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toEqual(
`"Error: {"a":1,"b":"x"}"` `Error: {"a":1,"b":"x"}`
) )
// fix previous error // fix previous error
@ -609,7 +609,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
outdent` outdent`
@ -623,7 +623,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toContain( expect(await session.getRedboxDescription()).toContain(
`Error: class Hello {` `Error: class Hello {`
) )
@ -639,7 +639,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
outdent` outdent`
@ -651,10 +651,8 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toEqual(`Error: string error`)
`"Error: string error"`
)
// fix previous error // fix previous error
await session.patch( await session.patch(
@ -667,7 +665,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
outdent` outdent`
@ -679,7 +677,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toContain( expect(await session.getRedboxDescription()).toContain(
`Error: A null error was thrown` `Error: A null error was thrown`
) )
@ -703,7 +701,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
await cleanup() await cleanup()
@ -764,7 +762,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
() => browser.elementByCss('.nextjs-toast-errors').text(), () => browser.elementByCss('.nextjs-toast-errors').text(),
/4 errors/ /4 errors/
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
// Add Component error // Add Component error
await session.patch( await session.patch(
@ -776,7 +774,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
) )
// Render error should "win" and show up in fullscreen // Render error should "win" and show up in fullscreen
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await cleanup() await cleanup()
}) })
@ -815,7 +813,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
])('Call stack count is correct for %s error', async (_, fixture) => { ])('Call stack count is correct for %s error', async (_, fixture) => {
const { session, browser, cleanup } = await sandbox(next, fixture) const { session, browser, cleanup } = await sandbox(next, fixture)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await expandCallStack(browser) await expandCallStack(browser)
@ -856,7 +854,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
], ],
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await expandCallStack(browser) await expandCallStack(browser)
let callStackFrames = await browser.elementsByCss( let callStackFrames = await browser.elementsByCss(
'[data-nextjs-call-stack-frame]' '[data-nextjs-call-stack-frame]'
@ -884,7 +882,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await expandCallStack(browser) await expandCallStack(browser)
// Should still show the errored line in source code // Should still show the errored line in source code
@ -919,7 +917,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
], ],
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// Remove error // Remove error
await session.patch( await session.patch(
@ -933,7 +931,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
expect(await browser.waitForElementByCss('#text').text()).toBe( expect(await browser.waitForElementByCss('#text').text()).toBe(
'Hello world' 'Hello world'
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
// Re-add error // Re-add error
await session.patch( await session.patch(
@ -946,7 +944,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await cleanup() await cleanup()
}) })
@ -974,7 +972,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
await cleanup() await cleanup()
@ -1005,8 +1003,32 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) // Wait for patch to apply and new error to show.
expect(await session.getRedboxSource()).toMatchSnapshot() await session.assertHasRedbox()
if (isTurbopack) {
await retry(async () => {
expect(await session.getRedboxSource()).toEqual(outdent`
./app/styles2.css:1:2
Module not found: Can't resolve './boom.css'
> 1 | @import "./boom.css"
| ^
https://nextjs.org/docs/messages/module-not-found
`)
})
} else {
await retry(async () => {
expect(await session.getRedboxSource()).toEqual(outdent`
./app/styles2.css
Module not found: Can't resolve './boom.css'
https://nextjs.org/docs/messages/module-not-found
Import trace for requested module:
./app/styles1.css
`)
})
}
await cleanup() await cleanup()
}) })
@ -1017,12 +1039,12 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => {
const { session, cleanup } = await sandbox(next, undefined, '/' + type) const { session, cleanup } = await sandbox(next, undefined, '/' + type)
await next.patchFile('index.js', "throw new Error('module error')") await next.patchFile('index.js', "throw new Error('module error')")
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await next.patchFile( await next.patchFile(
'index.js', 'index.js',
'export default function Page() {return <p>hello world</p>}' 'export default function Page() {return <p>hello world</p>}'
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })

View file

@ -30,7 +30,7 @@ describe.skip('ReactRefreshLogBox app', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: Multiple children were passed to <Link> with \`href\` of \`/\` but only one child is supported https://nextjs.org/docs/messages/link-multiple-children"` `"Error: Multiple children were passed to <Link> with \`href\` of \`/\` but only one child is supported https://nextjs.org/docs/messages/link-multiple-children"`
) )
@ -64,7 +64,7 @@ describe.skip('ReactRefreshLogBox app', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: Failed prop type: The prop \`href\` expects a \`string\` or \`object\` in \`<Link>\`, but got \`undefined\` instead."` `"Error: Failed prop type: The prop \`href\` expects a \`string\` or \`object\` in \`<Link>\`, but got \`undefined\` instead."`
) )
@ -79,7 +79,7 @@ describe.skip('ReactRefreshLogBox app', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -103,7 +103,7 @@ describe.skip('ReactRefreshLogBox app', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -127,7 +127,7 @@ describe.skip('ReactRefreshLogBox app', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -151,7 +151,7 @@ describe.skip('ReactRefreshLogBox app', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -175,7 +175,7 @@ describe.skip('ReactRefreshLogBox app', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchSnapshot() expect(await session.getRedboxDescription()).toMatchSnapshot()
await session.patch( await session.patch(
@ -200,7 +200,7 @@ describe.skip('ReactRefreshLogBox app', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchSnapshot() expect(await session.getRedboxDescription()).toMatchSnapshot()
await cleanup() await cleanup()
@ -227,7 +227,7 @@ describe.skip('ReactRefreshLogBox app', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await cleanup() await cleanup()
}) })
}) })

View file

@ -11,7 +11,7 @@ describe('ReactRefreshModule app', () => {
it('should allow any variable names', async () => { it('should allow any variable names', async () => {
const { session, cleanup } = await sandbox(next, new Map([])) const { session, cleanup } = await sandbox(next, new Map([]))
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
const variables = [ const variables = [
'_a', '_a',
@ -33,7 +33,7 @@ describe('ReactRefreshModule app', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect(next.cliOutput).not.toContain( expect(next.cliOutput).not.toContain(
`'${variable}' has already been declared` `'${variable}' has already been declared`
) )

View file

@ -74,7 +74,7 @@ describe('ReactRefreshRegression app', () => {
) )
// Verify no hydration mismatch: // Verify no hydration mismatch:
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -279,7 +279,7 @@ describe('ReactRefreshRegression app', () => {
`export default function () { throw new Error('boom'); }` `export default function () { throw new Error('boom'); }`
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
expect(source.split(/\r?\n/g).slice(2).join('\n')).toMatchInlineSnapshot(` expect(source.split(/\r?\n/g).slice(2).join('\n')).toMatchInlineSnapshot(`
@ -298,7 +298,7 @@ describe('ReactRefreshRegression app', () => {
`export default function Page() { throw new Error('boom'); }` `export default function Page() { throw new Error('boom'); }`
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
expect(source.split(/\r?\n/g).slice(2).join('\n')).toMatchInlineSnapshot(` expect(source.split(/\r?\n/g).slice(2).join('\n')).toMatchInlineSnapshot(`
@ -320,7 +320,7 @@ describe('ReactRefreshRegression app', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
expect(source.split(/\r?\n/g).slice(2).join('\n')).toMatchInlineSnapshot(` expect(source.split(/\r?\n/g).slice(2).join('\n')).toMatchInlineSnapshot(`
@ -371,7 +371,7 @@ describe('ReactRefreshRegression app', () => {
let didNotReload = await session.patch('app/content.mdx', `Hello Foo!`) let didNotReload = await session.patch('app/content.mdx', `Hello Foo!`)
expect(didNotReload).toBe(true) expect(didNotReload).toBe(true)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate( await session.evaluate(
() => document.querySelector('#content').textContent () => document.querySelector('#content').textContent
@ -380,7 +380,7 @@ describe('ReactRefreshRegression app', () => {
didNotReload = await session.patch('app/content.mdx', `Hello Bar!`) didNotReload = await session.patch('app/content.mdx', `Hello Bar!`)
expect(didNotReload).toBe(true) expect(didNotReload).toBe(true)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate( await session.evaluate(
() => document.querySelector('#content').textContent () => document.querySelector('#content').textContent

View file

@ -1,15 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ReactRefreshLogBox app default Can't resolve @import in CSS file 1`] = `
"./app/styles2.css
Module not found: Can't resolve './boom.css'
https://nextjs.org/docs/messages/module-not-found
Import trace for requested module:
./app/styles1.css"
`;
exports[`ReactRefreshLogBox app default Import trace when module not found in layout 1`] = ` exports[`ReactRefreshLogBox app default Import trace when module not found in layout 1`] = `
"./app/module.js:1:1 "./app/module.js:1:1
Module not found: Can't resolve 'non-existing-module' Module not found: Can't resolve 'non-existing-module'
@ -72,7 +62,7 @@ exports[`ReactRefreshLogBox app default logbox: anchors links in error messages
exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 6`] = `"https://nextjs.org/"`; exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 6`] = `"https://nextjs.org/"`;
exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 8`] = `"https://nextjs.org/"`; exports[`ReactRefreshLogBox app default logbox: anchors links in error messages 7`] = `"https://nextjs.org/"`;
exports[`ReactRefreshLogBox app default module init error not shown 1`] = ` exports[`ReactRefreshLogBox app default module init error not shown 1`] = `
"index.js (3:7) @ eval "index.js (3:7) @ eval
@ -98,15 +88,6 @@ exports[`ReactRefreshLogBox app default should strip whitespace correctly with n
10 | </a>" 10 | </a>"
`; `;
exports[`ReactRefreshLogBox app turbo Can't resolve @import in CSS file 1`] = `
"./app/styles2.css:1:2
Module not found: Can't resolve './boom.css'
> 1 | @import "./boom.css"
| ^
https://nextjs.org/docs/messages/module-not-found"
`;
exports[`ReactRefreshLogBox app turbo Import trace when module not found in layout 1`] = ` exports[`ReactRefreshLogBox app turbo Import trace when module not found in layout 1`] = `
"./app/module.js:1:1 "./app/module.js:1:1
Module not found: Can't resolve 'non-existing-module' Module not found: Can't resolve 'non-existing-module'
@ -164,7 +145,7 @@ exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 5`
exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 6`] = `"https://nextjs.org/"`; exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 6`] = `"https://nextjs.org/"`;
exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 8`] = `"https://nextjs.org/"`; exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 7`] = `"https://nextjs.org/"`;
exports[`ReactRefreshLogBox app turbo module init error not shown 1`] = ` exports[`ReactRefreshLogBox app turbo module init error not shown 1`] = `
"index.js (3:7) @ <unknown> "index.js (3:7) @ <unknown>

View file

@ -51,12 +51,12 @@ describe('Error overlay - RSC build errors', () => {
await session.patch(pagePath, break2.replace('break 3', '<Hello />')) await session.patch(pagePath, break2.replace('break 3', '<Hello />'))
await session.patch(pagePath, break2) await session.patch(pagePath, break2)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await session.patch(pagePath, break1) await session.patch(pagePath, break1)
await session.patch(pagePath, originalPage) await session.patch(pagePath, originalPage)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
} }
expect( expect(

View file

@ -30,7 +30,7 @@ describe('dynamic = "error" in devmode', () => {
` `
) )
await session.hasRedbox() await session.assertHasRedbox()
console.log(await session.getRedboxDescription()) console.log(await session.getRedboxDescription())
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: Route /server with \`dynamic = "error"\` couldn't be rendered statically because it used \`cookies\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering"` `"Error: Route /server with \`dynamic = "error"\` couldn't be rendered statically because it used \`cookies\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering"`

View file

@ -65,7 +65,7 @@ describe('Error overlay - editor links', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await clickSourceFile(browser) await clickSourceFile(browser)
await check(() => editorRequestsCount, /1/) await check(() => editorRequestsCount, /1/)
@ -110,7 +110,7 @@ describe('Error overlay - editor links', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await clickImportTraceFiles(browser) await clickImportTraceFiles(browser)
await check(() => editorRequestsCount, /4/) await check(() => editorRequestsCount, /4/)
@ -153,7 +153,7 @@ describe('Error overlay - editor links', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await clickImportTraceFiles(browser) await clickImportTraceFiles(browser)
await check(() => editorRequestsCount, /3/) await check(() => editorRequestsCount, /3/)

View file

@ -19,7 +19,7 @@ describe('Error overlay - error message urls', () => {
content + '\nexport function getServerSideProps() {}' content + '\nexport function getServerSideProps() {}'
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const link = await browser.elementByCss('[data-nextjs-terminal] a') const link = await browser.elementByCss('[data-nextjs-terminal] a')
const text = await link.text() const text = await link.text()

View file

@ -39,7 +39,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
await session.patch('index.js', `export default () => <div/`) await session.patch('index.js', `export default () => <div/`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'export default () => <div/' 'export default () => <div/'
) )
@ -62,7 +62,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await check( await check(
() => session.evaluate(() => document.querySelector('p').textContent), () => session.evaluate(() => document.querySelector('p').textContent),
@ -89,7 +89,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
return <p>Hello world</p> return <p>Hello world</p>
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// Fix syntax error // Fix syntax error
await session.patch( await session.patch(
@ -170,7 +170,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect(await session.hasErrorToast()).toBe(false) expect(await session.hasErrorToast()).toBe(false)
expect( expect(
@ -181,7 +181,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('Count: 2') ).toBe('Count: 2')
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect(await session.hasErrorToast()).toBe(false) expect(await session.hasErrorToast()).toBe(false)
await cleanup() await cleanup()
@ -232,7 +232,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'export default function Child()' 'export default function Child()'
) )
@ -249,7 +249,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
// TODO-APP: re-enable when error recovery doesn't reload the page. // TODO-APP: re-enable when error recovery doesn't reload the page.
// expect(didNotReload).toBe(true) // expect(didNotReload).toBe(true)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('Hello') ).toBe('Hello')
@ -310,14 +310,14 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
) )
await new Promise((resolve) => setTimeout(resolve, 1000)) await new Promise((resolve) => setTimeout(resolve, 1000))
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
"Expected '}', got '<eof>'" "Expected '}', got '<eof>'"
) )
// Test that runtime error does not take over: // Test that runtime error does not take over:
await new Promise((resolve) => setTimeout(resolve, 2000)) await new Promise((resolve) => setTimeout(resolve, 2000))
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
"Expected '}', got '<eof>'" "Expected '}', got '<eof>'"
) )
@ -368,7 +368,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
) )
// We get an error because Foo didn't import React. Fair. // We get an error because Foo didn't import React. Fair.
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
"return React.createElement('h1', null, 'Foo');" "return React.createElement('h1', null, 'Foo');"
) )
@ -385,7 +385,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
) )
// Expected: this fixes the problem // Expected: this fixes the problem
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -428,7 +428,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
export default ClassDefault; export default ClassDefault;
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// Now change the code to introduce a runtime error without fixing the syntax error: // Now change the code to introduce a runtime error without fixing the syntax error:
await session.patch( await session.patch(
@ -446,7 +446,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
export default ClassDefault; export default ClassDefault;
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// Now fix the syntax error: // Now fix the syntax error:
await session.patch( await session.patch(
@ -464,7 +464,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
export default ClassDefault; export default ClassDefault;
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await check(async () => { await check(async () => {
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
@ -484,7 +484,7 @@ describe.each(['default', 'turbo'])('Error recovery app %s', () => {
new Map([['app/page.js', '{{{']]) new Map([['app/page.js', '{{{']])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await check(() => session.getRedboxSource(true), /Failed to compile/) await check(() => session.getRedboxSource(true), /Failed to compile/)
await cleanup() await cleanup()

View file

@ -83,7 +83,7 @@ describe('Error overlay for hydration errors', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect(await browser.elementByCss('.child').text()).toBe('Value') expect(await browser.elementByCss('.child').text()).toBe('Value')
@ -336,7 +336,7 @@ describe('Error overlay for hydration errors', () => {
) )
await session.waitForAndOpenRuntimeError() await session.waitForAndOpenRuntimeError()
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await getRedboxTotalErrorCount(browser)).toBe(1) expect(await getRedboxTotalErrorCount(browser)).toBe(1)
@ -396,7 +396,7 @@ describe('Error overlay for hydration errors', () => {
) )
await session.waitForAndOpenRuntimeError() await session.waitForAndOpenRuntimeError()
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await getRedboxTotalErrorCount(browser)).toBe(1) expect(await getRedboxTotalErrorCount(browser)).toBe(1)
@ -451,7 +451,7 @@ describe('Error overlay for hydration errors', () => {
) )
await session.waitForAndOpenRuntimeError() await session.waitForAndOpenRuntimeError()
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const description = await session.getRedboxDescription() const description = await session.getRedboxDescription()
expect(description).toContain( expect(description).toContain(
@ -523,7 +523,7 @@ describe('Error overlay for hydration errors', () => {
) )
await session.waitForAndOpenRuntimeError() await session.waitForAndOpenRuntimeError()
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await cleanup() await cleanup()
}) })
@ -569,7 +569,7 @@ describe('Error overlay for hydration errors', () => {
) )
await session.waitForAndOpenRuntimeError() await session.waitForAndOpenRuntimeError()
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const pseudoHtml = await session.getRedboxComponentStack() const pseudoHtml = await session.getRedboxComponentStack()
if (isTurbopack) { if (isTurbopack) {

View file

@ -63,7 +63,7 @@ describe('Error Overlay invalid imports', () => {
const withoutUseClient = content.replace("'use client'", '') const withoutUseClient = content.replace("'use client'", '')
await session.patch(pageFile, withoutUseClient) await session.patch(pageFile, withoutUseClient)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
expect(await session.getRedboxSource()).toMatchInlineSnapshot(` expect(await session.getRedboxSource()).toMatchInlineSnapshot(`
"./app "./app
@ -147,7 +147,7 @@ describe('Error Overlay invalid imports', () => {
const withoutUseClient = content.replace("'use client'", '') const withoutUseClient = content.replace("'use client'", '')
await session.patch(pageFile, withoutUseClient) await session.patch(pageFile, withoutUseClient)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
expect(await session.getRedboxSource()).toMatchInlineSnapshot(` expect(await session.getRedboxSource()).toMatchInlineSnapshot(`
"./node_modules/client-only-package "./node_modules/client-only-package
@ -229,7 +229,7 @@ describe('Error Overlay invalid imports', () => {
const content = await next.readFile(file) const content = await next.readFile(file)
await session.patch(file, "'use client'\n" + content) await session.patch(file, "'use client'\n" + content)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
expect(await session.getRedboxSource()).toMatchInlineSnapshot(` expect(await session.getRedboxSource()).toMatchInlineSnapshot(`
"./node_modules/server-only-package "./node_modules/server-only-package

View file

@ -25,7 +25,7 @@ describe('Error overlay - RSC build errors', () => {
) )
await session.patch(pageFile, uncomment) await session.patch(pageFile, uncomment)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'"getServerSideProps" is not supported in app/' '"getServerSideProps" is not supported in app/'
) )
@ -49,14 +49,14 @@ describe('Error overlay - RSC build errors', () => {
'export const metadata' 'export const metadata'
) )
await session.patch(pageFile, uncomment) await session.patch(pageFile, uncomment)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'You are attempting to export "metadata" from a component marked with "use client", which is disallowed.' 'You are attempting to export "metadata" from a component marked with "use client", which is disallowed.'
) )
// Restore file // Restore file
await session.patch(pageFile, content) await session.patch(pageFile, content)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
// Add `generateMetadata` error // Add `generateMetadata` error
uncomment = content.replace( uncomment = content.replace(
@ -64,14 +64,14 @@ describe('Error overlay - RSC build errors', () => {
'export async function generateMetadata' 'export async function generateMetadata'
) )
await session.patch(pageFile, uncomment) await session.patch(pageFile, uncomment)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'You are attempting to export "generateMetadata" from a component marked with "use client", which is disallowed.' 'You are attempting to export "generateMetadata" from a component marked with "use client", which is disallowed.'
) )
// Fix the error again to test error overlay works with hmr rebuild // Fix the error again to test error overlay works with hmr rebuild
await session.patch(pageFile, content) await session.patch(pageFile, content)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -91,7 +91,7 @@ describe('Error overlay - RSC build errors', () => {
) )
await session.patch(pageFile, uncomment) await session.patch(pageFile, uncomment)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'"metadata" and "generateMetadata" cannot be exported at the same time, please keep one of them.' '"metadata" and "generateMetadata" cannot be exported at the same time, please keep one of them.'
) )
@ -116,7 +116,7 @@ describe('Error overlay - RSC build errors', () => {
await session.patch(pageFile, uncomment) await session.patch(pageFile, uncomment)
await next.patchFile(pageFile, content) await next.patchFile(pageFile, content)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'"getStaticProps" is not supported in app/' '"getStaticProps" is not supported in app/'
) )
@ -136,7 +136,7 @@ describe('Error overlay - RSC build errors', () => {
'export const a = 123' 'export const a = 123'
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toInclude( expect(await session.getRedboxDescription()).toInclude(
'The default export is not a React Component in page: "/server-with-errors/page-export"' 'The default export is not a React Component in page: "/server-with-errors/page-export"'
) )
@ -151,7 +151,7 @@ describe('Error overlay - RSC build errors', () => {
'/server-with-errors/page-export-initial-error' '/server-with-errors/page-export-initial-error'
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toInclude( expect(await session.getRedboxDescription()).toInclude(
'The default export is not a React Component in page: "/server-with-errors/page-export-initial-error"' 'The default export is not a React Component in page: "/server-with-errors/page-export-initial-error"'
) )
@ -171,7 +171,7 @@ describe('Error overlay - RSC build errors', () => {
const uncomment = content.replace("// 'use client'", "'use client'") const uncomment = content.replace("// 'use client'", "'use client'")
await next.patchFile(pageFile, uncomment) await next.patchFile(pageFile, uncomment)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'directive must be placed before other expressions' 'directive must be placed before other expressions'
) )
@ -194,7 +194,7 @@ describe('Error overlay - RSC build errors', () => {
) )
await session.patch(pageFile, uncomment) await session.patch(pageFile, uncomment)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
`Youre importing a class component. It only works in a Client Component` `Youre importing a class component. It only works in a Client Component`
) )
@ -218,7 +218,7 @@ describe('Error overlay - RSC build errors', () => {
) )
await next.patchFile(file, uncomment) await next.patchFile(file, uncomment)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (isTurbopack) { if (isTurbopack) {
// TODO: fix the issue ordering. // TODO: fix the issue ordering.
// turbopack emits the resolve issue first instead of the transform issue. // turbopack emits the resolve issue first instead of the transform issue.
@ -268,7 +268,7 @@ describe('Error overlay - RSC build errors', () => {
`/server-with-errors/react-apis/${api.toLowerCase()}` `/server-with-errors/react-apis/${api.toLowerCase()}`
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
// `Component` has a custom error message // `Component` has a custom error message
api === 'Component' api === 'Component'
@ -294,7 +294,7 @@ describe('Error overlay - RSC build errors', () => {
`/server-with-errors/react-dom-apis/${api.toLowerCase()}` `/server-with-errors/react-dom-apis/${api.toLowerCase()}`
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
`You're importing a component that needs \`${api}\`. This React hook only works in a client component. To fix, mark the file (or its parent) with the \`"use client"\` directive.` `You're importing a component that needs \`${api}\`. This React hook only works in a client component. To fix, mark the file (or its parent) with the \`"use client"\` directive.`
) )
@ -320,7 +320,7 @@ describe('Error overlay - RSC build errors', () => {
await session.patch(file, uncomment) await session.patch(file, uncomment)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
`You're importing a component that needs "server-only". That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component.` `You're importing a component that needs "server-only". That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component.`
) )
@ -342,7 +342,7 @@ describe('Error overlay - RSC build errors', () => {
content.replace('() => <p>hello dynamic world</p>', 'undefined') content.replace('() => <p>hello dynamic world</p>', 'undefined')
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toInclude( expect(await session.getRedboxDescription()).toInclude(
`Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.` `Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.`
) )
@ -363,7 +363,7 @@ describe('Error overlay - RSC build errors', () => {
'export default function Error() {}' 'export default function Error() {}'
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await check( await check(
() => session.getRedboxSource(), () => session.getRedboxSource(),
/must be a Client \n| Component/ /must be a Client \n| Component/
@ -412,7 +412,7 @@ describe('Error overlay - RSC build errors', () => {
// Empty file // Empty file
await session.patch('app/server-with-errors/error-file/error.js', '') await session.patch('app/server-with-errors/error-file/error.js', '')
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await check(() => session.getRedboxSource(), /must be a Client Component/) await check(() => session.getRedboxSource(), /must be a Client Component/)
// TODO: investigate flakey snapshot due to spacing below // TODO: investigate flakey snapshot due to spacing below
@ -459,10 +459,7 @@ describe('Error overlay - RSC build errors', () => {
await session.patch(pagePath, content) await session.patch(pagePath, content)
await check( await session.assertHasRedbox()
async () => ((await session.hasRedbox()) ? 'success' : 'fail'),
/success/
)
expect(await session.getRedboxDescription()).toContain( expect(await session.getRedboxDescription()).toContain(
'Cannot add property x, object is not extensible' 'Cannot add property x, object is not extensible'

View file

@ -2,12 +2,10 @@ import path from 'path'
import { outdent } from 'outdent' import { outdent } from 'outdent'
import { FileRef, nextTestSetup } from 'e2e-utils' import { FileRef, nextTestSetup } from 'e2e-utils'
import { import {
check, assertHasRedbox,
getRedboxDescription, getRedboxDescription,
getRedboxSource, getRedboxSource,
getVersionCheckerText, getVersionCheckerText,
hasRedbox,
retry,
} from 'next-test-utils' } from 'next-test-utils'
describe('Error overlay - RSC runtime errors', () => { describe('Error overlay - RSC runtime errors', () => {
@ -29,10 +27,7 @@ describe('Error overlay - RSC runtime errors', () => {
const browser = await next.browser('/server') const browser = await next.browser('/server')
await check( await assertHasRedbox(browser)
async () => ((await hasRedbox(browser)) ? 'success' : 'fail'),
/success/
)
const errorDescription = await getRedboxDescription(browser) const errorDescription = await getRedboxDescription(browser)
expect(errorDescription).toContain( expect(errorDescription).toContain(
@ -55,12 +50,9 @@ describe('Error overlay - RSC runtime errors', () => {
const browser = await next.browser('/client') const browser = await next.browser('/client')
await check( await assertHasRedbox(browser)
async () => ((await hasRedbox(browser)) ? 'success' : 'fail'),
/success/
)
const errorDescription = await getRedboxDescription(browser)
const errorDescription = await getRedboxDescription(browser)
expect(errorDescription).toContain( expect(errorDescription).toContain(
'Error: `cookies` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context' 'Error: `cookies` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context'
) )
@ -77,10 +69,7 @@ describe('Error overlay - RSC runtime errors', () => {
) )
const browser = await next.browser('/server') const browser = await next.browser('/server')
await check( await assertHasRedbox(browser)
async () => ((await hasRedbox(browser)) ? 'success' : 'fail'),
/success/
)
const errorDescription = await getRedboxDescription(browser) const errorDescription = await getRedboxDescription(browser)
@ -98,10 +87,7 @@ describe('Error overlay - RSC runtime errors', () => {
` `
) )
const browser = await next.browser('/server') const browser = await next.browser('/server')
await check( await assertHasRedbox(browser)
async () => ((await hasRedbox(browser)) ? 'success' : 'fail'),
/success/
)
const source = await getRedboxSource(browser) const source = await getRedboxSource(browser)
// Can show the original source code // Can show the original source code
@ -120,11 +106,9 @@ describe('Error overlay - RSC runtime errors', () => {
) )
const browser = await next.browser('/server') const browser = await next.browser('/server')
await retry(async () => { await assertHasRedbox(browser)
expect(await hasRedbox(browser)).toBe(true)
})
const versionText = await getVersionCheckerText(browser) const versionText = await getVersionCheckerText(browser)
await expect(versionText).toMatch(/Next.js \([\w.-]+\)/) expect(versionText).toMatch(/Next.js \([\w.-]+\)/)
}) })
it('should not show the bundle layer info in the file trace', async () => { it('should not show the bundle layer info in the file trace', async () => {
@ -138,9 +122,7 @@ describe('Error overlay - RSC runtime errors', () => {
) )
const browser = await next.browser('/server') const browser = await next.browser('/server')
await retry(async () => { await assertHasRedbox(browser)
expect(await hasRedbox(browser)).toBe(true)
})
const source = await getRedboxSource(browser) const source = await getRedboxSource(browser)
expect(source).toContain('app/server/page.js') expect(source).toContain('app/server/page.js')
expect(source).not.toContain('//app/server/page.js') expect(source).not.toContain('//app/server/page.js')

View file

@ -541,7 +541,7 @@ describe('Error Overlay for server components', () => {
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// In webpack when the message too long it gets truncated with ` | ` with new lines. // In webpack when the message too long it gets truncated with ` | ` with new lines.
// So we need to check for the first part of the message. // So we need to check for the first part of the message.
const normalizedSource = await session.getRedboxSource() const normalizedSource = await session.getRedboxSource()

View file

@ -17,7 +17,7 @@ describe.each(['default', 'turbo'])(
next, next,
new Map([['pages/_app.js', ``]]) new Map([['pages/_app.js', ``]])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: The default export is not a React Component in page: "/_app""` `"Error: The default export is not a React Component in page: "/_app""`
) )
@ -31,7 +31,7 @@ describe.each(['default', 'turbo'])(
export default MyApp export default MyApp
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -40,7 +40,7 @@ describe.each(['default', 'turbo'])(
next, next,
new Map([['pages/_document.js', ``]]) new Map([['pages/_document.js', ``]])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: The default export is not a React Component in page: "/_document""` `"Error: The default export is not a React Component in page: "/_document""`
) )
@ -72,7 +72,7 @@ describe.each(['default', 'turbo'])(
export default MyDocument export default MyDocument
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -91,7 +91,7 @@ describe.each(['default', 'turbo'])(
], ],
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const content = await session.getRedboxSource() const content = await session.getRedboxSource()
const source = next.normalizeTestDirContent(content) const source = next.normalizeTestDirContent(content)
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
@ -142,7 +142,7 @@ describe.each(['default', 'turbo'])(
export default MyApp export default MyApp
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -179,7 +179,7 @@ describe.each(['default', 'turbo'])(
], ],
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = next.normalizeTestDirContent( const source = next.normalizeTestDirContent(
await session.getRedboxSource() await session.getRedboxSource()
) )
@ -244,7 +244,7 @@ describe.each(['default', 'turbo'])(
export default MyDocument export default MyDocument
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
} }

View file

@ -44,7 +44,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
expect(await session.getRedboxSource()).toMatchInlineSnapshot(` expect(await session.getRedboxSource()).toMatchInlineSnapshot(`
"./node_modules/my-package/index.js:1:13 "./node_modules/my-package/index.js:1:13
@ -92,7 +92,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
@ -145,7 +145,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
@ -201,7 +201,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
], ],
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
@ -238,7 +238,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.documentElement.innerHTML) await session.evaluate(() => document.documentElement.innerHTML)
).toContain('index page') ).toContain('index page')

View file

@ -32,11 +32,11 @@ describe.skip('ReactRefreshLogBox scss', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
// Syntax error // Syntax error
await session.patch('index.module.scss', `.button { font-size: :5px; }`) await session.patch('index.module.scss', `.button { font-size: :5px; }`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
expect(source).toMatchSnapshot() expect(source).toMatchSnapshot()
@ -64,7 +64,7 @@ describe.skip('ReactRefreshLogBox scss', () => {
// Checks for selectors that can't be prefixed. // Checks for selectors that can't be prefixed.
// Selector "button" is not pure (pure selectors must contain at least one local class or id) // Selector "button" is not pure (pure selectors must contain at least one local class or id)
await session.patch('index.module.scss', `button { font-size: 5px; }`) await session.patch('index.module.scss', `button { font-size: 5px; }`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source2 = await session.getRedboxSource() const source2 = await session.getRedboxSource()
expect(source2).toMatchSnapshot() expect(source2).toMatchSnapshot()

View file

@ -35,7 +35,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
) )
await session.evaluate(() => document.querySelector('a').click()) await session.evaluate(() => document.querySelector('a').click())
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
await cleanup() await cleanup()
@ -80,7 +80,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
await cleanup() await cleanup()
@ -141,7 +141,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
`export default function FunctionDefault() { throw new Error('no'); }` `export default function FunctionDefault() { throw new Error('no'); }`
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
expect( expect(
await session.evaluate(() => document.querySelector('h2').textContent) await session.evaluate(() => document.querySelector('h2').textContent)
@ -165,7 +165,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
}` }`
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// We internally only check the script path, not including the line number // We internally only check the script path, not including the line number
// and error message because the error comes from an external library. // and error message because the error comes from an external library.
// This test ensures that the errored script path is correctly resolved. // This test ensures that the errored script path is correctly resolved.
@ -192,7 +192,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -207,7 +207,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = next.normalizeTestDirContent(await session.getRedboxSource()) const source = next.normalizeTestDirContent(await session.getRedboxSource())
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
expect(source).toMatchInlineSnapshot(` expect(source).toMatchInlineSnapshot(`
@ -281,7 +281,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('hello') ).toBe('hello')
@ -298,7 +298,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
await session.patch( await session.patch(
@ -313,7 +313,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('hello new') ).toBe('hello new')
@ -339,11 +339,11 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
// Syntax error // Syntax error
await session.patch('index.module.css', `.button`) await session.patch('index.module.css', `.button`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
expect(source).toMatch( expect(source).toMatch(
process.env.TURBOPACK process.env.TURBOPACK
@ -365,7 +365,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
// Checks for selectors that can't be prefixed. // Checks for selectors that can't be prefixed.
// Selector "button" is not pure (pure selectors must contain at least one local class or id) // Selector "button" is not pure (pure selectors must contain at least one local class or id)
await session.patch('index.module.css', `button {}`) await session.patch('index.module.css', `button {}`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source2 = await session.getRedboxSource() const source2 = await session.getRedboxSource()
expect(source2).toMatchSnapshot() expect(source2).toMatchSnapshot()
@ -393,9 +393,9 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.evaluate(() => document.querySelector('button').click()) await session.evaluate(() => document.querySelector('button').click())
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const header = await session.getRedboxDescription() const header = await session.getRedboxDescription()
expect(header).toMatchSnapshot() expect(header).toMatchSnapshot()
@ -439,9 +439,9 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.evaluate(() => document.querySelector('button').click()) await session.evaluate(() => document.querySelector('button').click())
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const header2 = await session.getRedboxDescription() const header2 = await session.getRedboxDescription()
expect(header2).toMatchSnapshot() expect(header2).toMatchSnapshot()
@ -485,9 +485,9 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.evaluate(() => document.querySelector('button').click()) await session.evaluate(() => document.querySelector('button').click())
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const header3 = await session.getRedboxDescription() const header3 = await session.getRedboxDescription()
expect(header3).toMatchSnapshot() expect(header3).toMatchSnapshot()
@ -531,9 +531,9 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.evaluate(() => document.querySelector('button').click()) await session.evaluate(() => document.querySelector('button').click())
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const header4 = await session.getRedboxDescription() const header4 = await session.getRedboxDescription()
expect(header4).toMatchInlineSnapshot( expect(header4).toMatchInlineSnapshot(
@ -592,9 +592,9 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.evaluate(() => document.querySelector('button').click()) await session.evaluate(() => document.querySelector('button').click())
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const header5 = await session.getRedboxDescription() const header5 = await session.getRedboxDescription()
expect(header5).toMatchInlineSnapshot( expect(header5).toMatchInlineSnapshot(
@ -653,7 +653,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: {"a":1,"b":"x"}"` `"Error: {"a":1,"b":"x"}"`
) )
@ -669,7 +669,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
outdent` outdent`
@ -683,7 +683,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toContain( expect(await session.getRedboxDescription()).toContain(
`Error: class Hello {` `Error: class Hello {`
) )
@ -699,7 +699,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
outdent` outdent`
@ -711,7 +711,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: string error"` `"Error: string error"`
) )
@ -727,7 +727,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
outdent` outdent`
@ -739,7 +739,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toContain( expect(await session.getRedboxDescription()).toContain(
`Error: A null error was thrown` `Error: A null error was thrown`
) )
@ -765,7 +765,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await expandCallStack(browser) await expandCallStack(browser)
@ -806,7 +806,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
], ],
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await expandCallStack(browser) await expandCallStack(browser)
let callStackFrames = await browser.elementsByCss( let callStackFrames = await browser.elementsByCss(
'[data-nextjs-call-stack-frame]' '[data-nextjs-call-stack-frame]'
@ -836,7 +836,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
], ],
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await expandCallStack(browser) await expandCallStack(browser)
// Should still show the errored line in source code // Should still show the errored line in source code

View file

@ -30,7 +30,7 @@ describe.skip('ReactRefreshLogBox', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: Multiple children were passed to <Link> with \`href\` of \`/\` but only one child is supported https://nextjs.org/docs/messages/link-multiple-children"` `"Error: Multiple children were passed to <Link> with \`href\` of \`/\` but only one child is supported https://nextjs.org/docs/messages/link-multiple-children"`
) )
@ -64,7 +64,7 @@ describe.skip('ReactRefreshLogBox', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot( expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
`"Error: Failed prop type: The prop \`href\` expects a \`string\` or \`object\` in \`<Link>\`, but got \`undefined\` instead."` `"Error: Failed prop type: The prop \`href\` expects a \`string\` or \`object\` in \`<Link>\`, but got \`undefined\` instead."`
) )
@ -79,7 +79,7 @@ describe.skip('ReactRefreshLogBox', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -103,7 +103,7 @@ describe.skip('ReactRefreshLogBox', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -127,7 +127,7 @@ describe.skip('ReactRefreshLogBox', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -151,7 +151,7 @@ describe.skip('ReactRefreshLogBox', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await session.patch( await session.patch(
'index.js', 'index.js',
@ -175,7 +175,7 @@ describe.skip('ReactRefreshLogBox', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchSnapshot() expect(await session.getRedboxDescription()).toMatchSnapshot()
await session.patch( await session.patch(
@ -200,7 +200,7 @@ describe.skip('ReactRefreshLogBox', () => {
} }
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchSnapshot() expect(await session.getRedboxDescription()).toMatchSnapshot()
await cleanup() await cleanup()
@ -226,7 +226,7 @@ describe.skip('ReactRefreshLogBox', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await cleanup() await cleanup()
}) })
}) })

View file

@ -10,7 +10,7 @@ describe('ReactRefreshModule', () => {
it('should allow any variable names', async () => { it('should allow any variable names', async () => {
const { session, cleanup } = await sandbox(next) const { session, cleanup } = await sandbox(next)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
const variables = [ const variables = [
'_a', '_a',
@ -29,7 +29,7 @@ describe('ReactRefreshModule', () => {
return null return null
}` }`
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect(next.cliOutput).not.toContain( expect(next.cliOutput).not.toContain(
`'${variable}' has already been declared` `'${variable}' has already been declared`
) )

View file

@ -74,7 +74,7 @@ describe('ReactRefreshRegression', () => {
) )
// Verify no hydration mismatch: // Verify no hydration mismatch:
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -283,7 +283,7 @@ describe('ReactRefreshRegression', () => {
) )
expect(didNotReload).toBe(false) expect(didNotReload).toBe(false)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
expect(source.split(/\r?\n/g).slice(2).join('\n')).toMatchInlineSnapshot(` expect(source.split(/\r?\n/g).slice(2).join('\n')).toMatchInlineSnapshot(`
@ -326,7 +326,7 @@ describe('ReactRefreshRegression', () => {
let didNotReload = await session.patch('pages/mdx.mdx', `Hello Foo!`) let didNotReload = await session.patch('pages/mdx.mdx', `Hello Foo!`)
expect(didNotReload).toBe(true) expect(didNotReload).toBe(true)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate( await session.evaluate(
() => document.querySelector('#__next').textContent () => document.querySelector('#__next').textContent
@ -335,7 +335,7 @@ describe('ReactRefreshRegression', () => {
didNotReload = await session.patch('pages/mdx.mdx', `Hello Bar!`) didNotReload = await session.patch('pages/mdx.mdx', `Hello Bar!`)
expect(didNotReload).toBe(true) expect(didNotReload).toBe(true)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate( await session.evaluate(
() => document.querySelector('#__next').textContent () => document.querySelector('#__next').textContent

View file

@ -39,7 +39,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
await session.patch('index.js', `export default () => <div/`) await session.patch('index.js', `export default () => <div/`)
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'export default () => <div/' 'export default () => <div/'
) )
@ -67,7 +67,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
/Count: 1/ /Count: 1/
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -104,7 +104,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('1') ).toBe('1')
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (isTurbopack) { if (isTurbopack) {
expect(await session.getRedboxSource()).toMatchInlineSnapshot(` expect(await session.getRedboxSource()).toMatchInlineSnapshot(`
"index.js (7:11) @ <unknown> "index.js (7:11) @ <unknown>
@ -148,7 +148,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
@ -158,7 +158,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('Count: 2') ).toBe('Count: 2')
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -204,7 +204,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
'export default function Child()' 'export default function Child()'
) )
@ -219,7 +219,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
) )
expect(didNotReload).toBe(true) expect(didNotReload).toBe(true)
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect( expect(
await session.evaluate(() => document.querySelector('p').textContent) await session.evaluate(() => document.querySelector('p').textContent)
).toBe('Hello') ).toBe('Hello')
@ -265,7 +265,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
export default ClassDefault; export default ClassDefault;
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// Now change the code to introduce a runtime error without fixing the syntax error: // Now change the code to introduce a runtime error without fixing the syntax error:
await session.patch( await session.patch(
@ -283,7 +283,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
export default ClassDefault; export default ClassDefault;
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
// Now fix the syntax error: // Now fix the syntax error:
await session.patch( await session.patch(
@ -301,7 +301,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
export default ClassDefault; export default ClassDefault;
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await check(async () => { await check(async () => {
const source = await session.getRedboxSource() const source = await session.getRedboxSource()
@ -358,7 +358,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
) )
// We get an error because Foo didn't import React. Fair. // We get an error because Foo didn't import React. Fair.
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource()).toInclude( expect(await session.getRedboxSource()).toInclude(
"return React.createElement('h1', null, 'Foo');" "return React.createElement('h1', null, 'Foo');"
) )
@ -375,7 +375,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
) )
// Expected: this fixes the problem // Expected: this fixes the problem
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await cleanup() await cleanup()
}) })
@ -412,7 +412,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
) )
await new Promise((resolve) => setTimeout(resolve, 1000)) await new Promise((resolve) => setTimeout(resolve, 1000))
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
if (process.platform === 'win32') { if (process.platform === 'win32') {
expect(await session.getRedboxSource()).toMatchSnapshot() expect(await session.getRedboxSource()).toMatchSnapshot()
} else { } else {
@ -433,7 +433,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
) )
await new Promise((resolve) => setTimeout(resolve, 1000)) await new Promise((resolve) => setTimeout(resolve, 1000))
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
let redboxSource = next.normalizeTestDirContent( let redboxSource = next.normalizeTestDirContent(
await session.getRedboxSource() await session.getRedboxSource()
) )
@ -474,7 +474,7 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => {
// Test that runtime error does not take over: // Test that runtime error does not take over:
await new Promise((resolve) => setTimeout(resolve, 2000)) await new Promise((resolve) => setTimeout(resolve, 2000))
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
redboxSource = next.normalizeTestDirContent(await session.getRedboxSource()) redboxSource = next.normalizeTestDirContent(await session.getRedboxSource())
if (isTurbopack) { if (isTurbopack) {
// TODO: Remove this branching once import traces are implemented in Turbopack // TODO: Remove this branching once import traces are implemented in Turbopack

View file

@ -30,7 +30,7 @@ describe('Error overlay for hydration errors', () => {
]) ])
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toMatchInlineSnapshot(` expect(await session.getRedboxDescription()).toMatchInlineSnapshot(`
"Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used "Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used
@ -59,7 +59,7 @@ describe('Error overlay for hydration errors', () => {
` `
) )
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
expect(await browser.elementByCss('.child').text()).toBe('Value') expect(await browser.elementByCss('.child').text()).toBe('Value')

View file

@ -44,7 +44,7 @@ describe('Error Overlay for server components compiler errors in pages', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await check( await check(
() => session.getRedboxSource(), () => session.getRedboxSource(),
/That only works in a Server Component/ /That only works in a Server Component/
@ -103,7 +103,7 @@ describe('Error Overlay for server components compiler errors in pages', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await check( await check(
() => session.getRedboxSource(), () => session.getRedboxSource(),
/That only works in a Server Component/ /That only works in a Server Component/
@ -161,7 +161,7 @@ describe('Error Overlay for server components compiler errors in pages', () => {
` `
) )
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
await check( await check(
() => session.getRedboxSource(), () => session.getRedboxSource(),
/That only works in a Server Component/ /That only works in a Server Component/

View file

@ -9,7 +9,7 @@ describe.each(['default', 'turbo'])('basic app-dir tests', () => {
it('should reload app pages without error', async () => { it('should reload app pages without error', async () => {
const { session, cleanup, browser } = await sandbox(next, undefined, '/') const { session, cleanup, browser } = await sandbox(next, undefined, '/')
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
browser.refresh() browser.refresh()
@ -17,7 +17,7 @@ describe.each(['default', 'turbo'])('basic app-dir tests', () => {
await waitForHydration(browser) await waitForHydration(browser)
for (let i = 0; i < 15; i++) { for (let i = 0; i < 15; i++) {
expect(await session.hasRedbox()).toBe(false) await session.assertNoRedbox()
await waitFor(1000) await waitFor(1000)
} }

View file

@ -1,7 +1,7 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { import {
assertHasRedbox,
getRedboxCallStack, getRedboxCallStack,
hasRedbox,
shouldRunTurboDevTest, shouldRunTurboDevTest,
expandCallStack, expandCallStack,
getRedboxSource, getRedboxSource,
@ -29,7 +29,7 @@ describe('app dir - dynamic error trace', () => {
it('should show the error trace', async () => { it('should show the error trace', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
await hasRedbox(browser) await assertHasRedbox(browser)
await expandCallStack(browser) await expandCallStack(browser)
const callStack = await getRedboxCallStack(browser) const callStack = await getRedboxCallStack(browser)

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { assertHasRedbox, assertNoRedbox } from 'next-test-utils'
describe('develop - app-dir - edge errros hmr', () => { describe('develop - app-dir - edge errros hmr', () => {
const { next } = nextTestSetup({ const { next } = nextTestSetup({
@ -14,11 +14,11 @@ describe('develop - app-dir - edge errros hmr', () => {
return content.replace('{/* < */}', '<') // uncomment return content.replace('{/* < */}', '<') // uncomment
}) })
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await next.patchFile('app/comp.server.js', clientComponentSource) await next.patchFile('app/comp.server.js', clientComponentSource)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
}) })
it('should recover from build errors when client component error', async () => { it('should recover from build errors when client component error', async () => {
@ -29,10 +29,10 @@ describe('develop - app-dir - edge errros hmr', () => {
return content.replace('{/* < */}', '<') // uncomment return content.replace('{/* < */}', '<') // uncomment
}) })
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await next.patchFile('app/comp.client.js', clientComponentSource) await next.patchFile('app/comp.client.js', clientComponentSource)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
}) })
}) })

View file

@ -1,7 +1,7 @@
import { join } from 'path' import { join } from 'path'
import { nextTestSetup, FileRef } from 'e2e-utils' import { nextTestSetup, FileRef } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { assertHasRedbox, assertNoRedbox } from 'next-test-utils'
import { waitForHydration } from 'development-sandbox' import { waitForHydration } from 'development-sandbox'
describe('hmr-deleted-page', () => { describe('hmr-deleted-page', () => {
@ -19,12 +19,12 @@ describe('hmr-deleted-page', () => {
await next.deleteFile('app/page/style.css') await next.deleteFile('app/page/style.css')
await waitForHydration(browser) await waitForHydration(browser)
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await next.deleteFile('app/page') await next.deleteFile('app/page')
await waitForHydration(browser) await waitForHydration(browser)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await browser.elementByCss('h1').text()).toBe('404') expect(await browser.elementByCss('h1').text()).toBe('404')
}) })
}) })

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { assertNoRedbox } from 'next-test-utils'
describe('HMR Move File', () => { describe('HMR Move File', () => {
const { next } = nextTestSetup({ const { next } = nextTestSetup({
@ -17,7 +17,7 @@ describe('HMR Move File', () => {
content.replace('./button', './button2') content.replace('./button', './button2')
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await browser.elementByCss('#hello-world-button').text()).toBe( expect(await browser.elementByCss('#hello-world-button').text()).toBe(
'hello world' 'hello world'

View file

@ -1,5 +1,11 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxDescription, hasRedbox, retry } from 'next-test-utils' import {
assertHasRedbox,
assertNoRedbox,
getRedboxDescription,
retry,
} from 'next-test-utils'
import { outdent } from 'outdent'
describe('app-dir - missing required html tags', () => { describe('app-dir - missing required html tags', () => {
const { next } = nextTestSetup({ files: __dirname }) const { next } = nextTestSetup({ files: __dirname })
@ -7,7 +13,7 @@ describe('app-dir - missing required html tags', () => {
it('should show error overlay', async () => { it('should show error overlay', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(` expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(`
"The following tags are missing in the Root Layout: <html>, <body>. "The following tags are missing in the Root Layout: <html>, <body>.
Read more at https://nextjs.org/docs/messages/missing-root-layout-tags" Read more at https://nextjs.org/docs/messages/missing-root-layout-tags"
@ -21,11 +27,14 @@ describe('app-dir - missing required html tags', () => {
code.replace('return children', 'return <body>{children}</body>') code.replace('return children', 'return <body>{children}</body>')
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(` // Wait for the HMR to apply and the updated error to show.
"The following tags are missing in the Root Layout: <html>. await retry(async () => {
Read more at https://nextjs.org/docs/messages/missing-root-layout-tags" expect(await getRedboxDescription(browser)).toEqual(outdent`
`) The following tags are missing in the Root Layout: <html>.
Read more at https://nextjs.org/docs/messages/missing-root-layout-tags
`)
})
await next.patchFile('app/layout.js', (code) => await next.patchFile('app/layout.js', (code) =>
code.replace( code.replace(
@ -34,7 +43,7 @@ describe('app-dir - missing required html tags', () => {
) )
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await browser.elementByCss('p').text()).toBe('hello world') expect(await browser.elementByCss('p').text()).toBe('hello world')
// Reintroduce the bug, but only missing html tag // Reintroduce the bug, but only missing html tag
@ -45,9 +54,7 @@ describe('app-dir - missing required html tags', () => {
) )
) )
await retry(async () => { await assertHasRedbox(browser)
expect(await hasRedbox(browser)).toBe(true)
})
// Fix the issue again // Fix the issue again
await next.patchFile('app/layout.js', (code) => await next.patchFile('app/layout.js', (code) =>
@ -57,8 +64,6 @@ describe('app-dir - missing required html tags', () => {
) )
) )
await retry(async () => { await assertNoRedbox(browser)
expect(await hasRedbox(browser)).toBe(false)
})
}) })
}) })

View file

@ -1,6 +1,6 @@
import { join } from 'path' import { join } from 'path'
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { assertNoRedbox } from 'next-test-utils'
// Skipped in Turbopack, will be added later. // Skipped in Turbopack, will be added later.
;(process.env.TURBOPACK ? describe.skip : describe)( ;(process.env.TURBOPACK ? describe.skip : describe)(
@ -32,7 +32,7 @@ import { hasRedbox } from 'next-test-utils'
expect(await $('#typography').text()).toContain('typography') expect(await $('#typography').text()).toContain('typography')
const browser = await next.browser('/mui') const browser = await next.browser('/mui')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
const modules = [...logs.matchAll(/\((\d+) modules\)/g)] const modules = [...logs.matchAll(/\((\d+) modules\)/g)]
expect(modules.length).toBeGreaterThanOrEqual(1) expect(modules.length).toBeGreaterThanOrEqual(1)

View file

@ -1,6 +1,6 @@
import { join } from 'path' import { join } from 'path'
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { assertNoRedbox } from 'next-test-utils'
describe('optimizePackageImports - mui', () => { describe('optimizePackageImports - mui', () => {
const { next } = nextTestSetup({ const { next } = nextTestSetup({
@ -20,6 +20,6 @@ describe('optimizePackageImports - mui', () => {
it('should work', async () => { it('should work', async () => {
// Without barrel optimization, the reproduction breaks. // Without barrel optimization, the reproduction breaks.
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
}) })
}) })

View file

@ -3,7 +3,12 @@
import { join } from 'path' import { join } from 'path'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { createNext, FileRef } from 'e2e-utils' import { createNext, FileRef } from 'e2e-utils'
import { check, getRedboxHeader, hasRedbox } from 'next-test-utils' import {
assertHasRedbox,
assertNoRedbox,
check,
getRedboxHeader,
} from 'next-test-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
const installCheckVisible = (browser) => { const installCheckVisible = (browser) => {
@ -271,13 +276,13 @@ describe('GS(S)P Server-Side Change Reloading', () => {
try { try {
await next.patchFile(page, originalContent.replace('props:', 'propss:')) await next.patchFile(page, originalContent.replace('props:', 'propss:'))
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Additional keys were returned from' 'Additional keys were returned from'
) )
await next.patchFile(page, originalContent) await next.patchFile(page, originalContent)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} finally { } finally {
await next.patchFile(page, originalContent) await next.patchFile(page, originalContent)
} }
@ -301,11 +306,11 @@ describe('GS(S)P Server-Side Change Reloading', () => {
'throw new Error("custom oops"); const count' 'throw new Error("custom oops"); const count'
) )
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain('custom oops') expect(await getRedboxHeader(browser)).toContain('custom oops')
await next.patchFile(page, originalContent) await next.patchFile(page, originalContent)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} finally { } finally {
await next.patchFile(page, originalContent) await next.patchFile(page, originalContent)
} }

View file

@ -2,12 +2,13 @@ import { join } from 'path'
import cheerio from 'cheerio' import cheerio from 'cheerio'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { import {
assertHasRedbox,
assertNoRedbox,
check, check,
getBrowserBodyText, getBrowserBodyText,
getRedboxHeader, getRedboxHeader,
getRedboxDescription, getRedboxDescription,
getRedboxSource, getRedboxSource,
hasRedbox,
renderViaHTTP, renderViaHTTP,
retry, retry,
waitFor, waitFor,
@ -498,7 +499,7 @@ describe.each([[''], ['/docs']])(
await next.patchFile(aboutPage, aboutContent.replace('</div>', 'div')) await next.patchFile(aboutPage, aboutContent.replace('</div>', 'div'))
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const source = next.normalizeTestDirContent( const source = next.normalizeTestDirContent(
await getRedboxSource(browser) await getRedboxSource(browser)
) )
@ -608,7 +609,7 @@ describe.each([[''], ['/docs']])(
browser = await webdriver(next.url, basePath + '/hmr/contact') browser = await webdriver(next.url, basePath + '/hmr/contact')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toMatch(/Unexpected eof/) expect(await getRedboxSource(browser)).toMatch(/Unexpected eof/)
await next.patchFile(aboutPage, aboutContent) await next.patchFile(aboutPage, aboutContent)
@ -651,7 +652,7 @@ describe.each([[''], ['/docs']])(
aboutContent.replace('export', 'aa=20;\nexport') aboutContent.replace('export', 'aa=20;\nexport')
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch(/aa is not defined/) expect(await getRedboxHeader(browser)).toMatch(/aa is not defined/)
await next.patchFile(aboutPage, aboutContent) await next.patchFile(aboutPage, aboutContent)
@ -687,7 +688,7 @@ describe.each([[''], ['/docs']])(
) )
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toMatch(/an-expected-error/) expect(await getRedboxSource(browser)).toMatch(/an-expected-error/)
await next.patchFile(aboutPage, aboutContent) await next.patchFile(aboutPage, aboutContent)
@ -732,7 +733,7 @@ describe.each([[''], ['/docs']])(
) )
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot( expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
`"Error: The default export is not a React Component in page: "/hmr/about5""` `"Error: The default export is not a React Component in page: "/hmr/about5""`
) )
@ -780,7 +781,7 @@ describe.each([[''], ['/docs']])(
) )
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
// TODO: Replace this when webpack 5 is the default // TODO: Replace this when webpack 5 is the default
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
`Objects are not valid as a React child (found: [object RegExp]). If you meant to render a collection of children, use an array instead.` `Objects are not valid as a React child (found: [object RegExp]). If you meant to render a collection of children, use an array instead.`
@ -830,7 +831,7 @@ describe.each([[''], ['/docs']])(
) )
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot( expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
`"Error: The default export is not a React Component in page: "/hmr/about7""` `"Error: The default export is not a React Component in page: "/hmr/about7""`
) )
@ -841,7 +842,7 @@ describe.each([[''], ['/docs']])(
() => getBrowserBodyText(browser), () => getBrowserBodyText(browser),
/This is the about page/ /This is the about page/
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} catch (err) { } catch (err) {
await next.patchFile(aboutPage, aboutContent) await next.patchFile(aboutPage, aboutContent)
@ -880,7 +881,7 @@ describe.each([[''], ['/docs']])(
) )
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch('Failed to compile') expect(await getRedboxHeader(browser)).toMatch('Failed to compile')
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
@ -913,7 +914,7 @@ describe.each([[''], ['/docs']])(
() => getBrowserBodyText(browser), () => getBrowserBodyText(browser),
/This is the about page/ /This is the about page/
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} catch (err) { } catch (err) {
await next.patchFile(aboutPage, aboutContent) await next.patchFile(aboutPage, aboutContent)
@ -952,7 +953,7 @@ describe.each([[''], ['/docs']])(
) )
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch('Failed to compile') expect(await getRedboxHeader(browser)).toMatch('Failed to compile')
let redboxSource = await getRedboxSource(browser) let redboxSource = await getRedboxSource(browser)
@ -999,7 +1000,7 @@ describe.each([[''], ['/docs']])(
() => getBrowserBodyText(browser), () => getBrowserBodyText(browser),
/This is the about page/ /This is the about page/
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} catch (err) { } catch (err) {
await next.patchFile(aboutPage, aboutContent) await next.patchFile(aboutPage, aboutContent)
@ -1024,7 +1025,7 @@ describe.each([[''], ['/docs']])(
browser = await webdriver(next.url, basePath + '/hmr') browser = await webdriver(next.url, basePath + '/hmr')
await browser.elementByCss('#error-in-gip-link').click() await browser.elementByCss('#error-in-gip-link').click()
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot( expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
`"Error: an-expected-error-in-gip"` `"Error: an-expected-error-in-gip"`
) )
@ -1065,7 +1066,7 @@ describe.each([[''], ['/docs']])(
try { try {
browser = await webdriver(next.url, basePath + '/hmr/error-in-gip') browser = await webdriver(next.url, basePath + '/hmr/error-in-gip')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot( expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
`"Error: an-expected-error-in-gip"` `"Error: an-expected-error-in-gip"`
) )
@ -1212,7 +1213,7 @@ describe.each([[''], ['/docs']])(
pageName, pageName,
`import hello from 'non-existent'\n` + originalContent `import hello from 'non-existent'\n` + originalContent
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await waitFor(3000) await waitFor(3000)
await next.patchFile(pageName, originalContent) await next.patchFile(pageName, originalContent)
await check( await check(

View file

@ -2,7 +2,7 @@ import { join } from 'path'
import cheerio from 'cheerio' import cheerio from 'cheerio'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { createNext, FileRef } from 'e2e-utils' import { createNext, FileRef } from 'e2e-utils'
import { renderViaHTTP, check, hasRedbox } from 'next-test-utils' import { assertNoRedbox, renderViaHTTP, check } from 'next-test-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
const customDocumentGipContent = `\ const customDocumentGipContent = `\
@ -166,7 +166,7 @@ describe('next/dynamic', () => {
try { try {
browser = await webdriver(next.url, basePath + '/dynamic/no-ssr') browser = await webdriver(next.url, basePath + '/dynamic/no-ssr')
await check(() => browser.elementByCss('body').text(), /navigator/) await check(() => browser.elementByCss('body').text(), /navigator/)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} finally { } finally {
if (browser) { if (browser) {
await browser.close() await browser.close()
@ -179,7 +179,7 @@ describe('next/dynamic', () => {
try { try {
browser = await webdriver(next.url, basePath + '/dynamic/no-ssr-esm') browser = await webdriver(next.url, basePath + '/dynamic/no-ssr-esm')
await check(() => browser.elementByCss('body').text(), /esm.mjs/) await check(() => browser.elementByCss('body').text(), /esm.mjs/)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} finally { } finally {
if (browser) { if (browser) {
await browser.close() await browser.close()

View file

@ -1,6 +1,6 @@
import fs from 'fs-extra' import fs from 'fs-extra'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { check, findPort, hasRedbox } from 'next-test-utils' import { assertNoRedbox, check, findPort } from 'next-test-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { createNext } from 'e2e-utils' import { createNext } from 'e2e-utils'
import stripAnsi from 'strip-ansi' import stripAnsi from 'strip-ansi'
@ -42,7 +42,7 @@ describe.skip('Project Directory Renaming', () => {
await check(async () => { await check(async () => {
return (await browser.eval('window.beforeNav')) === 1 ? 'pending' : 'done' return (await browser.eval('window.beforeNav')) === 1 ? 'pending' : 'done'
}, 'done') }, 'done')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
try { try {
// should still HMR correctly // should still HMR correctly

View file

@ -1,8 +1,9 @@
import { createNext, FileRef } from 'e2e-utils' import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { import {
assertHasRedbox,
assertNoRedbox,
check, check,
hasRedbox,
renderViaHTTP, renderViaHTTP,
getRedboxSource, getRedboxSource,
} from 'next-test-utils' } from 'next-test-utils'
@ -83,7 +84,7 @@ describe('jsconfig-path-reloading', () => {
)}` )}`
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain('"@lib/second-data"') expect(await getRedboxSource(browser)).toContain('"@lib/second-data"')
await next.patchFile( await next.patchFile(
@ -104,7 +105,7 @@ describe('jsconfig-path-reloading', () => {
) )
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
const html2 = await browser.eval('document.documentElement.innerHTML') const html2 = await browser.eval('document.documentElement.innerHTML')
expect(html2).toContain('first button') expect(html2).toContain('first button')
@ -159,7 +160,7 @@ describe('jsconfig-path-reloading', () => {
indexContent.replace('@mybutton', '@myotherbutton') indexContent.replace('@mybutton', '@myotherbutton')
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
const html2 = await browser.eval('document.documentElement.innerHTML') const html2 = await browser.eval('document.documentElement.innerHTML')

View file

@ -1,4 +1,9 @@
import { check, getRedboxSource, hasRedbox } from 'next-test-utils' import {
assertHasRedbox,
assertNoRedbox,
check,
getRedboxSource,
} from 'next-test-utils'
import stripAnsi from 'strip-ansi' import stripAnsi from 'strip-ansi'
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
@ -48,9 +53,9 @@ describe('middleware - development errors', () => {
it('renders the error correctly and recovers', async () => { it('renders the error correctly and recovers', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await next.patchFile('middleware.js', `export default function () {}`) await next.patchFile('middleware.js', `export default function () {}`)
await hasRedbox(browser) await assertHasRedbox(browser)
}) })
}) })
@ -85,7 +90,7 @@ describe('middleware - development errors', () => {
it('does not render the error', async () => { it('does not render the error', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await browser.elementByCss('#page-title')).toBeTruthy() expect(await browser.elementByCss('#page-title')).toBeTruthy()
}) })
}) })
@ -122,10 +127,10 @@ describe('middleware - development errors', () => {
it('renders the error correctly and recovers', async () => { it('renders the error correctly and recovers', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain(`eval('test')`) expect(await getRedboxSource(browser)).toContain(`eval('test')`)
await next.patchFile('middleware.js', `export default function () {}`) await next.patchFile('middleware.js', `export default function () {}`)
await hasRedbox(browser) await assertHasRedbox(browser)
}) })
}) })
@ -160,13 +165,13 @@ describe('middleware - development errors', () => {
it('renders the error correctly and recovers', async () => { it('renders the error correctly and recovers', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const source = await getRedboxSource(browser) const source = await getRedboxSource(browser)
expect(source).toContain(`throw new Error('booooom!')`) expect(source).toContain(`throw new Error('booooom!')`)
expect(source).toContain('middleware.js') expect(source).toContain('middleware.js')
expect(source).not.toContain('//middleware.js') expect(source).not.toContain('//middleware.js')
await next.patchFile('middleware.js', `export default function () {}`) await next.patchFile('middleware.js', `export default function () {}`)
await hasRedbox(browser) await assertHasRedbox(browser)
}) })
}) })
@ -201,7 +206,7 @@ describe('middleware - development errors', () => {
it('does not render the error', async () => { it('does not render the error', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await browser.elementByCss('#page-title')).toBeTruthy() expect(await browser.elementByCss('#page-title')).toBeTruthy()
}) })
}) })
@ -239,7 +244,7 @@ describe('middleware - development errors', () => {
it('does not render the error', async () => { it('does not render the error', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await browser.elementByCss('#page-title')).toBeTruthy() expect(await browser.elementByCss('#page-title')).toBeTruthy()
}) })
}) })
@ -265,12 +270,12 @@ describe('middleware - development errors', () => {
it('renders the error correctly and recovers', async () => { it('renders the error correctly and recovers', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect( expect(
await browser.elementByCss('#nextjs__container_errors_desc').text() await browser.elementByCss('#nextjs__container_errors_desc').text()
).toEqual('Failed to compile') ).toEqual('Failed to compile')
await next.patchFile('middleware.js', `export default function () {}`) await next.patchFile('middleware.js', `export default function () {}`)
await hasRedbox(browser) await assertHasRedbox(browser)
expect(await browser.elementByCss('#page-title')).toBeTruthy() expect(await browser.elementByCss('#page-title')).toBeTruthy()
}) })
}) })
@ -295,11 +300,11 @@ describe('middleware - development errors', () => {
it('renders the error correctly and recovers', async () => { it('renders the error correctly and recovers', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await next.patchFile('middleware.js', `export default function () }`) await next.patchFile('middleware.js', `export default function () }`)
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await next.patchFile('middleware.js', `export default function () {}`) await next.patchFile('middleware.js', `export default function () {}`)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await browser.elementByCss('#page-title')).toBeTruthy() expect(await browser.elementByCss('#page-title')).toBeTruthy()
}) })
}) })

View file

@ -2,7 +2,11 @@ import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { join } from 'path' import { join } from 'path'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { getRedboxSource, hasRedbox } from 'next-test-utils' import {
assertHasRedbox,
assertNoRedbox,
getRedboxSource,
} from 'next-test-utils'
// TODO: The error overlay is not closed when restoring the working code. // TODO: The error overlay is not closed when restoring the working code.
describe.skip('next/font build-errors', () => { describe.skip('next/font build-errors', () => {
@ -32,7 +36,7 @@ export default function Page() {
` `
) )
expect(await hasRedbox(browser)).toBeTrue() await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
"app/page.js "app/page.js
\`next/font\` error: \`next/font\` error:
@ -40,7 +44,7 @@ export default function Page() {
`) `)
await next.patchFile('app/page.js', content) await next.patchFile('app/page.js', content)
expect(await hasRedbox(browser)).toBeFalse() await assertNoRedbox(browser)
}) })
it("should show a module not found error if local font file can' be resolved", async () => { it("should show a module not found error if local font file can' be resolved", async () => {
@ -60,7 +64,7 @@ export default function Page() {
` `
) )
expect(await hasRedbox(browser)).toBeTrue() await assertHasRedbox(browser)
const sourceLines = (await getRedboxSource(browser)).split('\n') const sourceLines = (await getRedboxSource(browser)).split('\n')
// Should display the file name correctly // Should display the file name correctly
@ -71,6 +75,6 @@ export default function Page() {
) )
await next.patchFile('app/page.js', content) await next.patchFile('app/page.js', content)
expect(await hasRedbox(browser)).toBeFalse() await assertNoRedbox(browser)
}) })
}) })

View file

@ -1,6 +1,6 @@
import { createNext, FileRef } from 'e2e-utils' import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { getRedboxSource, hasRedbox } from 'next-test-utils' import { assertHasRedbox, getRedboxSource } from 'next-test-utils'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { join } from 'path' import { join } from 'path'
@ -18,7 +18,7 @@ describe('font-loader-in-document-error', () => {
test('next/font inside _document', async () => { test('next/font inside _document', async () => {
const browser = await webdriver(next.url, '/') const browser = await webdriver(next.url, '/')
expect(await hasRedbox(browser)).toBeTrue() await assertHasRedbox(browser)
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
// TODO: Turbopack doesn't include pages/ // TODO: Turbopack doesn't include pages/
expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`

View file

@ -1,9 +1,10 @@
/* eslint-env jest */ /* eslint-env jest */
import { import {
assertHasRedbox,
assertNoRedbox,
fetchViaHTTP, fetchViaHTTP,
getRedboxSource, getRedboxSource,
hasRedbox,
getRedboxHeader, getRedboxHeader,
waitFor, waitFor,
check, check,
@ -55,7 +56,7 @@ describe('Client Navigation', () => {
it('should have proper error when no children are provided', async () => { it('should have proper error when no children are provided', async () => {
const browser = await webdriver(next.appPort, '/link-no-child') const browser = await webdriver(next.appPort, '/link-no-child')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'No children were passed to <Link> with `href` of `/about` but one child is required' 'No children were passed to <Link> with `href` of `/about` but one child is required'
) )
@ -63,7 +64,7 @@ describe('Client Navigation', () => {
it('should not throw error when one number type child is provided', async () => { it('should not throw error when one number type child is provided', async () => {
const browser = await webdriver(next.appPort, '/link-number-child') const browser = await webdriver(next.appPort, '/link-number-child')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
if (browser) await browser.close() if (browser) await browser.close()
}) })
@ -279,7 +280,7 @@ describe('Client Navigation', () => {
try { try {
browser = await webdriver(next.appPort, '/nav') browser = await webdriver(next.appPort, '/nav')
await browser.elementByCss('#empty-props').click() await browser.elementByCss('#empty-props').click()
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
/should resolve to an object\. But found "null" instead\./ /should resolve to an object\. But found "null" instead\./
) )
@ -1377,7 +1378,7 @@ describe('Client Navigation', () => {
let browser let browser
try { try {
browser = await webdriver(next.appPort, '/error-inside-browser-page') browser = await webdriver(next.appPort, '/error-inside-browser-page')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxSource(browser) const text = await getRedboxSource(browser)
expect(text).toMatch(/An Expected error occurred/) expect(text).toMatch(/An Expected error occurred/)
expect(text).toMatch(/pages[\\/]error-inside-browser-page\.js \(5:13\)/) expect(text).toMatch(/pages[\\/]error-inside-browser-page\.js \(5:13\)/)
@ -1395,7 +1396,7 @@ describe('Client Navigation', () => {
next.appPort, next.appPort,
'/error-in-the-browser-global-scope' '/error-in-the-browser-global-scope'
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxSource(browser) const text = await getRedboxSource(browser)
expect(text).toMatch(/An Expected error occurred/) expect(text).toMatch(/An Expected error occurred/)
expect(text).toMatch(/error-in-the-browser-global-scope\.js \(2:9\)/) expect(text).toMatch(/error-in-the-browser-global-scope\.js \(2:9\)/)
@ -1478,7 +1479,7 @@ describe('Client Navigation', () => {
await browser.waitForElementByCss('.nav-about') await browser.waitForElementByCss('.nav-about')
await browser.back() await browser.back()
await waitFor(1000) await waitFor(1000)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} finally { } finally {
if (browser) { if (browser) {
await browser.close() await browser.close()
@ -1498,7 +1499,7 @@ describe('Client Navigation', () => {
await browser.waitForElementByCss('.nav-about') await browser.waitForElementByCss('.nav-about')
await browser.back() await browser.back()
await waitFor(1000) await waitFor(1000)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} finally { } finally {
if (browser) { if (browser) {
await browser.close() await browser.close()
@ -1516,7 +1517,7 @@ describe('Client Navigation', () => {
await browser.waitForElementByCss('.nav-about') await browser.waitForElementByCss('.nav-about')
await browser.back() await browser.back()
await waitFor(1000) await waitFor(1000)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} finally { } finally {
if (browser) { if (browser) {
await browser.close() await browser.close()

View file

@ -3,9 +3,9 @@
import cheerio from 'cheerio' import cheerio from 'cheerio'
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { import {
assertHasRedbox,
fetchViaHTTP, fetchViaHTTP,
getRedboxHeader, getRedboxHeader,
hasRedbox,
renderViaHTTP, renderViaHTTP,
} from 'next-test-utils' } from 'next-test-utils'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
@ -133,7 +133,7 @@ describe('Client Navigation rendering', () => {
const expectedErrorMessage = const expectedErrorMessage =
'Circular structure in "getInitialProps" result of page "/circular-json-error".' 'Circular structure in "getInitialProps" result of page "/circular-json-error".'
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxHeader(browser) const text = await getRedboxHeader(browser)
expect(text).toContain(expectedErrorMessage) expect(text).toContain(expectedErrorMessage)
}) })
@ -147,7 +147,7 @@ describe('Client Navigation rendering', () => {
const expectedErrorMessage = const expectedErrorMessage =
'"InstanceInitialPropsPage.getInitialProps()" is defined as an instance method - visit https://nextjs.org/docs/messages/get-initial-props-as-an-instance-method for more information.' '"InstanceInitialPropsPage.getInitialProps()" is defined as an instance method - visit https://nextjs.org/docs/messages/get-initial-props-as-an-instance-method for more information.'
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxHeader(browser) const text = await getRedboxHeader(browser)
expect(text).toContain(expectedErrorMessage) expect(text).toContain(expectedErrorMessage)
}) })
@ -157,7 +157,7 @@ describe('Client Navigation rendering', () => {
const expectedErrorMessage = const expectedErrorMessage =
'"EmptyInitialPropsPage.getInitialProps()" should resolve to an object. But found "null" instead.' '"EmptyInitialPropsPage.getInitialProps()" should resolve to an object. But found "null" instead.'
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxHeader(browser) const text = await getRedboxHeader(browser)
expect(text).toContain(expectedErrorMessage) expect(text).toContain(expectedErrorMessage)
}) })
@ -193,14 +193,14 @@ describe('Client Navigation rendering', () => {
test('default export is not a React Component', async () => { test('default export is not a React Component', async () => {
const browser = await webdriver(next.appPort, '/no-default-export') const browser = await webdriver(next.appPort, '/no-default-export')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxHeader(browser) const text = await getRedboxHeader(browser)
expect(text).toMatch(/The default export is not a React Component/) expect(text).toMatch(/The default export is not a React Component/)
}) })
test('error-inside-page', async () => { test('error-inside-page', async () => {
const browser = await webdriver(next.appPort, '/error-inside-page') const browser = await webdriver(next.appPort, '/error-inside-page')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxHeader(browser) const text = await getRedboxHeader(browser)
expect(text).toMatch(/This is an expected error/) expect(text).toMatch(/This is an expected error/)
// Sourcemaps are applied by react-error-overlay, so we can't check them on SSR. // Sourcemaps are applied by react-error-overlay, so we can't check them on SSR.
@ -211,7 +211,7 @@ describe('Client Navigation rendering', () => {
next.appPort, next.appPort,
'/error-in-the-global-scope' '/error-in-the-global-scope'
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxHeader(browser) const text = await getRedboxHeader(browser)
expect(text).toMatch(/aa is not defined/) expect(text).toMatch(/aa is not defined/)
// Sourcemaps are applied by react-error-overlay, so we can't check them on SSR. // Sourcemaps are applied by react-error-overlay, so we can't check them on SSR.
@ -311,7 +311,7 @@ describe('Client Navigation rendering', () => {
it('should show a valid error when undefined is thrown', async () => { it('should show a valid error when undefined is thrown', async () => {
const browser = await webdriver(next.appPort, '/throw-undefined') const browser = await webdriver(next.appPort, '/throw-undefined')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const text = await getRedboxHeader(browser) const text = await getRedboxHeader(browser)
expect(text).toContain( expect(text).toContain(

View file

@ -1,6 +1,6 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import fs from 'fs-extra' import fs from 'fs-extra'
import { hasRedbox } from 'next-test-utils' import { assertNoRedbox } from 'next-test-utils'
import path from 'path' import path from 'path'
describe('repeated-dev-edits', () => { describe('repeated-dev-edits', () => {
@ -25,7 +25,7 @@ describe('repeated-dev-edits', () => {
expect(await browser.elementByCss('p').text()).toBe('version-2') expect(await browser.elementByCss('p').text()).toBe('version-2')
// Verify no hydration mismatch: // Verify no hydration mismatch:
expect(await hasRedbox(browser)).toBeFalse() await assertNoRedbox(browser)
await next.patchFile( await next.patchFile(
pagePath, pagePath,
@ -35,11 +35,11 @@ describe('repeated-dev-edits', () => {
expect(await browser.elementByCss('p').text()).toBe('version-3') expect(await browser.elementByCss('p').text()).toBe('version-3')
// Verify no hydration mismatch: // Verify no hydration mismatch:
expect(await hasRedbox(browser)).toBeFalse() await assertNoRedbox(browser)
await browser.refresh() await browser.refresh()
// Verify no hydration mismatch: // Verify no hydration mismatch:
expect(await hasRedbox(browser)).toBeFalse() await assertNoRedbox(browser)
}) })
}) })

View file

@ -1,8 +1,9 @@
import { createNext, FileRef } from 'e2e-utils' import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { import {
assertHasRedbox,
assertNoRedbox,
check, check,
hasRedbox,
renderViaHTTP, renderViaHTTP,
getRedboxSource, getRedboxSource,
} from 'next-test-utils' } from 'next-test-utils'
@ -83,7 +84,7 @@ describe('tsconfig-path-reloading', () => {
)}` )}`
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain("'@lib/second-data'") expect(await getRedboxSource(browser)).toContain("'@lib/second-data'")
await next.patchFile( await next.patchFile(
@ -104,7 +105,7 @@ describe('tsconfig-path-reloading', () => {
) )
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
const html2 = await browser.eval('document.documentElement.innerHTML') const html2 = await browser.eval('document.documentElement.innerHTML')
expect(html2).toContain('first button') expect(html2).toContain('first button')
@ -159,7 +160,7 @@ describe('tsconfig-path-reloading', () => {
indexContent.replace('@mybutton', '@myotherbutton') indexContent.replace('@mybutton', '@myotherbutton')
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
const html2 = await browser.eval('document.documentElement.innerHTML') const html2 = await browser.eval('document.documentElement.innerHTML')

View file

@ -1,11 +1,11 @@
/* eslint-disable jest/no-standalone-expect */ /* eslint-disable jest/no-standalone-expect */
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { import {
assertHasRedbox,
check, check,
retry, retry,
waitFor, waitFor,
getRedboxSource, getRedboxSource,
hasRedbox,
} from 'next-test-utils' } from 'next-test-utils'
import type { Request, Response, Route } from 'playwright' import type { Request, Response, Route } from 'playwright'
import fs from 'fs-extra' import fs from 'fs-extra'
@ -705,7 +705,7 @@ describe('app-dir action handling', () => {
origContent + '\n\nexport const foo = 1' origContent + '\n\nexport const foo = 1'
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain( expect(await getRedboxSource(browser)).toContain(
'Only async functions are allowed to be exported in a "use server" file.' 'Only async functions are allowed to be exported in a "use server" file.'
) )

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, hasRedbox, waitFor } from 'next-test-utils' import { assertNoRedbox, check, waitFor } from 'next-test-utils'
describe('app dir', () => { describe('app dir', () => {
const { next, isNextDev, isNextStart, skipped } = nextTestSetup({ const { next, isNextDev, isNextStart, skipped } = nextTestSetup({
@ -36,7 +36,7 @@ describe('app dir', () => {
await waitFor(1000) await waitFor(1000)
// It should not have an error // It should not have an error
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
// HMR should still work // HMR should still work
const code = await next.readFile('app/page-with-loading/page.js') const code = await next.readFile('app/page-with-loading/page.js')

View file

@ -1,5 +1,10 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, hasRedbox, retry, shouldRunTurboDevTest } from 'next-test-utils' import {
assertNoRedbox,
check,
retry,
shouldRunTurboDevTest,
} from 'next-test-utils'
async function resolveStreamResponse(response: any, onData?: any) { async function resolveStreamResponse(response: any, onData?: any) {
let result = '' let result = ''
@ -250,7 +255,7 @@ describe('app dir - external dependency', () => {
expect($('#transpile-cjs-lib').text()).toBe('transpile-cjs-lib') expect($('#transpile-cjs-lib').text()).toBe('transpile-cjs-lib')
const browser = await next.browser('/cjs/client') const browser = await next.browser('/cjs/client')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
}) })
it('should export client module references in esm', async () => { it('should export client module references in esm', async () => {

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxHeader, hasRedbox } from 'next-test-utils' import { assertHasRedbox, getRedboxHeader } from 'next-test-utils'
process.env.__TEST_SENTINEL = 'build' process.env.__TEST_SENTINEL = 'build'
@ -198,7 +198,7 @@ describe('dynamic-data with dynamic = "error"', () => {
it('displays redbox when `dynamic = "error"` and dynamic data is read in dev', async () => { it('displays redbox when `dynamic = "error"` and dynamic data is read in dev', async () => {
let browser = await next.browser('/cookies?foo=foosearch') let browser = await next.browser('/cookies?foo=foosearch')
try { try {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
'Error: Route /cookies with `dynamic = "error"` couldn\'t be rendered statically because it used `cookies`' 'Error: Route /cookies with `dynamic = "error"` couldn\'t be rendered statically because it used `cookies`'
) )
@ -208,7 +208,7 @@ describe('dynamic-data with dynamic = "error"', () => {
browser = await next.browser('/headers?foo=foosearch') browser = await next.browser('/headers?foo=foosearch')
try { try {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
'Error: Route /headers with `dynamic = "error"` couldn\'t be rendered statically because it used `headers`' 'Error: Route /headers with `dynamic = "error"` couldn\'t be rendered statically because it used `headers`'
) )
@ -218,7 +218,7 @@ describe('dynamic-data with dynamic = "error"', () => {
browser = await next.browser('/search?foo=foosearch') browser = await next.browser('/search?foo=foosearch')
try { try {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
'Error: Route /search with `dynamic = "error"` couldn\'t be rendered statically because it used `searchParams`' 'Error: Route /search with `dynamic = "error"` couldn\'t be rendered statically because it used `searchParams`'
) )
@ -276,7 +276,7 @@ describe('dynamic-data inside cache scope', () => {
it('displays redbox when accessing dynamic data inside a cache scope', async () => { it('displays redbox when accessing dynamic data inside a cache scope', async () => {
let browser = await next.browser('/cookies') let browser = await next.browser('/cookies')
try { try {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
'Error: Route /cookies used "cookies" inside a function cached with "unstable_cache(...)".' 'Error: Route /cookies used "cookies" inside a function cached with "unstable_cache(...)".'
) )
@ -286,7 +286,7 @@ describe('dynamic-data inside cache scope', () => {
browser = await next.browser('/headers') browser = await next.browser('/headers')
try { try {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
'Error: Route /headers used "headers" inside a function cached with "unstable_cache(...)".' 'Error: Route /headers used "headers" inside a function cached with "unstable_cache(...)".'
) )

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxDescription, hasRedbox } from 'next-test-utils' import { assertHasRedbox, getRedboxDescription } from 'next-test-utils'
describe('dynamic-href', () => { describe('dynamic-href', () => {
const { const {
@ -20,7 +20,7 @@ describe('dynamic-href', () => {
const browser = await next.browser('/object') const browser = await next.browser('/object')
// Error should show up // Error should show up
expect(await hasRedbox(browser)).toBeTrue() await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot( expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
`"Error: Dynamic href \`/object/[slug]\` found in <Link> while using the \`/app\` router, this is not supported. Read more: https://nextjs.org/docs/messages/app-dir-dynamic-href"` `"Error: Dynamic href \`/object/[slug]\` found in <Link> while using the \`/app\` router, this is not supported. Read more: https://nextjs.org/docs/messages/app-dir-dynamic-href"`
) )
@ -48,7 +48,7 @@ describe('dynamic-href', () => {
const browser = await next.browser('/string') const browser = await next.browser('/string')
// Error should show up // Error should show up
expect(await hasRedbox(browser)).toBeTrue() await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot( expect(await getRedboxDescription(browser)).toMatchInlineSnapshot(
`"Error: Dynamic href \`/object/[slug]\` found in <Link> while using the \`/app\` router, this is not supported. Read more: https://nextjs.org/docs/messages/app-dir-dynamic-href"` `"Error: Dynamic href \`/object/[slug]\` found in <Link> while using the \`/app\` router, this is not supported. Read more: https://nextjs.org/docs/messages/app-dir-dynamic-href"`
) )

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxHeader, hasRedbox, retry } from 'next-test-utils' import { assertHasRedbox, getRedboxHeader, retry } from 'next-test-utils'
describe('app-dir - errors', () => { describe('app-dir - errors', () => {
const { next, isNextDev, isNextStart, skipped } = nextTestSetup({ const { next, isNextDev, isNextStart, skipped } = nextTestSetup({
@ -19,7 +19,7 @@ describe('app-dir - errors', () => {
if (isNextDev) { if (isNextDev) {
// TODO: investigate desired behavior here as it is currently // TODO: investigate desired behavior here as it is currently
// minimized by default // minimized by default
// expect(await hasRedbox(browser)).toBe(true) // await assertHasRedbox(browser)
// expect(await getRedboxHeader(browser)).toMatch(/this is a test/) // expect(await getRedboxHeader(browser)).toMatch(/this is a test/)
} else { } else {
await browser await browser
@ -47,7 +47,7 @@ describe('app-dir - errors', () => {
// Digest of the error message should be stable. // Digest of the error message should be stable.
).not.toBe('') ).not.toBe('')
// TODO-APP: ensure error overlay is shown for errors that happened before/during hydration // TODO-APP: ensure error overlay is shown for errors that happened before/during hydration
// expect(await hasRedbox(browser)).toBe(true) // await assertHasRedbox(browser)
// expect(await getRedboxHeader(browser)).toMatch(/this is a test/) // expect(await getRedboxHeader(browser)).toMatch(/this is a test/)
} else { } else {
await browser await browser
@ -68,7 +68,7 @@ describe('app-dir - errors', () => {
await browser.elementByCss('#error-trigger-button').click() await browser.elementByCss('#error-trigger-button').click()
if (isNextDev) { if (isNextDev) {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch(/this is a test/) expect(await getRedboxHeader(browser)).toMatch(/this is a test/)
} else { } else {
expect( expect(
@ -83,7 +83,7 @@ describe('app-dir - errors', () => {
const browser = await next.browser('/global-error-boundary/server') const browser = await next.browser('/global-error-boundary/server')
if (isNextDev) { if (isNextDev) {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch(/custom server error/) expect(await getRedboxHeader(browser)).toMatch(/custom server error/)
} else { } else {
expect( expect(

View file

@ -1,8 +1,8 @@
import { getRedboxHeader, hasRedbox } from 'next-test-utils' import { assertHasRedbox, getRedboxHeader } from 'next-test-utils'
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
async function testDev(browser, errorRegex) { async function testDev(browser, errorRegex) {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch(errorRegex) expect(await getRedboxHeader(browser)).toMatch(errorRegex)
} }

View file

@ -1,8 +1,8 @@
import { getRedboxHeader, hasRedbox } from 'next-test-utils' import { assertHasRedbox, getRedboxHeader } from 'next-test-utils'
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
async function testDev(browser, errorRegex) { async function testDev(browser, errorRegex) {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch(errorRegex) expect(await getRedboxHeader(browser)).toMatch(errorRegex)
} }

View file

@ -1,11 +1,11 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxHeader, hasRedbox } from 'next-test-utils' import { assertHasRedbox, getRedboxHeader } from 'next-test-utils'
const errorMessage = const errorMessage =
'images.loaderFile detected but the file is missing default export.\nRead more: https://nextjs.org/docs/messages/invalid-images-config' 'images.loaderFile detected but the file is missing default export.\nRead more: https://nextjs.org/docs/messages/invalid-images-config'
async function testDev(browser, errorRegex) { async function testDev(browser, errorRegex) {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch(errorRegex) expect(await getRedboxHeader(browser)).toMatch(errorRegex)
} }

View file

@ -339,7 +339,7 @@ describe.each(runtimes)('unstable_after() in %s runtime', (runtimeValue) => {
) )
try { try {
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxDescription()).toContain( expect(await session.getRedboxDescription()).toContain(
`Route /static with \`dynamic = "${dynamicValue}"\` couldn't be rendered statically because it used \`unstable_after\`` `Route /static with \`dynamic = "${dynamicValue}"\` couldn't be rendered statically because it used \`unstable_after\``
) )
@ -365,7 +365,7 @@ describe.each(runtimes)('unstable_after() in %s runtime', (runtimeValue) => {
'/invalid-in-client' '/invalid-in-client'
) )
try { try {
expect(await session.hasRedbox()).toBe(true) await session.assertHasRedbox()
expect(await session.getRedboxSource(true)).toMatch( expect(await session.getRedboxSource(true)).toMatch(
/You're importing a component that needs "?unstable_after"?\. That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component\./ /You're importing a component that needs "?unstable_after"?\. That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component\./
) )

View file

@ -1,6 +1,6 @@
/* eslint-env jest */ /* eslint-env jest */
import { nextTestSetup, isNextDev } from 'e2e-utils' import { nextTestSetup, isNextDev } from 'e2e-utils'
import { getRedboxSource, hasRedbox, retry } from 'next-test-utils' import { assertHasRedbox, getRedboxSource, retry } from 'next-test-utils'
import * as fs from 'fs' import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
import * as os from 'os' import * as os from 'os'
@ -69,7 +69,7 @@ _describe('unstable_after() - pages', () => {
])('$title', async ({ path }) => { ])('$title', async ({ path }) => {
const browser = await next.browser(path) const browser = await next.browser(path)
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toMatch( expect(await getRedboxSource(browser)).toMatch(
/You're importing a component that needs "?unstable_after"?\. That only works in a Server Component which is not supported in the pages\/ directory\./ /You're importing a component that needs "?unstable_after"?\. That only works in a Server Component which is not supported in the pages\/ directory\./
) )

View file

@ -1,5 +1,5 @@
import { nextTestSetup, FileRef } from 'e2e-utils' import { nextTestSetup, FileRef } from 'e2e-utils'
import { getRedboxSource, hasRedbox } from 'next-test-utils' import { assertHasRedbox, getRedboxSource } from 'next-test-utils'
import { join } from 'path' import { join } from 'path'
import cheerio from 'cheerio' import cheerio from 'cheerio'
@ -456,7 +456,7 @@ describe('app dir - next/font', () => {
'./does-not-exist.woff2' './does-not-exist.woff2'
) )
) )
expect(await hasRedbox(browser)).toBeTrue() await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toInclude( expect(await getRedboxSource(browser)).toInclude(
"Can't resolve './does-not-exist.woff2'" "Can't resolve './does-not-exist.woff2'"
) )

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, getRedboxDescription, hasRedbox } from 'next-test-utils' import { assertHasRedbox, check, getRedboxDescription } from 'next-test-utils'
describe('app dir - not found with default 404 page', () => { describe('app dir - not found with default 404 page', () => {
const { next, isNextDev, skipped } = nextTestSetup({ const { next, isNextDev, skipped } = nextTestSetup({
@ -18,7 +18,7 @@ describe('app dir - not found with default 404 page', () => {
if (isNextDev) { if (isNextDev) {
await check(async () => { await check(async () => {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toMatch( expect(await getRedboxDescription(browser)).toMatch(
/notFound\(\) is not allowed to use in root layout/ /notFound\(\) is not allowed to use in root layout/
) )
@ -45,7 +45,7 @@ describe('app dir - not found with default 404 page', () => {
const browser = await next.browser('/?root-not-found=1') const browser = await next.browser('/?root-not-found=1')
if (isNextDev) { if (isNextDev) {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toBe( expect(await getRedboxDescription(browser)).toBe(
'Error: notFound() is not allowed to use in root layout' 'Error: notFound() is not allowed to use in root layout'
) )

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, getRedboxSource, hasRedbox } from 'next-test-utils' import { assertHasRedbox, check, getRedboxSource } from 'next-test-utils'
describe('app-dir root layout', () => { describe('app-dir root layout', () => {
const { const {
@ -23,7 +23,7 @@ describe('app-dir root layout', () => {
waitHydration: false, waitHydration: false,
}) })
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
"Please make sure to include the following tags in your root layout: <html>, <body>. "Please make sure to include the following tags in your root layout: <html>, <body>.
@ -37,7 +37,7 @@ describe('app-dir root layout', () => {
}) })
await browser.elementByCss('a').click() await browser.elementByCss('a').click()
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
"Please make sure to include the following tags in your root layout: <html>, <body>. "Please make sure to include the following tags in your root layout: <html>, <body>.
@ -50,7 +50,7 @@ describe('app-dir root layout', () => {
waitHydration: false, waitHydration: false,
}) })
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`
"Please make sure to include the following tags in your root layout: <html>, <body>. "Please make sure to include the following tags in your root layout: <html>, <body>.

View file

@ -2,7 +2,7 @@ import { join } from 'path'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { createNext, FileRef } from 'e2e-utils' import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { assertNoRedbox } from 'next-test-utils'
describe('basePath + trailingSlash', () => { describe('basePath + trailingSlash', () => {
let next: NextInstance let next: NextInstance
@ -47,7 +47,7 @@ describe('basePath + trailingSlash', () => {
expect(await browser.eval('window.location.search')).toBe('?query=true') expect(await browser.eval('window.location.search')).toBe('?query=true')
if (dev) { if (dev) {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} }
} finally { } finally {
await browser.close() await browser.close()
@ -73,7 +73,7 @@ describe('basePath + trailingSlash', () => {
expect(await browser.eval('window.location.search')).toBe('?query=true') expect(await browser.eval('window.location.search')).toBe('?query=true')
if (dev) { if (dev) {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} }
} finally { } finally {
await browser.close() await browser.close()

View file

@ -6,9 +6,9 @@ import webdriver from 'next-webdriver'
import { createNext, FileRef } from 'e2e-utils' import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { import {
assertNoRedbox,
check, check,
fetchViaHTTP, fetchViaHTTP,
hasRedbox,
renderViaHTTP, renderViaHTTP,
waitFor, waitFor,
} from 'next-test-utils' } from 'next-test-utils'
@ -946,7 +946,7 @@ describe('basePath', () => {
expect(await browser.eval('window.location.search')).toBe('?query=true') expect(await browser.eval('window.location.search')).toBe('?query=true')
if (isDev) { if (isDev) {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} }
} finally { } finally {
await browser.close() await browser.close()
@ -970,7 +970,7 @@ describe('basePath', () => {
expect(await browser.eval('window.location.search')).toBe('?query=true') expect(await browser.eval('window.location.search')).toBe('?query=true')
if (isDev) { if (isDev) {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} }
} finally { } finally {
await browser.close() await browser.close()

View file

@ -1,6 +1,7 @@
import { import {
assertHasRedbox,
assertNoRedbox,
getRedboxHeader, getRedboxHeader,
hasRedbox,
getRedboxSource, getRedboxSource,
retry, retry,
getRedboxDescription, getRedboxDescription,
@ -48,7 +49,7 @@ describe('Conflict between app file and pages file', () => {
async function containConflictsError(browser, conflicts) { async function containConflictsError(browser, conflicts) {
await retry(async () => { await retry(async () => {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {
expect(await getRedboxDescription(browser)).toContain( expect(await getRedboxDescription(browser)).toContain(
'App Router and Pages Router both match path:' 'App Router and Pages Router both match path:'
@ -69,7 +70,7 @@ describe('Conflict between app file and pages file', () => {
it('should show error overlay for /another', async () => { it('should show error overlay for /another', async () => {
await next.start() await next.start()
const browser = await next.browser('/another') const browser = await next.browser('/another')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await containConflictsError(browser, [ await containConflictsError(browser, [
['pages/index.js', 'app/page.js'], ['pages/index.js', 'app/page.js'],
['pages/another.js', 'app/another/page.js'], ['pages/another.js', 'app/another/page.js'],
@ -78,7 +79,7 @@ describe('Conflict between app file and pages file', () => {
it('should show error overlay for /', async () => { it('should show error overlay for /', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await containConflictsError(browser, [ await containConflictsError(browser, [
['pages/index.js', 'app/page.js'], ['pages/index.js', 'app/page.js'],
['pages/another.js', 'app/another/page.js'], ['pages/another.js', 'app/another/page.js'],
@ -87,14 +88,14 @@ describe('Conflict between app file and pages file', () => {
it('should support hmr with conflicts', async () => { it('should support hmr with conflicts', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await next.renameFile('pages/index.js', 'pages/index2.js') await next.renameFile('pages/index.js', 'pages/index2.js')
await next.renameFile('pages/another.js', 'pages/another2.js') await next.renameFile('pages/another.js', 'pages/another2.js')
// Wait for successful recompilation // Wait for successful recompilation
await browser.loadPage(next.url + '/') await browser.loadPage(next.url + '/')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await browser.elementByCss('p').text()).toContain('index - app') expect(await browser.elementByCss('p').text()).toContain('index - app')
await browser.loadPage(next.url + '/another') await browser.loadPage(next.url + '/another')
@ -103,23 +104,23 @@ describe('Conflict between app file and pages file', () => {
it('should not show error overlay for non conflict pages under app or pages dir', async () => { it('should not show error overlay for non conflict pages under app or pages dir', async () => {
const browser = await next.browser('/non-conflict') const browser = await next.browser('/non-conflict')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await getRedboxHeader(browser)).toBeUndefined() expect(await getRedboxHeader(browser)).toBeUndefined()
expect(await browser.elementByCss('p').text()).toBe('non-conflict app') expect(await browser.elementByCss('p').text()).toBe('non-conflict app')
await browser.loadPage(next.url + '/non-conflict-pages') await browser.loadPage(next.url + '/non-conflict-pages')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(await getRedboxHeader(browser)).toBeUndefined() expect(await getRedboxHeader(browser)).toBeUndefined()
expect(await browser.elementByCss('h1').text()).toBe('non-conflict pages') expect(await browser.elementByCss('h1').text()).toBe('non-conflict pages')
}) })
it('should error again when there is new conflict', async () => { it('should error again when there is new conflict', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
// Re-trigger the conflicted errors // Re-trigger the conflicted errors
await next.renameFile('pages/index2.js', 'pages/index.js') await next.renameFile('pages/index2.js', 'pages/index.js')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
await containConflictsError(browser, [['pages/index.js', 'app/page.js']]) await containConflictsError(browser, [['pages/index.js', 'app/page.js']])
}) })
} }

View file

@ -1,7 +1,7 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { import {
hasRedbox, assertHasRedbox,
getRedboxSource, getRedboxSource,
getRedboxDescription, getRedboxDescription,
check, check,
@ -27,7 +27,7 @@ describe('fetch failures have good stack traces in edge runtime', () => {
} else if (isNextDev) { } else if (isNextDev) {
expect(next.cliOutput).toContain('src/fetcher.js') expect(next.cliOutput).toContain('src/fetcher.js')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const source = await getRedboxSource(browser) const source = await getRedboxSource(browser)
expect(source).toContain('async function anotherFetcher(...args)') expect(source).toContain('async function anotherFetcher(...args)')

View file

@ -1,5 +1,5 @@
import { nextTestSetup } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxSource, hasRedbox, retry } from 'next-test-utils' import { assertHasRedbox, getRedboxSource, retry } from 'next-test-utils'
describe('module layer', () => { describe('module layer', () => {
const { next, isNextStart, isNextDev } = nextTestSetup({ const { next, isNextStart, isNextDev } = nextTestSetup({
@ -115,7 +115,7 @@ describe('module layer', () => {
) )
await retry(async () => { await retry(async () => {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const source = await getRedboxSource(browser) const source = await getRedboxSource(browser)
expect(source).toContain( expect(source).toContain(
`You're importing a component that imports client-only. It only works in a Client Component but none of its parents are marked with "use client"` `You're importing a component that imports client-only. It only works in a Client Component but none of its parents are marked with "use client"`

View file

@ -1,5 +1,5 @@
import { createNext, FileRef, isNextDev } from 'e2e-utils' import { createNext, FileRef, isNextDev } from 'e2e-utils'
import { getRedboxDescription, hasRedbox } from 'next-test-utils' import { assertHasRedbox, getRedboxDescription } from 'next-test-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import path from 'path' import path from 'path'
@ -30,7 +30,7 @@ describe('New Link Behavior with <a> child', () => {
if (isNextDev) { if (isNextDev) {
expect(next.cliOutput).toContain(msg) expect(next.cliOutput).toContain(msg)
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxDescription(browser)).toContain(msg) expect(await getRedboxDescription(browser)).toContain(msg)
expect(link.length).toBe(0) expect(link.length).toBe(0)
} else { } else {

View file

@ -6,11 +6,11 @@ import escapeRegex from 'escape-string-regexp'
import { createNext, FileRef } from 'e2e-utils' import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { import {
assertHasRedbox,
check, check,
fetchViaHTTP, fetchViaHTTP,
getBrowserBodyText, getBrowserBodyText,
getRedboxHeader, getRedboxHeader,
hasRedbox,
normalizeRegEx, normalizeRegEx,
renderViaHTTP, renderViaHTTP,
retry, retry,
@ -1099,7 +1099,7 @@ describe('Prerender', () => {
// we need to reload the page to trigger getStaticProps // we need to reload the page to trigger getStaticProps
await browser.refresh() await browser.refresh()
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const errOverlayContent = await getRedboxHeader(browser) const errOverlayContent = await getRedboxHeader(browser)
const errorMsg = /oops from getStaticProps/ const errorMsg = /oops from getStaticProps/
expect(next.cliOutput).toMatch(errorMsg) expect(next.cliOutput).toMatch(errorMsg)
@ -1239,7 +1239,7 @@ describe('Prerender', () => {
// ) // )
// FIXME: disable this // FIXME: disable this
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
/Failed to load static props/ /Failed to load static props/
) )
@ -1255,7 +1255,7 @@ describe('Prerender', () => {
// ) // )
// FIXME: disable this // FIXME: disable this
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
/Failed to load static props/ /Failed to load static props/
) )

View file

@ -1,6 +1,6 @@
import { createNext } from 'e2e-utils' import { createNext } from 'e2e-utils'
import { NextInstance } from 'e2e-utils' import { NextInstance } from 'e2e-utils'
import { hasRedbox, renderViaHTTP } from 'next-test-utils' import { assertNoRedbox, renderViaHTTP } from 'next-test-utils'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import cheerio from 'cheerio' import cheerio from 'cheerio'
@ -95,7 +95,7 @@ describe('Type module interop', () => {
it('should render client-side', async () => { it('should render client-side', async () => {
const browser = await webdriver(next.url, '/') const browser = await webdriver(next.url, '/')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await browser.close() await browser.close()
}) })
@ -107,7 +107,7 @@ describe('Type module interop', () => {
it('should render client-side with modules', async () => { it('should render client-side with modules', async () => {
const browser = await webdriver(next.url, '/modules') const browser = await webdriver(next.url, '/modules')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await browser.close() await browser.close()
}) })
}) })

View file

@ -1,10 +1,10 @@
/* eslint-env jest */ /* eslint-env jest */
import { join } from 'path' import { join } from 'path'
import { import {
assertNoRedbox,
killApp, killApp,
findPort, findPort,
launchApp, launchApp,
hasRedbox,
waitFor, waitFor,
} from 'next-test-utils' } from 'next-test-utils'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
@ -25,7 +25,7 @@ describe('App assetPrefix config', () => {
const browser = await webdriver(appPort, '/') const browser = await webdriver(appPort, '/')
try { try {
await waitFor(2000) await waitFor(2000)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
const title = await browser.elementById('title').text() const title = await browser.elementById('title').text()
expect(title).toBe('IndexPage') expect(title).toBe('IndexPage')
} finally { } finally {

View file

@ -6,13 +6,13 @@ import fs from 'fs-extra'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import globOrig from 'glob' import globOrig from 'glob'
import { import {
assertHasRedbox,
check, check,
fetchViaHTTP, fetchViaHTTP,
File, File,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
getRedboxSource, getRedboxSource,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -154,7 +154,7 @@ export async function runTests({
if (isDev) { if (isDev) {
const url = dynamicPage ? '/another/first' : '/api/json' const url = dynamicPage ? '/another/first' : '/api/json'
const browser = await webdriver(port, url) const browser = await webdriver(port, url)
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const header = await getRedboxHeader(browser) const header = await getRedboxHeader(browser)
const source = await getRedboxSource(browser) const source = await getRedboxSource(browser)
expect(`${header}\n${source}`).toContain(expectedErrMsg) expect(`${header}\n${source}`).toContain(expectedErrMsg)

View file

@ -1,10 +1,10 @@
/* eslint-env jest */ /* eslint-env jest */
import { import {
assertHasRedbox,
check, check,
findPort, findPort,
getRedboxSource, getRedboxSource,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
} from 'next-test-utils' } from 'next-test-utils'
@ -35,7 +35,7 @@ const appDir = join(__dirname, '../')
) )
const browser = await webdriver(appPort, '/') const browser = await webdriver(appPort, '/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
if (process.platform === 'win32') { if (process.platform === 'win32') {
// TODO: add win32 snapshot // TODO: add win32 snapshot
} else { } else {

View file

@ -1,10 +1,11 @@
/* eslint-env jest */ /* eslint-env jest */
import { import {
assertHasRedbox,
assertNoRedbox,
fetchViaHTTP, fetchViaHTTP,
File, File,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
} from 'next-test-utils' } from 'next-test-utils'
@ -220,7 +221,7 @@ describe('config-output-export', () => {
await killApp(app).catch(() => {}) await killApp(app).catch(() => {})
fs.rmSync(blog) fs.rmSync(blog)
} }
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'ISR cannot be used with "output: export".' 'ISR cannot be used with "output: export".'
) )
@ -255,7 +256,7 @@ describe('config-output-export', () => {
await killApp(app).catch(() => {}) await killApp(app).catch(() => {})
fs.rmSync(blog) fs.rmSync(blog)
} }
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
}) })
it('should work with getStaticProps and without revalidate', async () => { it('should work with getStaticProps and without revalidate', async () => {
@ -283,7 +284,7 @@ describe('config-output-export', () => {
await killApp(app).catch(() => {}) await killApp(app).catch(() => {})
fs.rmSync(blog) fs.rmSync(blog)
} }
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
}) })
it('should error with getServerSideProps without fallback', async () => { it('should error with getServerSideProps without fallback', async () => {
@ -311,7 +312,7 @@ describe('config-output-export', () => {
await killApp(app).catch(() => {}) await killApp(app).catch(() => {})
fs.rmSync(blog) fs.rmSync(blog)
} }
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'getServerSideProps cannot be used with "output: export".' 'getServerSideProps cannot be used with "output: export".'
) )
@ -351,7 +352,7 @@ describe('config-output-export', () => {
output: 'export', output: 'export',
}) })
browser = await webdriver(result.port, '/posts/one') browser = await webdriver(result.port, '/posts/one')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'getStaticPaths with "fallback: true" cannot be used with "output: export".' 'getStaticPaths with "fallback: true" cannot be used with "output: export".'
) )
@ -395,7 +396,7 @@ describe('config-output-export', () => {
output: 'export', output: 'export',
}) })
browser = await webdriver(result.port, '/posts/one') browser = await webdriver(result.port, '/posts/one')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'getStaticPaths with "fallback: blocking" cannot be used with "output: export".' 'getStaticPaths with "fallback: blocking" cannot be used with "output: export".'
) )
@ -445,7 +446,7 @@ describe('config-output-export', () => {
} }
const h1 = await browser.elementByCss('h1') const h1 = await browser.elementByCss('h1')
expect(await h1.text()).toContain('Hello from one') expect(await h1.text()).toContain('Hello from one')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(result.stderr).toBeEmpty() expect(result.stderr).toBeEmpty()
}) })
}) })

View file

@ -10,6 +10,7 @@ import cheerio from 'cheerio'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import escapeRegex from 'escape-string-regexp' import escapeRegex from 'escape-string-regexp'
import { import {
assertNoRedbox,
launchApp, launchApp,
killApp, killApp,
findPort, findPort,
@ -21,7 +22,6 @@ import {
getBrowserBodyText, getBrowserBodyText,
waitFor, waitFor,
normalizeRegEx, normalizeRegEx,
hasRedbox,
check, check,
} from 'next-test-utils' } from 'next-test-utils'
@ -296,7 +296,7 @@ const runTests = (isDev = false) => {
expect(await browser.eval('window.beforeNav')).toBe(1) expect(await browser.eval('window.beforeNav')).toBe(1)
if (isDev) { if (isDev) {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
} }
}) })

View file

@ -5,6 +5,7 @@ import { join, dirname } from 'path'
import fs from 'fs-extra' import fs from 'fs-extra'
import url from 'url' import url from 'url'
import { import {
assertHasRedbox,
renderViaHTTP, renderViaHTTP,
fetchViaHTTP, fetchViaHTTP,
findPort, findPort,
@ -15,7 +16,6 @@ import {
nextStart, nextStart,
normalizeRegEx, normalizeRegEx,
check, check,
hasRedbox,
getRedboxHeader, getRedboxHeader,
} from 'next-test-utils' } from 'next-test-utils'
import cheerio from 'cheerio' import cheerio from 'cheerio'
@ -1200,7 +1200,7 @@ function runTests({ dev }) {
await browser await browser
.elementByCss('#view-post-1-interpolated-incorrectly') .elementByCss('#view-post-1-interpolated-incorrectly')
.click() .click()
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const header = await getRedboxHeader(browser) const header = await getRedboxHeader(browser)
expect(header).toContain( expect(header).toContain(
'The provided `href` (/[name]?another=value) value is missing query values (name) to be interpolated properly.' 'The provided `href` (/[name]?another=value) value is missing query values (name) to be interpolated properly.'

View file

@ -1,9 +1,9 @@
/* eslint-env jest */ /* eslint-env jest */
import { import {
assertHasRedbox,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -49,7 +49,7 @@ const showsError = async (pathname, regex, click = false, isWarn = false) => {
return warnLogs.join('\n') return warnLogs.join('\n')
}, regex) }, regex)
} else { } else {
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
const errorContent = await getRedboxHeader(browser) const errorContent = await getRedboxHeader(browser)
expect(errorContent).toMatch(regex) expect(errorContent).toMatch(regex)
} }

View file

@ -1,10 +1,11 @@
/* eslint-env jest */ /* eslint-env jest */
import { import {
assertHasRedbox,
assertNoRedbox,
check, check,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -375,7 +376,7 @@ function runTests(mode) {
it('should show missing src error', async () => { it('should show missing src error', async () => {
const browser = await webdriver(appPort, '/docs/missing-src') const browser = await webdriver(appPort, '/docs/missing-src')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -385,7 +386,7 @@ function runTests(mode) {
it('should show invalid src error', async () => { it('should show invalid src error', async () => {
const browser = await webdriver(appPort, '/docs/invalid-src') const browser = await webdriver(appPort, '/docs/invalid-src')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`' 'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`'
) )
@ -397,7 +398,7 @@ function runTests(mode) {
'/docs/invalid-src-proto-relative' '/docs/invalid-src-proto-relative'
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)' 'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)'
) )

View file

@ -3,11 +3,12 @@
import cheerio from 'cheerio' import cheerio from 'cheerio'
import validateHTML from 'html-validator' import validateHTML from 'html-validator'
import { import {
assertHasRedbox,
assertNoRedbox,
check, check,
fetchViaHTTP, fetchViaHTTP,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -813,7 +814,7 @@ function runTests(mode) {
it('should show missing src error', async () => { it('should show missing src error', async () => {
const browser = await webdriver(appPort, '/missing-src') const browser = await webdriver(appPort, '/missing-src')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -823,7 +824,7 @@ function runTests(mode) {
it('should show invalid src error', async () => { it('should show invalid src error', async () => {
const browser = await webdriver(appPort, '/invalid-src') const browser = await webdriver(appPort, '/invalid-src')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`' 'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`'
) )
@ -832,7 +833,7 @@ function runTests(mode) {
it('should show invalid src error when protocol-relative', async () => { it('should show invalid src error when protocol-relative', async () => {
const browser = await webdriver(appPort, '/invalid-src-proto-relative') const browser = await webdriver(appPort, '/invalid-src-proto-relative')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)' 'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)'
) )
@ -841,7 +842,7 @@ function runTests(mode) {
it('should show error when string src and placeholder=blur and blurDataURL is missing', async () => { it('should show error when string src and placeholder=blur and blurDataURL is missing', async () => {
const browser = await webdriver(appPort, '/invalid-placeholder-blur') const browser = await webdriver(appPort, '/invalid-placeholder-blur')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.png" has "placeholder='blur'" property but is missing the "blurDataURL" property.` `Image with src "/test.png" has "placeholder='blur'" property but is missing the "blurDataURL" property.`
) )
@ -850,7 +851,7 @@ function runTests(mode) {
it('should show error when not numeric string width or height', async () => { it('should show error when not numeric string width or height', async () => {
const browser = await webdriver(appPort, '/invalid-width-or-height') const browser = await webdriver(appPort, '/invalid-width-or-height')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" has invalid "width" or "height" property. These should be numeric values.` `Image with src "/test.jpg" has invalid "width" or "height" property. These should be numeric values.`
) )
@ -862,7 +863,7 @@ function runTests(mode) {
'/invalid-placeholder-blur-static' '/invalid-placeholder-blur-static'
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
/Image with src "(.*)bmp" has "placeholder='blur'" property but is missing the "blurDataURL" property/ /Image with src "(.*)bmp" has "placeholder='blur'" property but is missing the "blurDataURL" property/
) )
@ -874,7 +875,7 @@ function runTests(mode) {
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
}, /Image with src (.*)jpg(.*) may not render properly as a child of a flex container. Consider wrapping the image with a div to configure the width/gm) }, /Image with src (.*)jpg(.*) may not render properly as a child of a flex container. Consider wrapping the image with a div to configure the width/gm)
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
}) })
it('should warn when img with layout=fill is inside a container without position relative', async () => { it('should warn when img with layout=fill is inside a container without position relative', async () => {
@ -899,7 +900,7 @@ function runTests(mode) {
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Image with src (.*)webp(.*) may not render properly/gm /Image with src (.*)webp(.*) may not render properly/gm
) )
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
}) })
it('should warn when using a very small image with placeholder=blur', async () => { it('should warn when using a very small image with placeholder=blur', async () => {
@ -908,7 +909,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)jpg(.*) is smaller than 40x40. Consider removing(.*)/gm /Image with src (.*)jpg(.*) is smaller than 40x40. Consider removing(.*)/gm
) )
@ -920,7 +921,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Expected server HTML to contain a matching/gm /Expected server HTML to contain a matching/gm
) )
@ -944,7 +945,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)test(.*) was detected as the Largest Contentful Paint/gm /Image with src (.*)test(.*) was detected as the Largest Contentful Paint/gm
) )
@ -959,7 +960,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)png(.*) has a "loader" property that does not implement width/gm /Image with src (.*)png(.*) has a "loader" property that does not implement width/gm
) )
@ -983,7 +984,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)png(.*) has "sizes" property but it will be ignored/gm /Image with src (.*)png(.*) has "sizes" property but it will be ignored/gm
) )
@ -1004,7 +1005,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Image with src (.*) has a "loader" property that does not implement width/gm /Image with src (.*) has a "loader" property that does not implement width/gm
) )

View file

@ -3,11 +3,12 @@
import cheerio from 'cheerio' import cheerio from 'cheerio'
import validateHTML from 'html-validator' import validateHTML from 'html-validator'
import { import {
assertHasRedbox,
assertNoRedbox,
check, check,
fetchViaHTTP, fetchViaHTTP,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -798,7 +799,7 @@ function runTests(mode) {
'position:absolute;height:100%;width:100%;left:0;top:0;right:0;bottom:0;object-fit:cover;object-position:10% 10%;color:transparent' 'position:absolute;height:100%;width:100%;left:0;top:0;right:0;bottom:0;object-fit:cover;object-position:10% 10%;color:transparent'
) )
if (mode === 'dev') { if (mode === 'dev') {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
@ -830,7 +831,7 @@ function runTests(mode) {
'color:transparent;width:100%;height:auto' 'color:transparent;width:100%;height:auto'
) )
if (mode === 'dev') { if (mode === 'dev') {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
@ -880,7 +881,7 @@ function runTests(mode) {
it('should show missing src error', async () => { it('should show missing src error', async () => {
const browser = await webdriver(appPort, '/missing-src') const browser = await webdriver(appPort, '/missing-src')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -890,7 +891,7 @@ function runTests(mode) {
it('should show empty string src error', async () => { it('should show empty string src error', async () => {
const browser = await webdriver(appPort, '/empty-string-src') const browser = await webdriver(appPort, '/empty-string-src')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -900,7 +901,7 @@ function runTests(mode) {
it('should show invalid src error', async () => { it('should show invalid src error', async () => {
const browser = await webdriver(appPort, '/invalid-src') const browser = await webdriver(appPort, '/invalid-src')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`' 'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`'
) )
@ -909,7 +910,7 @@ function runTests(mode) {
it('should show invalid src error when protocol-relative', async () => { it('should show invalid src error when protocol-relative', async () => {
const browser = await webdriver(appPort, '/invalid-src-proto-relative') const browser = await webdriver(appPort, '/invalid-src-proto-relative')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)' 'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)'
) )
@ -917,7 +918,7 @@ function runTests(mode) {
it('should show invalid src with leading space', async () => { it('should show invalid src with leading space', async () => {
const browser = await webdriver(appPort, '/invalid-src-leading-space') const browser = await webdriver(appPort, '/invalid-src-leading-space')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Image with src " /test.jpg" cannot start with a space or control character.' 'Image with src " /test.jpg" cannot start with a space or control character.'
) )
@ -925,7 +926,7 @@ function runTests(mode) {
it('should show invalid src with trailing space', async () => { it('should show invalid src with trailing space', async () => {
const browser = await webdriver(appPort, '/invalid-src-trailing-space') const browser = await webdriver(appPort, '/invalid-src-trailing-space')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Image with src "/test.png " cannot end with a space or control character.' 'Image with src "/test.png " cannot end with a space or control character.'
) )
@ -934,7 +935,7 @@ function runTests(mode) {
it('should show error when string src and placeholder=blur and blurDataURL is missing', async () => { it('should show error when string src and placeholder=blur and blurDataURL is missing', async () => {
const browser = await webdriver(appPort, '/invalid-placeholder-blur') const browser = await webdriver(appPort, '/invalid-placeholder-blur')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.png" has "placeholder='blur'" property but is missing the "blurDataURL" property.` `Image with src "/test.png" has "placeholder='blur'" property but is missing the "blurDataURL" property.`
) )
@ -943,7 +944,7 @@ function runTests(mode) {
it('should show error when invalid width prop', async () => { it('should show error when invalid width prop', async () => {
const browser = await webdriver(appPort, '/invalid-width') const browser = await webdriver(appPort, '/invalid-width')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" has invalid "width" property. Expected a numeric value in pixels but received "100%".` `Image with src "/test.jpg" has invalid "width" property. Expected a numeric value in pixels but received "100%".`
) )
@ -952,7 +953,7 @@ function runTests(mode) {
it('should show error when invalid Infinity width prop', async () => { it('should show error when invalid Infinity width prop', async () => {
const browser = await webdriver(appPort, '/invalid-Infinity-width') const browser = await webdriver(appPort, '/invalid-Infinity-width')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" has invalid "width" property. Expected a numeric value in pixels but received "Infinity".` `Image with src "/test.jpg" has invalid "width" property. Expected a numeric value in pixels but received "Infinity".`
) )
@ -961,7 +962,7 @@ function runTests(mode) {
it('should show error when invalid height prop', async () => { it('should show error when invalid height prop', async () => {
const browser = await webdriver(appPort, '/invalid-height') const browser = await webdriver(appPort, '/invalid-height')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" has invalid "height" property. Expected a numeric value in pixels but received "50vh".` `Image with src "/test.jpg" has invalid "height" property. Expected a numeric value in pixels but received "50vh".`
) )
@ -970,7 +971,7 @@ function runTests(mode) {
it('should show missing alt error', async () => { it('should show missing alt error', async () => {
const browser = await webdriver(appPort, '/missing-alt') const browser = await webdriver(appPort, '/missing-alt')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -980,7 +981,7 @@ function runTests(mode) {
it('should show error when missing width prop', async () => { it('should show error when missing width prop', async () => {
const browser = await webdriver(appPort, '/missing-width') const browser = await webdriver(appPort, '/missing-width')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" is missing required "width" property.` `Image with src "/test.jpg" is missing required "width" property.`
) )
@ -989,7 +990,7 @@ function runTests(mode) {
it('should show error when missing height prop', async () => { it('should show error when missing height prop', async () => {
const browser = await webdriver(appPort, '/missing-height') const browser = await webdriver(appPort, '/missing-height')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" is missing required "height" property.` `Image with src "/test.jpg" is missing required "height" property.`
) )
@ -998,7 +999,7 @@ function runTests(mode) {
it('should show error when width prop on fill image', async () => { it('should show error when width prop on fill image', async () => {
const browser = await webdriver(appPort, '/invalid-fill-width') const browser = await webdriver(appPort, '/invalid-fill-width')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/wide.png" has both "width" and "fill" properties.` `Image with src "/wide.png" has both "width" and "fill" properties.`
) )
@ -1007,7 +1008,7 @@ function runTests(mode) {
it('should show error when CSS position changed on fill image', async () => { it('should show error when CSS position changed on fill image', async () => {
const browser = await webdriver(appPort, '/invalid-fill-position') const browser = await webdriver(appPort, '/invalid-fill-position')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/wide.png" has both "fill" and "style.position" properties. Images with "fill" always use position absolute - it cannot be modified.` `Image with src "/wide.png" has both "fill" and "style.position" properties. Images with "fill" always use position absolute - it cannot be modified.`
) )
@ -1019,7 +1020,7 @@ function runTests(mode) {
'/invalid-placeholder-blur-static' '/invalid-placeholder-blur-static'
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
/Image with src "(.*)bmp" has "placeholder='blur'" property but is missing the "blurDataURL" property/ /Image with src "(.*)bmp" has "placeholder='blur'" property but is missing the "blurDataURL" property/
) )
@ -1031,7 +1032,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)jpg(.*) is smaller than 40x40. Consider removing(.*)/gm /Image with src (.*)jpg(.*) is smaller than 40x40. Consider removing(.*)/gm
) )
@ -1043,7 +1044,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Expected server HTML to contain a matching/gm /Expected server HTML to contain a matching/gm
) )
@ -1067,7 +1068,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)test(.*) was detected as the Largest Contentful Paint/gm /Image with src (.*)test(.*) was detected as the Largest Contentful Paint/gm
) )
@ -1082,7 +1083,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)png(.*) has a "loader" property that does not implement width/gm /Image with src (.*)png(.*) has a "loader" property that does not implement width/gm
) )
@ -1105,7 +1106,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Image with src (.*) has "fill" but is missing "sizes" prop. Please add it to improve page performance/gm /Image with src (.*) has "fill" but is missing "sizes" prop. Please add it to improve page performance/gm
) )
@ -1117,7 +1118,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Image with src (.*) has a "loader" property that does not implement width/gm /Image with src (.*) has a "loader" property that does not implement width/gm
) )

View file

@ -1,10 +1,11 @@
/* eslint-env jest */ /* eslint-env jest */
import { import {
assertHasRedbox,
assertNoRedbox,
check, check,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -130,7 +131,7 @@ function runTests(mode) {
it('should show missing src error', async () => { it('should show missing src error', async () => {
const browser = await webdriver(appPort, '/docs/missing-src') const browser = await webdriver(appPort, '/docs/missing-src')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -140,7 +141,7 @@ function runTests(mode) {
it('should show invalid src error', async () => { it('should show invalid src error', async () => {
const browser = await webdriver(appPort, '/docs/invalid-src') const browser = await webdriver(appPort, '/docs/invalid-src')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`' 'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`'
) )
@ -152,7 +153,7 @@ function runTests(mode) {
'/docs/invalid-src-proto-relative' '/docs/invalid-src-proto-relative'
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)' 'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)'
) )

View file

@ -3,11 +3,12 @@
import cheerio from 'cheerio' import cheerio from 'cheerio'
import validateHTML from 'html-validator' import validateHTML from 'html-validator'
import { import {
assertHasRedbox,
assertNoRedbox,
check, check,
fetchViaHTTP, fetchViaHTTP,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -799,7 +800,7 @@ function runTests(mode) {
'position:absolute;height:100%;width:100%;left:0;top:0;right:0;bottom:0;object-fit:cover;object-position:10% 10%;color:transparent' 'position:absolute;height:100%;width:100%;left:0;top:0;right:0;bottom:0;object-fit:cover;object-position:10% 10%;color:transparent'
) )
if (mode === 'dev') { if (mode === 'dev') {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
@ -831,7 +832,7 @@ function runTests(mode) {
'color:transparent;width:100%;height:auto' 'color:transparent;width:100%;height:auto'
) )
if (mode === 'dev') { if (mode === 'dev') {
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
@ -881,7 +882,7 @@ function runTests(mode) {
it('should show missing src error', async () => { it('should show missing src error', async () => {
const browser = await webdriver(appPort, '/missing-src') const browser = await webdriver(appPort, '/missing-src')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -891,7 +892,7 @@ function runTests(mode) {
it('should show empty string src error', async () => { it('should show empty string src error', async () => {
const browser = await webdriver(appPort, '/empty-string-src') const browser = await webdriver(appPort, '/empty-string-src')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -901,7 +902,7 @@ function runTests(mode) {
it('should show invalid src error', async () => { it('should show invalid src error', async () => {
const browser = await webdriver(appPort, '/invalid-src') const browser = await webdriver(appPort, '/invalid-src')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`' 'Invalid src prop (https://google.com/test.png) on `next/image`, hostname "google.com" is not configured under images in your `next.config.js`'
) )
@ -910,7 +911,7 @@ function runTests(mode) {
it('should show invalid src error when protocol-relative', async () => { it('should show invalid src error when protocol-relative', async () => {
const browser = await webdriver(appPort, '/invalid-src-proto-relative') const browser = await webdriver(appPort, '/invalid-src-proto-relative')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)' 'Failed to parse src "//assets.example.com/img.jpg" on `next/image`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)'
) )
@ -918,7 +919,7 @@ function runTests(mode) {
it('should show invalid src with leading space', async () => { it('should show invalid src with leading space', async () => {
const browser = await webdriver(appPort, '/invalid-src-leading-space') const browser = await webdriver(appPort, '/invalid-src-leading-space')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Image with src " /test.jpg" cannot start with a space or control character.' 'Image with src " /test.jpg" cannot start with a space or control character.'
) )
@ -926,7 +927,7 @@ function runTests(mode) {
it('should show invalid src with trailing space', async () => { it('should show invalid src with trailing space', async () => {
const browser = await webdriver(appPort, '/invalid-src-trailing-space') const browser = await webdriver(appPort, '/invalid-src-trailing-space')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
'Image with src "/test.png " cannot end with a space or control character.' 'Image with src "/test.png " cannot end with a space or control character.'
) )
@ -935,7 +936,7 @@ function runTests(mode) {
it('should show error when string src and placeholder=blur and blurDataURL is missing', async () => { it('should show error when string src and placeholder=blur and blurDataURL is missing', async () => {
const browser = await webdriver(appPort, '/invalid-placeholder-blur') const browser = await webdriver(appPort, '/invalid-placeholder-blur')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.png" has "placeholder='blur'" property but is missing the "blurDataURL" property.` `Image with src "/test.png" has "placeholder='blur'" property but is missing the "blurDataURL" property.`
) )
@ -944,7 +945,7 @@ function runTests(mode) {
it('should show error when invalid width prop', async () => { it('should show error when invalid width prop', async () => {
const browser = await webdriver(appPort, '/invalid-width') const browser = await webdriver(appPort, '/invalid-width')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" has invalid "width" property. Expected a numeric value in pixels but received "100%".` `Image with src "/test.jpg" has invalid "width" property. Expected a numeric value in pixels but received "100%".`
) )
@ -953,7 +954,7 @@ function runTests(mode) {
it('should show error when invalid Infinity width prop', async () => { it('should show error when invalid Infinity width prop', async () => {
const browser = await webdriver(appPort, '/invalid-Infinity-width') const browser = await webdriver(appPort, '/invalid-Infinity-width')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" has invalid "width" property. Expected a numeric value in pixels but received "Infinity".` `Image with src "/test.jpg" has invalid "width" property. Expected a numeric value in pixels but received "Infinity".`
) )
@ -962,7 +963,7 @@ function runTests(mode) {
it('should show error when invalid height prop', async () => { it('should show error when invalid height prop', async () => {
const browser = await webdriver(appPort, '/invalid-height') const browser = await webdriver(appPort, '/invalid-height')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" has invalid "height" property. Expected a numeric value in pixels but received "50vh".` `Image with src "/test.jpg" has invalid "height" property. Expected a numeric value in pixels but received "50vh".`
) )
@ -971,7 +972,7 @@ function runTests(mode) {
it('should show missing alt error', async () => { it('should show missing alt error', async () => {
const browser = await webdriver(appPort, '/missing-alt') const browser = await webdriver(appPort, '/missing-alt')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
await check(async () => { await check(async () => {
return (await browser.log()).map((log) => log.message).join('\n') return (await browser.log()).map((log) => log.message).join('\n')
@ -981,7 +982,7 @@ function runTests(mode) {
it('should show error when missing width prop', async () => { it('should show error when missing width prop', async () => {
const browser = await webdriver(appPort, '/missing-width') const browser = await webdriver(appPort, '/missing-width')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" is missing required "width" property.` `Image with src "/test.jpg" is missing required "width" property.`
) )
@ -990,7 +991,7 @@ function runTests(mode) {
it('should show error when missing height prop', async () => { it('should show error when missing height prop', async () => {
const browser = await webdriver(appPort, '/missing-height') const browser = await webdriver(appPort, '/missing-height')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/test.jpg" is missing required "height" property.` `Image with src "/test.jpg" is missing required "height" property.`
) )
@ -999,7 +1000,7 @@ function runTests(mode) {
it('should show error when width prop on fill image', async () => { it('should show error when width prop on fill image', async () => {
const browser = await webdriver(appPort, '/invalid-fill-width') const browser = await webdriver(appPort, '/invalid-fill-width')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/wide.png" has both "width" and "fill" properties.` `Image with src "/wide.png" has both "width" and "fill" properties.`
) )
@ -1008,7 +1009,7 @@ function runTests(mode) {
it('should show error when CSS position changed on fill image', async () => { it('should show error when CSS position changed on fill image', async () => {
const browser = await webdriver(appPort, '/invalid-fill-position') const browser = await webdriver(appPort, '/invalid-fill-position')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain( expect(await getRedboxHeader(browser)).toContain(
`Image with src "/wide.png" has both "fill" and "style.position" properties. Images with "fill" always use position absolute - it cannot be modified.` `Image with src "/wide.png" has both "fill" and "style.position" properties. Images with "fill" always use position absolute - it cannot be modified.`
) )
@ -1020,7 +1021,7 @@ function runTests(mode) {
'/invalid-placeholder-blur-static' '/invalid-placeholder-blur-static'
) )
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
/Image with src "(.*)bmp" has "placeholder='blur'" property but is missing the "blurDataURL" property/ /Image with src "(.*)bmp" has "placeholder='blur'" property but is missing the "blurDataURL" property/
) )
@ -1032,7 +1033,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)jpg(.*) is smaller than 40x40. Consider removing(.*)/gm /Image with src (.*)jpg(.*) is smaller than 40x40. Consider removing(.*)/gm
) )
@ -1044,7 +1045,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Expected server HTML to contain a matching/gm /Expected server HTML to contain a matching/gm
) )
@ -1068,7 +1069,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)test(.*) was detected as the Largest Contentful Paint/gm /Image with src (.*)test(.*) was detected as the Largest Contentful Paint/gm
) )
@ -1083,7 +1084,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).toMatch( expect(warnings).toMatch(
/Image with src (.*)png(.*) has a "loader" property that does not implement width/gm /Image with src (.*)png(.*) has a "loader" property that does not implement width/gm
) )
@ -1106,7 +1107,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Image with src (.*) has "fill" but is missing "sizes" prop. Please add it to improve page performance/gm /Image with src (.*) has "fill" but is missing "sizes" prop. Please add it to improve page performance/gm
) )
@ -1118,7 +1119,7 @@ function runTests(mode) {
const warnings = (await browser.log()) const warnings = (await browser.log())
.map((log) => log.message) .map((log) => log.message)
.join('\n') .join('\n')
expect(await hasRedbox(browser)).toBe(false) await assertNoRedbox(browser)
expect(warnings).not.toMatch( expect(warnings).not.toMatch(
/Image with src (.*) has a "loader" property that does not implement width/gm /Image with src (.*) has a "loader" property that does not implement width/gm
) )

View file

@ -2,9 +2,9 @@
import { join } from 'path' import { join } from 'path'
import { import {
assertHasRedbox,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
} from 'next-test-utils' } from 'next-test-utils'
@ -35,7 +35,7 @@ describe('next/image with output export config', () => {
const browser = await webdriver(appPort, '/') const browser = await webdriver(appPort, '/')
const msg = const msg =
"Image Optimization using the default loader is not compatible with `{ output: 'export' }`." "Image Optimization using the default loader is not compatible with `{ output: 'export' }`."
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain(msg) expect(await getRedboxHeader(browser)).toContain(msg)
expect(stderr).toContain(msg) expect(stderr).toContain(msg)
}) })

View file

@ -2,10 +2,10 @@
import { join } from 'path' import { join } from 'path'
import { import {
assertHasRedbox,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
getRedboxSource, getRedboxSource,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -22,7 +22,7 @@ function runTests({ isDev }) {
it('should show error', async () => { it('should show error', async () => {
if (isDev) { if (isDev) {
const browser = await webdriver(appPort, '/') const browser = await webdriver(appPort, '/')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch('Failed to compile') expect(await getRedboxHeader(browser)).toMatch('Failed to compile')
const source = await getRedboxSource(browser) const source = await getRedboxSource(browser)
if (process.env.TURBOPACK) { if (process.env.TURBOPACK) {

View file

@ -4,11 +4,11 @@ import fs from 'fs-extra'
import { join } from 'path' import { join } from 'path'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { import {
assertHasRedbox,
killApp, killApp,
findPort, findPort,
launchApp, launchApp,
check, check,
hasRedbox,
getRedboxSource, getRedboxSource,
} from 'next-test-utils' } from 'next-test-utils'
import stripAnsi from 'strip-ansi' import stripAnsi from 'strip-ansi'
@ -60,11 +60,11 @@ describe('server-side dev errors', () => {
: err : err
}, 'success') }, 'success')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain('missingVar') expect(await getRedboxSource(browser)).toContain('missingVar')
await fs.writeFile(gspPage, content) await fs.writeFile(gspPage, content)
await hasRedbox(browser) await assertHasRedbox(browser)
} finally { } finally {
await fs.writeFile(gspPage, content) await fs.writeFile(gspPage, content)
} }
@ -92,11 +92,11 @@ describe('server-side dev errors', () => {
: err : err
}, 'success') }, 'success')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain('missingVar') expect(await getRedboxSource(browser)).toContain('missingVar')
await fs.writeFile(gsspPage, content) await fs.writeFile(gsspPage, content)
await hasRedbox(browser) await assertHasRedbox(browser)
} finally { } finally {
await fs.writeFile(gsspPage, content) await fs.writeFile(gsspPage, content)
} }
@ -124,11 +124,11 @@ describe('server-side dev errors', () => {
: err : err
}, 'success') }, 'success')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain('missingVar') expect(await getRedboxSource(browser)).toContain('missingVar')
await fs.writeFile(dynamicGsspPage, content) await fs.writeFile(dynamicGsspPage, content)
await hasRedbox(browser) await assertHasRedbox(browser)
} finally { } finally {
await fs.writeFile(dynamicGsspPage, content) await fs.writeFile(dynamicGsspPage, content)
} }
@ -156,11 +156,11 @@ describe('server-side dev errors', () => {
: err : err
}, 'success') }, 'success')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain('missingVar') expect(await getRedboxSource(browser)).toContain('missingVar')
await fs.writeFile(apiPage, content) await fs.writeFile(apiPage, content)
await hasRedbox(browser) await assertHasRedbox(browser)
} finally { } finally {
await fs.writeFile(apiPage, content) await fs.writeFile(apiPage, content)
} }
@ -188,11 +188,11 @@ describe('server-side dev errors', () => {
: err : err
}, 'success') }, 'success')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxSource(browser)).toContain('missingVar') expect(await getRedboxSource(browser)).toContain('missingVar')
await fs.writeFile(dynamicApiPage, content) await fs.writeFile(dynamicApiPage, content)
await hasRedbox(browser) await assertHasRedbox(browser)
} finally { } finally {
await fs.writeFile(dynamicApiPage, content) await fs.writeFile(dynamicApiPage, content)
} }

View file

@ -1,9 +1,9 @@
/* eslint-env jest */ /* eslint-env jest */
import { import {
assertHasRedbox,
findPort, findPort,
getRedboxHeader, getRedboxHeader,
hasRedbox,
killApp, killApp,
launchApp, launchApp,
nextBuild, nextBuild,
@ -103,7 +103,7 @@ describe('withRouter SSR', () => {
it('should show an error when trying to use router methods during SSR', async () => { it('should show an error when trying to use router methods during SSR', async () => {
const browser = await webdriver(port, '/router-method-ssr') const browser = await webdriver(port, '/router-method-ssr')
expect(await hasRedbox(browser)).toBe(true) await assertHasRedbox(browser)
expect(await getRedboxHeader(browser)).toMatch( expect(await getRedboxHeader(browser)).toMatch(
`No router instance found. you should only use "next/router" inside the client side of your app. https://` `No router instance found. you should only use "next/router" inside the client side of your app. https://`
) )

View file

@ -5,7 +5,8 @@ import {
getRedboxHeader, getRedboxHeader,
getRedboxSource, getRedboxSource,
getVersionCheckerText, getVersionCheckerText,
hasRedbox, assertHasRedbox,
assertNoRedbox,
waitFor, waitFor,
waitForAndOpenRuntimeError, waitForAndOpenRuntimeError,
getRedboxDescriptionWarning, getRedboxDescriptionWarning,
@ -112,8 +113,11 @@ export async function sandbox(
) )
} }
}, },
async hasRedbox() { async assertHasRedbox() {
return hasRedbox(browser) return assertHasRedbox(browser)
},
async assertNoRedbox() {
return assertNoRedbox(browser)
}, },
async waitForAndOpenRuntimeError() { async waitForAndOpenRuntimeError() {
return waitForAndOpenRuntimeError(browser) return waitForAndOpenRuntimeError(browser)

View file

@ -802,9 +802,36 @@ export async function retry<T>(
} }
} }
export async function hasRedbox(browser: BrowserInterface): Promise<boolean> { export async function assertHasRedbox(browser: BrowserInterface) {
try {
await retry(
async () => {
const hasRedbox = await evaluate(browser, () => {
return Boolean(
[].slice
.call(document.querySelectorAll('nextjs-portal'))
.find((p) =>
p.shadowRoot.querySelector(
'#nextjs__container_errors_label, #nextjs__container_errors_label'
)
)
)
})
expect(hasRedbox).toBe(true)
},
5000,
200
)
} catch (errorCause) {
const error = new Error('Expected Redbox but found none')
Error.captureStackTrace(error, assertHasRedbox)
throw error
}
}
export async function assertNoRedbox(browser: BrowserInterface) {
await waitFor(5000) await waitFor(5000)
const result = await evaluate(browser, () => { const hasRedbox = await evaluate(browser, () => {
return Boolean( return Boolean(
[].slice [].slice
.call(document.querySelectorAll('nextjs-portal')) .call(document.querySelectorAll('nextjs-portal'))
@ -815,7 +842,12 @@ export async function hasRedbox(browser: BrowserInterface): Promise<boolean> {
) )
) )
}) })
return result
if (hasRedbox) {
const error = new Error('Expected no Redbox but found one')
Error.captureStackTrace(error, assertHasRedbox)
throw error
}
} }
export async function hasErrorToast( export async function hasErrorToast(