Files
next.js/test/e2e/app-dir/cache-components-console/cache-components.console.test.ts
Hendrik LiebauandGitHub f3656691c2 [test] Use --debug-build-paths instead of NEXT_PRIVATE_APP_PATHS (#85504)
With `--debug-build-paths` being added in #85052, we can now use this
CLI flag in tests, instead of setting the private environment variable
`NEXT_PRIVATE_APP_PATHS`.

Related to this change, this PR fixes how we print the dev, start and
build commands during tests, by properly escaping the CLI arguments.
This ensures that the command is copy-pasteable even when the args
contain escaped characters.
2025-10-29 14:03:42 +01:00

792 lines
45 KiB
TypeScript

import { isNextDev, nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils'
import stripAnsi from 'strip-ansi'
// TODO(restart-on-cache-miss): cacheSignal timing changes break console log dimming/hiding tests
describe.skip('cache-components - Console Dimming - Validation', () => {
const { next, skipped, isTurbopack } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/default',
skipDeployment: true,
skipStart: !isNextDev,
})
if (skipped) {
return
}
it('dims console calls during prospective rendering', async () => {
const path: string = '/console'
if (isNextDev) {
const browser = await next.browser(path, {})
await retry(() => {
expect(stripAnsi(next.cliOutput)).toContain(`GET ${path} 200`)
})
// do not strip ANSI codes here since we're explicitly testing coloring.
const cliOutputFromPage = next.cliOutput.match(
new RegExp(`Compiled ${path}[^\n]+\n(.*)`, 's')
)[1]
const reorderedLines = reorderLinesByBadge(cliOutputFromPage)
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console: template(one: one, two: two)
:::0:out::: /console: This is a console page. Don't match the codeframe.
:::0:out::: /console: template(one: one, two: two)
:::0:out::: /console: This is a console page. Don't match the codeframe.
 Cache  :::0:out::: /console: template(one: one, two: two)
 Cache  :::0:out::: /console: This is a console page. Don't match the codeframe.
:::0:err::: /console: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console: test
at ConsolePage (app/console/page.tsx:<line>:<col>)
  40 | })
 41 | await 1
> 42 | console.error(new Error(\`\${errBadge} /console: test\`))
 | ^
 43 | await 1
 44 | console.assert(
 45 | false,
Assertion failed: :::0:err::: /console: This is an assert message with a template
:::0:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed: :::0:err::: /console: This is an assert message with a template
 Cache  :::0:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed:  Cache  :::0:err::: /console: This is an assert message with a template
 Cache  Assertion failed: :::0:err::: /console: This is an assert message with a template
:::1:out::: /console: template(one: one, two: two)
:::1:out::: /console: This is a console page. Don't match the codeframe.
:::1:out::: /console: template(one: one, two: two)
:::1:out::: /console: This is a console page. Don't match the codeframe.
 Cache  :::1:out::: /console: template(one: one, two: two)
 Cache  :::1:out::: /console: This is a console page. Don't match the codeframe.
:::1:err::: /console: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console: test
at ConsolePage (app/console/page.tsx:<line>:<col>)
  40 | })
 41 | await 1
> 42 | console.error(new Error(\`\${errBadge} /console: test\`))
 | ^
 43 | await 1
 44 | console.assert(
 45 | false,
Assertion failed: :::1:err::: /console: This is an assert message with a template
:::1:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed: :::1:err::: /console: This is an assert message with a template
 Cache  :::1:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed:  Cache  :::1:err::: /console: This is an assert message with a template
 Cache  Assertion failed: :::1:err::: /console: This is an assert message with a template
:::2:out::: /console: template(one: one, two: two)
:::2:out::: /console: This is a console page. Don't match the codeframe.
:::2:out::: /console: template(one: one, two: two)
:::2:out::: /console: This is a console page. Don't match the codeframe.
 Cache  :::2:out::: /console: template(one: one, two: two)
 Cache  :::2:out::: /console: This is a console page. Don't match the codeframe.
:::2:err::: /console: not a template { foo: 'just-some-object' }
Error: :::2:err::: /console: test
at ConsolePage (app/console/page.tsx:<line>:<col>)
  40 | })
 41 | await 1
> 42 | console.error(new Error(\`\${errBadge} /console: test\`))
 | ^
 43 | await 1
 44 | console.assert(
 45 | false,
Assertion failed: :::2:err::: /console: This is an assert message with a template
:::2:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed: :::2:err::: /console: This is an assert message with a template
 Cache  :::2:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed:  Cache  :::2:err::: /console: This is an assert message with a template
 Cache  Assertion failed: :::2:err::: /console: This is an assert message with a template
"
`)
await expect(browser).toDisplayCollapsedRedbox(`
{
"description": ":::0:err::: /console: test",
"environmentLabel": "Prerender",
"label": "Console Error",
"source": "app/console/page.tsx (42:17) @ ConsolePage
> 42 | console.error(new Error(\`\${errBadge} /console: test\`))
| ^",
"stack": [
"ConsolePage app/console/page.tsx (42:17)",
"ConsolePage <anonymous>",
],
}
`)
} else {
try {
await next.build({
args: ['--debug-build-paths', `app${path}/page.tsx`],
})
} catch (err) {
const error = new Error(
'Expected build to complete successfully, but it failed'
)
error.cause = err
throw error
}
// do not strip ANSI codes here since we're explicitly testing coloring.
const cliOutputFromPage = next.cliOutput.match(
/Collecting page data[^\n]+\n(.*)\n.*Finalizing page optimization /s
)[1]
const reorderedLines = reorderLinesByBadge(cliOutputFromPage)
if (isTurbopack) {
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console: template(one: one, two: two)
:::0:out::: /console: This is a console page. Don't match the codeframe.
:::0:out::: /console: template(one: one, two: two)
:::0:out::: /console: This is a console page. Don't match the codeframe.
:::0:err::: /console: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console: test
at e (turbopack:///[project]/app/console/page.tsx:<line>:<col>)
  40 | })
 41 | await 1
> 42 | console.error(new Error(\`\${errBadge} /console: test\`))
 | ^
 43 | await 1
 44 | console.assert(
 45 | false,
Assertion failed: :::0:err::: /console: This is an assert message with a template
:::0:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed: :::0:err::: /console: This is an assert message with a template
:::1:out::: /console: template(one: one, two: two)
:::1:out::: /console: This is a console page. Don't match the codeframe.
:::1:out::: /console: template(one: one, two: two)
:::1:out::: /console: This is a console page. Don't match the codeframe.
:::1:err::: /console: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console: test
at e (turbopack:///[project]/app/console/page.tsx:<line>:<col>)
  40 | })
 41 | await 1
> 42 | console.error(new Error(\`\${errBadge} /console: test\`))
 | ^
 43 | await 1
 44 | console.assert(
 45 | false,
Assertion failed: :::1:err::: /console: This is an assert message with a template
:::1:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed: :::1:err::: /console: This is an assert message with a template"
`)
} else {
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console: template(one: one, two: two)
:::0:out::: /console: This is a console page. Don't match the codeframe.
:::0:out::: /console: template(one: one, two: two)
:::0:out::: /console: This is a console page. Don't match the codeframe.
:::0:err::: /console: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console: test
at g (.next/server/app/console/page.js:<line>:<col>)
Assertion failed: :::0:err::: /console: This is an assert message with a template
:::0:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed: :::0:err::: /console: This is an assert message with a template
:::1:out::: /console: template(one: one, two: two)
:::1:out::: /console: This is a console page. Don't match the codeframe.
:::1:out::: /console: template(one: one, two: two)
:::1:out::: /console: This is a console page. Don't match the codeframe.
:::1:err::: /console: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console: test
at g (.next/server/app/console/page.js:<line>:<col>)
Assertion failed: :::1:err::: /console: This is an assert message with a template
:::1:err::: /console: not a template { foo: 'just-some-object' }
Assertion failed: :::1:err::: /console: This is an assert message with a template"
`)
}
}
})
})
// TODO(restart-on-cache-miss): cacheSignal timing changes break console log dimming/hiding tests
describe.skip('cache-components - Logging after Abort', () => {
describe('(default) With Dimming - Server', () => {
const { next, skipped, isTurbopack } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/default',
skipDeployment: true,
skipStart: !isNextDev,
})
if (skipped) {
return
}
it('dims console calls after a prerender has aborted', async () => {
const path: string = '/console-after-abort/server'
if (isNextDev) {
const browser = await next.browser(path, {})
await retry(() => {
expect(stripAnsi(next.cliOutput)).toContain(`GET ${path} 200`)
})
// do not strip ANSI codes here since we're explicitly testing coloring.
const cliOutputFromPage = next.cliOutput.match(
new RegExp(`Compiled ${path}[^\n]+\n(.*)`, 's')
)[1]
const reorderedLines = reorderLinesByBadge(cliOutputFromPage)
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/server: logging before trying await headers()
:::0:out::: /console-after-abort/server: template(one: one, two: two)
:::0:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::0:out::: /console-after-abort/server: template(one: one, two: two)
:::0:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
 Cache  :::0:out::: /console-after-abort/server: template(one: one, two: two)
 Cache  :::0:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::0:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console-after-abort/server: test
at ConsolePage (app/console-after-abort/server/page.tsx:<line>:<col>)
  57 | foo: 'just-some-object',
 58 | })
> 59 | console.error(new Error(\`\${errBadge} /console-after-abort/server: test\`))
 | ^
 60 | console.assert(
 61 | false,
 62 | \`\${errBadge} /console-after-abort/server: This is an assert message with a %s\`,
Assertion failed: :::0:err::: /console-after-abort/server: This is an assert message with a template
:::0:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Assertion failed: :::0:err::: /console-after-abort/server: This is an assert message with a template
 Cache  :::0:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Assertion failed:  Cache  :::0:err::: /console-after-abort/server: This is an assert message with a template
 Cache  Assertion failed: :::0:err::: /console-after-abort/server: This is an assert message with a template
:::1:out::: /console-after-abort/server: logging before trying await headers()
:::1:out::: /console-after-abort/server: template(one: one, two: two)
:::1:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::1:err::: /console-after-abort/server: caught error trying await headers()
:::1:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console-after-abort/server: test
at ConsolePage (app/console-after-abort/server/page.tsx:<line>:<col>)
  57 | foo: 'just-some-object',
 58 | })
> 59 | console.error(new Error(\`\${errBadge} /console-after-abort/server: test\`))
 | ^
 60 | console.assert(
 61 | false,
 62 | \`\${errBadge} /console-after-abort/server: This is an assert message with a %s\`,
Assertion failed: :::1:err::: /console-after-abort/server: This is an assert message with a template
:::2:out::: /console-after-abort/server: logging before trying await headers()
:::2:out::: /console-after-abort/server: template(one: one, two: two)
:::2:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::2:err::: /console-after-abort/server: caught error trying await headers()
:::2:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Error: :::2:err::: /console-after-abort/server: test
at ConsolePage (app/console-after-abort/server/page.tsx:<line>:<col>)
  57 | foo: 'just-some-object',
 58 | })
> 59 | console.error(new Error(\`\${errBadge} /console-after-abort/server: test\`))
 | ^
 60 | console.assert(
 61 | false,
 62 | \`\${errBadge} /console-after-abort/server: This is an assert message with a %s\`,
Assertion failed: :::2:err::: /console-after-abort/server: This is an assert message with a template
"
`)
await expect(browser).toDisplayCollapsedRedbox(`
{
"description": ":::0:err::: /console-after-abort/server: test",
"environmentLabel": "Server",
"label": "Console Error",
"source": "app/console-after-abort/server/page.tsx (59:17) @ ConsolePage
> 59 | console.error(new Error(\`\${errBadge} /console-after-abort/server: test\`))
| ^",
"stack": [
"ConsolePage app/console-after-abort/server/page.tsx (59:17)",
"ConsolePage <anonymous>",
],
}
`)
} else {
try {
await next.build({
args: ['--debug-build-paths', `app${path}/page.tsx`],
})
} catch (err) {
const error = new Error(
'Expected build to complete successfully, but it failed'
)
error.cause = err
throw error
}
const unorderedLines = next.cliOutput.match(
/Collecting page data[^\n]+\n(.*)\n.*Finalizing page optimization /s
)[1]
const reorderedLines = reorderLinesByBadge(unorderedLines)
if (isTurbopack) {
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/server: logging before trying await headers()
:::0:out::: /console-after-abort/server: template(one: one, two: two)
:::0:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::0:err::: /console-after-abort/server: caught error trying await headers()
:::0:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console-after-abort/server: test
at g (turbopack:///[project]/app/console-after-abort/server/page.tsx:<line>:<col>)
  57 | foo: 'just-some-object',
 58 | })
> 59 | console.error(new Error(\`\${errBadge} /console-after-abort/server: test\`))
 | ^
 60 | console.assert(
 61 | false,
 62 | \`\${errBadge} /console-after-abort/server: This is an assert message with a %s\`,
Assertion failed: :::0:err::: /console-after-abort/server: This is an assert message with a template
:::1:out::: /console-after-abort/server: logging before trying await headers()
:::1:out::: /console-after-abort/server: template(one: one, two: two)
:::1:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::1:err::: /console-after-abort/server: caught error trying await headers()
:::1:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console-after-abort/server: test
at g (turbopack:///[project]/app/console-after-abort/server/page.tsx:<line>:<col>)
  57 | foo: 'just-some-object',
 58 | })
> 59 | console.error(new Error(\`\${errBadge} /console-after-abort/server: test\`))
 | ^
 60 | console.assert(
 61 | false,
 62 | \`\${errBadge} /console-after-abort/server: This is an assert message with a %s\`,
Assertion failed: :::1:err::: /console-after-abort/server: This is an assert message with a template"
`)
} else {
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/server: logging before trying await headers()
:::0:out::: /console-after-abort/server: template(one: one, two: two)
:::0:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::0:err::: /console-after-abort/server: caught error trying await headers()
:::0:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console-after-abort/server: test
at i (.next/server/app/console-after-abort/server/page.js:<line>:<col>)
Assertion failed: :::0:err::: /console-after-abort/server: This is an assert message with a template
:::1:out::: /console-after-abort/server: logging before trying await headers()
:::1:out::: /console-after-abort/server: template(one: one, two: two)
:::1:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::1:err::: /console-after-abort/server: caught error trying await headers()
:::1:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console-after-abort/server: test
at i (.next/server/app/console-after-abort/server/page.js:<line>:<col>)
Assertion failed: :::1:err::: /console-after-abort/server: This is an assert message with a template"
`)
}
}
})
})
describe('(default) With Dimming - Client', () => {
const { next, skipped, isTurbopack } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/default',
skipDeployment: true,
skipStart: !isNextDev,
})
if (skipped) {
return
}
it('dims console calls after a prerender has aborted', async () => {
const path: string = '/console-after-abort/client'
if (isNextDev) {
const browser = await next.browser(path, {})
await retry(() => {
expect(stripAnsi(next.cliOutput)).toContain(`GET ${path} 200`)
})
// do not strip ANSI codes here since we're explicitly testing coloring.
const cliOutputFromPage = next.cliOutput.match(
new RegExp(`Compiled ${path}[^\n]+\n(.*)`, 's')
)[1]
const reorderedLines = reorderLinesByBadge(cliOutputFromPage)
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/client: logging before prerender abort
:::0:out::: /console-after-abort/client: logging before prerender aborts in client component
:::0:out::: /console-after-abort/client: template(one: one, two: two)
:::0:out::: /console-after-abort/client: This is a console page. Don't match the codeframe.
:::0:err::: /console-after-abort/client: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console-after-abort/client: test
at log (app/console-after-abort/client/client.tsx:<line>:<col>)
  15 | foo: 'just-some-object',
 16 | })
> 17 | console.error(new Error(\`\${errBadge} /console-after-abort/client: test\`))
 | ^
 18 | console.assert(
 19 | false,
 20 | \`\${errBadge} /console-after-abort/client: This is an assert message with a %s\`,
Assertion failed: :::0:err::: /console-after-abort/client: This is an assert message with a template
:::1:out::: /console-after-abort/client: logging before prerender abort
:::1:out::: /console-after-abort/client: logging before prerender aborts in client component
:::1:out::: /console-after-abort/client: template(one: one, two: two)
:::1:out::: /console-after-abort/client: This is a console page. Don't match the codeframe.
:::1:err::: /console-after-abort/client: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console-after-abort/client: test
at log (app/console-after-abort/client/client.tsx:<line>:<col>)
  15 | foo: 'just-some-object',
 16 | })
> 17 | console.error(new Error(\`\${errBadge} /console-after-abort/client: test\`))
 | ^
 18 | console.assert(
 19 | false,
 20 | \`\${errBadge} /console-after-abort/client: This is an assert message with a %s\`,
Assertion failed: :::1:err::: /console-after-abort/client: This is an assert message with a template
:::2:out::: /console-after-abort/client: logging before prerender abort
:::2:out::: /console-after-abort/client: logging before prerender aborts in client component
:::2:out::: /console-after-abort/client: template(one: one, two: two)
:::2:out::: /console-after-abort/client: This is a console page. Don't match the codeframe.
:::2:err::: /console-after-abort/client: not a template { foo: 'just-some-object' }
Error: :::2:err::: /console-after-abort/client: test
at log (app/console-after-abort/client/client.tsx:<line>:<col>)
  15 | foo: 'just-some-object',
 16 | })
> 17 | console.error(new Error(\`\${errBadge} /console-after-abort/client: test\`))
 | ^
 18 | console.assert(
 19 | false,
 20 | \`\${errBadge} /console-after-abort/client: This is an assert message with a %s\`,
Assertion failed: :::2:err::: /console-after-abort/client: This is an assert message with a template
"
`)
await expect(browser).toDisplayCollapsedRedbox(`
{
"description": ":::0:err::: /console-after-abort/client: test",
"environmentLabel": null,
"label": "Console Error",
"source": "app/console-after-abort/client/client.tsx (17:17) @ log
> 17 | console.error(new Error(\`\${errBadge} /console-after-abort/client: test\`))
| ^",
"stack": [
"log app/console-after-abort/client/client.tsx (17:17)",
],
}
`)
} else {
try {
await next.build({
args: ['--debug-build-paths', `app${path}/page.tsx`],
})
} catch (err) {
const error = new Error(
'Expected build to complete successfully, but it failed'
)
error.cause = err
throw error
}
const unorderedLines = next.cliOutput.match(
/Collecting page data[^\n]+\n(.*)\n.*Finalizing page optimization /s
)[1]
const reorderedLines = reorderLinesByBadge(unorderedLines)
if (isTurbopack) {
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/client: logging before prerender abort
:::0:out::: /console-after-abort/client: logging before prerender aborts in client component
:::0:out::: /console-after-abort/client: template(one: one, two: two)
:::0:out::: /console-after-abort/client: This is a console page. Don't match the codeframe.
:::0:err::: /console-after-abort/client: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console-after-abort/client: test
at c (turbopack:///[project]/app/console-after-abort/client/client.tsx:<line>:<col>)
  15 | foo: 'just-some-object',
 16 | })
> 17 | console.error(new Error(\`\${errBadge} /console-after-abort/client: test\`))
 | ^
 18 | console.assert(
 19 | false,
 20 | \`\${errBadge} /console-after-abort/client: This is an assert message with a %s\`,
Assertion failed: :::0:err::: /console-after-abort/client: This is an assert message with a template
:::1:out::: /console-after-abort/client: logging before prerender abort
:::1:out::: /console-after-abort/client: logging before prerender aborts in client component
:::1:out::: /console-after-abort/client: template(one: one, two: two)
:::1:out::: /console-after-abort/client: This is a console page. Don't match the codeframe.
:::1:err::: /console-after-abort/client: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console-after-abort/client: test
at c (turbopack:///[project]/app/console-after-abort/client/client.tsx:<line>:<col>)
  15 | foo: 'just-some-object',
 16 | })
> 17 | console.error(new Error(\`\${errBadge} /console-after-abort/client: test\`))
 | ^
 18 | console.assert(
 19 | false,
 20 | \`\${errBadge} /console-after-abort/client: This is an assert message with a %s\`,
Assertion failed: :::1:err::: /console-after-abort/client: This is an assert message with a template"
`)
} else {
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/client: logging before prerender abort
:::0:out::: /console-after-abort/client: logging before prerender aborts in client component
:::0:out::: /console-after-abort/client: template(one: one, two: two)
:::0:out::: /console-after-abort/client: This is a console page. Don't match the codeframe.
:::0:err::: /console-after-abort/client: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console-after-abort/client: test
at e (.next/server/app/console-after-abort/client/page.js:<line>:<col>)
Assertion failed: :::0:err::: /console-after-abort/client: This is an assert message with a template
:::1:out::: /console-after-abort/client: logging before prerender abort
:::1:out::: /console-after-abort/client: logging before prerender aborts in client component
:::1:out::: /console-after-abort/client: template(one: one, two: two)
:::1:out::: /console-after-abort/client: This is a console page. Don't match the codeframe.
:::1:err::: /console-after-abort/client: not a template { foo: 'just-some-object' }
Error: :::1:err::: /console-after-abort/client: test
at e (.next/server/app/console-after-abort/client/page.js:<line>:<col>)
Assertion failed: :::1:err::: /console-after-abort/client: This is an assert message with a template"
`)
}
}
})
})
describe('With Hiding - Server', () => {
const { next, skipped } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/hide-logs-after-abort',
skipDeployment: true,
skipStart: !isNextDev,
})
if (skipped) {
return
}
it('hides console calls after a prerender has aborted', async () => {
const path: string = '/console-after-abort/server'
if (isNextDev) {
const browser = await next.browser(path, {})
await retry(() => {
expect(stripAnsi(next.cliOutput)).toContain(`GET ${path} 200`)
})
// do not strip ANSI codes here since we're explicitly testing coloring.
const cliOutputFromPage = next.cliOutput.match(
new RegExp(`Compiled ${path}[^\n]+\n(.*)`, 's')
)[1]
const reorderedLines = reorderLinesByBadge(cliOutputFromPage)
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/server: logging before trying await headers()
:::0:out::: /console-after-abort/server: template(one: one, two: two)
:::0:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::0:out::: /console-after-abort/server: template(one: one, two: two)
:::0:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
 Cache  :::0:out::: /console-after-abort/server: template(one: one, two: two)
 Cache  :::0:out::: /console-after-abort/server: This is a console page. Don't match the codeframe.
:::0:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console-after-abort/server: test
at ConsolePage (app/console-after-abort/server/page.tsx:<line>:<col>)
  57 | foo: 'just-some-object',
 58 | })
> 59 | console.error(new Error(\`\${errBadge} /console-after-abort/server: test\`))
 | ^
 60 | console.assert(
 61 | false,
 62 | \`\${errBadge} /console-after-abort/server: This is an assert message with a %s\`,
Assertion failed: :::0:err::: /console-after-abort/server: This is an assert message with a template
:::0:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Assertion failed: :::0:err::: /console-after-abort/server: This is an assert message with a template
 Cache  :::0:err::: /console-after-abort/server: not a template { foo: 'just-some-object' }
Assertion failed:  Cache  :::0:err::: /console-after-abort/server: This is an assert message with a template
 Cache  Assertion failed: :::0:err::: /console-after-abort/server: This is an assert message with a template
:::1:out::: /console-after-abort/server: logging before trying await headers()
:::2:out::: /console-after-abort/server: logging before trying await headers()
"
`)
await expect(browser).toDisplayCollapsedRedbox(`
{
"description": ":::0:err::: /console-after-abort/server: test",
"environmentLabel": "Server",
"label": "Console Error",
"source": "app/console-after-abort/server/page.tsx (59:17) @ ConsolePage
> 59 | console.error(new Error(\`\${errBadge} /console-after-abort/server: test\`))
| ^",
"stack": [
"ConsolePage app/console-after-abort/server/page.tsx (59:17)",
"ConsolePage <anonymous>",
],
}
`)
} else {
try {
await next.build({
args: ['--debug-build-paths', `app${path}/page.tsx`],
})
} catch (err) {
const error = new Error(
'Expected build to complete successfully, but it failed'
)
error.cause = err
throw error
}
const unorderedLines = next.cliOutput.match(
/Collecting page data[^\n]+\n(.*)\n.*Finalizing page optimization /s
)[1]
const reorderedLines = reorderLinesByBadge(unorderedLines)
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/server: logging before trying await headers()
:::1:out::: /console-after-abort/server: logging before trying await headers()"
`)
}
})
})
describe('With Hiding - Client', () => {
const { next, skipped } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/hide-logs-after-abort',
skipDeployment: true,
skipStart: !isNextDev,
})
if (skipped) {
return
}
it('hides console calls after a prerender has aborted', async () => {
const path: string = '/console-after-abort/client'
if (isNextDev) {
const browser = await next.browser(path, {})
await retry(() => {
expect(stripAnsi(next.cliOutput)).toContain(`GET ${path} 200`)
})
// do not strip ANSI codes here since we're explicitly testing coloring.
const cliOutputFromPage = next.cliOutput.match(
new RegExp(`Compiled ${path}[^\n]+\n(.*)`, 's')
)[1]
const reorderedLines = reorderLinesByBadge(cliOutputFromPage)
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/client: logging before prerender abort
:::0:out::: /console-after-abort/client: logging before prerender aborts in client component
:::0:out::: /console-after-abort/client: template(one: one, two: two)
:::0:out::: /console-after-abort/client: This is a console page. Don't match the codeframe.
:::0:err::: /console-after-abort/client: not a template { foo: 'just-some-object' }
Error: :::0:err::: /console-after-abort/client: test
at log (app/console-after-abort/client/client.tsx:<line>:<col>)
  15 | foo: 'just-some-object',
 16 | })
> 17 | console.error(new Error(\`\${errBadge} /console-after-abort/client: test\`))
 | ^
 18 | console.assert(
 19 | false,
 20 | \`\${errBadge} /console-after-abort/client: This is an assert message with a %s\`,
Assertion failed: :::0:err::: /console-after-abort/client: This is an assert message with a template
:::1:out::: /console-after-abort/client: logging before prerender abort
:::1:out::: /console-after-abort/client: logging before prerender aborts in client component
:::2:out::: /console-after-abort/client: logging before prerender abort
:::2:out::: /console-after-abort/client: logging before prerender aborts in client component
"
`)
await expect(browser).toDisplayCollapsedRedbox(`
{
"description": ":::0:err::: /console-after-abort/client: test",
"environmentLabel": null,
"label": "Console Error",
"source": "app/console-after-abort/client/client.tsx (17:17) @ log
> 17 | console.error(new Error(\`\${errBadge} /console-after-abort/client: test\`))
| ^",
"stack": [
"log app/console-after-abort/client/client.tsx (17:17)",
],
}
`)
} else {
try {
await next.build({
args: ['--debug-build-paths', `app${path}/page.tsx`],
})
} catch (err) {
const error = new Error(
'Expected build to complete successfully, but it failed'
)
error.cause = err
throw error
}
const unorderedLines = next.cliOutput.match(
/Collecting page data[^\n]+\n(.*)\n.*Finalizing page optimization /s
)[1]
const reorderedLines = reorderLinesByBadge(unorderedLines)
expect(reorderedLines).toMatchInlineSnapshot(`
":::0:out::: /console-after-abort/client: logging before prerender abort
:::0:out::: /console-after-abort/client: logging before prerender aborts in client component
:::1:out::: /console-after-abort/client: logging before prerender abort
:::1:out::: /console-after-abort/client: logging before prerender aborts in client component"
`)
}
})
})
})
type RenderGroups = Map<string | null, StreamGroups>
type StreamGroups = Map<string | null, Lines>
type Lines = Array<string>
function reorderLinesByBadge(selectedOutput: string) {
const unorderedLines = selectedOutput
.split('\n')
.filter(
(l) => !(l.includes('Generating static pages') || l.includes(' GET '))
)
.map((l) => l.replace(/( at .*):\d+:\d+/, '$1:<line>:<col>'))
let currentLines: Lines = []
const renderGroups: RenderGroups = new Map([
[null, new Map([[null, currentLines]]) satisfies StreamGroups],
])
for (let line of unorderedLines) {
let match = line.match(/:::([^: \n]+):([^: \n]+):::/)
if (match) {
const [_, render, stream] = match
const streamGroups = renderGroups.get(render)
if (!streamGroups) {
currentLines = []
renderGroups.set(render, new Map([[stream, currentLines]]))
} else {
currentLines = streamGroups.get(stream)
if (!currentLines) {
streamGroups.set(stream, (currentLines = []))
}
}
}
currentLines.push(line)
}
const orderedRenders = Array.from(renderGroups.values())
const orderedStreams = orderedRenders.map((s) =>
Array.from(s.values()).flat()
)
return orderedStreams.flat().join('\n')
}