next.js/test/e2e/app-dir/use-cache-without-experimental-flag/use-cache-without-experimental-flag.test.ts
use-cache-without-experimental-flag.test.ts198 lines6.4 KB
import { nextTestSetup } from 'e2e-utils'
import { NextConfig } from 'next'
import {
  waitForRedbox,
  waitForNoRedbox,
  getRedboxDescription,
  getRedboxSource,
  retry,
} from 'next-test-utils'
import stripAnsi from 'strip-ansi'

const nextConfigWithUseCache: NextConfig = {
  experimental: { useCache: true },
}

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

  if (skipped) {
    return
  }

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

      if (isTurbopack) {
        expect(buildOutput).toContain(
          'To use "use cache", please enable the feature flag `cacheComponents` in your Next.js config.'
        )
        expect(buildOutput).toContain(
          'Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage'
        )
        expect(buildOutput).toContain('Ecmascript file had an error')
        expect(buildOutput).toContain('./app/page.tsx:1:1')
        expect(buildOutput).toContain("> 1 | 'use cache'")
        expect(buildOutput).toContain('at <unknown> (./app/page.tsx:1:1)')
      } else if (isRspack) {
        expect(buildOutput).toMatchInlineSnapshot(`
         "
         ./app/page.tsx
           ╰─▶   × Error:   x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config.
                 │   |
                 │   | Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage
                 │
                 │    ,-[1:1]
                 │  1 | 'use cache'
                 │    : ^^^^^^^^^^^
                 │  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 To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config.
           |
           | Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage

            ,-[1:1]
          1 | 'use cache'
            : ^^^^^^^^^^^
          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
         "
        `)
      }
    })
  } else {
    it('should show a build error', async () => {
      const browser = await next.browser('/')

      await waitForRedbox(browser)

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

      if (isTurbopack) {
        expect(errorDescription).toMatchInlineSnapshot(
          `"To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config."`
        )
      } else if (isRspack) {
        expect(errorDescription).toMatchInlineSnapshot(
          `"  ╰─▶   × Error:   x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config."`
        )
      } else {
        expect(errorDescription).toMatchInlineSnapshot(
          `"  x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config."`
        )
      }

      if (isTurbopack) {
        expect(errorSource).toContain('./app/page.tsx (1:1)')
        expect(errorSource).toContain(
          'To use "use cache", please enable the feature flag `cacheComponents` in your Next.js config.'
        )
        expect(errorSource).toContain(
          'Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage'
        )
        expect(errorSource).toContain("> 1 | 'use cache'")
        expect(errorSource).toContain('Ecmascript file had an error')
      } else if (isRspack) {
        expect(errorSource).toMatchInlineSnapshot(`
         "./app/page.tsx
           ╰─▶   × Error:   x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config.
                 │   |
                 │   | Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage
                 │
                 │    ,-[1:1]
                 │  1 | 'use cache'
                 │    : ^^^^^^^^^^^
                 │  2 |
                 │  3 | export default async function Page() {
                 │  4 |   return <p>hello world</p>
                 │    \`----
                 │"
        `)
      } else {
        expect(errorSource).toMatchInlineSnapshot(`
         "./app/page.tsx
         Error:   x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config.
           |
           | Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage

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

    it('should recover from the build error if useCache flag is set', async () => {
      const browser = await next.browser('/')

      await waitForRedbox(browser)

      await next.patchFile(
        'next.config.js',
        `module.exports = ${JSON.stringify(nextConfigWithUseCache)}`,
        () =>
          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