next.js/test/e2e/app-dir/use-cache-unknown-cache-kind/use-cache-unknown-cache-kind.test.ts
use-cache-unknown-cache-kind.test.ts216 lines6.8 KB
import { nextTestSetup } from 'e2e-utils'
import {
  waitForRedbox,
  waitForNoRedbox,
  getRedboxDescription,
  getRedboxSource,
  retry,
} from 'next-test-utils'
import stripAnsi from 'strip-ansi'
import { createSandbox } from 'development-sandbox'

describe('use-cache-unknown-cache-kind', () => {
  const { next, isNextStart, isTurbopack, isRspack, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: process.env.NEXT_TEST_MODE !== 'dev',
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  if (isNextStart) {
    beforeAll(async () => {
      await next.build()
    })

    it('should fail the build with an error', async () => {
      const buildOutput = getBuildOutput(next.cliOutput)

      if (isTurbopack) {
        expect(buildOutput).toMatchInlineSnapshot(`
         "Error: Turbopack build failed with 1 errors:
         ./app/page.tsx:1:1
         Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config.
         > 1 | 'use cache: custom'
             | ^^^^^^^^^^^^^^^^^^^
           2 |
           3 | export default async function Page() {
           4 |   return <p>hello world</p>

         Ecmascript file had an error


             at <unknown> (./app/page.tsx:1:1)
         "
        `)
      } else if (isRspack) {
        expect(buildOutput).toMatchInlineSnapshot(`
         "
         ./app/page.tsx
           ╰─▶   × Error:   x Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config.
                 │
                 │    ,-[1:1]
                 │  1 | 'use cache: custom'
                 │    : ^^^^^^^^^^^^^^^^^^^
                 │  2 |
                 │  3 | export default async function Page() {
                 │  4 |   return <p>hello world</p>
                 │    \`----
                 │
               
         Import trace for requested module:
         ./app/page.tsx


         > Build failed because of Rspack errors
         "
        `)
      } else {
        expect(buildOutput).toMatchInlineSnapshot(`
         "
         ./app/page.tsx
         Error:   x Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config.

            ,-[1:1]
          1 | 'use cache: custom'
            : ^^^^^^^^^^^^^^^^^^^
          2 | 
          3 | export default async function Page() {
          4 |   return <p>hello world</p>
            \`----

         Import trace for requested module:
         ./app/page.tsx


         > Build failed because of webpack errors
         "
        `)
      }
    })

    it('should not fail the build for default cache kinds', async () => {
      expect(next.cliOutput).not.toInclude('Unknown cache kind "remote"')
    })
  } else {
    it('should not show an error for default cache kinds', async () => {
      await using sandbox = await createSandbox(next, undefined, '/remote')
      const { browser } = sandbox
      await waitForNoRedbox(browser)
    })

    it('should show a build error', async () => {
      await using sandbox = await createSandbox(next, undefined, '/')
      const { browser } = sandbox

      await waitForRedbox(browser)

      const errorDescription = await getRedboxDescription(browser)
      const errorSource = await getRedboxSource(browser)

      if (isTurbopack) {
        expect(errorDescription).toMatchInlineSnapshot(
          `"Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config."`
        )
      } else if (isRspack) {
        expect(errorDescription).toMatchInlineSnapshot(
          `"  ╰─▶   × Error:   x Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config."`
        )
      } else {
        expect(errorDescription).toMatchInlineSnapshot(
          `"  x Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config."`
        )
      }

      if (isTurbopack) {
        expect(errorSource).toMatchInlineSnapshot(`
         "./app/page.tsx (1:1)
         Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config.
         > 1 | 'use cache: custom'
             | ^^^^^^^^^^^^^^^^^^^
           2 |
           3 | export default async function Page() {
           4 |   return <p>hello world</p>

         Ecmascript file had an error"
        `)
      } else if (isRspack) {
        expect(errorSource).toMatchInlineSnapshot(`
         "./app/page.tsx
           ╰─▶   × Error:   x Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config.
                 │
                 │    ,-[1:1]
                 │  1 | 'use cache: custom'
                 │    : ^^^^^^^^^^^^^^^^^^^
                 │  2 |
                 │  3 | export default async function Page() {
                 │  4 |   return <p>hello world</p>
                 │    \`----
                 │"
        `)
      } else {
        expect(errorSource).toMatchInlineSnapshot(`
         "./app/page.tsx
         Error:   x Unknown cache kind "custom". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config.

            ,-[1:1]
          1 | 'use cache: custom'
            : ^^^^^^^^^^^^^^^^^^^
          2 | 
          3 | export default async function Page() {
          4 |   return <p>hello world</p>
            \`----"
        `)
      }
    })

    it('should recover from the build error if the cache handler is defined', async () => {
      await using sandbox = await createSandbox(next, undefined, '/')
      const { browser, session } = sandbox

      await waitForRedbox(browser)

      await session.patch(
        'next.config.js',
        `module.exports = {
          cacheComponents: true,
          cacheHandlers: {
            custom: require.resolve(
              'next/dist/server/lib/cache-handlers/default.external'
            ),
          },
        }`
      )

      await retry(async () => {
        expect(await browser.elementByCss('p').text()).toBe('hello world')
        await waitForNoRedbox(browser)
      })
    })
  }
})

function getBuildOutput(cliOutput: string): string {
  const lines: string[] = []
  let skipLines = true

  for (const line of cliOutput.split('\n')) {
    if (!skipLines) {
      if (line.includes('at turbopackBuild')) {
        break
      }

      lines.push(stripAnsi(line))
    } else if (
      line.includes('Build error occurred') ||
      line.includes('Failed to compile')
    ) {
      skipLines = false
    }
  }

  return lines.join('\n')
}
Quest for Codev2.0.0
/
SIGN IN