Files
vercel__next.js/test/e2e/app-dir/cache-components-console/cache-components.console.test.ts
Josh Story e0966df114 test: migrate caching deploy exclusions to force gates (#98154)
## Summary

- migrate Cache Components, PPR, prefetching, prerendering,
revalidation, and SSG deployment exclusions to `@force-gate`
- remove the corresponding `skipDeployment` options and `skipped`
control flow while preserving each suite's rationale

This keeps caching-related exclusions together so their deployed
semantics can be reviewed by the same owners.

## Verification

- verified on the combined top-of-stack tree with `pnpm typescript`
- compared ordinary-mode collection before and after: all 4,670 existing
test names matched
- collected all 510 affected files in deploy mode: 4,578 skipped tests,
zero failures

<!-- NEXT_JS_LLM -->
2026-09-09 08:25:36 -07:00

783 lines
45 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
// TODO(deploy-test-completion): Re-enable this suite in deploy mode.
// It likely asserts local CLI or runtime output that deploy tests do not expose.
// @force-gate !deploy
// @force-gate TODO
describe('cache-components - Console Dimming - Validation', () => {
const { next, isTurbopack } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/default',
skipStart: !isNextDev,
})
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', () => {
// TODO(deploy-test-completion): Re-enable this suite in deploy mode.
// It likely asserts local CLI or runtime output that deploy tests do not expose.
// @force-gate !deploy
describe('(default) With Dimming - Server', () => {
const { next, isTurbopack } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/default',
skipStart: !isNextDev,
})
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"
`)
}
}
})
})
// TODO(deploy-test-completion): Re-enable this suite in deploy mode.
// It likely asserts local CLI or runtime output that deploy tests do not expose.
// @force-gate !deploy
describe('(default) With Dimming - Client', () => {
const { next, isTurbopack } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/default',
skipStart: !isNextDev,
})
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"
`)
}
}
})
})
// TODO(deploy-test-completion): Re-enable this suite in deploy mode.
// It likely asserts local CLI or runtime output that deploy tests do not expose.
// @force-gate !deploy
describe('With Hiding - Server', () => {
const { next } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/hide-logs-after-abort',
skipStart: !isNextDev,
})
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()"
`)
}
})
})
// TODO(deploy-test-completion): Re-enable this suite in deploy mode.
// It likely asserts local CLI or runtime output that deploy tests do not expose.
// @force-gate !deploy
describe('With Hiding - Client', () => {
const { next } = nextTestSetup({
env: {
FORCE_COLOR: '1',
},
files: __dirname + '/fixtures/hide-logs-after-abort',
skipStart: !isNextDev,
})
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')
}