next.js/test/e2e/app-dir/cache-components-console/cache-components.console.test.ts
cache-components.console.test.ts792 lines44.9 KB
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')
}
Quest for Codev2.0.0
/
SIGN IN