 nextConfigPath = 'next.config.js'
  const outdir = 'out'
  const outNoTrailSlash = 'outNoTrailSlash'
  let server: Server
  let port: number
  let serverNoTrailSlash: Server
  let portNoTrailSlash: number

  beforeAll(async () => {
    const nextConfig = await next.readFile(nextConfigPath)
    await next.build()

    await next.patchFile(
      nextConfigPath,
      nextConfig
        .replace(`trailingSlash: true`, `trailingSlash: false`)
        .replace(`distDir: 'out'`, `distDir: '${outNoTrailSlash}'`)

Dir, outNoTrailSlash)
    )
    port = (server.address() as AddressInfo).port
    portNoTrailSlash = (serverNoTrailSlash.address() as AddressInfo).port
  })

  afterAll(async () => {
    await Promise.all([
      new Promise((resolve) => server.close(resol

    )
    await next.build()
    await next.patchFile(nextConfigPath, nextConfig)

    server = await startStaticServer(path.join(next.testDir, outdir))
    serverNoTrailSlash = await startStaticServer(
      path.join(next.test


ts = (phase) => {
  return {
    output: 'export',
    distDir: 'out',
    trailingSlash: true,
    exportPathMap: function () {
      return {
        '/': { page: '/' },
        '/index': { page: '/' },
        '/about': { page: '/about' },
        '/button-link': { page: '/button-link' },
        '/hash-link': { page: '/hash-link' },
        '/empty-hash-link': { page: '/empty-hash-link' },
        '/empty-query-link': { page: '/empty-query-link' },
        '/get-initial-props-with-no-query': {

} },
        '/dynamic/one': {
          page: '/dynamic',
          query: { text: 'next export is nice' },
        },
        '/dynamic/two': {
          page: '/dynamic',
          query: { text: 'Vercel is awesome' },
        },
        '/file-name.md'

 page: '/get-initial-props-with-no-query',
        },
        '/counter': { page: '/counter' },
        '/dynamic-imports': { page: '/dynamic-imports' },
        '/dynamic': { page: '/dynamic', query: { text: 'cool dynamic text'


nk'
import Router from 'next/router'

function routeToAbout(e) {
  e.preventDefault()
  Router.push('/about')
}

export default () => (

      <Link href="/about" id="about-via-link">
        About via Link
      </Link>

        About via Router

      <Link href="/counter" id="counter">
        Counter
      </Link>
      <Link href="/dynamic?text=cool+dynamic+text" id="get-initial-props">
        getI

some"
        as="/dynamic/two"
        id="dynamic-2"
      >
        Dynamic 2
      </Link>
      <Link href="/dynamic?text=Vercel+is+awesome#cool" id="with-hash">
        With Hash
      </Link>
      <Link
        href="/dynamic?text=this+file+has+an+

nitialProps
      </Link>
      <Link
        href="/dynamic?text=next+export+is+nice"
        as="/dynamic/one"
        id="dynamic-1"
      >
        Dynamic 1
      </Link>
      <Link
        href="/dynamic?text=Vercel+is+awe


eRef, nextTestSetup } from 'e2e-utils'
import { join } from 'path'
import { fetchViaHTTP, waitFor } from 'next-test-utils'

describe('app-dir-prevent-304-caching', () => {
  const { next } = nextTestSetup({
    files: {
      'next.config.js': new FileRef(join(__dirname, 'next.config.js')),
      app: new FileRef(join(__dirname, 'app')),
    },
  })

  // https://github.com/vercel/next.js/issues/56580
  it('should not cache 304 status', async () => {
    // Ensure the first request hits a stale page trigger

nst rHit = await fetchViaHTTP(
      next.url,
      '/',
      {},
      {
        headers: {
          'If-None-Match': rStale.headers.get('etag'),
        },
      }
    )
    expect(rHit.status).toBe(200)
    await waitFor(500)

    // Here happens the

ing background revalidation.
    await next.waitForMinPrerenderAge(1000 + 50)
    const rStale = await fetchViaHTTP(next.url, '/')
    expect(rStale.status).toBe(200)

    await waitFor(500)

    // Cache HIT but still 200
    co


('TypeScript with error handling options', () => {
  describe('production mode', () => {
    const { next, skipped } = nextTestSetup({
      files: __dirname,
      skipStart: true,
      skipDeployment: true,
    })
    if (skipped) return

    for (const incremental of [false, true]) {
      for (const ignoreBuildErrors of [false, true]) {
        describe(`ignoreBuildErrors: ${ignoreBuildErrors}`, () => {
          let originalNextConfig: string
          let originalTsConfig: string

          beforeAll

= {
              typescript: { ignoreBuildErrors },
            }
            await next.patchFile(
              'next.config.js',
              'module.exports = ' + JSON.stringify(nextConfig)
            )
            const tsconfig = JSON.parse(origin

(async () => {
            originalNextConfig = await next
              .readFile('next.config.js')
              .catch(() => '')
            originalTsConfig = await next.readFile('tsconfig.json')
            const nextConfig


 { nextTestSetup } from 'e2e-utils'

describe('ipc-forbidden-headers', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should not error if expect header is included', async () => {
    let res = await next.fetch('/api/pages-api', {
      method: 'POST',
      headers: { expect: '100-continue' },
    })
    let text = await res.text()

    expect(text).toEqual('Hello, Next.js!')

    res = await next.fetch('/api/app-api', {
      method: 'POST',
      headers: {
        expect: '

t shouldn't contain a payload", async () => {
    let res = await next.fetch('/api/pages-api', {
      method: 'DELETE',
      headers: { 'content-length': '0' },
    })

    expect(res.status).toBe(200)

    res = await next.fetch('/api/app-api', {

100-continue',
      },
    })
    text = await res.text()

    expect(text).toEqual('Hello, Next.js!')
    expect(next.cliOutput).not.toContain('UND_ERR_NOT_SUPPORTED')
  })

  it("should not error on content-length: 0 if reques


tTestSetup } from 'e2e-utils'

const fileNames = ['1', '2.ext', '3.html']

describe('GS(S)P with file extension', () => {
  describe('production mode', () => {
    const { next, skipped } = nextTestSetup({
      files: __dirname,
      skipDeployment: true,
    })
    if (skipped) return

    it('should support slug with different extensions', async () => {
      for (const name of fileNames) {
        expect(await next.hasFile(`.next/server/pages/${name}.html`)).toBe(true)
        expect(await next.hasFile

map((path) => next.render(path))
      const contents = await Promise.all(contentPromises)
      contents.forEach((content, i) => expect(content).toContain(fileNames[i]))
    })

    it('should contain extension in name of json files in _next/data', async

(`.next/server/pages/${name}.json`)).toBe(true)
      }
    })

    it('should render properly for routes with extension', async () => {
      const paths = fileNames.map((name) => `/${name}`)
      const contentPromises = paths.


ations', () => {
  const { next } = nextTestSetup({
    skipStart: true,
    files: {
      'pages/index.js': `
          export default function Page() {
            return
hello world

          }
        `,
      'middleware.js': `
          import { NextResponse } from 'next/server'
          export default async function middleware(request) {
            return NextResponse.next()
          }

          export const config = { unstable_allowDynamic: true }
        `,
    },
  })

  it('fails to

async () => {
    const res = await next.build()
    expect(res.exitCode).toBe(1)
    expect(res.cliOutput).toContain(
      'middleware contains invalid middleware config: Expected string, received boolean at "unstable_allowDynamic", or Expected array, re

build when unstable_allowDynamic is not a string',


from 'e2e-utils'
import { findAllTelemetryEvents } from 'next-test-utils'

describe('build-lifecycle-hooks', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    env: {
      NEXT_TELEMETRY_DEBUG: '1',
    },
  })

  it('should run runAfterProductionCompile', async () => {
    const output = next.cliOutput

    expect(output).toContain('')
    expect(output).toContain(`Using distDir: ${next.testDir}/.next`)
    expect(output).toContain(`Using projectDir: ${next.testDir}`)
    expect(output).

UILD_FEATURE_USAGE')
    expect(events).toContainEqual({
      featureName: 'runAfterProductionCompile',
      invocationCount: 1,
    })
  })

  it('should allow throwing error in runAfterProductionCompile', async () => {
    try {
      await next.stop()

toContain(`Total files in ${next.testDir}/.next folder:`)
    expect(output).toContain('Completed runAfterProductionCompile in')

    // Ensure telemetry event is recorded
    const events = findAllTelemetryEvents(output, 'NEXT_B


tTestSetup } from 'e2e-utils'

describe('standalone mode - metadata routes', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    dependencies: {
      swr: 'latest',
    },
  })

  beforeAll(async () => {
    // Hide source files to make sure route.js can read files from source
    // in order to hit the prerender cache
    await next.renameFolder('app', 'app_hidden')
  })

  it('should handle metadata icons correctly', async () => {
    const faviconRes = await next.fetch('/favicon.ico')

-found/does-not-exist')
    expect(res.status).toBe(404)
    const html = await res.text()
    expect(html).toContain('app-not-found')
  })

  it('should handle private _next unmatched route correctly', async () => {
    const res = await next.fetch('/_nex

   const iconRes = await next.fetch('/icon.svg')
    expect(faviconRes.status).toBe(200)
    expect(iconRes.status).toBe(200)
  })

  it('should handle correctly not-found.js', async () => {
    const res = await next.fetch('/not


describe('create-next-app', () => {
  let nextTgzFilename: string

  beforeAll(() => {
    nextTgzFilename = resolveNextTgzFilename()
  })

  it('should not create if the target directory is not empty', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'non-empty-dir'
      await mkdir(join(cwd, projectName))
      const pkg = join(cwd, projectName, 'package.json')
      await writeFile(pkg, `{ "name": "${projectName}" }`)

      const res = await run(
        [
          proje

process.env.NEXT_RSPACK ? ['--rspack'] : []),
        ],
        nextTgzFilename,
        {
          cwd,
          reject: false,
        }
      )
      expect(res.exitCode).toBe(1)
      expect(res.stdout).toMatch(/contains files that could conflict/)

ctName,
          '--ts',
          '--app',
          '--no-linter',
          '--no-tailwind',
          '--no-src-dir',
          '--no-import-alias',
          '--no-react-compiler',
          '--no-agents-md',
          ...(


 prompts', () => {
  let nextTgzFilename: string

  beforeAll(() => {
    nextTgzFilename = resolveNextTgzFilename()
  })

  it('should prompt user for choice if directory name is absent', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'no-dir-name'
      const childProcess = createNextApp(
        [
          '--ts',
          '--app',
          '--eslint',
          '--no-src-dir',
          '--no-tailwind',
          '--no-import-alias',
          '--no-react-compiler',

).toBe(0)
          projectFilesShouldExist({
            cwd,
            projectName,
            files: ['package.json'],
          })
          resolve()
        })

        // enter project name
        childProcess.stdin.write(`${projectName}\n`)

       '--no-agents-md',
        ],
        {
          cwd,
        },
        nextTgzFilename
      )

      await new Promise<void>((resolve) => {
        childProcess.on('exit', async (exitCode) => {
          expect(exitCode


lly-packed workspace tarballs available to
 * `create-next-app` tests. The result is forwarded to spawned CNA
 * processes via `NEXT_TEST_PKG_PATHS` so the CNA template can install
 * siblings (`next-rspack`, `eslint-config-next`, ...) from their own
 * tarballs without reverse-engineering the repo layout.
 */

import { existsSync, readdirSync } from 'fs'
import { join, resolve } from 'path'

const REPO_PACKAGES_DIR = resolve(__dirname, '../../../..', 'packages')

/**
 * Returns a Map of <packageName, absol

tgz` files (used
 *    when running jest directly via `pnpm test-start-turbo` etc.).
 *
 * Returns `null` when no source is available, so callers can produce
 * targeted error messages.
 */
export function resolveTestPkgPaths(): Map<string, string> | null

utePathToPackedTarball> for every
 * locally-packed workspace package available to tests.
 *
 * Resolution order:
 * 1. `NEXT_TEST_PKG_PATHS` (JSON, set by `run-tests.js`).
 * 2. Discovery from the repo's `packages/<name>/packed.


_EXAMPLE_PATH,
  projectFilesShouldExist,
  resolveNextTgzFilename,
  run,
  useTempDir,
} from '../utils'

describe('create-next-app with package manager bun', () => {
  let nextTgzFilename: string
  let files: string[]

  beforeAll(async () => {
    nextTgzFilename = resolveNextTgzFilename()

    await command('bun', ['--version'])
      // install bun if not available
      .catch(() => command('npm', ['i', '-g', 'bun']))

    const bunVersion = (await execa('bun', ['--version'])).stdout.trim()
    // So

-bun flag', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'use-bun'
      const res = await run(
        [
          projectName,
          '--ts',
          '--app',
          '--use-bun',
          '--no-linter',

me CI runners pre-install Bun.
    // Locally, we don't pin Bun either.
    const lockFile = semver.gte(bunVersion, '1.2.0') ? 'bun.lock' : 'bun.lockb'
    files = [...DEFAULT_FILES, lockFile]
  })

  it('should use bun for --use


uldNotExist,
  resolveNextTgzFilename,
  run,
  useTempDir,
} from '../utils'

const lockFile = 'pnpm-lock.yaml'
const files = [...DEFAULT_FILES, lockFile]

// Match the monorepo's pinned pnpm so CNA's `pnpm install` doesn't drift to
// whichever version corepack happens to fetch as "latest" at test time.
const rootPackageManager: string =
  require('../../../../package.json').packageManager

describe('create-next-app with package manager pnpm', () => {
  let nextTgzFilename: string

  beforeAll(async () =>

      const projectName = 'use-pnpm'
      const res = await run(
        [
          projectName,
          '--ts',
          '--app',
          '--use-pnpm',
          '--no-linter',
          '--no-src-dir',
          '--no-tailwind',
          '--no-im

 {
    nextTgzFilename = resolveNextTgzFilename()
    await command('corepack', ['prepare', '--activate', rootPackageManager])
  })

  it('should use pnpm for --use-pnpm flag', async () => {
    await useTempDir(async (cwd) => {


  projectFilesShouldExist,
} from '../utils'
import { mapSrcFiles, projectSpecification } from '../lib/specification'
import { projectDepsShouldBe } from '../lib/utils'

function shouldBeApiTemplateProject({
  cwd,
  projectName,
  mode,
  srcDir,
}: {
  cwd: string
  projectName: string
  mode: 'js' | 'ts'
  srcDir?: boolean
}) {
  const template = 'app-api'

  projectFilesShouldExist({
    cwd,
    projectName,
    files: mapSrcFiles(projectSpecification[template][mode].files, srcDir),
  })

  projectDep

ps: mapSrcFiles(projectSpecification[template][mode].devDeps, srcDir),
  })
}

describe('create-next-app --api (Headless App)', () => {
  let nextTgzFilename: string

  beforeAll(() => {
    nextTgzFilename = resolveNextTgzFilename()
  })

  it('should cre

sShouldBe({
    type: 'dependencies',
    cwd,
    projectName,
    deps: mapSrcFiles(projectSpecification[template][mode].deps, srcDir),
  })

  projectDepsShouldBe({
    type: 'devDependencies',
    cwd,
    projectName,
    de


pack } from 'next-test-utils'

const isTurbopack = shouldUseTurbopack()

// Each test runs a full create-next-app and (for `pages` templates) an
// install, build, and start cycle. Webpack builds are slower than Turbopack
// and can exceed the default 60-second per-test timeout, so give each matrix
// test a generous timeout.
const PER_TEST_TIMEOUT_MS = 5 * 60 * 1000

describe.each(['app', 'pages'] as const)(
  'CNA options matrix - %s',
  (pagesOrApp) => {
    let nextTgzFilename: string

    beforeAll(()

Running all 3 variants with
    // webpack pushes the total suite runtime past the 15-minute runner
    // timeout; Turbopack is fast enough to keep the full coverage.
    const importAliasValues = isTurbopack
      ? ['--import-alias=@acme/*', '--import-a

=> {
      nextTgzFilename = resolveNextTgzFilename()
    })

    const isApp = pagesOrApp === 'app'

    // The `--import-alias` flag doesn't interact with the bundler, so under
    // webpack we only exercise a single variant.


fined,
    keywords: undefined,
    referrer: undefined,
    themeColor: undefined,
    colorScheme: undefined,
    viewport: undefined,
    creator: undefined,
    publisher: undefined,
    robots: undefined,
    alternates: undefined,
    icons: undefined,
    manifest: undefined,
    openGraph: undefined,
    twitter: undefined,
    facebook: undefined,
    verification: undefined,
    appleWebApp: undefined,
    formatDetection: undefined,
    itunes: undefined,
    abstract: undefined,
    appLinks: un

     name: undefined,
    },
    themeColor: {
      color: '',
      media: undefined,
    },
    viewport: {
      width: undefined,
      height: undefined,
      initialScale: undefined,
      minimumScale: undefined,
      maximumScale: undefined,

defined,
    archives: undefined,
    assets: undefined,
    bookmarks: undefined,
    category: undefined,
    classification: undefined,
    other: undefined,
  }) satisfies Metadata
  ;({
    authors: {
      url: undefined,


pack internals (stats.json via webpack-bundle-analyzer).
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)('Chunking', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    dependencies: {
      lodash: 'latest',
      'webpack-bundle-analyzer': 'latest',
    },
  })

  let chunks: string[]
  let stats: any

  beforeAll(async () => {
    const statsRaw = (await next.readFile('.next/stats.json')).replace(
      /"static\\(.*?":?)/g,
      (match) => match.replace(/\\/g, '\\\\')
    )

 }

  it('should use all url friendly names', () => {
    expect(chunks).toEqual(chunks.map((name) => encodeURIComponent(name)))
  })

  it('should create a framework chunk', () => {
    expect(existsChunkNamed('framework')).toBe(true)
  })

  it('should n

    stats = JSON.parse(statsRaw)
    chunks = fs.readdirSync(join(next.testDir, '.next', 'static', 'chunks'))
  })

  const existsChunkNamed = (name: string) => {
    return chunks.some((chunk) => new RegExp(name).test(chunk))


import { join } from 'path'
import { nextTestSetup } from 'e2e-utils'
import { waitFor } from 'next-test-utils'

describe('react-virtualized wrapping next/image', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
    dependencies: {
      'react-virtualized': 'latest',
      'http-proxy': '1.18.1',
    },
  })
  if (skipped) return

  let proxyChild: ChildProcess
  let proxyPort: number

  async function getCancelCount() {
    const res

art()

    proxyChild = spawn(
      process.execPath,
      [join(next.testDir, 'server.js'), next.url, '0', '3000'],
      { stdio: ['ignore', 'pipe', 'inherit'] }
    )

    proxyPort = await new Promise<number>((resolve, reject) => {
      let buf = ''

 = await fetch(`http://localhost:${proxyPort}/_test/cancel-count`)
    const data = (await res.json()) as { cancelCount: number }
    return data.cancelCount
  }

  beforeAll(async () => {
    await next.build()
    await next.st


 test relied on these being hoisted in the
// monorepo root, but the isolated next install only sees declared deps.
const postcssPluginDeps = {
  pixrem: '5.0.0',
  'postcss-pseudoelements': '5.0.0',
  'postcss-short-size': '4.0.0',
  'postcss-trolling': '0.1.7',
}

describe('CSS Customization', () => {
  ;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
    'production mode',
    () => {
      describe('Basic CSS', () => {
        const { next } = nextTestSetup({
          files: path.join(__dir

cessfully', () => {
          expect(next.cliOutput).toMatch(/Compiled successfully/)
        })

        it(`should've compiled and prefixed`, async () => {
          const cssFolder = path.join(next.testDir, '.next/static/css')

          const files = a

name, 'css-fixtures/custom-configuration'),
          skipStart: true,
          dependencies: postcssPluginDeps,
        })

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

        it('should compile suc


getStaticProps() {
  // throw new Error('oops from getStaticProps')
  return {
    props: { world: 'world', time: new Date().getTime() },
  }
}

const Page = ({ world, time }) => {
  return (
    <>
      {/*
idk
 */}

hello {world}

      time: {time}
      <Link href="/non-json/[p]" as="/non-json/1" id="non-json">
        to non-json
      </Link>

      <Link href="/another?hello=world" as="/another/?hello=world" id="another">
        to an

"/blog/[post]" as="/blog/post-1" id="post-1">
        to dynamic
      </Link>
      <Link href="/blog/[post]" as="/blog/post-100" id="broken-post">
        to broken
      </Link>
      <Link
        href="/blog/[post]"
        as="/blog/post-999"

other
      </Link>

      <Link href="/something" id="something">
        to something
      </Link>

      <Link href="/normal" id="normal">
        to normal
      </Link>

      <Link href=


t async function getStaticProps({ params: { slug } }) {
  if (slug[0] === 'delayby3s') {
    await new Promise((resolve) => setTimeout(resolve, 3000))
  }

  return {
    props: {
      slug,
    },
  }
}

export async function getStaticPaths() {
  return {
    paths: [
      { params: { slug: ['first'] } },
      '/catchall-explicit/second',
      { params: { slug: ['another', 'value'] } },
      '/catchall-explicit/hello/another',
      '/catchall-explicit/[first]/[second]',
      { params: { slug: ['[thi

}
}

export default function Page({ slug }) {
  // Important to not check for `slug` existence (testing that build does not
  // render fallback version and error)
  return (
    <>

Hi {slug.join(' ')}
{' '}
      <Link href="/"

rd]', '[fourth]'] } },
    ],
    fallback: false,


t/link'
import { useRouter } from 'next/router'

export async function getStaticPaths() {
  return {
    paths: [],
    fallback: false,
  }
}

export async function getStaticProps({ params }) {
  await new Promise((resolve) => setTimeout(resolve, 1000))

  return {
    props: {
      params,
      hello: 'world',
      post: params.slug,
      random: Math.random(),
      time: (await import('perf_hooks')).performance.now(),
    },
  }
}

export default ({ post, time, params }) => {
  if (useRouter().isFal

(
    <>

Post: {post}

      time: {time}

{JSON.stringify(params)}

{JSON.stringify(useRouter().query)}

      <Link href="/" id="home">
        to home
      </Link>
    </>

lback) {
    return
hi fallback

  }

  return


ort { resolveNextTgzFilename, run, useTempDir } from './utils'

describe('create-next-app ESLint configuration', () => {
  let nextTgzFilename: string

  beforeAll(() => {
    nextTgzFilename = resolveNextTgzFilename()
  })

  it('should generate eslint.config.mjs for TypeScript project with ESLint', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'test-eslint-ts'
      const { exitCode } = await run(
        [
          projectName,
          '--ts',
          '--eslint',

   { cwd }
      )

      expect(exitCode).toBe(0)

      const projectDir = join(cwd, projectName)

      // Should have eslint.config.mjs
      expect(existsSync(join(projectDir, 'eslint.config.mjs'))).toBe(true)

      // Should NOT have biome.json

      '--no-tailwind',
          '--no-src-dir',
          '--no-react-compiler',
          '--no-agents-md',
          '--app',
          '--no-import-alias',
          '--skip-install',
        ],
        nextTgzFilename,


]
  devDeps: string[]
}

export type ProjectSpecification = {
  global: ProjectSettings
} & {
  [key in TemplateType]: {
    [key in TemplateMode]: ProjectSettings
  }
}

/**
 * Required files for a given project template and mode.
 */
export const projectSpecification: ProjectSpecification = {
  global: {
    files: [
      'package.json',
      'eslint.config.mjs',
      'node_modules/next',
      '.gitignore',
    ],
    deps: [
      'next',
      'react',
      'react-dom',
      ...(process.env.NEXT_R

on',
      ],
      deps: [],
      devDeps: [],
    },
    ts: {
      files: [
        'pages/index.tsx',
        'pages/_app.tsx',
        'pages/api/hello.ts',
        'tsconfig.json',
        'next-env.d.ts',
      ],
      deps: [],
      devDeps: [

SPACK ? ['next-rspack'] : []),
    ],
    devDeps: ['eslint', 'eslint-config-next'],
  },
  default: {
    js: {
      files: [
        'pages/index.js',
        'pages/_app.js',
        'pages/api/hello.js',
        'jsconfig.js


ojectFilesShouldExist,
  resolveNextTgzFilename,
  run,
  useTempDir,
} from '../utils'

const lockFile = 'package-lock.json'
const files = [...DEFAULT_FILES, lockFile]

describe('create-next-app with package manager npm', () => {
  let nextTgzFilename: string

  beforeAll(() => {
    nextTgzFilename = resolveNextTgzFilename()
  })

  it('should use npm for --use-npm flag', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'use-npm'
      const res = await run(
        [

-no-agents-md',
        ],
        nextTgzFilename,
        {
          cwd,
        }
      )

      expect(res.exitCode).toBe(0)
      projectFilesShouldExist({
        cwd,
        projectName,
        files,
      })
    })
  })

  it('should use npm w

  projectName,
          '--ts',
          '--app',
          '--use-npm',
          '--no-linter',
          '--no-src-dir',
          '--no-tailwind',
          '--no-import-alias',
          '--no-react-compiler',
          '-


_PATH,
  projectFilesShouldExist,
  resolveNextTgzFilename,
  run,
  useTempDir,
} from '../utils'

const lockFile = 'yarn.lock'
const files = [...DEFAULT_FILES, lockFile]

describe('create-next-app with package manager yarn', () => {
  let nextTgzFilename: string

  beforeAll(async () => {
    nextTgzFilename = resolveNextTgzFilename()

    await command('yarn', ['--version'])
      // install yarn if not available
      .catch(() =>
        command('corepack', ['prepare', '--activate', 'yarn@1.22.19'])

        [
          projectName,
          '--ts',
          '--app',
          '--use-yarn',
          '--no-linter',
          '--no-src-dir',
          '--no-tailwind',
          '--no-import-alias',
          '--no-react-compiler',
          '--no-age

    )
      .catch(() => command('npm', ['i', '-g', 'yarn']))
  })

  it('should use yarn for --use-yarn flag', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'use-yarn'
      const res = await run(


v jest */

import { nextTestSetup } from 'e2e-utils'

describe('Cleaning distDir', () => {
  const { next, isTurbopack, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  if (skipped) return

  beforeEach(async () => {
    await next.stop()
    await next.remove('.next')
  })

  async function checkFileWrite(existsAfterBuild: boolean) {
    await next.build()

    const customFile = '.next/extra-file.txt'
    await next.patchFile(customFile, 'this is a testing file')

    await n

wait next.hasFile('.next/cache/swc')).toBe(true)
    }
  }

  describe('disabled write', () => {
    it('should clean up .next before build start', async () => {
      await checkFileWrite(false)
    })

    it('should not clean up .next before build start

ext.build()

    expect(await next.hasFile(customFile)).toBe(existsAfterBuild)

    // `.next/cache` should be preserved in all cases
    expect(await next.hasFile('.next/cache')).toBe(true)
    if (!isTurbopack) {
      expect(a


port { WindowScroller, List as VirtualizedList } from 'react-virtualized'

export default function Home() {
  return (
    <div>
      <WindowScroller serverHeight={800}>
        {({ height, isScrolling, onChildScroll, scrollTop }) => (
          <VirtualizedList
            autoHeight
            height={height}
            isScrolling={isScrolling}
            onScroll={onChildScroll}
            scrollTop={scrollTop}
            width={810}
            rowCount={5}
            estimatedRowSize={10}

> {
              return (
                <div>
                  <Image src={img} placeholder="blur" className="thumbnail" />
                  <Image src={img} className="large" />
                </div>
              )
            }}
            oversc

       rowHeight={400}
            rowRenderer={() =


 React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import 'firebase/firestore'

export async function getStaticPaths() {
  return {
    paths: [
      '/blog/post-1',
      { params: { post: 'post-2' } },
      '/blog/[post3]',
      '/blog/post-4',
      '/blog/post.1',
      '/blog/post.1', // handle duplicates
    ],
    fallback: false,
  }
}

let counter = 0

export async function getStaticProps({ params }) {
  if (params.post === 'post-10') {
    await new Promise

'try again..')
    }
  }

  return {
    props: {
      params,
      post: params.post,
      time: (await import('perf_hooks')).performance.now(),
    },
  }
}

export default ({ post, time, params }) => {
  return (
    <>

Post: {post}

((resolve) => {
      setTimeout(() => resolve(), 1000)
    })
  }

  if (params.post === 'post-100') {
    throw new Error('such broken..')
  }

  if (params.post === 'post-999') {
    if (++counter < 6) {
      throw new Error(


export async function getStaticPaths() {
  return {
    paths: [{ params: { slug: 'a' } }, { params: { slug: 'b' } }],
    fallback: false,
  }
}

export async function getStaticProps({ params }) {
  await new Promise((resolve) => setTimeout(resolve, 1000))

  return {
    props: {
      params,
      hello: 'world',
      post: params.slug,
      random: Math.random(),
      time: (await import('perf_hooks')).performance.now(),
    },
  }
}

export default ({ post, time, params }) => {
  if (useRouter().

eturn (
    <>

Post: {post}

      time: {time}

{JSON.stringify(params)}

{JSON.stringify(useRouter().query)}

      <Link href="/" id="home">
        to home
      </Link>

isFallback) {
    return
hi fallback

  }

  r


tPkgPathsEnv,
} from './lib/test-pkg-paths'

export const CNA_PATH = require.resolve('create-next-app/dist/index.js')

/**
 * Resolves the path to the packed `next` tarball. Uses NEXT_TEST_PKG_PATHS
 * when available (set by run-tests.js), otherwise finds packed.tgz files
 * directly from the repo packages/ directory.
 */
export function resolveNextTgzFilename(): string {
  const pkgPaths = resolveTestPkgPaths()
  const tarballPath = pkgPaths?.get('next')

  if (!tarballPath) {
    throw new Error(
      `C

github.com/vercel/next.js/tree/canary'
export const EXAMPLE_PATH = 'examples/basic-css'
export const FULL_EXAMPLE_PATH = `${EXAMPLE_REPO}/${EXAMPLE_PATH}`
export const DEFAULT_FILES = [
  '.gitignore',
  'package.json',
  'app/page.tsx',
  'app/layout.tsx'

ould not find packed "next" tarball. ` +
        `Run "pnpm turbo run pack-for-isolated-tests" first, ` +
        `or run this test via "node run-tests.js".`
    )
  }

  return tarballPath
}
export const EXAMPLE_REPO = 'https://


execSync, spawn, SpawnOptions } from 'child_process'
import { existsSync } from 'fs'
import { join, resolve } from 'path'
import glob from 'glob'
import Conf from 'next/dist/compiled/conf'

import {
  getProjectSetting,
  mapSrcFiles,
  projectSpecification,
} from './specification'
import {
  CustomTemplateOptions,
  DefaultTemplateOptions,
  ProjectDeps,
  ProjectFiles,
} from './types'
import { serializeTestPkgPathsEnv } from './test-pkg-paths'

const cli = require.resolve('create-next-app/dist/index.js'

st conf = new Conf({ projectName: 'create-next-app' })
  if (clearPreferences) {
    conf.clear()
  }

  console.log(`[TEST] $ ${cli} ${args.join(' ')}`, { options })

  const cloneEnv = { ...process.env }
  // unset CI env as this skips the auto-install b

)

/**
 * Run the built version of `create-next-app` with the given arguments.
 */
export const createNextApp = (
  args: string[],
  options?: SpawnOptions,
  testVersion?: string,
  clearPreferences: boolean = true
) => {
  con


{ MetadataRoute } from 'next'
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
;() => {
  ;({
    url: '',
    lastModified: undefined,
    changeFrequency: undefined,
    priority: undefined,
    alternates: undefined,
    images: undefined,
    videos: undefined,
  }) satisfies MetadataRoute.Sitemap[number]
  ;({
    url: '',
    alternates: {
      languages: undefined,
    },
    videos: [
      {
        title: '',
        thumbnail_loc: '',
        description: '',
        content_

y: undefined,
        restriction: undefined,
        platform: undefined,
        requires_subscription: undefined,
        uploader: undefined,
        live: undefined,
        tag: undefined,
      },
    ],
  }) satisfies MetadataRoute.Sitemap[number]

loc: undefined,
        player_loc: undefined,
        duration: undefined,
        expiration_date: undefined,
        rating: undefined,
        view_count: undefined,
        publication_date: undefined,
        family_friendl


nder export', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
    dependencies: {
      firebase: '7.14.5',
    },
  })
  if (skipped) return

  let server: Server
  let appPort: number
  let buildId: string

  beforeAll(async () => {
    await next.build()
    const exportDir = path.join(next.testDir, 'out')
    server = await startStaticServer(exportDir)
    appPort = (server.address() as AddressInfo).port
    buildId = (await next.r

ash', async () => {
    const routes = [
      '/another',
      '/something',
      '/blog/post-1',
      '/blog/post-2/comment-2',
    ]

    for (const route of routes) {
      await next.readFile(`out${route}/index.html`)
      await next.readFile(`out

eadFile('.next/BUILD_ID')).trim()
  })

  afterAll(async () => {
    if (server) {
      await new Promise<void>((resolve) => server.close(() => resolve()))
    }
  })

  it('should copy prerender files and honor exportTrailingSl


tils'

describe('create-next-app --example', () => {
  let nextTgzFilename: string

  beforeAll(() => {
    nextTgzFilename = resolveNextTgzFilename()
  })

  it('should create on valid Next.js example name', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'valid-example'
      const res = await run(
        [
          projectName,
          '--example',
          'basic-css',
          ...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
        ],
        nextTgzFilename,

',
          'app/layout.tsx',
          'node_modules/next',
        ],
      })
    })
  })

  it('should create with GitHub URL', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'github-url'
      const res = await run(

   {
          cwd,
        }
      )
      expect(res.exitCode).toBe(0)
      projectFilesShouldExist({
        cwd,
        projectName,
        files: [
          '.gitignore',
          'package.json',
          'app/page.tsx


  let nextTgzFilename: string

  beforeAll(() => {
    nextTgzFilename = resolveNextTgzFilename()
  })

  it('should create JavaScript project with --js flag', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'app-js'
      const { exitCode } = await run(
        [
          projectName,
          '--js',
          '--app',
          '--eslint',
          '--no-src-dir',
          '--no-tailwind',
          '--no-import-alias',
          '--no-react-compiler',
          '--no-ag

, template: 'app', mode: 'js' })
      await tryNextDev({
        cwd,
        projectName,
      })
    })
  })

  it('should create TypeScript project with --ts flag', async () => {
    await useTempDir(async (cwd) => {
      const projectName = 'app-ts'

ents-md',
          ...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
        ],
        nextTgzFilename,
        {
          cwd,
        }
      )

      expect(exitCode).toBe(0)
      shouldBeTemplateProject({ cwd, projectName


d by react-virtualized.test.ts to introduce
// per-request stalls and count cancelled image requests. The script is run
// inside the isolated test directory so `http-proxy` can be installed via the
// `dependencies` option of `nextTestSetup`. The test process communicates
// with this server via the `_test/cancel-count` and `_test/wait-ms` endpoints.
const http = require('http')
const httpProxy = require('http-proxy')

const target = process.argv[2]
const port = Number(process.argv[3] || 0)
const stallMs =

tp.createServer(async (req, res) => {
  if (req.url === '/_test/cancel-count') {
    res.setHeader('content-type', 'application/json')
    res.end(JSON.stringify({ cancelCount }))
    return
  }

  if (req.url.startsWith('/_next/image')) {
    let isComple

 Number(process.argv[4] || 3000)

if (!target) {
  console.error('usage: node server.js <target> [port] [stallMs]')
  process.exit(1)
}

let cancelCount = 0
const proxy = httpProxy.createProxyServer({ target })

const server = ht


from 'e2e-utils'
import fs from 'fs-extra'
import {
  findPort,
  initNextServerScript,
  killApp,
  renderViaHTTP,
} from 'next-test-utils'
import { join } from 'path'

let MY_DEPLOYMENT_ID = 'test-deployment-id'

describe('standalone mode: runtimeServerDeploymentId', () => {
  let server
  let appPort
  let output = ''

  const { next } = nextTestSetup({
    files: __dirname,
    env: {
      NEXT_DEPLOYMENT_ID: MY_DEPLOYMENT_ID,
    },
    skipStart: true,
    disableAutoSkewProtection: true,
  })

  bef

xt.testDir, 'standalone')
    )

    for (const file of await fs.readdir(next.testDir)) {
      if (file !== 'standalone') {
        await fs.remove(join(next.testDir, file))
        console.log('removed', file)
      }
    }

    const testServer = join(n

oreAll(async () => {
    let { exitCode } = await next.build()
    // eslint-disable-next-line jest/no-standalone-expect
    expect(exitCode).toBe(0)

    await fs.move(
      join(next.testDir, '.next/standalone'),
      join(ne


iles: path.resolve(__dirname, './invalid-runtime/app'),
      skipStart: true,
    })

    test('fails to build on malformed input', async () => {
      const { exitCode, cliOutput } = await next.build()
      expect(exitCode).toBe(1)
      if (process.env.IS_TURBOPACK_TEST) {
        expect(cliOutput).toContain(
          'runtime` has an invalid value: unknown variant `something-odd`, expected one of `nodejs`, `edge`, `experimental-edge`'
        )
      } else {
        expect(cliOutput).toContain(

resolve(__dirname, './invalid-middleware'),
      skipStart: true,
    })

    test('fails the build on invalid middleware matcher', async () => {
      const { exitCode, cliOutput } = await next.build()
      expect(exitCode).toBe(1)

      // TODO: Turbo

     `Invalid enum value. Expected 'edge' | 'experimental-edge' | 'nodejs', received 'something-odd'`
        )
      }
    })
  })

  describe('invalid-middleware', () => {
    const { next } = nextTestSetup({
      files: path.


ort { nextTestSetup } from 'e2e-utils'

describe('jsconfig.json', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  it('should build normally', async () => {
    const { exitCode } = await next.build()
    expect(exitCode).toBe(0)
  })

  it('should fail on invalid jsconfig.json', async () => {
    const originalJsconfig = await next.readFile('jsconfig.json')
    try {
      await next.patchFile('jsconfig.json', '{')
      const { exitCode } = await n

Output).toMatch(
          /tsconfig is not parseable: invalid JSON: Unterminated object/
        )
      } else {
        expect(next.cliOutput).toMatch(/Error: Failed to parse "/)
        expect(next.cliOutput).toMatch(/JSON5: invalid end of input at 1:2

ext.build()
      expect(exitCode).not.toBe(0)
      if (isTurbopack) {
        expect(next.cliOutput).toMatch(/An issue occurred while parsing/)
        expect(next.cliOutput).toMatch(/jsconfig.json:1:1/)
        expect(next.cli


dering', () => {
  describe('production mode', () => {
    const { next, skipped } = nextTestSetup({
      files: __dirname,
      skipDeployment: true,
    })
    if (skipped) return

    it('correctly measures hydrate followed by render', async () => {
      const browser = await next.browser('/')
      await browser.waitForElementByCss('#to-other')
      await browser.elementByCss('#to-other').click()
      await browser.waitForElementByCss('#on-other', { state: 'attached' })

      const beacons = (awai

 value]) => Object.fromEntries(new URLSearchParams(value)))
        .filter((p) => p.label === 'custom')
      expect(beacons).toMatchObject([
        { name: 'Next.js-hydration' },
        { name: 'Next.js-render' },
        { name: 'Next.js-route-change-

t browser.eval('window.__BEACONS'))
        .map(([,


und revalidate', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    dependencies: { 'fs-extra': 'latest' },
  })

  it('should revalidate page when notFound returned during build', async () => {
    let res = await next.fetch('/initial-not-found/first')
    let $ = await next.render$('/initial-not-found/first')
    expect(res.status).toBe(404)
    expect($('#not-found').text()).toBe('404 page')

    res = await next.fetch('/initial-not-found/second')
    $ = await next.render$('/initial-no

404)
    expect($('#not-found').text()).toBe('404 page')

    await next.patchFile('data.txt', '200')

    try {
      await retry(async () => {
        const r = await next.fetch('/initial-not-found/first')
        const $r = await next.render$('/initial-

t-found/second')
    expect(res.status).toBe(404)
    expect($('#not-found').text()).toBe('404 page')

    res = await next.fetch('/initial-not-found')
    $ = await next.render$('/initial-not-found')
    expect(res.status).toBe(


from 'next/router'

export default function Page(props) {
  if (useRouter().isFallback) return 'Loading...'

  return (
    <>

fallback true page

{JSON.stringify(props)}

    </>
  )
}

export const getStaticProps = async ({ params }) => {
  const { slug } = params

  if (!slug) {
    throw new Error(`missing slug value for /fallback-true/[slug]`)
  }

  const dir = path.join(process.cwd(), '.tmp/fallback-true', slug)

  if (await fs.exists(dir)) {

nd: true,
        hello: 'world',
        random: Math.random(),
      },
      revalidate: 1,
    }
  }

  await fs.ensureDir(dir)

  return {
    notFound: true,
    revalidate: 1,
  }
}

export const getStaticPaths = async () => {
  await fs.remove(path

 return {
      props: {
        params,
        fou


urn (
    <>

fallback blocking page

{JSON.stringify(props)}

    </>
  )
}

export const getStaticProps = async ({ params }) => {
  const { slug } = params

  if (!slug) {
    throw new Error(`missing slug value for /fallback-true/[slug]`)
  }

  const dir = path.join(process.cwd(), '.tmp/fallback-blocking', slug)

  if (await fs.exists(dir)) {
    return {
      props: {
        params,
        found: true,
        hello: 'world',
        random: M

}

  await fs.ensureDir(dir)

  return {
    notFound: true,
    revalidate: 1,
  }
}

export const getStaticPaths = async () => {
  await fs.remove(path.join(process.cwd(), '.tmp/fallback-blocking'))

  return {
    paths: [],
    fallback: 'blocking',

ath.random(),
      },
      revalidate: 1,
    }


heck

const { requestIdStorage } = require('./als')

const defaultCacheHandler =
  require('next/dist/server/lib/cache-handlers/default.external').default

/**
 * @type {import('next/dist/server/lib/cache-handlers/types').CacheHandler}
 */
const cacheHandler = {
  async get(cacheKey) {
    return defaultCacheHandler.get(cacheKey)
  },

  async set(cacheKey, pendingEntry) {
    const requestId = requestIdStorage.getStore()
    console.log('set cache', cacheKey, 'requestId:', requestId)
    return defaultCach

efreshTags() {
    return defaultCacheHandler.refreshTags()
  },

  async getExpiration(tags) {
    return defaultCacheHandler.getExpiration(tags)
  },

  async updateTags(tags) {
    return defaultCacheHandler.updateTags(tags)
  },
}

module.exports = cac

eHandler.set(cacheKey, pendingEntry)
  },

  async r


 } = nextTestSetup({
    files: __dirname,
    startCommand: 'node server.js',
    serverReadyPattern: /^- Local:/,
    dependencies: {
      'get-port': '5.1.1',
    },
  })

  it.each(['a', 'b', 'c'])('can navigate to /%s', async (page) => {
    const $ = await next.render$(`/${page}`)
    expect($('p').text()).toBe(`Page ${page}`)
  })

  it('should log any error messages when server is started without "quiet" setting', async () => {
    await next.render(`/error`)
    expect(next.cliOutput).toInclude('S

 it('should render pages with installed react', async () => {
      const $ = await next.render$(`/2`)
      if (isReact18) {
        expect($('body').text()).toMatch(/pages: 18\.\d+\.\d+\{/)
      } else {
        expect($('body').text()).toMatch(/pages:

erver side error')
  })

  describe('with app dir', () => {
    it('should render app with react canary', async () => {
      const $ = await next.render$(`/1`)
      expect($('body').text()).toMatch(/app: .+-canary/)
    })


require('http')
const { parse } = require('url')
const next = require('next')
const getPort = require('get-port')
const { requestIdStorage } = require('./als')
const quiet = process.env.USE_QUIET === 'true'

let requestId = 0

async function main() {
  const port = await getPort()
  const hostname = 'localhost'
  let conf = undefined

  if (process.env.PROVIDED_CONFIG) {
    conf = require('./.next/required-server-files.json').config
    conf.basePath = '/docs'
  }

  // when using middleware `hostname` and

c () => {
        try {
          // Be sure to pass `true` as the second argument to `url.parse`.
          // This tells it to parse the query portion of the URL.
          const parsedUrl = parse(req.url, true)
          let { pathname, query } = parsed

 `port` must be provided below
  const app = next({ hostname, port, quiet, conf })
  const handle = app.getRequestHandler()

  app.prepare().then(() => {
    createServer((req, res) =>
      requestIdStorage.run(requestId++, asyn


om 'e2e-utils'

describe('build trace with extra entries', () => {
  describe('production mode', () => {
    const { next, isTurbopack, skipped } = nextTestSetup({
      files: path.join(__dirname, 'app'),
      skipStart: true,
      skipDeployment: true,
    })
    if (skipped) return

    it('should build and trace correctly', async () => {
      const { exitCode } = await next.build()
      expect(exitCode).toBe(0)

      const appTrace = JSON.parse(
        await next.readFile('.next/server/pages/_app.

.js.nft.json')
      )
      const imageTrace = JSON.parse(
        await next.readFile('.next/server/pages/image-import.js.nft.json')
      )
      const appDirRoute1Trace = JSON.parse(
        await next.readFile('.next/server/app/route1/route.js.nft.jso

js.nft.json')
      )
      const indexTrace = JSON.parse(
        await next.readFile('.next/server/pages/index.js.nft.json')
      )
      const anotherTrace = JSON.parse(
        await next.readFile('.next/server/pages/another


('File Dependencies', () => {
  describe('production mode', () => {
    const { next, skipped } = nextTestSetup({
      files: __dirname,
      skipDeployment: true,
    })
    if (skipped) return

    it('should apply styles defined in global and module css files in a standard page.', async () => {
      const browser = await next.browser('/')
      await browser.elementByCss('#index')

      const styles = await browser.eval(() => {
        const computed = getComputedStyle(
          document.getElementB

    backgroundColor: 'rgb(200, 200, 200)',
      })
    })

    it('should apply styles defined in global and module css files in 404 page', async () => {
      const browser = await next.browser('/__not_found__')
      await browser.elementByCss('#notFoun

yId('index') as HTMLElement
        )
        return {
          color: computed.color,
          backgroundColor: computed.backgroundColor,
        }
      })

      expect(styles).toEqual({
        color: 'rgb(0, 0, 255)',


stdout = result.cliOutput
    })

    it('should not include internal pages', () => {
      expect(stdout).toMatch(/\//)
      expect(stdout).not.toContain(' /_document')
      expect(stdout).not.toContain(' /_app')
      expect(stdout).not.toContain(' /_error')
      expect(stdout).not.toContain('<buildId>')
      expect(stdout).toContain('○ /')
    })

    // TODO: change format of this test to be more reliable
    it.skip('should not deviate from snapshot', () => {
      console.log(stdout)

      if (pr

arsePageFirstLoad = (page: string) =>
        stdout.match(
          new RegExp(
            ` ${page} .*?(?:(?:\\d|\\.){1,}) .*? ((?:\\d|\\.){1,} (?:\\w{1,}))`
          )
        )![1]

      const parseSharedSize = (sharedPartName: string) => {

ocess.env.NEXT_PRIVATE_SKIP_SIZE_TESTS) {
        return
      }

      const parsePageSize = (page: string) =>
        stdout.match(
          new RegExp(` ${page} .*?((?:\\d|\\.){1,} (?:\\w{1,})) `)
        )![1]

      const p


port default ({ renderDuration }) => {
  const target = Date.now() + (+renderDuration || 200)
  while (Date.now() < target);
  return <div>{renderDuration}</div>
}

export function getStaticPaths() {
  return {
    paths: [
      [2000, 10],
      [5, 5],
      [25, 25],
      [20, 20],
      [10, 10],
      [15, 15],
      [15, 10],
      [10, 10],
      [300, 10],
      [10, 1000],
    ].map(([propsDuration, renderDuration]) => ({
      params: {
        renderDuration: `${renderDuration}`,
        propsD

opsDuration}`,
      },
    })),
    fallback: true,
  }
}

export async function getStaticProps({ params }) {
  const { renderDuration, propsDuration } = params
  await new Promise((r) => setTimeout(r, +propsDuration))
  return { props: { renderDuration }


successfully', () => {
      expect(next.cliOutput).toMatch(/Compiled successfully/)
    })

    it(`should've emitted a single CSS file`, async () => {
      const $ = await next.render$('/')

      const cssSheet = $('link[rel="stylesheet"]')
      expect(cssSheet.length).toBe(1)
      const stylesheet = cssSheet.attr('href')

      const cssContent = await next.fetch(stylesheet).then((res) => res.text())

      if (isTurbopack) {
        expect(
          cssContent.replace(/\/\*.*?\*\//g, '').trim()

"`)
      }
    })

    it(`should've injected the CSS on server render`, async () => {
      const $ = await next.render$('/')

      const cssPreload = $('link[rel="preload"][as="style"]')
      expect(cssPreload.length).toBe(1)
      expect(cssPreload.a

     ).toMatchInlineSnapshot(`".index-module__KWKY6G__redText{color:red}"`)
      } else {
        expect(
          cssContent.replace(/\/\*.*?\*\//g, '').trim()
        ).toMatchInlineSnapshot(`".index_redText__honUV{color:red}


Setup } from 'e2e-utils'

describe('Handles Errors During Export', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  it('Does not crash workers', async () => {
    const { cliOutput } = await next.build()

    expect(cliOutput).not.toMatch(/ERR_IPC_CHANNEL_CLOSED/)
    expect(cliOutput).toMatch(/Export encountered errors on \d+ paths?:/)
    expect(cliOutput).toContain('/page')
    expect(cliOutput).toContain('/page-1')
    expect(cliOutput).toContain('/page-2')

(cliOutput).toContain('/page-13')
    expect(cliOutput).toContain('/blog/[slug]: /blog/first')
    expect(cliOutput).toContain('/blog/[slug]: /blog/second')
    expect(cliOutput).toContain('/custom-error')
    expect(cliOutput).toContain('custom error mess

   expect(cliOutput).toContain('/page-3')
    expect


nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  const ssrfProbePath = '/secret-upgrade'
  const ssrfProbeBody =
    'SSRF_CONFIRMED: You reached the internal service at 127.0.0.1'
  let backend: http.Server
  let backendPort: number
  let intermediary: http.Server
  let intermediaryPort: number
  const backendRequests: string[] = []

  async function sendSmugglingPayload({
    nextPort,
    connectionHeader,
    method = 'DELETE',
    rewritePath = '/rewrites/poc',
  }: {
    nextPort: nu

)
    const chunkSize = Buffer.from(
      `${smuggledRequest.length.toString(16).toUpperCase()}\r\n`,
      'latin1'
    )

    const payload = Buffer.concat([
      Buffer.from(
        `${method} ${rewritePath} HTTP/1.1\r\nHost: 127.0.0.1:${nextPort}\r\

mber
    connectionHeader: string
    method?: 'DELETE' | 'OPTIONS'
    rewritePath?: string
  }) {
    const smuggledRequest = Buffer.from(
      `GET /secret HTTP/1.1\r\nHost: 127.0.0.1:${nextPort}\r\n\r\n`,
      'latin1'


age component', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  afterEach(async () => {
    await next.patchFile(
      'next.config.js',
      '// prettier-ignore\nmodule.exports = { /* replaceme */ }\n'
    )
    await next.patchFile(
      'pages/index.js',
      `import Image from 'next/image'

const loader = undefined

export default () => (

Should succeed during export

    <Image alt="icon" src="/i.png" width="10" height="10" loader={loa

       output: 'export',
          images: {
            loader: 'cloudinary',
            path: 'https://example.com/',
          },
        })
      )
    )
    const { exitCode } = await next.build()
    expect(exitCode).toBe(0)

    const html = await

der} />
  </div>
)
`
    )
  })

  it('should build with cloudinary loader', async () => {
    await next.patchFile('next.config.js', (content) =>
      content.replace(
        '{ /* replaceme */ }',
        JSON.stringify({


retry } from 'next-test-utils'

describe('SSG Prerender Revalidate', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  function runTests(route: string) {
    it(`[${route}] should regenerate page when revalidate time exceeded`, async () => {
      const initialHtml = await next.render(route)

      await retry(async () => {
        const newHtml = await next.render(route)
        expect(newHtml).not.toBe(initialHtml)
      })
    })

    it(`[${route}] should regenerate /_next/data wh

     const newData = await next.render(dataRoute)
        expect(newData).not.toBe(initialData)
      })
    })
  }

  runTests('/')
  runTests('/named')
  runTests('/nested')
  runTests('/nested/named')

  it('should return cache-control header on 304 sta

en revalidate time exceeded`, async () => {
      const dataRoute = `/_next/data/${next.buildId}${route === '/' ? '/index' : route}.json`
      const initialData = await next.render(dataRoute)

      await retry(async () => {


p } from 'e2e-utils'
import { retry, waitFor } from 'next-test-utils'

describe('Root Optional Catch-all Revalidate', () => {
  describe('production mode', () => {
    const { next, skipped } = nextTestSetup({
      files: __dirname,
      skipDeployment: true,
    })
    if (skipped) return

    const getProps = async (path: string) => {
      const html = await next.render(path)
      const $ = cheerio.load(html)
      return JSON.parse($('#props').text())
    }

    it('should render / correctly', async

ndex)).toEqual(
        'getStaticProps({ revalidateReason: "stale" })\n'
      )

      // Rendering takes time before the new cache entry is filled
      await retry(async () => {
        const newProps = await getProps('/')
        expect(newProps.param

() => {
      const props = await getProps('/')
      expect(props.params).toEqual({})

      const outputIndex = next.cliOutput.length
      await waitFor(1000)
      await getProps('/')
      expect(next.cliOutput.slice(outputI


rig from 'glob'
import { promisify } from 'util'
import { join } from 'path'
import { nextTestSetup } from 'e2e-utils'

const glob = promisify(globOrig)

describe('CSS optimization for SSR apps', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    disableAutoSkewProtection: true,
    dependencies: {
      critters: '0.0.16',
    },
  })

  it('should have all CSS files in manifest', async () => {
    const cssFiles = (
      await glob('**/*.css', {
        cwd: join(next.testDir, '.next/st

ng) => file.endsWith('.css'))
    ).toEqual(cssFiles)
  })

  it('should inline critical CSS', async () => {
    const html = await next.render('/')
    expect(html).toMatch(
      /<link rel="stylesheet" href="\/_next\/static\/.*\.css(\?dpl=.*)?" .*>/

atic'),
      })
    ).map((file) => join('.next/static', file))

    const requiredServerFiles = await next.readJSON(
      '.next/required-server-files.json'
    )

    expect(
      requiredServerFiles.files.filter((file: stri


import { nextTestSetup } from 'e2e-utils'

describe('with-electron', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should render the home page', async () => {
    const html = await next.render('/')
    expect(html).toContain('This is the home page')
  })

  it('should render the about page', async () => {
    const html = await next.render('/about')
    expect(html).toContain('This is the about page')
  })

  it('should do navigations via Link', async () => {
    const browse

ations via Router', async () => {
    const browser = await next.browser('/')
    await browser.elementByCss('#about-via-router').click()
    const text = await browser.elementByCss('#about-page p').text()
    expect(text).toBe('This is the about page')

r = await next.browser('/')
    await browser.elementByCss('#about-via-link').click()
    const text = await browser.elementByCss('#about-page p').text()
    expect(text).toBe('This is the about page')
  })

  it('should do navig


async () => {
      await assertSingleGlobalCss(next, false, isTurbopack)
    })
  })

  describe('with lightningcss', () => {
    const { next, isTurbopack } = nextTestSetup({
      files: join(__dirname, 'fixtures', 'single-global'),
      nextConfig: {
        productionBrowserSourceMaps: true,
        experimental: {
          useLightningcss: true,
        },
      },
    })

    it(`should've emitted a single CSS file`, async () => {
      await assertSingleGlobalCss(next, true, isTurbopack)
    })

,
        'single-global-special-characters',
        'a+b'
      ),
      nextConfig: {
        productionBrowserSourceMaps: true,
      },
    })

    it(`should've emitted a single CSS file`, async () => {
      await assertSingleGlobalCss(next, false,

})
})

describe('Basic Global Support with special characters in path', () => {
  describe('without lightningcss', () => {
    const { next, isTurbopack } = nextTestSetup({
      files: join(
        __dirname,
        'fixtures'


) => {
  const { next, isTurbopack } = nextTestSetup({
    files: join(__dirname, 'fixtures', 'browsers-old'),
  })

  it(`should've emitted a single CSS file`, async () => {
    const $ = await next.render$('/')

    const cssSheet = $('link[rel="stylesheet"]')
    expect(cssSheet.length).toBe(1)

    const stylesheetUrl = cssSheet.attr('href')!
    const cssContent = await next.fetch(stylesheetUrl).then((res) => res.text())

    const cssContentWithoutSourceMap = cssContent
      .replace(/\/\*.*?\*\/\n?/

a:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}}"`
      )
    } else {
      expect(cssContentWithoutSourceMap).toMatchInlineSnapshot(
        `"a{-webkit-animation:none 0s ease 0s 1 normal none running;animation:none 0s

g, '')
      .trim()

    if (isTurbopack) {
      expect(cssContentWithoutSourceMap).toMatchInlineSnapshot(
        `"a{all:initial}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:2dppx){.image{background-image:url(dat


 packageJson: {
          browserslist: ['chrome 60'],
        },
      })

      it(`should've compiled and prefixed`, async () => {
        const $ = await next.render$('/')

        const cssSheet = $('link[rel="stylesheet"]')
        expect(cssSheet.length).toBe(1)

        const stylesheetUrl = cssSheet.attr('href')!

        const cssContent = await next
          .fetch(stylesheetUrl)
          .then((res) => res.text())

        const cssContentWithoutSourceMap = cssContent
          .replace(/\/\*.

r{color:green}}.flex-parsing{flex:0 0 calc(50% - var(--vertical-gutter))}.transform-parsing{transform:translate3d(0px, 0px)}.css-grid-shorthand{grid-column:span 2}.g-docs-sidenav .filter::-webkit-input-placeholder{opacity:.8}"`
          )
        } else i

*?\*\/\n?/g, '')
          .trim()

        if (isTurbopack && useLightningcss) {
          expect(cssContentWithoutSourceMap).toMatchInlineSnapshot(
            `"@media (min-width:480px) and (not (min-width:768px)){::placeholde


join } from 'path'

describe('Custom Properties: Pass-Through IE11', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: join(__dirname, 'fixtures', 'cp-ie-11'),
  })

  it(`should've emitted a single CSS file`, async () => {
    const $ = await next.render$('/')

    const cssSheet = $('link[rel="stylesheet"]')
    expect(cssSheet.length).toBe(1)

    const stylesheet = cssSheet.attr('href')!
    const cssContent = (await next.fetch(stylesheet).then((res) => res.text()))
      .replace(/\/\*

   cssContent.replace(/\/\*.*?\*\//g, '').trim()
      ).toMatchInlineSnapshot(`":root{--color:red}h1{color:var(--color)}"`)
    }
  })
})

describe('Custom Properties: Pass-Through Modern', () => {
  const { next, isTurbopack } = nextTestSetup({
    files

.*?\*\//g, '')
      .trim()

    if (isTurbopack) {
      expect(
        cssContent.replace(/\/\*.*?\*\//g, '').trim()
      ).toMatchInlineSnapshot(`":root{--color:red}h1{color:var(--color)}"`)
    } else {
      expect(


listClientChunks } from 'next-test-utils'
import path from 'path'

describe('CSS modules ordering — build output (unresolved-css-url)', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: path.join(__dirname, 'fixtures', 'unresolved-css-url'),
    skipStart: true,
    dependencies: {
      sass: '1.54.0',
    },
  })

  it('should build correctly', async () => {
    const { exitCode } = await next.build()
    expect(exitCode).toBe(0)
  })

  it('should have correct file references in CSS outp

  for (const file of cssFiles) {
      const content = await next.readFile(path.join(next.distDir, file))

      const svgCount = content.match(/\(\/vercel\.svg/g)?.length ?? 0
      expect(svgCount === 1 || svgCount === 2).toBe(true)

      if (isTurbopac

ut', async () => {
    const distRoot = path.join(next.testDir, next.distDir)
    const cssFiles = (await listClientChunks(distRoot)).filter((f) =>
      f.endsWith('.css')
    )
    expect(cssFiles.length).toBeGreaterThan(0)


 = $('link[rel="stylesheet"]')
    expect(cssSheet.length).toBe(1)
    const stylesheet = cssSheet.attr('href')!

    const cssContent = await next.fetch(stylesheet).then((res) => res.text())

    if (isTurbopack) {
      expect(
        cssContent.replace(/\/\*.*?\*\//g, '').trim()
      ).toMatchInlineSnapshot(`".index-module__KWKY6G__redText{color:red}"`)
    } else {
      expect(
        cssContent.replace(/\/\*.*?\*\//g, '').trim()
      ).toMatchInlineSnapshot(`".index_redText__honUV{color:red}"`)

eload.attr('href')).toMatch(
      /^\/_next\/static\/.*\.css(\?dpl=.*)?$/
    )

    const cssSheet = $('link[rel="stylesheet"]')
    expect(cssSheet.length).toBe(1)
    expect(cssSheet.attr('href')).toMatch(
      /^\/_next\/static\/.*\.css(\?dpl=.*)?$/

  }
  })

  it(`should've injected the CSS on server render`, async () => {
    const $ = await next.render$('/')

    const cssPreload = $('link[rel="preload"][as="style"]')
    expect(cssPreload.length).toBe(1)
    expect(cssPr


 from 'path'

// Turbopack uses LightningCSS which supports scoping `:root` to the CSS module.
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
  'Custom Properties: Fail for :root {} in CSS Modules',
  () => {
    const { next } = nextTestSetup({
      files: join(__dirname, 'fixtures', 'cp-global-modules'),
      skipStart: true,
    })

    it('should fail to build', async () => {
      const { exitCode, cliOutput } = await next.build()
      expect(exitCode).not.toBe(0)
      expect(cliOutpu

n CSS Modules', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: join(__dirname, 'fixtures', 'cp-el-modules'),
    skipStart: true,
  })

  it('should fail to build', async () => {
    const { exitCode, cliOutput } = await next.build()

t).toContain('Failed to compile')
      expect(cliOutput).toContain('pages/styles.module.css')
      expect(cliOutput).toContain('Selector ":root" is not pure')
    })
  }
)

describe('Custom Properties: Fail for global element i


${useLightningcss},
  },
}
`
}

describe('CSS Support', () => {
  describe('CSS Import from node_modules', () => {
    describe('experimental.useLightningcss: true', () => {
      const { next } = nextTestSetup({
        files: join(fixturesDir, 'npm-import-bad'),
        dependencies: { nprogress: '0.2.0' },
        skipStart: true,
        overrideFiles: {
          'next.config.js': baseNextConfigWithLightning(true),
        },
      })

      // Turbopack always uses Lightning CSS; webpack also runs the

).not.toMatch(/Can't resolve '[^']*?nprogress[^']*?'/)
        expect(cliOutput).not.toMatch(/Build error occurred/)
      })
    })

    // Webpack runs postcss/lightning toggles; Turbopack always uses Lightning CSS.
    ;(process.env.IS_TURBOPACK_TEST ?

 false case below.
      it('should build successfully without false nprogress resolution errors', async () => {
        const { exitCode, cliOutput } = await next.build()
        expect(exitCode).toBe(0)
        expect(cliOutput


ument is allowed in Turbopack
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
  'Invalid CSS in _document',
  () => {
    const { next } = nextTestSetup({
      files: join(__dirname, 'fixtures', 'invalid-module-document'),
      skipStart: true,
    })

    it('should fail to build', async () => {
      const { exitCode, cliOutput } = await next.build()
      expect(exitCode).not.toBe(0)
      expect(cliOutput).toContain('Failed to compile')
      expect(cliOutput).toContain('styles.module.css

) {
        expect(cliOutput).toMatch(/Location:.*pages[\\/]_document\.js/)
      }
    })
  }
)

describe('Invalid Global CSS', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: join(__dirname, 'fixtures', 'invalid-global'),
    skipStart

')
      expect(cliOutput).toMatch(
        /CSS.*cannot.*be imported within.*pages[\\/]_document\.js/
      )
      // Skip: Rspack loaders cannot access module issuer info for location details
      if (!process.env.NEXT_RSPACK


Setup({
    files: __dirname,
    skipStart: true,
  })

  it('builds without error when export const config is used outside page', async () => {
    const { cliOutput } = await next.build()
    expect(cliOutput).not.toMatch(/Failed to compile\./)
  })

  it('shows valid error when page config is a string', async () => {
    const origContent = await next.readFile('pages/invalid/string-config.js')
    const newContent = origContent.replace('// export', 'export')
    await next.patchFile('pages/invalid/strin

ges/invalid/string-config.js', origContent)
    }
  })

  it('shows valid error when page config has no init', async () => {
    const origContent = await next.readFile('pages/invalid/no-init.js')
    const newContent = origContent.replace('// export', 'ex

g-config.js', newContent)

    try {
      const { cliOutput } = await next.build()
      expect(cliOutput).toContain(
        "Next.js can't recognize the exported `config`"
      )
    } finally {
      await next.patchFile('pa


tTestSetup } from 'e2e-utils'
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
  'Webpack - Bun Externals',
  () => {
    const { next } = nextTestSetup({
      files: __dirname,
      skipStart: true,
    })

    let buildExitCode: number

    beforeAll(async () => {
      const result = await next.build()
      buildExitCode = typeof result.exitCode === 'number' ? result.exitCode : -1
    })

    it('should successfully build with Bun module imports', () => {
      expect(buildExitCode).toBe(0

       'bun:sqlite',
        'bun:test',
        'bun:wrap',
        'bun',
      ]

      bunModules.forEach((mod) => {
        const escapedMod = mod.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
        expect(serverBundle).toInclude(`require("${escapedMod}")`

)
    })

    it('should externalize Bun builtins in server bundles', async () => {
      const serverBundle = await next.readFile('.next/server/pages/index.js')

      const bunModules = [
        'bun:ffi',
        'bun:jsc',


rom 'child_process'
import { nextTestSetup } from 'e2e-utils'
import fs from 'fs-extra'
import { findPort, initNextServerScript, killApp } from 'next-test-utils'
import { join } from 'path'

describe('standalone mode: server actions', () => {
  let server: ChildProcess
  let appPort: number

  const { next } = nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  beforeAll(async () => {
    await next.build()

    await fs.move(
      join(next.testDir, '.next/standalone'),
      join(next.test

ne/.next/static')
    )

    for (const file of await fs.readdir(next.testDir)) {
      if (file !== 'standalone') {
        await fs.remove(join(next.testDir, file))
        console.log('removed', file)
      }
    }

    const testServer = join(next.test

Dir, 'standalone')
    )

    await fs.copy(
      join(next.testDir, 'public'),
      join(next.testDir, 'standalone/public')
    )

    await fs.copy(
      join(next.testDir, '.next/static'),
      join(next.testDir, 'standalo


e client'

import { Component, type ReactNode } from 'react'
import { useActionState } from 'react'

class ErrorBoundary extends Component<
  { children: ReactNode },
  { error: string | null }
> {
  constructor(props: { children: ReactNode }) {
    super(props)
    this.state = { error: null }
  }

  static getDerivedStateFromError(error: Error) {
    return { error: error.message }
  }

  render() {
    if (this.state.error) {
      return (
        <p id="result" style={{ color: 'red' }}>
          {this

={formAction}>
      <button>Submit</button>
      {result && (
        <p id="result" style={{ color: 'green' }}>
          {result}
        </p>
      )}
    </form>
  )
}

export function FormWithErrorBoundary({
  action,
}: {
  action: () => Promise<st

.state.error}
        </p>
      )
    }

    return this.props.children
  }
}

function Form({ action }: { action: () => Promise<string> }) {
  const [result, formAction] = useActionState(action, '')

  return (
    <form action


ath) when the
    // @next/swc-wasm-nodejs package is available on the registry.
    packageJson: {
      scripts: {
        build: 'next build',
      },
    },
    installCommand: 'pnpm i',
    buildCommand: 'pnpm build',
    nextConfig: {
      i18n: {
        locales: ['en', 'fr'],
        defaultLocale: 'en',
      },
      output: 'standalone',
      async rewrites() {
        return [
          {
            source: '/some-catch-all/:path*',
            destination: '/',
          },
          {

equiredFilesManifest

  beforeAll(async () => {
    process.env.NEXT_PRIVATE_TEST_HEADERS = '1'

    const res = await nodeFetch(
      `https://registry.npmjs.com/@next/swc-wasm-nodejs/-/swc-wasm-nodejs-${
        require('next/package.json').version

        source: '/to-dynamic/:path',
            destination: '/dynamic/:path',
          },
        ]
      },
    },
    skipStart: true,
  })

  let server: ChildProcess
  let appPort: number | string
  let errors = []
  let r


xt',
            },
          ],
          afterFiles: [
            {
              source: '/some-catch-all/:path*',
              destination: '/',
            },
            {
              source: '/to-dynamic/post-2',
              destination: '/dynamic/post-2?hello=world',
            },
            {
              source: '/to-dynamic/:path',
              destination: '/dynamic/:path',
            },
          ],
        }
      },
    },
    skipStart: true,
  })

  let server: ChildProcess
  let

1'
    process.env.NEXT_PRIVATE_TEST_HEADERS = '1'

    let { exitCode } = await next.build()
    if (exitCode !== 0) {
      throw new Error(`Failed to build next: ${exitCode}`)
    }

    requiredFilesManifest = JSON.parse(
      await next.readFile('.ne

 appPort: number | string
  let errors = []
  let stderr = ''
  let requiredFilesManifest
  let minimalMode = true

  beforeAll(async () => {
    // test build against environment with next support
    process.env.NOW_BUILDER = '


e
import next from 'next' // force a warning during `next build`
import { useRouter } from 'next/router'

export async function getServerSideProps({ res }) {
  res.setHeader('cache-control', 's-maxage=1, stale-while-revalidate=31535999')

  const data = await fs.promises.readFile(
    path.join(process.cwd(), 'data.txt'),
    'utf8'
  )

  if (data.trim() === 'hide') {
    return {
      notFound: true,
    }
  }

  return {
    props: {
      hello: 'world',
      data,
      random: Math.random(),
      /

fetch('https://example.vercel.sh').then((res) =>
        res.text()
      ),
    },
  }
}

export default function Page(props) {
  const router = useRouter()

  return (
    <>

getServerSideProps page

{JSON.stri

/ make sure fetch if polyfilled
      example: await


from 'e2e-utils'
import fs from 'fs-extra'
import glob from 'glob'
import {
  findPort,
  initNextServerScript,
  killApp,
  renderViaHTTP,
} from 'next-test-utils'
import { join } from 'path'

describe('standalone mode: ipv6 hostname', () => {
  let server
  let appPort
  let output = ''

  const { next } = nextTestSetup({
    files: __dirname,
  })

  beforeAll(async () => {
    await next.stop()

    await fs.move(
      join(next.testDir, '.next/standalone'),
      join(next.testDir, 'standalone')
    )

, {
      cwd: join(next.testDir, 'standalone/.next/server/pages'),
      dot: true,
    })

    for (const file of files) {
      if (file.endsWith('.json') || file.endsWith('.html')) {
        await fs.remove(join(next.testDir, '.next/server', file))

    for (const file of await fs.readdir(next.testDir)) {
      if (file !== 'standalone') {
        await fs.remove(join(next.testDir, file))
        console.log('removed', file)
      }
    }
    const files = glob.sync('**/*'


 tracing-side-effects-false', () => {
  const dependencies = require('./package.json').dependencies

  const { next, skipped } = nextTestSetup({
    files: __dirname,
    dependencies,
    skipStart: true,
  })

  if (skipped) {
    return
  }

  it('should trace sideeffect imports even when sideEffects is false', async () => {
    let { exitCode } = await next.build()
    expect(exitCode).toBe(0)

    let trace = await next.readJSON('.next/server/app/page.js.nft.json')

    expect(trace.files).toContainEqu

index\.js$/)
    )
    expect(trace.files).toContainEqual(
      expect.stringMatching(/node_modules\/foo\/package\.json$/)
    )
    expect(trace.files).toContainEqual(
      expect.stringMatching(/node_modules\/foo\/side-effect\.js$/)
    )
    expect(tr


TP,
  initNextServerScript,
  fetchViaHTTP,
} from 'next-test-utils'

describe('minimal-mode-response-cache', () => {
  let server
  let port
  let appPort
  let output = ''

  beforeAll(() => {
    // test build against environment with next support
    process.env.NOW_BUILDER = '1'
    process.env.NEXT_PRIVATE_TEST_HEADERS = '1'
  })

  const { next } = nextTestSetup({
    files: new FileRef(join(__dirname, 'app')),
  })

  beforeAll(async () => {
    await next.stop()

    await fs.move(
      join(next.

ole.log('removed', file)
      }
    }
    const files = glob.sync('**/*', {
      cwd: join(next.testDir, 'standalone/.next/server'),
      nodir: true,
      dot: true,
    })

    for (const file of files) {
      if (file.match(/(pages|app)[/\\]/) && !

testDir, '.next/standalone'),
      join(next.testDir, 'standalone')
    )
    for (const file of await fs.readdir(next.testDir)) {
      if (file !== 'standalone') {
        await fs.remove(join(next.testDir, file))
        cons


om 'e2e-utils'

describe('build trace with extra entries', () => {
  ;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
    'production mode',
    () => {
      const { next, skipped } = nextTestSetup({
        files: path.join(__dirname, 'app'),
        skipStart: true,
        skipDeployment: true,
      })
      if (skipped) return

      it('should build and trace correctly', async () => {
        const { exitCode } = await next.build()
        console.log(next.cliOutput)
        expect(exitCo

t.json')
        )
        const anotherTrace = JSON.parse(
          await next.readFile('.next/server/pages/another.js.nft.json')
        )
        const imageTrace = JSON.parse(
          await next.readFile('.next/server/pages/image-import.js.nft.json'

de).toBe(0)

        const appTrace = JSON.parse(
          await next.readFile('.next/server/pages/_app.js.nft.json')
        )
        const indexTrace = JSON.parse(
          await next.readFile('.next/server/pages/index.js.nf


from 'e2e-utils'

// Only Turbopack prints these warnings
;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)(
  'build-tracing-message',
  () => {
    const { next } = nextTestSetup({
      files: __dirname,
      skipStart: true,
    })

    it('should warn when tracing all files in the project', async () => {
      const { exitCode } = await next.build()
      expect(exitCode).toBe(0)

      let output = next.cliOutput
        .slice(
          next.cliOutput.indexOf('Turbopack build encountered'

xpected file in NFT list
       A file was traced that indicates that the whole project was traced unintentionally. Somewhere in the import trace below, there are:
       - filesystem operations (like path.join, path.resolve or fs.readFile), or
       - ve

),
          next.cliOutput.indexOf('✓ Compiled successfully')
        )
        .trim()

      expect(output).toMatchInlineSnapshot(`
       "Turbopack build encountered 1 warnings:
       ./next.config.js
       Encountered une


 { nextTestSetup } from 'e2e-utils'
import path from 'path'

describe('app-type', () => {
  describe('app-only', () => {
    const { next } = nextTestSetup({
      files: path.join(__dirname, 'fixtures', 'app-only'),
    })

    it('should have the app-only app type', async () => {
      const requiredServerFiles = JSON.parse(
        await next.readFile('.next/routes-manifest.json')
      )

      expect(requiredServerFiles.appType).toBe('app')
    })
  })

  describe('pages-only', () => {
    const { next

t/routes-manifest.json')
      )

      expect(requiredServerFiles.appType).toBe('pages')
    })
  })

  describe('hybrid', () => {
    const { next } = nextTestSetup({
      files: path.join(__dirname, 'fixtures', 'hybrid'),
    })

    it('should have th

 } = nextTestSetup({
      files: path.join(__dirname, 'fixtures', 'pages-only'),
    })

    it('should have the pages-only app type', async () => {
      const requiredServerFiles = JSON.parse(
        await next.readFile('.nex


from 'e2e-utils'
import { fetchViaHTTP } from 'next-test-utils'

describe('dependencies can use env vars in middlewares', () => {
  beforeAll(() => {
    process.env.MY_CUSTOM_PACKAGE_ENV_VAR = 'my-custom-package-env-var'
    process.env.ENV_VAR_USED_IN_MIDDLEWARE = 'env-var-used-in-middleware'
  })

  const { next } = nextTestSetup({
    files: {
      // A 3rd party dependency
      'node_modules/my-custom-package/package.json': JSON.stringify({
        name: 'my-custom-package',
        version: '1.0.0',

() { return
Hello, world!
 }
      `,

      'middleware.js': `
        import customPackage from 'my-custom-package';
        export default function middleware(_req) {
          return new Response(null, {
            headers: {

        browser: 'index.js',
      }),
      'node_modules/my-custom-package/index.js': `
        module.exports = () => process.env.MY_CUSTOM_PACKAGE_ENV_VAR;
      `,

      'pages/index.js': `
        export default function


skipDeployment: true,
    })
    if (skipped) return

    describe('new line', () => {
      it('should have correct query on SSR', async () => {
        const browser = await next.browser('/?test=abc%0A')
        try {
          const text = await browser.elementByCss('#query-content').text()
          expect(text).toBe('{"test":"abc\\n"}')
        } finally {
          await browser.close()
        }
      })

      it('should have correct query on Router#push', async () => {
        const browser = await

t text = await browser
            .waitForElementByCss('#query-content')
            .text()
          expect(text).toBe('{"abc":"def\\n"}')
        } finally {
          await browser.close()
        }
      })

      it('should have correct query on sim

 next.browser('/')
        try {
          await browser.waitForCondition('!!window.next.router')
          await browser.eval(
            `window.next.router.push({pathname:'/',query:{abc:'def\\n'}})`
          )
          cons


mport { nextTestSetup } from 'e2e-utils'
import { waitFor } from 'next-test-utils'

describe('Root Catch-all Cache', () => {
  describe('production mode', () => {
    const { next, skipped } = nextTestSetup({
      files: __dirname,
      skipDeployment: true,
    })
    if (skipped) return

    const getRandom = async (path: string) => {
      const $ = await next.render$(path)
      return $('#random').text()
    }

    it('should cache / correctly', async () => {
      const random = await getRandom('/')

validate
        await waitFor(1000)
        const newRandom = await getRandom('/')
        expect(random).toBe(newRandom)
      }
      {
        //new response
        await waitFor(100)
        const newRandom = await getRandom('/')
        expect(rando

      {
        //cached response (revalidate is 2 seconds)
        await waitFor(1000)
        const newRandom = await getRandom('/')
        expect(random).toBe(newRandom)
      }
      {
        //stale response, triggers re


const { next } = nextTestSetup({
    files: {
      'pages/index.js': `
        import styles from './index.module.css'

        export default function Page() {
          return
hello world

        }
      `,
      'pages/index.module.css': `
        .home {
          background: orange;
          color: black;
        }
      `,
    },
    nextConfig: {
      experimental: {
        optimizeCss: true,
      },
      output: 'standalone',
    },
    dependencies:

mizeCss is broken when ?dpl is added to CSS URLs
    disableAutoSkewProtection: true,
  })

  it('should work', async () => {
    const html = await next.render('/')
    expect(html).toContain('hello world')
    expect(html).toContain('background:orange')

 {
      critters: '0.0.16',
    },
    // TODO opti


am {import('http').ServerResponse} res
 * @returns {{
 *   onCacheEntry: import('next/dist/server/request-meta').OnCacheEntryHandler,
 *   onCacheEntryV2: import('next/dist/server/request-meta').OnCacheEntryHandler
 * }}
 */
module.exports = (res) => ({
  onCacheEntry: (cacheEntry, meta) => {
    // If this isn't a static app page response from the response cache, then
    // mark it as a miss.
    if (
      !cacheEntry.value ||
      cacheEntry.value.kind !== 'APP_PAGE' ||
      !cacheEntry.value.html ||

')
      return false
    }

    // If this is for a RSC request, then mark it as a miss.
    if (meta.url.endsWith('.rsc')) {
      res.setHeader('x-nextjs-cache-entry-handler', 'MISS_1')
      return false
    }

    // Mark this as a hit against the cac

      typeof cacheEntry.value.html.toUnchunkedString !== 'function' ||
      !cacheEntry.value.postponed ||
      !meta.url ||
      typeof meta.url !== 'string'
    ) {
      res.setHeader('x-nextjs-cache-entry-handler', 'MISS_1


=
      './cache-entry-handlers.js'
  })

  const { next } = nextTestSetup({
    files: {
      app: new FileRef(join(__dirname, 'app')),
      'pages/catch-all/[[...rest]].js': new FileRef(
        join(__dirname, 'pages', 'catch-all', '[[...rest]].js')
      ),
      lib: new FileRef(join(__dirname, 'lib')),
      'cache-handler.js': new FileRef(join(__dirname, 'cache-handler.js')),
      'middleware.js': new FileRef(join(__dirname, 'middleware.js')),
      'data.txt': new FileRef(join(__dirname, 'data.tx

new FileRef(
        join(__dirname, 'cache-entry-handlers.js')
      ),
    },
    overrideFiles: {
      'app/not-found.js': new FileRef(
        join(__dirname, 'ppr', 'app', 'not-found.js')
      ),
    },
    nextConfig: {
      cacheHandler: './cache

t')),
      '.env': new FileRef(join(__dirname, '.env')),
      '.env.local': new FileRef(join(__dirname, '.env.local')),
      '.env.production': new FileRef(join(__dirname, '.env.production')),
      'cache-entry-handlers.js':


ort const getStaticProps = ({ params }) => {
  console.log('getStaticProps /optional-ssg/[[...rest]]', params)

  switch (params.rest?.[0]) {
    case 'redirect-1': {
      return {
        redirect: { destination: '/somewhere', permanent: false },
      }
    }
    case 'redirect-2': {
      return {
        redirect: { destination: '/somewhere-else', permanent: false },
        revalidate: 5,
      }
    }
    case 'not-found-1': {
      return {
        notFound: true,
      }
    }
    case 'not-found-2

  }
    }
    default: {
      break
    }
  }

  return {
    props: {
      random: Math.random(),
      params: params || null,
    },
    revalidate: 1,
  }
}

export const getStaticPaths = () => {
  return {
    paths: [],
    fallback: true,
  }
}

e

': {
      return {
        notFound: true,
        revalidate: 5,
      }
    }
    case 'props-no-revalidate': {
      return {
        props: {
          random: Math.random(),
          params: params || null,
        },


('Build warnings', () => {
  describe('minification warnings', () => {
    const { next, isTurbopack } = nextTestSetup({
      files: __dirname,
      skipStart: true,
    })

    it('should not show warning about minification without any modification', async () => {
      const start = next.cliOutput.length
      await next.build()
      expect(next.cliOutput.slice(start)).not.toContain(
        'optimization has been disabled'
      )
    })
    ;(isTurbopack ? it.skip : it)(
      'should show warning ab

}`
        )
        const start = next.cliOutput.length
        await next.build()
        // eslint-disable-next-line jest/no-standalone-expect
        expect(next.cliOutput.slice(start)).toContain(
          'optimization has been disabled'
        )

out minification for minimize',
      async () => {
        await next.patchFile(
          'next.config.js',
          `module.exports = {
  webpack: (config) => {
    config.optimization.minimize = false
    return config
  },


t { nextTestSetup } from 'e2e-utils'

describe('image-generation', () => {
  describe('production mode', () => {
    const { next, isNextStart } = nextTestSetup({
      files: __dirname,
      dependencies: {
        '@vercel/og': '0.11.1',
      },
    })

    if (!isNextStart) {
      it('skipped for non-start mode', () => {})
      return
    }

    it('should generate the image without errors', async () => {
      const res = await next.fetch('/api/image')
      expect(res.status).toBe(200)
      expect

et('Content-Type')).toBe('image/png')

      const buffer = await res.buffer()

      // It should be a PNG
      expect(
        [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].every(
          (b, i) => buffer[i] === b
        )
      ).toBeTrue()
    }


from 'e2e-utils'

describe('Page Extensions', () => {
  describe('production mode', () => {
    const { next, skipped } = nextTestSetup({
      files: __dirname,
      skipStart: true,
      skipDeployment: true,
    })
    if (skipped) return

    it('should use the default pageExtensions if set to undefined', async () => {
      await next.patchFile(
        'next.config.js',
        `module.exports = { pageExtensions: undefined }`
      )

      await next.build()

      expect(next.cliOutput).toContain(

t next.build()

      expect(next.cliOutput).toContain(
        'Specified pageExtensions is an empty array. Please update it with the relevant extensions or remove it'
      )
    })

    it('should throw if pageExtensions has invalid extensions', async (

'Compiled successfully')
    })

    it('should throw if pageExtensions is an empty array', async () => {
      await next.patchFile(
        'next.config.js',
        `module.exports = { pageExtensions: [] }`
      )

      awai


  killApp,
  retry,
  waitFor,
} from 'next-test-utils'
import fs from 'fs-extra'
import glob from 'glob'
import { LONG_RUNNING_MS } from './src/pages/api/long-running'
import { once } from 'events'

const appDir = join(__dirname, './src')
let appPort: number
let app: ChildProcess
let currentExit: Promise<any> | undefined

function assertDefined<T>(value: T | void): asserts value is T {
  expect(value).toBeDefined()
}

async function launchChildServer(
  next: NextInstance,
  args: string[],
  readyPattern:

 resolveReady = () => {
      if (!ready) {
        ready = true
        r()
      }
    }
  })

  const exit = next
    .runCommand(args, {
      onStdout: (msg) => {
        if (readyPattern.test(msg)) resolveReady()
      },
      onStderr: (msg) => {

 RegExp = /- Local:|✓ Ready|Ready in/i
): Promise<{ child: ChildProcess; exit: Promise<any> }> {
  let child!: ChildProcess
  let resolveReady!: () => void
  let ready = false
  const readyPromise = new Promise<void>((r) => {


tTestSetup } from 'e2e-utils'

describe('standalone mode - tracing-static-files', () => {
  const dependencies = require('./package.json').dependencies

  const { next, skipped } = nextTestSetup({
    files: __dirname,
    dependencies,
    skipStart: true,
  })

  if (skipped) {
    return
  }

  it('should trace process.cwd calls in node_modules', async () => {
    let { exitCode } = await next.build()
    expect(exitCode).toBe(0)

    let trace = await next.readJSON('.next/server/app/page.js.nft.json')

tive reference
      expect(trace.files).toContain(
        '../../../data/static-from-app-rel-join.txt'
      )
      expect(trace.files).toContain(
        '../../../data/static-from-app-rel-read.txt'
      )
    }

    if (process.env.IS_TURBOPACK_TEST)

    // should trace process.cwd and relative calls relative to the root
    expect(trace.files).toContain('../../../data/static-from-app-cwd.txt')
    if (process.env.IS_TURBOPACK_TEST) {
      // Webpack doesn't trace these rela


 next } = nextTestSetup({
    files: {
      app: new FileRef(join(__dirname, 'app')),
      lib: new FileRef(join(__dirname, 'lib')),
      'cache-handler.js': new FileRef(join(__dirname, 'cache-handler.js')),
      'middleware.js': new FileRef(join(__dirname, 'middleware.js')),
      'data.txt': new FileRef(join(__dirname, 'data.txt')),
      '.env': new FileRef(join(__dirname, '.env')),
      '.env.local': new FileRef(join(__dirname, '.env.local')),
      '.env.production': new FileRef(join(__dirname, '.

tring

  beforeAll(async () => {
    // test build against environment with next support
    process.env.NOW_BUILDER = '1'
    process.env.NEXT_PRIVATE_TEST_HEADERS = '1'

    const { exitCode } = await next.build()
    if (exitCode !== 0) {
      throw ne

env.production')),
    },
    nextConfig: {
      cacheHandler: './cache-handler.js',
      cacheMaxMemorySize: 0,
      output: 'standalone',
    },
    skipStart: true,
  })

  let server: ChildProcess
  let appPort: number | s


ire('path')

module.exports = {
  webpack(cfg, { isServer, nextRuntime }) {
    console.log(cfg.entry)
    const origEntry = cfg.entry
    cfg.entry = async () => {
      const origEntries = await origEntry()

      if (isServer && nextRuntime === 'nodejs') {
        const curEntry = origEntries['pages/_app']
        origEntries['pages/_app'] = [
          path.join(__dirname, 'lib/get-data.js'),
          ...curEntry,
        ]
        console.log(origEntries)
      }
      return origEntries
    }
    ret

dex': ['include-me/*'],
  },
  outputFileTracingExcludes: {
    '/index': ['public/exclude-me/**/*'],
  },
  experimental: {
    turbotrace: {
      contextDirectory: path.join(__dirname, '..', '..', '..', '..'),
      memoryLimit: 2048,
    },
    webpack

urn cfg
  },
  outputFileTracingIncludes: {
    '/in


from 'e2e-utils'
import { retry } from 'next-test-utils'

describe('Revalidate asPath Normalizing', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  const checkAsPath = async (urlPath: string, expectedAsPath: string) => {
    const $ = await next.render$(urlPath)
    const asPath = $('#as-path').text()
    expect(asPath).toBe(expectedAsPath)
  }

  it('should render with correct asPath with /_next/data /index requested', async () => {
    const outputIndex = next.cliOutput.length

utput = next.cliOutput.slice(outputIndex)
      expect(newOutput).toContain('asPath')
    })
    const newOutput = next.cliOutput.slice(outputIndex)
    const asPath = newOutput.split('asPath: ').pop()!.split('\n').shift()
    expect(asPath).toBe('/')
  })

 const path = `/_next/data/${next.buildId}/index.json`

    await retry(async () => {
      const data = await next.render(path)
      expect(JSON.parse(data).pageProps).toEqual({
        hello: 'world',
      })
      const newO


ort fs from 'fs'
import cheerio from 'cheerio'
import { nextTestSetup } from 'e2e-utils'

describe('Export Dynamic Pages', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  let server: http.Server
  let port: number
  beforeAll(async () => {
    await next.build()

    const outDir = path.join(next.testDir, 'out')
    server = http.createServer((req, res) => {
      let urlPath = (req.url || '/').split('?')[0]
      try {
        urlPath = decodeURIComponent(urlPa

ad(404)
          res.end('Not Found')
          return
        }
        const ext = path.extname(filePath)
        const contentType =
          {
            '.html': 'text/html',
            '.js': 'application/javascript',
            '.css': 'text/cs

th)
      } catch {}
      let filePath = path.join(outDir, urlPath)

      if (!path.extname(filePath)) {
        filePath += '.html'
      }

      fs.readFile(filePath, (err, data) => {
        if (err) {
          res.writeHe


join } from 'path'
import fs from 'fs-extra'
import cheerio from 'cheerio'
import {
  fetchViaHTTP,
  findPort,
  initNextServerScript,
  killApp,
} from 'next-test-utils'

describe('type-module', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    packageJson: {
      type: 'module',
    },
  })

  it('should work', async () => {
    await next.stop()
    const standalonePath = join(next.testDir, '.next/standalone')

    expect(fs.existsSync(join(standalonePath, 'package.json'))).toBe(true

   // walks up to the project package.json and tries to load the server
    // bundles as ESM, which fails at runtime.
    const distPackageJsonPath = join(standalonePath, '.next', 'package.json')
    expect(fs.existsSync(distPackageJsonPath)).toBe(true)

)

    // The distDir package.json acts as a commonjs boundary marker so that
    // server bundles in `.next/server/**/*.js` are loaded as CJS even when
    // the user's project has `"type": "module"`. Without this file, Node


{ nextTestSetup } from 'e2e-utils'

describe('typeof window replace', () => {
  describe('production mode', () => {
    const { next, skipped } = nextTestSetup({
      files: path.join(__dirname, 'app'),
      skipStart: true,
      skipDeployment: true,
    })
    if (skipped) return

    let buildManifest: any

    beforeAll(async () => {
      await next.build()
      buildManifest = JSON.parse(
        await next.readFile('.next/build-manifest.json')
      )
    })

    it('Replaces `typeof window` with

= await next.readFile(path.join('.next', file))
        allContent += content
      }
      expect(allContent).toMatch(/Hello.*?,.*?\n?.*?("|')object("|')/)
    })

    it('Replaces `typeof window` with undefined for server code', async () => {
      let a

 object for client code', async () => {
      let allContent = ''
      const files = buildManifest.pages['/'].filter((item: string) =>
        item.endsWith('.js')
      )
      for (const file of files) {
        const content


ort { nextTestSetup } from 'e2e-utils'

describe('standalone mode - tracing-unparsable', () => {
  const dependencies = require('./package.json').dependencies

  const { next, skipped } = nextTestSetup({
    files: __dirname,
    dependencies,
    skipStart: true,
  })

  if (skipped) {
    return
  }

  it('should not error when dynamic require includes non-JS files', async () => {
    let { exitCode } = await next.build()
    expect(exitCode).toBe(0)

    let trace = await next.readJSON('.next/server/app/

)
    )
    expect(trace.files).toContainEqual(
      expect.stringMatching(/.*\/node_modules\/foo\/index\.js$/)
    )
    expect(trace.files).toContainEqual(
      expect.stringMatching(/.*\/node_modules\/foo\/value\.js$/)
    )
    expect(trace.files).to

page.js.nft.json')

    expect(trace.files).toContainEqual(
      expect.stringMatching(/.*\/node_modules\/foo\/LICENSE$/)
    )
    expect(trace.files).toContainEqual(
      expect.stringMatching(/.*\/node_modules\/foo\/binary$/


= nextTestSetup({
    files: __dirname,
    dependencies: { sass: '1.54.0' },
    env: {
      NEXT_DEPLOYMENT_ID: 'test-deployment-id',
    },
    disableAutoSkewProtection: true,
  })

  it('should include dpl query in CSS url() references for images and fonts', async () => {
    const $ = await next.render$('/')

    // Collect all CSS file URLs from link tags
    const cssUrls: string[] = []
    const links = Array.from($('link'))
    for (const link of links) {
      const href = link.attribs.href

tents
    let allCssContent = ''
    for (const cssUrl of cssUrls) {
      const res = await next.fetch(cssUrl)
      const cssText = await res.text()
      allCssContent += cssText + '\n'
    }

    // Also collect inline style content
    for (const styl

  if (href && href.includes('.css')) {
        cssUrls.push(href)
      }
    }

    // Also check for inline styles that may contain CSS
    const styles = Array.from($('style'))

    // Fetch all CSS files and collect their con