Script = `document.querySelectorAll('body link[rel="icon"], body link[rel="apple-touch-icon"]').forEach(el => document.head.appendChild(el))`

describe('app-dir - metadata-icons', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should only have 1 favicon link in root page', async () => {
    const $ = await next.render$('/')
    expect($('link[href^="/favicon.ico"]').length).toBe(1)
  })

  it('should only have 1 favicon link in nested page', async () => {
    const $ = await ne

"shortcut icon"]').attr('href')).toBe(
      '/shortcut-icon.png'
    )
  })

  it('should render custom icons along with favicon in nested page', async () => {
    const $ = await next.render$('/nested')
    expect($('link[rel="shortcut icon"]').attr('hre

xt.render$('/nested')
    expect($('link[href^="/favicon.ico"]').length).toBe(1)
  })

  it('should render custom icons along with favicon in root page', async () => {
    const $ = await next.render$('/')
    expect($('link[rel=


retry } from 'next-test-utils'

describe('parallel-routes-layouts', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should properly render layouts for multiple slots', async () => {
    const browser = await next.browser('/nested')

    let layouts = await getLayoutHeadings(browser)
    expect(layouts).toHaveLength(4)
    expect(layouts).toEqual(
      expect.arrayContaining([
        'Root Layout',
        'Nested Layout',
        '@foo Layout',
        '@bar Layout',
      ])

ser.elementById('foo-children').text()).toBe('Foo Slot')
    expect(await browser.elementById('bar-children').text()).toBe('Bar Slot')

    // Navigate to a subroute that only has a match for the @foo slot
    await browser.elementByCss('[href="/nested/sub

    )

    // ensure nested/page is showing its contents
    expect(await browser.elementById('nested-children').text()).toBe(
      'Hello from Nested'
    )

    // Ensure each slot is showing its contents
    expect(await brow


'use client'

import { useInsertionEffect } from 'react'

export default function ClientPage() {
  useInsertionEffect(() => {
    // Logging in client component useInsertionEffect
    // Test complex partial circular object
    const circularObj: any = {
      name: 'test',
      data: {
        nested: {
          value: 42,
          items: [1, 2, 3],
        },
      },
      metadata: {
        name: 'safe stringify',
        version: '1.0.0',
      },
    }
    // Create partial circular reference

g('Client: Complex circular object:', circularObj)
    console.error('Client: This is an error message from client component')
    console.warn('Client: This is a warning message from client component')
  }, [])

  return
client page with logging

}

circularObj.data.parent = circularObj
    console.lo


) => {
  const { next } = nextTestSetup({
    files: new FileRef(__dirname),
    dependencies: {
      typescript: 'latest',
      '@types/react': 'latest',
      '@types/node': 'latest',
    },
  })

  it('It should be able to navigate app -> pages', async () => {
    const browser = await next.browser('/app')
    expect(await browser.elementById('app-page').text()).toBe('App Page')
    // Increased timeout: in dev mode, cross-router navigation triggers on-demand
    // compilation which can take longer th

    expect(await browser.elementById('pages-page').text()).toBe('Pages Page')
  })

  it('It should be able to navigate pages -> app', async () => {
    const browser = await next.browser('/pages')
    expect(await browser.elementById('pages-page').text()

an the default timeout.
    await browser
      .elementById('link-to-pages')
      .click()
      .waitForElementByCss('#pages-page', { timeout: 30000 })
    expect(await browser.hasElementByCssSelector('#app-page')).toBeFalse()


irname,
  })

  it('should delay the metadata render to body', async () => {
    const $ = await next.render$('/')
    expect($('head title').length).toBe(0)
    expect($('body title').length).toBe(1)
  })

  it('should still load viewport meta tags even if metadata is delayed', async () => {
    const $ = await next.render$('/slow')

    expect($('meta[name="viewport"]').attr('content')).toBe(
      'width=device-width, initial-scale=1'
    )
    expect($('meta[charset]').attr('charset')).toBe('utf-8')
  }

  it('should load the initial html without slow metadata during navigation', async () => {
    // navigate from / to /slow, the metadata should be empty first, e.g. no title.
    // then the metadata should be loaded after few seconds.
    const browser =

)

  it('should render the metadata in the browser', async () => {
    const browser = await next.browser('/')
    await retry(async () => {
      expect(await browser.elementByCss('title').text()).toBe('index page')
    })
  })


('dynamic-href', () => {
  const {
    isNextDev: isDev,
    next,
    skipped,
  } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  if (isDev) {
    it('should error when using dynamic href.pathname in app dir', async () => {
      const browser = await next.browser('/object')

      await expect(browser).toDisplayRedbox(`
       {
         "code": "E267",
         "description": "Dynamic href \`/object/[slug]\` found in <Link> while using the \`/ap

      > 5 |     <Link
           |     ^",
         "stack": [
           "HomePage app/object/page.js (5:5)",
         ],
       }
      `)

      // Fix error
      const pageContent = await next.readFile('app/object/page.js')
      await next.patchFile(

p\` router, this is not supported. Read more: https://nextjs.org/docs/messages/app-dir-dynamic-href",
         "environmentLabel": null,
         "label": "Runtime Error",
         "source": "app/object/page.js (5:5) @ HomePage


act'
import { expensiveCalculation } from './actions'

export function Form({ randomNum }) {
  const [isPending, setIsPending] = React.useState(false)
  const [result, setResult] = React.useState(null)

  async function handleSubmit(event) {
    event.preventDefault()

    setIsPending(true)
    const result = await expensiveCalculation()
    setIsPending(false)
    setResult(result)
  }

  return (
    <form
      style={{ display: 'flex', gap: '2rem', flexDirection: 'column' }}
      id="form"
      onSub

tton style={{ width: 'max-content' }} type="submit" id="submit">
          Submit
        </button>
        {isPending && 'Loading...'}

Server side rendered number: {randomNum}

      {result &&
RESULT FROM

mit={handleSubmit}
    >
      <section>
        <bu


from 'e2e-utils'

const isPPREnabled = process.env.__NEXT_CACHE_COMPONENTS === 'true'

;(isPPREnabled ? describe.skip : describe)(
  'app-dir - metadata-static-generation',
  () => {
    const { next, isNextDev, isNextStart } = nextTestSetup({
      files: __dirname,
    })

    // In dev, it suspenses as dynamic rendering so it's inserted into body;
    // In build, it's resolved as static rendering so it's inserted into head.
    const rootSelector = isNextDev ? 'body' : 'head'

    if (isNextStart) {

c', async () => {
        const prerenderManifest = JSON.parse(
          await next.readFile('.next/prerender-manifest.json')
        )
        const staticRoutes = prerenderManifest.routes
        expect(Object.keys(staticRoutes).sort()).toEqual([

   // Precondition for the following tests in build mode.
      // This test is only useful for non-PPR mode as in PPR mode those routes
      // are all listed in the prerender manifest.
      it('should generate all pages stati


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

describe('app-dir action allowed from opaque origins', () => {
  const { next, skipped } = nextTestSetup({
    files: join(__dirname, 'opaque-origin'),
    skipDeployment: true,
    env: {
      NEXT_TEST_ALLOW_OPAQUE_ORIGIN: '1',
    },
  })

  if (skipped) {
    return
  }

  it('should succeed on submission', async function () {
    const browser = await next.browser('/sandboxed')

    await browser.elementByCss('input[

 () => {
  const { isNextDev, next, skipped } = nextTestSetup({
    files: join(__dirname, 'opaque-origin'),
    skipDeployment: true,
    env: {
      NEXT_TEST_ALLOW_OPAQUE_ORIGIN: '',
    },
  })

  if (skipped) {
    return
  }

  it('should fail on su

type="submit"]').click()

    await retry(async () => {
      expect(await browser.elementByCss('output').text()).toEqual(
        'Action Invoked'
      )
    })
  })
})

describe('app-dir action disallowed from opaque origins',


ime root layout', () => {
  const { next, isNextStart, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should not emit metadata files into bad paths', async () => {
    await next.fetch('/favicon.ico')
    // issue: If metadata files are not filter out properly with image-loader,
    // an incorrect static/media folder will be generated

    // Check that the static folder is not generated
    const incorrectGeneratedStaticFolder = awa

tedStaticFolder).toBe(false)
  })

  if (isNextStart) {
    it('should mark static contain metadata routes as edge functions', async () => {
      const middlewareManifest = await next.readFile(
        '.next/server/middleware-manifest.json'
      )

it next.hasFile('static')
    expect(incorrectGenera


t'
import { cookies } from 'next/headers'
import { Delay, Login } from './state'

export async function Dynamic({ fallback }) {
  const dynamic = fallback !== true

  let signedIn
  let active
  if (dynamic) {
    signedIn = (await cookies()).has('session')
    active = (await cookies()).has('delay')
    if (active) {
      await new Promise((resolve) => setTimeout(resolve, 1000))
    }
  }

  if (!dynamic) {
    return (

Loading...

        <Login fallbac

}

  return (

        {signedIn ? 'Signed In' : 'Not Signed In'}

      <Login signedIn={signedIn} />
      <Delay active={active} />

k />
        <Delay fallback />
      </div>
    )


ref: '/no-suspense' },
  { href: '/suspense/node' },
  { href: '/suspense/edge' },
  { href: '/suspense/node/nested/1' },
  { href: '/loading/nested/1' },
  { href: '/loading/nested/2' },
  { href: '/loading/nested/3' },
]

export default function Root({ children }) {
  return (

Page

          {children}

links.map(({ href }) => (

                {href} - <Link href={href}>link</Link> -{' '}
                anchor

            ))}


h')

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  turbopack: {
    resolveAlias: {
      'alias-data': './alias-data.mjs',
      'alias-dep': './esm-dep.mjs',
    },
    rules: {
      '*.test-file.ts': {
        loaders: [require.resolve('./test-file-loader.js')],
        as: '*.js',
      },
      '*.custom-data': {
        loaders: [require.resolve('./text-to-export-loader.js')],
        as: '*.js',
      },
    },
  },
  webpack(config) {
    config.resolve.alias = {
      ...conf

 treated as external ESM packages by Next.js.
    const aliasedModules = new Set(['alias-data', 'alias-dep'])
    config.externals = config.externals.map((fn) => {
      if (typeof fn !== 'function') return fn
      return async function (ctx) {
        if

ig.resolve.alias,
      'alias-data': path.resolve(__dirname, 'alias-data.mjs'),
      'alias-dep': path.resolve(__dirname, 'esm-dep.mjs'),
    }
    // Wrap externals handlers to prevent aliased bare specifiers from
    // being


('webpack-loader-import-module', () => {
  const { next, skipped, isTurbopack } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should support this.importModule() in a webpack loader', async () => {
    const $ = await next.render$('/')
    expect($('#title').text()).toBe('Import Module Works')
    expect($('#items').text()).toBe('apple, banana, cherry')
    // CJS dependency that itself requires a JSON file
    expect($('#cjs-greeting').text())

ct($('#mjs-title').text()).toBe('ESM Config Works')
    expect($('#mjs-esm-label').text()).toBe('hello from esm')

    // resolveAlias: importModule with alias as request
    expect($('#alias-value').text()).toBe('resolved via alias')
    // resolveAlias:

.toBe('hello from cjs')
    expect($('#version').text()).toBe('1.0.0')
    // ESM dependency imported from config-data.ts
    expect($('#esm-label').text()).toBe('hello from esm')
    // ESM .mjs module (config-data.mjs)
    expe


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

function normalizeCliOutput(output: string) {
  return stripAnsi(output)
}

describe('app-dir - server source maps edge runtime', () => {
  const { skipped, next, isNextDev } = nextTestSetup({
    files: path.join(__dirname, 'fixtures/edge'),
    // Deploy tests don't have access to runtime logs.
    // Manually verify that the runtime logs match.
    skipDeployment: true,
  })

  if (skipped) return

  it('logged errors have a sourcemapped stack with a codeframe

 rsc-error-log'
        )
      })
      expect(normalizeCliOutput(next.cliOutput.slice(outputIndex))).toContain(
        'Error: rsc-error-log' +
          '\n    at logError (app/rsc-error-log/page.js:2:17)' +
          '\n    at Page (app/rsc-error-log/

', async () => {
    const outputIndex = next.cliOutput.length
    await next.render('/rsc-error-log')

    if (isNextDev) {
      await retry(() => {
        expect(next.cliOutput.slice(outputIndex)).toContain(
          'Error:


t'
import { runInternal } from 'internal-pkg'
import { runInternalSourceMapped } from 'internal-pkg/sourcemapped'
import { runInternalIgnored } from 'internal-pkg/ignored'
import { runExternal } from 'external-pkg'
import { runExternalSourceMapped } from 'external-pkg/sourcemapped'

function logError() {
  const error = new Error('ssr-error-log-ignore-listed')
  console.error(error)
}

export default function Page() {
  runInternal(function runWithInternal() {
    runInternalSourceMapped(function runWithInt

ped() {
      runExternal(function runWithExternal() {
        runExternalSourceMapped(function runWithExternalSourceMapped() {
          runInternalIgnored(function runWithInternalIgnored() {
            logError()
          })
        })
      })
    })


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

async function expectContainOnce(next: any, search: string) {
  // Ensure the search string is found once
  await retry(() => {
    const parts = next.cliOutput.split(search)
    expect(parts.length).toBe(2)
  })
}

describe('dedupe-rsc-error-log', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    // Runtime logs aren't available when deployed
    skipDeployment: true,
  })

  it('should only log RSC error once f

rver/edge')
    await expectContainOnce(next, 'Custom error:server-edge')
  })

  it('should only log SSR error once for nodejs runtime', async () => {
    await next.fetch('/client')
    await expectContainOnce(next, 'Custom error:client-node')
  })

  it

or nodejs runtime', async () => {
    await next.fetch('/server')
    await expectContainOnce(next, 'Custom error:server-node')
  })

  it('should only log RSC error once for edge runtime', async () => {
    await next.fetch('/se


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

  if (isNextDev) {
    test('skipped in dev mode', () => {})
    return
  }

  // Uses Playwright's built-in network emulation, which fires the browser's
  // native offline/online events and blocks all requests at the network layer.
  async function goOffline(page: Playwright.Page) {
    await page.context().setOffline(true)
  }

  async function goOnline(page: Playwright.Page) {
    await page.context().setOffline(false)
  }

  it(

e) {
        page = p
        act = createRouterAct(p)
      },
    })

    // Verify we're on the home page and online
    expect(await browser.elementById('home').text()).toContain('Home')
    expect(await browser.elementById('offline-status').text()).to

'retries navigation after connectivity is restored', async () => {
    let act: ReturnType<typeof createRouterAct>
    let page: Playwright.Page
    const browser = await next.browser('/', {
      beforePageLoad(p: Playwright.Pag


 { nextTestSetup } from 'e2e-utils'

describe('app-dir - metadata-streaming-customized-rule', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
    overrideFiles: {
      'next.config.js': `
        module.exports = {
          htmlLimitedBots: /Minibot/i,
        }
      `,
    },
  })

  it('should send the blocking response for html limited bots', async () => {
    const $ = await next.render$(
      '/',
      undefined, // no query
      {
        headers: {
          'user-ag

) => {
    const $ = await next.render$(
      '/',
      undefined, // no query
      {
        headers: {
          'user-agent': 'Weebot',
        },
      }
    )
    expect(await $('head title').length).toBe(0)
    expect(await $('body title').length)

ent': 'Minibot',
        },
      }
    )
    expect(await $('head title').text()).toBe('index page')
    expect(await $('body title').length).toBe(0)
  })

  it('should send streaming response for headless browser bots', async (


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

describe('app-dir action handling', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should handle actions correctly after navigation / redirection events', async () => {
    const browser = await next.browser('/')

    await browser.elementByCss('#middleware-redirect').click()

    expect(await browser.elementByCss('#form').text()).not.toContain(
      'Loading...'
    )

    await browser.ele

ct(await browser.elementByCss('#form').text()).not.toContain(
      'Loading...'
    )

    expect(await browser.elementByCss('#result').text()).toContain(
      'RESULT FROM SERVER ACTION'
    )
  })

  it('should handle actions correctly after following

mentByCss('#submit').click()

    await check(() => {
      return browser.elementByCss('#form').text()
    }, /Loading.../)

    // wait for 2 seconds, since the action takes a second to resolve
    await waitFor(2000)

    expe


t'

import { useState } from 'react'
import { log } from './action'

if (typeof window !== 'undefined') {
  // hijack fetch
  const originalFetch = window.fetch
  window.fetch = function (url, init) {
    if (init?.method === 'POST') {
      console.log('fetch', url, init)

      // override forwarded host
      init.headers = init.headers || {}
      init.headers['x-forwarded-host'] = 'my-proxy.com'
    }

    return originalFetch(url, init)
  }
}

export default function Page() {
  const [res, setRes] = u

return (

{res}

      <button
        onClick={async () => {
          try {
            setRes(await log())
          } catch (err) {
            setRes(err.message)
          }
        }}
      >
        fetch


ePathname } from 'next/navigation'
import React from 'react'
import { Suspense } from 'react'
import { useCallback } from 'react'

function Pathname() {
  const pathname = usePathname()
  return
{pathname}

}

export function Login({ signedIn = false, fallback }) {
  const onClick = useCallback(async () => {
    if (signedIn) {
      await fetch('/api/cookie?name=session', {
        method: 'DELETE',
        credentials: 'same-origin',
      })
    } else {
      await fetch('/api/co

ton
        id="login"
        className="bg-gray-400 hover:bg-gray-500 px-4 py-2 text-white rounded-md"
        onClick={onClick}
      >
        {fallback ? 'Sign ..' : signedIn ? 'Sign Out' : 'Sign In'}
      </button>
    </>
  )
}

export function Del

okie?name=session', {
        method: 'POST',
        credentials: 'same-origin',
      })
    }

    window.location.reload()
  }, [signedIn])

  return (
    <>
      <Suspense>
        <Pathname />
      </Suspense>
      <but


ort {
  title,
  items,
  cjsGreeting,
  version,
  esmLabel,
  imageUrl,
  wasmAddResult,
  dynamicValue,
  mjsTitle,
  mjsEsmLabel,
  mjsImageUrl,
  mjsWasmAddResult,
  mjsDynamicValue,
  aliasValue,
  aliasDepLabel,
  customDataValue,
  consumedValue,
} from './file.test-file'

export default function Page() {
  return (

{title}

{items}

{cjsGreeting}

{version}

{esmLab

{mjsImageUrl}

{mjsWasmAddResult}

{mjsDynamicValue}

{aliasValue}

{aliasDepLabel}

el}

{imageUrl}

{wasmAddResult}

{dynamicValue}

{mjsTitle}

{mjsEsmLabel}


gation on not-found', async () => {
    const browser = await next.browser('/trigger-404')
    expect(await browser.elementByCss('#not-found-component').text()).toBe(
      'Not Found!'
    )

    expect(
      await browser
        .elementByCss('#to-result')
        .click()
        .waitForElementByCss('#result-page')
        .text()
    ).toBe('Result Page!')
  })

  it('should allow navigation on error', async () => {
    const browser = await next.browser('/trigger-error')
    expect(await browser.ele

Be('Result Page!')
  })

  it('should allow navigation to other routes on route that was initially not-found', async () => {
    // Intentionally non-existent route.
    const browser = await next.browser('/testabc')
    expect(await browser.elementByCss('

mentByCss('#error-component').text()).toBe(
      'Error Happened!'
    )

    expect(
      await browser
        .elementByCss('#to-result')
        .click()
        .waitForElementByCss('#result-page')
        .text()
    ).to


tTestSetup } from 'e2e-utils'
import { listClientChunks } from 'next-test-utils'
import fs from 'node:fs/promises'
import path from 'node:path'

describe('css-server-chunks', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should not write CSS chunks for the server', async () => {
    // Fetch all routes to compile them in development
    expect((await next.fetch('/client')).status).toBe(200)
    expect((await n

 || f.endsWith('.css'))
    expect(clientChunks).toEqual(
      expect.arrayContaining([expect.stringMatching(/\.css$/)])
    )

    let serverChunks = (
      await Promise.all(
        [`${next.distDir}/server/app`, `${next.distDir}/server/pages`].map(

ext.fetch('/server')).status).toBe(200)
    expect((await next.fetch('/pages')).status).toBe(200)

    let clientChunks = (
      await listClientChunks(path.join(next.testDir, next.distDir))
    ).filter((f) => f.endsWith('.js')


ppr', () => {
  const { next, isNextDev, isNextStart } = nextTestSetup({
    files: __dirname,
    env: {
      NEXT_TELEMETRY_DEBUG: '1',
    },
  })

  it('should indicate the feature is experimental', async () => {
    await retry(() => {
      expect(next.cliOutput).toContain('Experiments (use with caution)')
      expect(stripAnsi(next.cliOutput)).toContain('✓ ppr')
    })
  })
  if (isNextStart) {
    describe('build output', () => {
      it('correctly marks pages as being partially prerendered in th

     expect(next.cliOutput).toContain(' /suspense/node/nested/[slug]')
      })
    })

    describe('telemetry', () => {
      it('should send ppr feature usage event', async () => {
        const events = findAllTelemetryEvents(
          next.cliOutput,

e build output', () => {
        expect(next.cliOutput).toContain('◐ /loading/nested/[slug]')
        expect(next.cliOutput).toContain('◐ /suspense/node')
        expect(next.cliOutput).toContain(' /suspense/node/gsp/[slug]')


    |                 ^' +
          '\n  5 |   console.error(error)' +
          '\n  6 | }' +
          '\n  7 |' +
          '\n'
      )
    } else {
      if (isTurbopack) {
        // TODO(veil): Sourcemap names
        // TODO(veil): relative paths in webpack
        expect(normalizeCliOutput(next.cliOutput)).toContain(
          '(app/rsc-error-log/page.js:4:17)'
        )
        expect(normalizeCliOutput(next.cliOutput)).toContain(
          '' +
            "\n> 4 |   const error = new Error('rsc

    if (isNextDev) {
      const outputIndex = next.cliOutput.length
      await next.render('/rsc-error-log-cause')

      await retry(() => {
        expect(next.cliOutput.slice(outputIndex)).toContain(
          'Error: rsc-error-log-cause'
        )

-error-log')" +
            '\n    |                 ^'
        )
      } else {
        // TODO(veil): line/column numbers are flaky in Webpack
      }
    }
  })

  it('logged errors have a sourcemapped `cause`', async () => {


('next-dynamic-css', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  it('should have correct order of styles between global and css modules', async () => {
    const browser = await next.browser('/page')
    expect(await browser.waitForElementByCss('#server').text()).toBe(
      'Hello Server'
    )

    expect(
      await browser.elementByCss('#server').getComputedCss('background-color')
    ).toBe('rgb(0, 128, 0)')
    expect(await browser.elementByCss('#server').getCo

 next/dynamic (TODO)'
    )
  } else {
    it('should have correct order of styles on client component that is sharing styles with next/dynamic', async () => {
      const browser = await next.browser('/page')
      expect(await browser.waitForElementByCss

mputedCss('color')).toBe(
      'rgb(0, 0, 0)'
    )
  })

  if (isNextDev) {
    // TODO Fix order of styling in development
    it.todo(
      'should have correct order of styles on client component that is sharing styles with


t has its own dependencies
  // (cjs-dep.ts -> metadata.json, esm-dep.mjs)
  const configPath = path.resolve(__dirname, 'config-data.ts')
  const configModule = await this.importModule(configPath)
  const config = configModule.default || configModule

  // Import an ESM .mjs module that also imports esm-dep.mjs
  // Uses a relative path (resolved relative to the transformed module, app/file.test-file.ts)
  const mjsModule = await this.importModule('../config-data.mjs')
  const mjsConfig = mjsModule.default

e
  const mjsEsmLabel = mjsConfig.esmLabel

  // --- resolveAlias tests ---
  let aliasValue = 'unsupported'
  let aliasDepLabel = 'unsupported'
  try {
    // importModule with alias as the request
    const aliasModule = await this.importModule('alias-da

|| mjsModule

  const title = config.title
  const items = config.items.join(', ')
  const cjsGreeting = config.cjsGreeting
  const version = config.version
  const esmLabel = config.esmLabel

  const mjsTitle = mjsConfig.mjsTitl


utils'
import { check } from 'next-test-utils'
import { join } from 'path'

describe('app-dir action disallowed origins', () => {
  const { next, skipped } = nextTestSetup({
    files: join(__dirname, 'unsafe-origins'),
    skipDeployment: true,
    dependencies: {
      'server-only': 'latest',
    },
  })

  if (skipped) {
    return
  }

  // Origin should be localhost
  it('should error if x-forwarded-host does not match the origin', async function () {
    const browser = await next.browser('/')

    a

it check(async () => {
      const t = await browser.elementByCss('#res').text()
      return t.includes('Invalid Server Actions request.') ||
        // In prod the message is hidden
        t.includes('https://react.dev/errors/441')
        ? 'yes'

wait browser.elementByCss('button').click()

    awa


 notFound } from 'next/navigation'

export async function generateStaticParams() {
  return [{ slug: ['about'] }]
}

async function validateSlug(slug: string[]) {
  try {
    const isValidPath =
      slug.length === 1 && (slug[0] === 'about' || slug[0] === 'contact')

    if (!isValidPath) {
      return false
    }

    return true
  } catch (error) {
    throw error
  }
}

export default async function CatchAll({
  params,
}: {
  params: Promise<{ slug?: string[] }>
}) {
  const { slug } = await params

// Validate the slug
  const isValid = await validateSlug(slugArray)

  // If not valid, show 404
  if (!isValid) {
    notFound()
  }

  return (

Catch All

This is a catch all page added to the APP router

const slugArray = Array.isArray(slug) ? slug : []


om 'e2e-utils'
import { waitForRedbox, retry } from 'next-test-utils'

describe('parallel-routes-leaf-segments-build-error', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: path.join(__dirname, 'fixtures', 'build-error'),
    skipStart: true,
    skipDeployment: true,
  })

  if (skipped) {
    it.skip('skip test', () => {})
    return
  }

  if (isNextDev) {
    beforeAll(() => next.start())
  } else {
    beforeAll(async () => {
      try {
        await next.build()
      } catc

const browser = await next.browser('/with-children/child')
        await waitForRedbox(browser)

        await retry(async () => {
          const logs = await browser.log()
          expect(logs).toEqual(
            expect.arrayContaining([

h {
        // Expect build error
      }
    })
  }

  describe('Non-leaf segment with child routes', () => {
    it('should throw MissingDefaultParallelRouteError for @header slot', async () => {
      if (isNextDev) {


// @ts-check
import { NextResponse } from 'next/server'
import { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers'

if (NEXT_RSC_UNION_QUERY !== '_rsc') {
  throw new Error(`NEXT_RSC_UNION_QUERY should be _rsc`)
}

/**
 * @param {import('next/server').NextRequest} request
 * @returns {NextResponse | undefined}
 */
export function middleware(request) {
  const rscQuery = request.nextUrl.searchParams.get(NEXT_RSC_UNION_QUERY)

  // Test that the RSC query is not present in the middl

est', request.url))
  }

  if (request.nextUrl.pathname === '/redirect-on-refresh/auth') {
    const cookie = request.cookies.get('token')
    if (cookie) {
      return NextResponse.redirect(
        new URL('/redirect-on-refresh/dashboard', request.url)

eware
  if (rscQuery) {
    throw new Error('RSC query should not be present in the middleware')
  }

  if (request.nextUrl.pathname === '/redirect-middleware-to-dashboard') {
    return NextResponse.redirect(new URL('/redirect-d


  })
          })
        },
      })

      expect(await browser.elementById('name').text()).toBe('名')
      await browser.elementById('link').click()
      await browser.waitForElementByCss('#set-query')

      await retry(() =>
        expect(requests).toContainEqual({
          pathname: '/',
          ok: true,
          headers: expect.objectContaining({
            'content-type': 'text/x-component',
          }),
        })
      )
    })

    it('should not reset shallow url updates on prefetch', a

nst link = await browser.elementByCss('a')
      await link.hover()
      // Hovering a prefetch link should keep the URL intact
      expect(await browser.url()).toMatch(/\?foo=bar$/)
    })

    describe('useParams identity between renders', () => {

sync () => {
      const browser = await next.browser('/search-params/shallow')
      const button = await browser.elementByCss('button')
      await button.click()
      expect(await browser.url()).toMatch(/\?foo=bar$/)
      co


tate } from 'react'

export function NavigateAndTrackRouterIdentity({ href }) {
  const router = useRouter()
  const [prevRouter, setPrevRouter] = useState(router)

  const [changedCount, setChangedCount] = useState(0)
  if (prevRouter !== router) {
    setPrevRouter(router)
    setChangedCount((p) => p + 1)
  }

  const [navigationCount, setNavigationCount] = useState(0)
  const navigate = () => {
    setNavigationCount((p) => p + 1)
    console.log('navigating to', href)
    router.push(href)
  }

  retur

unmounting this component):{' '}
        {navigationCount}

        router identity changes:{' '}
        {changedCount}

      <button id="

n (
    <>
      <div>
        navigations (without


ect } from 'next/navigation'

function createSuspenseyComponent(Component, { timeout = 0, expire = 10 }) {
  let result
  let promise
  return function Data() {
    if (result) return result
    if (!promise)
      promise = new Promise((resolve) => {
        setTimeout(() => {
          result = <Component />
          setTimeout(() => {
            result = undefined
            promise = undefined
          }, expire)
          resolve()
        }, timeout)
      })
    throw promise
  }
}

function Redi

/>
}

const SuspenseyRedirect = createSuspenseyComponent(Redirect, {
  timeout: 300,
})

export default function () {
  return (
    <div className="suspense">
      <Suspense fallback="fallback">
        <SuspenseyRedirect />
      </Suspense>
    </div>

rect() {
  redirect('/redirect/result')
  return <><


igation*/
'use client'

import { use } from 'react'

import { redirect, useSearchParams } from 'next/navigation'

let listening = false

export default function Page({ params }) {
  if (typeof window === 'undefined') {
    throw new Error('Client render only')
  }

  const { storageKey } = use(params)
  let searchParams = useSearchParams()

  if (searchParams.get('read')) {
    // Read all matching logs and print them
    let storage = Object.fromEntries(
      Object.entries(sessionStorage).flatMap(([key,

nt number of navigations triggered (in browsers that support it)
    sessionStorage.setItem(
      `${storageKey}/navigation-supported`,
      typeof navigation !== 'undefined'
    )
    if (!listening && typeof navigation !== 'undefined') {
      listenin

value]) =>
        key.startsWith(`${storageKey}/`)
          ? [[key.slice(storageKey.length + 1), value]]
          : []
      )
    )

    return
{JSON.stringify(storage, null, 2)}

  } else {
    // Cou


port { permanentRedirect } from 'next/navigation'

function createSuspenseyComponent(Component, { timeout = 0, expire = 10 }) {
  let result
  let promise
  return function Data() {
    if (result) return result
    if (!promise)
      promise = new Promise((resolve) => {
        setTimeout(() => {
          result = <Component />
          setTimeout(() => {
            result = undefined
            promise = undefined
          }, expire)
          resolve()
        }, timeout)
      })
    throw promise

redirect/result')
  return <></>
}

const SuspenseyRedirect = createSuspenseyComponent(Redirect, {
  timeout: 300,
})

export default function () {
  return (
    <div className="suspense">
      <Suspense fallback="fallback">
        <SuspenseyRedirect />

  }
}

function Redirect() {
  permanentRedirect('/


ort Link from 'next/link'
import './global.css'

export default function HashPage() {
  // Create list of 5000 items that all have unique id
  const items = Array.from({ length: 5000 }, (_, i) => ({ id: i }))

  return (

Hash Page

      <Link href="/hash#hash-6" id="link-to-6">
        To 6
      </Link>
      <Link href="/hash#hash-50" id="link-to-50">
        To 50
      </Link>
      <Link href="/hash#hash-160" id="link-to-160"

id="link-to-top">
        To Top
      </Link>
      <Link href="/hash#non-existent" id="link-to-non-existent">
        To non-existent
      </Link>

        {items.map((item) => (

            <div id={`hash-${item

>
        To 160
      </Link>
      <Link href="/hash#hash-300" id="link-to-300">
        To 300
      </Link>
      <Link href="#hash-500" id="link-to-500">
        To 500 (hash only)
      </Link>
      <Link href="/hash#top"


import Link from 'next/link'
import { useEffect, useRef } from 'react'

export default function Page() {
  const prefetchRef = useRef()
  const slowPageRef = useRef()

  useEffect(() => {
    function triggerPrefetch() {
      const event = new MouseEvent('mouseover', {
        view: window,
        bubbles: true,
        cancelable: true,
      })

      prefetchRef.current.dispatchEvent(event)
      console.log('dispatched')
    }

    slowPageRef.current.click()

    setInterval(() => {
      triggerPre

 1000)
  }, [])

  return (
    <>
      <Link id="link-to-slow-page" href="/slow-page" ref={slowPageRef}>
        To /slow-page
      </Link>
      <Link id="prefetch-link" href="/hash" ref={prefetchRef}>
        Prefetch link
      </Link>
    </>
  )
}


Link from 'next/link'
import './global.css'

export default function HashPage() {
  // Create list of 5000 items that all have unique id
  const items = Array.from({ length: 5000 }, (_, i) => ({ id: i }))

  return (

Hash Page

      <Link href="/hash#hash-6" id="link-to-6">
        To 6
      </Link>
      <Link href="/hash#hash-50" id="link-to-50">
        To 50
      </Link>
      <Link href="/hash#hash-160" id="link-to-160">

"link-to-top">
        To Top
      </Link>
      <Link href="/hash#non-existent" id="link-to-non-existent">
        To non-existent
      </Link>
      <div>
        <Link href="?with-query-param#hash-160" id="link-to-query-param">
          To 160 (with

       To 160
      </Link>
      <Link href="/hash#hash-300" id="link-to-300">
        To 300
      </Link>
      <Link href="#hash-500" id="link-to-500">
        To 500 (hash only)
      </Link>
      <Link href="/hash#top" id=


from 'next/link'
import '../hash/global.css'

export default function HashPage() {
  // Create list of 5000 items that all have unique id
  const items = Array.from({ length: 5000 }, (_, i) => ({ id: i }))

  return (

Hash Page

      <Link href="/hash-link-back-to-same-page#hash-6" id="link-to-6">
        To 6
      </Link>
      <Link href="/hash-link-back-to-same-page#hash-50" id="link-to-50">
        To 50
      </Link>
      <

                  <div id={`hash-${item.id}`}>{item.id}

                    <Link
                      href="/hash-link-back-to-same-page/o

Link href="/hash-link-back-to-same-page#hash-160" id="link-to-160">
        To 160
      </Link>

        {items.map((item) => {
          if (item.id === 160) {
            return (


 } from 'react'
import { notFound } from 'next/navigation'

function createSuspenseyComponent(Component, { timeout = 0, expire = 10 }) {
  let result
  let promise
  return function Data() {
    if (result) return result
    if (!promise)
      promise = new Promise((resolve) => {
        setTimeout(() => {
          result = <Component />
          setTimeout(() => {
            result = undefined
            promise = undefined
          }, expire)
          resolve()
        }, timeout)
      })
    thro

  return <></>
}

const SuspenseyNotFound = createSuspenseyComponent(NotFound, {
  timeout: 300,
})

export default function () {
  return (
    <div className="suspense">
      <Suspense fallback="fallback">
        <SuspenseyNotFound />
      </Suspense>

w promise
  }
}

function NotFound() {
  notFound()


from 'react'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useEffect, useTransition } from 'react'

let listening = false
let startedNavigating = false

export default function Page({ params }) {
  if (typeof window === 'undefined') {
    throw new Error('Client render only')
  }

  const { storageKey } = use(params)
  let router = useRouter()
  let path = usePathname()
  let searchParams = useSearchParams().toString()
  if (searchParams) {
    path += `?${searchParams}`

sionStorage.setItem(`${storageKey}/lastIsPending`, isPending)
    }
  })

  // Read all matching logs and print them
  let storage = Object.fromEntries(
    Object.entries(sessionStorage).flatMap(([key, value]) =>
      key.startsWith(`${storageKey}/`)

  }

  // Log every pathname+searchParams we've seen
  sessionStorage.setItem(`${storageKey}/path-${path}`, 'true')

  let [isPending, startTransition] = useTransition()
  useEffect(() => {
    if (startedNavigating) {
      ses


 getCategories = () => [
  {
    name: 'Electronics',
    slug: 'electronics',
    count: 11,
    items: [
      { name: 'Phones', slug: 'phones', count: 4 },
      { name: 'Tablets', slug: 'tablets', count: 5 },
      { name: 'Laptops', slug: 'laptops', count: 2 },
    ],
  },
  {
    name: 'Clothing',
    slug: 'clothing',
    count: 12,
    items: [
      { name: 'Tops', slug: 'tops', count: 3 },
      { name: 'Shorts', slug: 'shorts', count: 4 },
      { name: 'Shoes', slug: 'shoes', count: 5 },
    ],

n', count: 3 },
    ],
  },
  {
    name: 'Shoes',
    slug: 'shoes',
    count: 5,
    items: [],
    prefetch: false,
  },
]

export async function fetchCategoryBySlug(slug) {
  // Assuming it always return expected categories
  return getCategories().fi

  },
  {
    name: 'Books',
    slug: 'books',
    count: 10,
    items: [
      { name: 'Fiction', slug: 'fiction', count: 5 },
      { name: 'Biography', slug: 'biography', count: 2 },
      { name: 'Education', slug: 'educatio


t from 'react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'

const HashChanges = () => {
  const router = useRouter()

  return (

        <Link href="#via-link" id="via-link">
          Via Link
        </Link>

          Via A

        <Link href="#" id="via-empty-hash">
          Via Empty Hash
        </Link>

ink>

        <Link
          href="#name-item-400"
          scroll={false}
          id="scroll-to-name-item-400-no-scroll"
        >
          Go to name item 400 (no scroll)
        </Link>

        <Li

       <Link href="#item-400" id="scroll-to-item-400">
          Go to item 400
        </Link>
      </div>

      <div>
        <Link href="#name-item-400" id="scroll-to-name-item-400">
          Go to name item 400
        </L


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

const { i18n } = require('./next.config')

const urls = [
  // Include the app page without a locale.
  ...(global.isNextDeploy
    ? []
    : [
        // TODO: enable for deploy mode when behavior is corrected
        {
          pathname: '/blog/first-post',
          expected: {
            pathname: '/blog/first-post',
            page: '/app/blog/[slug]/page.js',
          },
        },
      ]),

  // Include th

lt
  // locale).
  {
    pathname: '/about',
    expected: {
      pathname: `/${i18n.defaultLocale}/about`,
      page: '/pages/about.js',
    },
  },

  // Include the locale prefixed urls for the pages page (should resolve).
  ...i18n.locales.map((local

e app pages with locales (should not resolve).
  ...i18n.locales.map((locale) => ({
    pathname: `/${locale}/blog/first-post`,
    expected: null,
  })),

  // Include the pages page without a locale (should default to the defau


from 'e2e-utils'
import stripAnsi from 'strip-ansi'

describe('proxy-runtime', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
    skipStart: true,
  })

  if (skipped) {
    return
  }

  it('should error when proxy file has runtime config export', async () => {
    let cliOutput: string

    if (isNextDev) {
      await next.start().catch(() => {})
      // Use .catch() because Turbopack errors during compile and exits before runtime.
      aw

 CLI output.
    if (process.env.IS_TURBOPACK_TEST && !isNextDev) {
      expect(stripAnsi(cliOutput)).toContain(`proxy.ts:3:14
Next.js can't recognize the exported \`config\` field in route. Proxy does not support Edge runtime.
  1 | export default functi

ait next.browser('/').catch(() => {})
      cliOutput = next.cliOutput
    } else {
      cliOutput = (await next.build()).cliOutput
    }

    // TODO: Investigate why in dev-turbo, the error is shown in the browser console, not


check } from 'next-test-utils'

describe('parallel-routes-catchall', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should match correctly when defining an explicit page & slot', async () => {
    const browser = await next.browser('/')
    await check(() => browser.elementById('slot').text(), /@slot default/)

    await browser.elementByCss('[href="/foo"]').click()

    // foo has defined a page route and a corresponding parallel slot
    // so we'd expect to see the custom sl

 page but no slot', async () => {
    const browser = await next.browser('/')
    await check(() => browser.elementById('slot').text(), /@slot default/)

    await browser.elementByCss('[href="/bar"]').click()

    // bar has defined a slot but no page rou

ot content & the page content
    await check(() => browser.elementById('children').text(), /foo/)
    await check(() => browser.elementById('slot').text(), /foo slot/)
  })

  it('should match correctly when defining an explicit


xtTestSetup } from 'e2e-utils'

describe('adapter-dynamic-metadata', () => {
  const { next, isNextDev, isNextDeploy } = nextTestSetup({
    files: __dirname,
  })

  if (isNextDev) {
    it('should skip next dev', () => {})
    return
  }

  if (!isNextDeploy) {
    it('should classify dynamic metadata routes as app routes in adapter outputs', async () => {
      const { outputs }: Parameters<NextAdapter['onBuildComplete']>[0] =
        await next.readJSON('build-complete.json')

      const expectedDynami

= outputs.prerenders.map((item) => item.pathname)
      const appRoutePathnames = outputs.appRoutes.map((item) => item.pathname)

      expect(staticFilePathnames).toEqual(
        expect.not.arrayContaining(expectedDynamicMetadataRoutes)
      )
      exp

cMetadataRoutes = [
        '/robots.txt',
        '/sitemap.xml',
        '/favicon.ico',
      ]
      const staticFilePathnames = outputs.staticFiles.map(
        (item) => item.pathname
      )
      const prerenderPathnames


leRef(path.resolve(__dirname, 'packages')),
      'pnpm-workspace.yaml': `packages:
      - 'apps/*'
      - 'packages/*'
      `,
    },
    packageJson: require('./package.json'),
    buildCommand: 'pnpm build',
    startCommand: (global as any).isNextDev ? 'pnpm dev' : 'pnpm start',
    installCommand: 'pnpm i',
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  describe('monorepo-package', () => {
    it('should work during RSC', async () => {
      const $ = await next.render$('/monorep

cript')
    })

    it('should work on client-side', async () => {
      const browser = await next.browser('/monorepo-package-ssr')
      expect(await browser.elementByCss('p').text()).toBe('Hello Typescript')
      await waitForNoRedbox(browser)
      ex

o-package-rsc')
      expect($('p').text()).toBe('Hello Typescript')
    })

    it('should work during SSR', async () => {
      const $ = await next.render$('/monorepo-package-ssr')
      expect($('p').text()).toBe('Hello Types


p } from 'e2e-utils'
import { splitResponseWithPPRSentinel } from 'e2e-utils/ppr'

const isAdapterTest = Boolean(process.env.NEXT_ENABLE_ADAPTER)

describe('partial-fallback-root-blocking', () => {
  const { next, isNextDev, isNextDeploy } = nextTestSetup({
    files: __dirname,
    // The latest changes to support this behavior on deployed infra are available in the adapter,
    // and are not being backported to the CLI
    skipDeployment: !isAdapterTest,
  })

  if (isNextDev) {
    it('skipped in dev',

ync () => {
        response = await next.fetch(pathname)
        expect(response.status).toBe(200)

        if (!response.body) {
          throw new Error(`Expected a streamed response body for ${pathname}`)
        }

        return response.body

() => {})
    return
  }

  async function fetchSplitHTML(pathname: string) {
    let response: Awaited<ReturnType<typeof next.fetch>> | undefined
    const [staticPart, dynamicPart] = await splitResponseWithPPRSentinel(
      as


tTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils'

describe('app dir - search params keys', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should keep the React router instance the same when changing the search params', async () => {
    const browser = await next.browser('/')

    const searchParams = await browser
      .waitForElementByCss('#search-params')
      .text()

    await browser.elementByCss('#increment').click()
    await browser.elementByCss(

 await browser.waitForElementByCss('#count').text()

      return newSearchParams !== searchParams && count === '2'
        ? 'success'
        : 'retry'
    }, 'success')

    await browser.elementByCss('#increment').click()
    await browser.elementByCss

'#increment').click()

    await browser.elementByCss('#push').click()

    await check(async () => {
      const newSearchParams = await browser
        .waitForElementByCss('#search-params')
        .text()

      const count =


e,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  if (isNextDev) {
    it('should update cached data after editing a file', async () => {
      const browser = await next.browser('/')

      const [initialFetchedRandom, initialText, initialMathRandom] =
        await Promise.all([
          browser.elementById('fetchedRandom').text(),
          browser.elementById('text').text(),
          browser.elementById('mathRandom').text(),
        ])

      expect(initialFetchedRandom).toMatch(/[

        content.replace('foo', 'bar')
      )

      let newFetchedRandom: string
      let newText: string
      let newMathRandom: string

      await retry(async () => {
        ;[newFetchedRandom, newText, newMathRandom] = await Promise.all([

0,1]\.\d+/)
      expect(initialText).toBe('foo')
      expect(initialMathRandom).toMatch(/[0,1]\.\d+/)

      // Edit something inside of "use cache" in the page.tsx file.
      await next.patchFile('app/page.tsx', (content) =>


import { revalidatePath } from 'next/cache'
import Link from 'next/link'

async function getRandomValue() {
  'use cache'

  return Math.random()
}

async function getData() {
  'use cache'

  return fetch('https://next-data-api-endpoint.vercel.app/api/random').then(
    (res) =>
      res
        .text()
        .then(async (text) => [text, 'foo', await getRandomValue()] as const)
  )
}

export default async function Page() {
  const [fetchedRandom, text, mathRandom] = await getData()

  return (
    <>

        action={async () => {
          'use server'
          revalidatePath('/')
        }}
      >
        <button id="revalidate">Revalidate</button>
      </form>
      <p>
        <Link href="/some/path">Go to /some/path</Link>
      </p>
    </>

{fetchedRandom}

{text}

{mathRandom}

{new Date().toISOString()}

      <form


`) was passed to startActiveSpan which means it will receive a Span argument with a possibly random ID on every invocation leading to cache misses. Provide a wrapping function around the Cache Function that does not forward the Span argument to avoid this issue.",
           "environmentLabel": "Cache",
           "label": "Console Error",
           "source": "app/traced-work.tsx (26:19) @ <anonymous>
         > 26 |     return tracer.startActiveSpan('span-active-span', fn)
              |

it expect(browser).toDisplayCollapsedRedbox(`
         {
           "code": "E394",
           "description": "A Cache Function (\`use cache\`) was passed to startActiveSpan which means it will receive a Span argument with a possibly random ID on every inv

  ^",
           "stack": [
             "<anonymous> app/traced-work.tsx (26:19)",
             "Inner app/traced-work.tsx (97:26)",
             "Page <anonymous>",
           ],
         }
        `)
      } else {
        awa


lt function Page() {
  return (

OTel Cache Components Compat Test

        Span generation causes random IDs to be created. There is a tradeoff
        with this while prerendering since sync IO like Math.random() should be
        excluded from static prerenders but spans are so widely used for
        providing telemetry for rendering and they would ideally be side effect
        free. Next.js now allows random id generation and current time reading
        while OTel sp

ssed into Cache Functions for proper functioning of Cache
        Components.

            "use cache" Page without build-time prerendering

ans are constructed. However it is possible for the span
        object to be passed to a Cache Component where the random ID will cause
        cache misses while prerendering. It is important that Span objects not
        be pa


 function asyncWork() {
  await new Promise((resolve) => setTimeout(resolve, 1000))
  return 42
}

async function cachedAsyncWork() {
  'use cache'
  return asyncWork()
}

function withSpan(fn) {
  return function () {
    const tracer = trace.getTracer('tracer-manual-span')
    const span = tracer.startSpan('span-manual-span')
    const ctx = trace.setSpan(context.active(), span)
    return context.with(ctx, fn)
  }
}

function withActiveSpan(fn) {
  return function () {
    const tracer = trace.getTracer(

pan = withSpan(cachedAsyncWork)
const cachedAsyncWorkWithActiveSpan = withActiveSpan(cachedAsyncWork)

export function CachedInnerTraceManualSpan() {
  async function Inner() {
    const result = await cachedAsyncWorkWithManualSpan()
    return <p classNam

'tracer-active-span')
    return tracer.startActiveSpan('span-active-span', fn)
  }
}

const asyncWorkWithManualSpan = withSpan(asyncWork)
const asyncWorkWithActiveSpan = withActiveSpan(asyncWork)
const cachedAsyncWorkWithManualS


InnerTraceManualSpan,
  InnerTraceManualSpan,
  CachedTracedComponentManualSpan,
  TracedComponentManualSpan,
  CachedInnerTraceActiveSpan,
  InnerTraceActiveSpan,
  CachedTracedComponentActiveSpan,
  TracedComponentActiveSpan,
} from '../../traced-work'

export function generateStaticParams() {
  return [{ slug: 'prerendered' }]
}

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  return (
    <>

{(await params).slug}

We are inside a "u

Span />
      <InnerTraceManualSpan />
      <CachedTracedComponentManualSpan />
      <TracedComponentManualSpan />
      <CachedInnerTraceActiveSpan />
      <InnerTraceActiveSpan />
      <CachedTracedComponentActiveSpan />
      <TracedComponentActiveS

se server" scope</div>
      <CachedInnerTraceManual


raceManualSpan,
  CachedTracedComponentManualSpan,
  TracedComponentManualSpan,
  CachedInnerTraceActiveSpan,
  InnerTraceActiveSpan,
  CachedTracedComponentActiveSpan,
  TracedComponentActiveSpan,
} from '../../traced-work'

export function generateStaticParams() {
  return [{ slug: 'prerendered' }]
}

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  'use cache'
  return (
    <>

{(await params).slug}

We are inside a "use cache" scope<

nerTraceManualSpan />
      <CachedTracedComponentManualSpan />
      <TracedComponentManualSpan />
      <CachedInnerTraceActiveSpan />
      <InnerTraceActiveSpan />
      <CachedTracedComponentActiveSpan />
      <TracedComponentActiveSpan />
    </>

/div>
      <CachedInnerTraceManualSpan />
      <In


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

describe('proxy-with-middleware', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
    skipStart: true,
  })

  if (skipped) {
    return
  }

  it('should error when both middleware and proxy files are detected', async () => {
    const message =
      'Both middleware file "./middleware.ts" and proxy file "./proxy.ts" are detected. Please use "./proxy.ts" only.'

tDev) {
      await next.start().catch(() => {})
      await retry(async () => {
        expect(next.cliOutput).toContain(message)
      })
    } else {
      const { cliOutput } = await next.build()
      expect(cliOutput).toContain(message)
    }
  })
})


as cheerio from 'cheerio'

const isAdapterTest = Boolean(process.env.NEXT_ENABLE_ADAPTER)

describe('sub-shell-generation', () => {
  const { next, isNextDev, isNextDeploy } = nextTestSetup({
    files: __dirname,
    // The latest changes to support this behavior on deployed infra are available in the adapter,
    // and are not being backported to the CLI
    skipDeployment: !isAdapterTest,
  })

  if (isNextDev) {
    it.skip('skipping dev test', () => {})
    return
  }

  describe('should serve the cor

        ['/es/1', '/es/2'],
        true,
      ],
      [
        '/en/[slug]',
        {
          page: 'Page: (runtime)',
          langLayout: 'Lang Layout: (buildtime)',
          rootLayout: 'Root Layout: (buildtime)',
        },
        ['/en/1', '

rect shell', () => {
    describe.each([
      [
        '/[lang]/[slug]',
        {
          page: 'Page: (runtime)',
          langLayout: 'Lang Layout: (runtime)',
          rootLayout: 'Root Layout: (buildtime)',
        },


deredAt1).toBe(renderedAt2)
  } else {
    // Should be re-rendered.
    expect(renderedAt1).toBeLessThan(renderedAt2)
  }
}

describe('Switchable runtime', () => {
  let context

  if ((global as any).isNextDeploy) {
    // TODO-APP: re-enable after Prerenders are handled on deploy
    it('should skip for deploy temporarily', () => {})
    return
  }

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

  beforeAll(() => {
    context = {
      appPort: next.url,
      appDir: next.t

fest', async () => {
        const res = await fetchViaHTTP(
          next.url,
          `/_next/static/${next.buildId}/_devMiddlewareManifest.json`
        )
        const devMiddlewareManifest = await res.json()
        expect(devMiddlewareManifest).to

estDir,
      stdout: '',
      stderr: '',
    }
  })

  if ((global as any).isNextDev) {
    describe('Switchable runtime (dev)', () => {
      it('should not include edge api routes and edge ssr routes into dev middleware mani


om 'e2e-utils'

describe('parallel-routes-leaf-segments-no-build-error', () => {
  const { next } = nextTestSetup({
    files: path.join(__dirname, 'fixtures', 'no-build-error'),
  })

  it('should build successfully without default.tsx for leaf segments', async () => {
    // This test verifies that the build does not throw
    // MissingDefaultParallelRouteError for leaf segments
    expect(next.cliOutput).not.toContain('MissingDefaultParallelRouteError')
  })

  afterAll(() => {
    if (next.cliOutput.in

th all parallel slots', async () => {
      const $ = await next.render$('/leaf-segment')

      // Verify main page content
      expect($('h2').text()).toBe('Leaf Segment Page')
      expect($('.main p').first().text()).toContain(
        'This is a leaf

cludes('MissingDefaultParallelRouteError')) {
      throw new Error('MissingDefaultParallelRouteError was thrown')
    }
  })

  describe('leaf segment without child routes', () => {
    it('should render the leaf segment page wi


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

describe('after during server shutdown - next start', () => {
  const { next, skipped, isNextDev } = nextTestSetup({
    files: __dirname,
    skipDeployment: true, // the tests use cli logs
    skipStart: true,
  })
  if (skipped) {
    return
  }

  beforeEach(async () => {
    await next.start()
  })

  afterEach(async () => {
    // if the test didn't manage to kill next, we should do it ourselves
    await next.stop()
  }, 10_000)

  if (isNextD

it for after callbacks when the server receives %s',
      async (signal) => {
        await next.render('/')
        await retry(async () => {
          expect(next.cliOutput).toInclude('[after] starting sleep')
        })
        await next.stop(signal)

ev) {
    // `next dev` shuts down the child process that runs the server without waiting for cleanups,
    // so `after` callbacks won't have the chance to complete
    it.each(['SIGINT', 'SIGTERM'] as const)(
      'does not wa


= process.env.__NEXT_CACHE_COMPONENTS === 'true'

// Skip PPR test as it's covered in test/e2e/app-dir/ppr-metadata-streaming/ppr-metadata-streaming.test.ts
;(isPPREnabled ? describe.skip : describe)(
  'app-dir - metadata-streaming-static-generation',
  () => {
    const { next, isNextDev, isNextStart } = nextTestSetup({
      files: __dirname,
    })

    if (isNextStart) {
      // Precondition for the following tests in build mode.
      // This test is only useful for non-PPR mode as in PPR mode those

     )
        const staticRoutes = prerenderManifest.routes
        expect(Object.keys(staticRoutes).sort()).toEqual([
          '/',
          '/_global-error',
          '/_not-found',
          '/slow/static',
          '/suspenseful/static',
        ]

routes
      // are all listed in the prerender manifest.
      it('should generate all pages static', async () => {
        const prerenderManifest = JSON.parse(
          await next.readFile('.next/prerender-manifest.json')


ev, isTurbopack, isRspack } = nextTestSetup({
    files: __dirname,
    skipStart: process.env.NEXT_TEST_MODE !== 'dev',
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it("it should error when using segment configs that aren't supported by useCache", async () => {
    if (isNextDev) {
      const browser = await next.browser('/runtime')

      await waitForRedbox(browser)

      if (isTurbopack) {
        await expect(browser).toDisplayRedbox(`
         {
           "description": "Route

)
         Route segment config "runtime" is not compatible with \`nextConfig.experimental.useCache\`. Please remove it.
         > 1 | export const runtime = 'edge'
             |              ^^^^^^^",
           "stack": [],
         }
        `)

 segment config "runtime" is not compatible with \`nextConfig.experimental.useCache\`. Please remove it.",
           "environmentLabel": null,
           "label": "Build Error",
           "source": "./app/runtime/page.tsx (1:14


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

describe('app-prefetch-static', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  if (isNextDev) {
    it('should skip next dev', () => {})
    return
  }

  it('should correctly navigate between static & dynamic pages', async () => {
    const browser = await next.browser('/')
    // Ensure the page is prefetched
    await waitFor(1000)

    await browser.elementByCss('#static-prefetch').c

s('#dynamic-prefetch-page').text()).toBe(
      'Hello from Dynamic Prefetch Page'
    )

    await browser.elementByCss('#static-prefetch').click()

    expect(await browser.elementByCss('#static-prefetch-page').text()).toBe(
      'Hello from Static Pref

lick()

    expect(await browser.elementByCss('#static-prefetch-page').text()).toBe(
      'Hello from Static Prefetch Page'
    )

    await browser.elementByCss('#dynamic-prefetch').click()

    expect(await browser.elementByCs


tTestSetup } from 'e2e-utils'

describe('turbo-resolve-extensions', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should SSR', async () => {
    const res = await next.fetch('/')
    const html = await res.text()
    expect(html).toContain('hello world')
    expect(html).toContain('hello server')
    expect(html).toContain('hello image 1')
    expect(html).toContain('hello image 2')
  })

  it('should work using browser', async () => {
    const browser = await next.browser('/

nc () => {
    // When both PlatformComponent.web.tsx and PlatformComponent.tsx exist,
    // the .web.tsx variant must win because it appears first in resolveExtensions.
    // This guards against a Turbopack bug where the alternative index was
    // har

')
    const text = await browser.elementByCss('body').text()
    expect(text).toContain('hello world')
    expect(text).toContain('hello client')
  })

  it('should respect resolveExtensions priority (.web.tsx before .tsx)', asy


nd-interception-nested-dynamic-routes', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    // TODO: re-enable when resolved related thread
    // https://vercel.slack.com/archives/C07UCHRBWGK/p1759165345308879
    skipDeployment: true,
  })

  it('should intercept the route for nested dynamic routes', async () => {
    const browser = await next.browser('/1/1')
    expect(await browser.elementByCss('h1').text()).toBe('foo id 1, bar id 1')
    await browser.elementByCss('a').click()

    //

r.waitForElementByCss('p').text()).toBe('intercepted!')
    // Should preserve the previous component.
    expect(await browser.elementByCss('h1').text()).toBe('foo id 1, bar id 1')

    await browser.refresh()
    // Should display the correct /baz_id/1 c

 Should intercept the route.
    expect(await browse


('css-media-query', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should preserve max-width media query syntax instead of transpiling to range syntax', async () => {
    const browser = await next.browser('/')

    // Get all stylesheets from the document
    const stylesheetContents = await browser.eval(() => {
      const stylesheets = Array.from(document.styleSheets)
      const contents: string[] = []

      for (const stylesheet of stylesheets) {
        try {
          /

contents.push(rule.cssText)
            }
          }
        } catch (e) {
          // Skip stylesheets we can't access due to CORS
          continue
        }
      }

      return contents
    })

    // Find the media query rule
    const mediaQueryR

/ Only check stylesheets that have cssRules (not external ones we can't access)
          if (stylesheet.cssRules) {
            const rules = Array.from(stylesheet.cssRules)
            for (const rule of rules) {


import { nextTestSetup } from 'e2e-utils'

describe('next-image-legacy-src-with-query-without-local-patterns', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should throw error for relative image with query without localPatterns for legacy Image', async () => {
    if (isNextDev) {
      await next.start()
      await next.browser('/')
      expect(next.cliOutput).toContain(

liOutput } = await next.build()
      expect(cliOutput).toContain(
        'Image with src "/test.png?v=1" is using a query string which is not configured in images.localPatterns.\nRead more: https://nextjs.org/docs/messages/next-image-unconfigured-localpa

    'Image with src "/test.png?v=1" is using a query string which is not configured in images.localPatterns.\nRead more: https://nextjs.org/docs/messages/next-image-unconfigured-localpatterns'
      )
    } else {
      const { c


 error after reset', async () => {
    const browser = await next.browser('/client-component')

    // Try triggering and resetting a few times in a row
    for (let i = 0; i < 5; i++) {
      await browser
        .elementByCss('#error-trigger-button')
        .click()
        .waitForElementByCss('#error-boundary-message')

      expect(await browser.elementByCss('#error-boundary-message').text()).toBe(
        'this is a test'
      )

      await browser
        .elementByCss('#reset')
        .click()

unstable_retry', async () => {
    const browser = await next.browser('/client-component')

    // Try triggering and retrying a few times in a row
    for (let i = 0; i < 5; i++) {
      await browser
        .elementByCss('#error-trigger-button')

        .waitForElementByCss('#error-trigger-button')

      expect(await browser.elementByCss('#error-trigger-button').text()).toBe(
        'Trigger Error!'
      )
    }
  })

  it('should recover Client Component error after


  waitForRedbox,
  waitForNoRedbox,
  getRedboxDescription,
} from 'next-test-utils'

describe('app dir - forbidden with default forbidden boundary', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  // TODO: error forbidden usage in root layout
  it.skip('should error on client forbidden from root layout in browser', async () => {
    const browser = await next.browser('/')

    await browser.elementByCss(

// TODO: error forbidden usage in root layout
  it.skip('should error on server forbidden from root layout on server-side', async () => {
    const browser = await next.browser('/?root-forbidden=1')

    if (isNextDev) {
      await waitForRedbox(browser)

'#trigger-forbidden').click()

    if (isNextDev) {
      await waitForRedbox(browser)
      expect(await getRedboxDescription(browser)).toMatch(
        /forbidden\(\) is not allowed to use in root layout/
      )
    }
  })


during rendering', async () => {
      const pageErrors: unknown[] = []
      const browser = await next.browser('/client-component', {
        beforePageLoad: (page) => {
          page.on('pageerror', (error: unknown) => {
            pageErrors.push(error)
          })
        },
      })
      await browser.elementByCss('#error-trigger-button').click()

      if (isNextDev) {
        // TODO: investigate desired behavior here as it is currently
        // minimized by default
        // await waitForRed

ed: this is a test')
      }

      // Handled by custom error boundary.
      expect(pageErrors).toEqual([])
    })

    it('should trigger error component when undefined is thrown from a client component in the browser', async () => {
      const pageErr

box(browser)
        // expect(await getRedboxHeader(browser)).toMatch(/this is a test/)
      } else {
        expect(
          await browser.waitForElementByCss('#error-boundary-message').text()
        ).toBe('An error occurr


Setup } from 'e2e-utils'

describe('next-dist-client-esm-import', () => {
  const dependencies = require('./package.json').dependencies

  if ((global as any).isNextDeploy) {
    // The `link:` protocol is incompatible with the npm version that's used
    // when this test is deployed, so we use `file:` instead.
    dependencies['@monorepo/adapter-next'] = 'file:./adapter-next'
  }

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

  it('should resolve ESM modules that have "n

   // The filename for the client component module that's imported in this
    // fixture is: <node_modules>/@monorepo/adapter-next/dist/client/index.js
    const browser = await next.browser('/')
    expect(await browser.elementByCss('p').text()).toBe('he

ext/dist/client" in their filename', async () => {


tTestSetup } from 'e2e-utils'
import fs from 'fs'
import path from 'path'

// This test verifies a case when the "proxy.ts" bundle is being traced into the NFT file as "proxy.js".
// As Next.js renames "proxy.js" to "middleware.js" during webpack build, the files in NFT will differ
// from the actual outputs, which will fail for the providers like Vercel that checks for the files in NFT.

describe('proxy-nfc-traced', () => {
  const { next, isTurbopack, isNextStart } = nextTestSetup({
    files: __dirname,

 () => {
      const nfc = JSON.parse(
        fs.readFileSync(
          path.join(next.testDir, '.next/server/middleware.js.nft.json'),
          'utf-8'
        )
      )
      expect(nfc.files).toContain('middleware.js')
      expect(nfc.files).not.toC

  })

  // 'middleware.js' won't be traced because Turbopack doesn't bundle all code to .next/server/middleware.js
  if (isNextStart && !isTurbopack) {
    it('should have renamed trace file as middleware instead of proxy', async


node:fs/promises'

const errorMessage = `This function is what Next.js runs for every request handled by this proxy (previously called middleware).

Why this happens:
- You are migrating from \`middleware\` to \`proxy\`, but haven't updated the exported function.
- The file exists but doesn't export a function.
- The export is not a function (e.g., an object or constant).
- There's a syntax error preventing the export from being recognized.

To fix it:
- Ensure this file has either a default or "proxy" func

skipStart: true,
  })

  if (skipped) {
    return
  }

  it('should error when proxy file has invalid export named middleware', async () => {
    await writeFile(
      join(next.testDir, 'proxy.ts'),
      'export function middleware() {}'
    )

    let

tion export.

Learn more: https://nextjs.org/docs/messages/middleware-to-proxy`

describe('proxy-missing-export', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,


extDev, nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils'

describe('after during server shutdown - custom server', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    startCommand: 'node server.mjs',
    serverReadyPattern: /Custom server started/,
    forcedPort: 'random',
    skipStart: true,
    skipDeployment: true, // the tests use cli logs and a custom server
    env: {
      NODE_ENV: isNextDev ? 'development' : 'production',
      DEBUG: '1',
    },

  // unlike the above test for `next dev`, NextCustomServer has no logic that'd cause it to skip cleanups in dev mode,
  // so this is the same in both modes
  it.each(['SIGINT', 'SIGTERM'] as const)(
    'waits for after callbacks when the server receives

  })
  if (skipped) {
    return
  }

  beforeEach(async () => {
    await next.start()
  })

  afterEach(async () => {
    // if the test didn't manage to kill next, we should do it ourselves
    await next.stop()
  }, 10_000)


import { nextTestSetup } from 'e2e-utils'

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

  // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
  it('should work using cheerio', async () => {
    const $ = await next.render$('/')
    expect($('p').text()).toBe('hello world')
  })

  // Recommended for tests that need a full browser.
  it('should work using browser', async () => {
    const browser = await next.browser

ender('/')
    expect(html).toContain('hello world')
  })

  // In case you need to test the response object.
  it('should work with fetch', async () => {
    const res = await next.fetch('/')
    const html = await res.text()
    expect(html).toContain('h

('/')
    expect(await browser.elementByCss('p').text()).toBe('hello world')
  })

  // In case you need the full HTML. Can also use $.html() with cheerio.
  it('should work with html', async () => {
    const html = await next.r


e NextInstance, nextTestSetup } from 'e2e-utils'
import type { Response } from 'node-fetch'

async function getLastModifiedTime(next: NextInstance, pathname: string) {
  const content = await (await next.fetch(pathname)).text()
  return content.match(/<lastmod>([^<]+)<\/lastmod>/)[1]
}

function assertSitemapResponse(res: Response) {
  expect(res.status).toBe(200)
  expect(res.headers.get('content-type')).toContain('application/xml')
}

describe('app-dir - dynamic in generate params', () => {
  const { next

, 'sitemap/0.xml')
    const secondTime = await getLastModifiedTime(next, 'sitemap/0.xml')

    expect(firstTime).not.toEqual(secondTime)
  })

  it('should be able to call while generating multiple dynamic sitemaps', async () => {
    const res0 = await n

 } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  it('should render sitemap with generateSitemaps in force-dynamic config dynamically', async () => {
    const firstTime = await getLastModifiedTime(next


, isNextDev, skipped } = nextTestSetup({
    files: __dirname + '/fixtures/cache-components',
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should make content after io() dynamic during prerender', async () => {
    const $ = await next.render$('/io-boundary')
    if (isNextDev) {
      // In dev mode everything renders at runtime
      expect($('#before').text()).toBe('at runtime')
      expect($('#after-io').text()).toBe('at runtime')
      expect($('#page').text()).toBe('at runti

     // hanging promise prevented it from executing during the build prerender.
      expect($('#before').text()).toBe('at buildtime')
      expect($('#page').text()).toBe('at buildtime')
      expect($('#after-io').text()).toBe('at runtime')
    }
  })

me')
    } else {
      // In production with cache components, io() creates a dynamic
      // boundary. Content in the static shell is rendered at buildtime.
      // Content after io() is rendered at request time because the


p the test for now. Need to address react/compiler-runtime
// compatibility with React below 19.
// _describe for cleaner git history.
const _describe = isReact18 ? describe.skip : describe

_describe('app-dir - unstable_catchError with react compiler', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
    nextConfig: {
      reactCompiler: true,
    },
    dependencies: {
      'babel-plugin-react-compiler': 'latest',
    },
  })

  it('should recover Client Component error after

er-button')
        .click()
        .waitForElementByCss('#error-boundary-message')

      expect(await browser.elementByCss('#error-boundary-message').text()).toBe(
        'this is a test'
      )

      await browser
        .elementByCss('#reset')

reset', async () => {
    const browser = await next.browser('/client-component')

    // Try triggering and resetting a few times in a row
    for (let i = 0; i < 5; i++) {
      await browser
        .elementByCss('#error-trigg


State } from 'react'
import { unstable_catchError, type ErrorInfo } from 'next/error'

function ErrorFallback(
  { clearError }: { clearError: () => void },
  { error, reset, unstable_retry }: ErrorInfo
) {
  const [retryError, setRetryError] = useState<string | null>(null)

  return (
    <>

{(error as Error).message}

      <button
        id="pages-reset"
        onClick={() => {
          clearError()
          reset()
        }}
      >
        Reset
      </button>

Retry
      </button>
      {retryError ?
{retryError}
 : null}
    </>
  )
}

const ErrorBoundary = unstable_catchError(ErrorFallback)

function ErrorThrower({ shouldThrow }: { shouldThrow: boolean }) {
  if (shouldThrow) {

      <button
        id="pages-retry"
        onClick={() => {
          try {
            unstable_retry()
          } catch (error) {
            setRetryError((error as Error).message)
          }
        }}
      >


} from 'next/cache'

const getData = unstable_cache(
  async () => {
    const noStore = await fetch(
      process.env.TEST_DATA_SERVER + '?cache=no-store',
      { method: 'GET', cache: 'no-store' }
    ).then((res) => res.text())

    const forceCache = await fetch(
      process.env.TEST_DATA_SERVER + '?cache=force-cache',
      { method: 'GET', cache: 'force-cache' }
    ).then((res) => res.text())

    return JSON.stringify(
      {
        random: Math.floor(Math.random() * 1000).toString(),

forceCache,
          noStore,
        },
      },
      null,
      2
    )
  },
  undefined,
  {
    tags: ['unstable-cache-fetch'],
  }
)

export default async function Page() {
  const data = await getData()

  return
{data}

}


tTestSetup } from 'e2e-utils'

describe('app-dir - reexport-client-component-metadata', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should render the page metadata if override', async () => {
    const $ = await next.render$('/override')
    expect($('title').text()).toBe('Page 1')
    expect($('meta[name="description"]').attr('content')).toBe(
      'Page 1 Description'
    )

    const browser = await next.browser('/override')
    expect(await browser.elementByCss('title')

ride', async () => {
    const $ = await next.render$('/no-override')
    expect($('title').text()).toBe('Root Layout')
    expect($('meta[name="description"]').attr('content')).toBe(
      'Root Description'
    )

    const browser = await next.browser('

.text()).toBe('Page 1')
    expect(
      await browser
        .elementByCss('meta[name="description"]')
        .getAttribute('content')
    ).toBe('Page 1 Description')
  })

  it('should render the layout metadata if not over


path = require('path')

/** @type {import('next').NextConfig} */
const nextConfig = {
  turbopack: {
    rules: {
      '*.mdx': {
        loaders: [require.resolve('./test-file-loader.js')],
        as: '*.js',
      },
      '*.txt': [
        {
          condition: { query: '?reverse' },
          loaders: [require.resolve('./reverse-loader.js')],
          as: '*.js',
        },
        {
          condition: { query: /\?upper/ },
          loaders: [require.resolve('./upper-loader.js')],
          as:

nfig.module.rules.push({
      resourceQuery: '?reverse',
      use: require.resolve('./reverse-loader.js'),
    })
    config.module.rules.push({
      resourceQuery: /\?upper/,
      use: require.resolve('./upper-loader.js'),
    })
    config.resolve.al

'*.js',
        },
      ],
    },
    resolveAlias: {
      '@/*': './app/*',
    },
  },
  webpack(config) {
    config.module.rules.push({
      test: /\.mdx/,
      use: require.resolve('./test-file-loader.js'),
    })
    co


NK_HEADER_SIZE = 111

/**
 * Calculates the minimum header length that will be emitted by the server. This
 * is calculated by taking the maximum header length and dividing it by the
 * average header size including joining `, ` characters.
 *
 * @param maxLength the maximum header length
 * @returns the minimum header length
 */
function calculateMinHeaderLength(maxLength) {
  const averageHeaderSize = LINK_HEADER_SIZE + 2
  return Math.floor(maxLength / averageHeaderSize) * averageHeaderSize - 2
}

descri

ength === 'number') {
        env.TEST_REACT_MAX_HEADERS_LENGTH = reactMaxHeadersLength.toString()
      }

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

      it('should respect reactMaxHeadersLength', async () => {
        const res =

be('react-max-headers-length', () => {
  describe.each([0, 400, undefined, 10000])(
    'reactMaxHeadersLength = %s',
    (reactMaxHeadersLength) => {
      const env: Record<string, string> = {}
      if (typeof reactMaxHeadersL


tTestSetup } from 'e2e-utils'

describe('app dir - forbidden with customized boundary', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should match dynamic route forbidden boundary correctly', async () => {
    // `/dynamic` display works
    const browserDynamic = await next.browser('/dynamic')
    expect(await browserDynamic.elementByCss('main').text()).toBe('dynamic')

    // `/dynamic/403` calling forbidden() will match the same level forbidden boundary
    const browserErr

 browserDynamicId.elementByCss('#page').text()).toBe(
      'dynamic [id]'
    )
  })

  it('should escalate forbidden to parent layout if no forbidden boundary present in current layer', async () => {
    const browserDynamic = await next.browser(
      '

or = await next.browser('/dynamic/403')
    expect(await browserError.elementByCss('#forbidden').text()).toBe(
      'dynamic/[id] forbidden'
    )

    const browserDynamicId = await next.browser('/dynamic/123')
    expect(await


from 'e2e-utils'

const isAdapterTest = Boolean(process.env.NEXT_ENABLE_ADAPTER)

describe('not-found-with-pages-i18n', () => {
  const { next, isNextStart, isNextDeploy } = nextTestSetup({
    files: __dirname,
  })

  if (isNextStart) {
    it('should write all locales to the pages manifest', async () => {
      const pagesManifest = JSON.parse(
        await next.readFile('.next/server/pages-manifest.json')
      )

      expect(pagesManifest['/404']).toBe('pages/404.html')
      expect(pagesManifest['/e

 SKIP_TEST_FOR_BUILDER = isNextDeploy ? !isAdapterTest : false

  if (!SKIP_TEST_FOR_BUILDER) {
    it.each(['/app-dir/foo', '/foo'])(
      'should prefer the app router 404 over the pages router 404 when both are present - browser %s',
      async (s) =>

n/404']).toBe('pages/404.html')
      expect(pagesManifest['/en-GB/404']).toBe('pages/404.html')
    })
  }

  // When using the builder, pages router is incorrectly preferred. This is already fixed when using the adapter
  const


rom 'e2e-utils'
import { findPort } from 'next-test-utils'
import http from 'node:http'

describe('ppr-unstable-cache', () => {
  if (isNextDeploy) {
    it.skip('should not run in deploy mode', () => {})
    return
  }

  if (isNextDev) {
    it.skip('should not run in dev mode', () => {})
    return
  }

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

  let server: http.Server | null = null
  afterEach(async () => {
    if (server) {
      await server.close()
      ser

        const cache = new URL(req.url, 'http://n').searchParams.get('cache')
        if (!cache) throw new Error('No cache key')

        const random = Math.floor(Math.random() * 1000).toString()
        const data = cache + ':' + random
        generatio

ver = null
    }
  })

  it('should not cache inner fetch calls', async () => {
    let generations: string[] = []
    server = http.createServer(async (req, res) => {
      try {
        if (!req.url) throw new Error('No URL')


 * as React from 'react'
import * as react from 'library-with-exports/react'
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'

export const config = {
  runtime: 'experimental-edge',
}

let server = {
  react: react.condition,
  serverFavoringBrowser: serverFavoringBrowser.condition,
  serverFavoringEdge: serverFavoringEdge.condition,
}
if (typeof window !== 'undefined') {
  server = JSON.par

    react: react.condition,
      serverFavoringBrowser: serverFavoringBrowser.condition,
      serverFavoringEdge: serverFavoringEdge.condition,
    })
  }, [])

  return (
    <output aria-busy={client === null}>
      {client === null ? (
        <pre d

se(
    document.querySelector('[data-testid="server"]')!.textContent!
  )
}

export default function Page() {
  const [client, setClient] = React.useState<unknown | null>(null)

  React.useLayoutEffect(() => {
    setClient({


lient'
import React from 'react'
import Image from 'next/image'

const Page = () => {
  return (

Warn for this loader that doesnt use width

      <Image
        id="no-width"
        src="/test.png"
        width={100}
        height={100}
        loader={({ src }) => `${src}`}
      />
      <Image
        id="width-path"
        src="/test.jpg"
        width={100}
        height={100}
        loader={({ src, width }) => `${src}/${width}/file.jpg`}
      />
      <Image
        id=

f"
        width={100}
        height={100}
        loader={({ src, width }) =>
          `https://example.vercel.sh${src}?width=${width * 2}`
        }
      />
      <Image
        id="width-querystring-size"
        src="/test.tiff"
        width={100}

"width-querystring-w"
        src="/test.webp"
        width={100}
        height={100}
        loader={({ src, width }) => `${src}?w=${width / 2}`}
      />
      <Image
        id="width-querystring-width"
        src="/test.gi


FzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgIC8+Cjwvc3ZnPg==`

export default function Page() {
  return (

Data URL Placeholder

      <Image
        priority
        id="data-url-placeholder-raw"
        src="/test.ico"
        width="400


React from 'react'
import Image from 'next/image'

export default function Page() {
  return (

Data Url With Fill And Sizes

      <Image
        src="data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' %3E%3Cfilter id='b' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1'/%3E%3C/feComponentTransfer%3E

%%3C/filter%3E%3Cimage filter='url(%23b)' x='0' y='0' height='100%' width='100%' preserveAspectRatio='none' href='data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUo


eact from 'react'
import Image from 'next/image'

import test from '../../public/test.jpg'

const Page = () => {
  return (

Fill Mode

        <Image id="fill-image-1" src="/wide.png" sizes="300px" fill />

      <div
        id="image-container-blur"
        style={{
          heig

ition: 'relative',
          overflow: 'hidden',
        }}
      >
        <Image
          id="fill-image-blur"
          src={test}
          sizes="300px"
          placeholder="blur"
          fill
        />
      </div>
    </div>
  )
}

export defa

ht: '300px',
          width: '300px',
          pos


/image'

import testJPG from '../../public/test.jpg'
import testPNG from '../../public/test.png'
import testWEBP from '../../public/test.webp'
import testAVIF from '../../public/test.avif'
import testSVG from '../../public/test.svg'
import testGIF from '../../public/test.gif'
import testBMP from '../../public/test.bmp'
import testICO from '../../public/test.ico'
import widePNG from '../../public/wide.png'
import tallPNG from '../../components/tall.png'
import superWidePNG from '../../public/super-wide.png'

import TallImage from '../../components/TallImage'

const blurDataURL =
  'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNM/s/wBwAFjwJgf8HDLgAAAABJRU5ErkJggg=='

const shimmer = `data:image/svg+


import Image from 'next/image'

const Page = () => {
  return (

Priority Page

      <Image
        priority
        id="basic-image"
        alt="basic-image"
        src="/test.jpg"
        width="400"
        height="400"
      ></Image>
      <Image
        priority
        id="basic-image-crossorigin"
        alt="basic-image-crossorigin"
        src="/test.webp"
        width="400"
        height="400"
        crossOrigin="use-credentials"
      ></Image>
      <Image
        pr

ading="eager"
        id="load-eager"
        alt="load-eager"
        src="/test.png"
        width="200"
        height="200"
      ></Image>
      <Image
        priority
        id="responsive1"
        alt="responsive1"
        src="/wide.png"

iority
        id="basic-image-referrerpolicy"
        alt="basic-image-referrerpolicy"
        src="/test.png"
        width="400"
        height="400"
        referrerPolicy="no-referrer"
      ></Image>
      <Image
        lo


() => {
  return (

Fill Mode

        <Image id="fill-image-1" src="/wide.png" fill />

        <Image id="fill-image-2" src="/wide.png" fill />

      <div
        id="image-container-3"
        style={{
          position: 'relative'

       <Image id="fill-image-3" src="/wide.png" fill />
      </div>
      <div
        id="image-container-4"
        style={{ position: 'relative', width: '30vw', height: '30vw' }}
      >
        <Image id="fill-image-4" src="/test.png" sizes="100vw" fi

,
          overflow: 'hidden',
        }}
      >


t Image from 'next/image'

const Page = () => {
  const [idToCount, setIdToCount] = useState({})
  const [clicked, setClicked] = useState(false)

  const red =
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mO8ysv7HwAEngHwC+JqOgAAAABJRU5ErkJggg=='

  return (

Test onLoad

This is the native onLoad

      <button id="toggle" onClick={() => setClicked(!clicked)}>
        Toggle
      </button>

      <ImageWithMessage
        id="1"

../public/test.png') : red}
        placeholder={clicked ? 'blur' : 'empty'}
        width="256"
        height="256"
        idToCount={idToCount}
        setIdToCount={setIdToCount}
      />

      <ImageWithMessage
        id="3"
        src={clicked ?

    src={clicked ? '/test.jpg' : red}
        width="128"
        height="128"
        idToCount={idToCount}
        setIdToCount={setIdToCount}
      />

      <ImageWithMessage
        id="2"
        src={clicked ? require('../


from 'react'
import Image from 'next/image'

// We don't use a static import intentionally
const blurDataURL =
  'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAAAAABd+vKJAAAANklEQVR42mNg4GRwdWBgZ2BgUGI4dYhBmYFBgiHy308PBlEGKYbr//9fYJBlYDBYv3nzGkUGANGMDBq2MCnBAAAAAElFTkSuQmCC'

export default function Page() {
  return (
    <>

Image with fill with blurDataURL

        <Image
          fill
          alt="a

isplay: 'flex', minHeight: '30vh' }}>
        <Image
          fill
          alt="alt"
          src="/wide.png"
          placeholder="blur"
          blurDataURL={blurDataURL}
          id="fit-contain"
          style={{ objectFit: 'contain' }}

lt"
          src="/wide.png"
          placeholder="blur"
          blurDataURL={blurDataURL}
          id="fit-cover"
          style={{ objectFit: 'cover' }}
        />
      </div>

      <div style={{ position: 'relative', d


hrow build error when import statement is used with missing file', async () => {
    await next.patchFile(
      'pages/static-img.js',
      (content) =>
        content.replace(
          '../public/foo/test-rect.jpg',
          '../public/foo/test-rect-broken.jpg'
        ),
      async () => {
        const { cliOutput } = await next.build()
        expect(cliOutput).toContain(
          "Module not found: Can't resolve '../public/foo/test-rect-broken.jpg"
        )
        expect(cliOutput).toContain('

   files: __dirname,
    skipDeployment: true,
    disableAutoSkewProtection: true,
  })
  if (skipped) return

  let browser: Playwright
  let $: ReturnType<typeof cheerio.load>

  beforeAll(async () => {
    const html = await next.render('/static-img')

pages/static-img.js')
        expect(cliOutput).not.toContain('Import trace for requested module')
      }
    )
  })
})

describe('Static Image Component Tests', () => {
  const { next, isTurbopack, skipped } = nextTestSetup({


      referrerpolicy,
      })
    }

    expect(
      entries.find(
        (item) =>
          item.imagesrcset ===
          `/_next/image?url=%2Ftest.webp&w=640&q=75${dpl} 1x, /_next/image?url=%2Ftest.webp&w=828&q=75${dpl} 2x`
      )
    ).toEqual({
      fetchpriority: '',
      imagesizes: '',
      imagesrcset: `/_next/image?url=%2Ftest.webp&w=640&q=75${dpl} 1x, /_next/image?url=%2Ftest.webp&w=828&q=75${dpl} 2x`,
      crossorigin: 'use-credentials',
      referrerpolicy: '',
    })

    expect(

28w, /_next/image?url=%2Fwide.png&w=1080&q=75${dpl} 1080w, /_next/image?url=%2Fwide.png&w=1200&q=75${dpl} 1200w, /_next/image?url=%2Fwide.png&w=1920&q=75${dpl} 1920w, /_next/image?url=%2Fwide.png&w=2048&q=75${dpl} 2048w, /_next/image?url=%2Fwide.png&w=3840

    entries.find(
        (item) =>
          item.imagesrcset ===
          `/_next/image?url=%2Fwide.png&w=640&q=75${dpl} 640w, /_next/image?url=%2Fwide.png&w=750&q=75${dpl} 750w, /_next/image?url=%2Fwide.png&w=828&q=75${dpl} 8


port React from 'react'
import Image from 'next/image'

export default function Page() {
  return (

Blurry Placeholder

      <Image
        priority
        id="blurry-placeholder-raw"
        src="/test.ico"
        width="400"
        height="400"
        placeholder="blur"
        blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8P4nhDwAGuAKPn6cicwAAAABJRU5ErkJggg=="
      />

       src="/test.bmp"
        width="400"
        height="400"
        placeholder="blur"
        blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mO0/8/wBwAE/wI85bEJ6gAAAABJRU5ErkJggg=="
      />
    </div>
  )

  <Image
        id="blurry-placeholder-with-lazy"


mage'

// We don't use a static import intentionally
const shimmer = `data:image/svg+xml;base64,Cjxzdmcgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgPGRlZnM+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImciPgogICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMzMzIiBvZmZzZXQ9IjIwJSIgLz4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzIyMiIgb2Zmc2V0PSI1MCUiIC8+CiAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMzMzMiIG9mZnNldD0iNzAlIiAvPgogICAgPC9saW5lYXJH

m9tPSItMjAwIiB0bz0iMjAwIiBkdXI9IjFzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgIC8+Cjwvc3ZnPg==`

export default function Page() {
  return (
    <>

Image with fill with Data URL placeholder

      <div style={{ position: 'relative', display: 'flex', m


t from 'react'
import Image from 'next/image'

import test from '../public/test.jpg'

const Page = () => {
  return (

Fill Mode

        <Image id="fill-image-1" src="/wide.png" sizes="300px" fill />

      <div
        id="image-container-blur"
        style={{
          height: '3

 'relative',
          overflow: 'hidden',
        }}
      >
        <Image
          id="fill-image-blur"
          src={test}
          sizes="300px"
          placeholder="blur"
          fill
        />
      </div>
    </div>
  )
}

export default Pa

00px',
          width: '300px',
          position:


React from 'react'
import Image from 'next/image'

const Page = () => {
  return (

Warn for this loader that doesnt use width

      <Image
        id="no-width"
        src="/test.png"
        width={100}
        height={100}
        loader={({ src }) => `${src}`}
      />
      <Image
        id="width-path"
        src="/test.jpg"
        width={100}
        height={100}
        loader={({ src, width }) => `${src}/${width}/file.jpg`}
      />
      <Image
        id="width-querys

dth={100}
        height={100}
        loader={({ src, width }) =>
          `https://example.vercel.sh${src}?width=${width * 2}`
        }
      />
      <Image
        id="width-querystring-size"
        src="/test.tiff"
        width={100}
        heigh

tring-w"
        src="/test.webp"
        width={100}
        height={100}
        loader={({ src, width }) => `${src}?w=${width / 2}`}
      />
      <Image
        id="width-querystring-width"
        src="/test.gif"
        wi


ort { useState } from 'react'
import Image from 'next/image'

const Page = () => {
  const [clicked, setClicked] = useState(false)

  return (

Test onError

        If error occurred while loading image, native onError should be called.

      <button id="toggle" onClick={() => setClicked(!clicked)}>
        Toggle
      </button>

      <ImageWithMessage id="1" src="/test.png" width={200} height={200} />
      <ImageWithMessage
        id="2"
        src={clicked

{id}`)

  return (
    <>
      <div className="wrap">
        <Image
          id={`img${id}`}
          onError={(e) => {
            setMsg(`error occurred while loading ${e.target.id}`)
          }}
          {...props}
        />
      </div>
      <p

 ? '/404.jpg' : '/test.jpg'}
        width="200"
        height="200"
      />
      <div id="footer" />
    </div>
  )
}

function ImageWithMessage({ id, ...props }) {
  const [msg, setMsg] = useState(`no error occurred for img$


'next/image'

const Page = () => {
  const [idToCount, setIdToCount] = useState({})
  const [clicked, setClicked] = useState(false)

  const red =
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mO8ysv7HwAEngHwC+JqOgAAAABJRU5ErkJggg=='

  return (

Test onLoad

This is the native onLoad

      <button id="toggle" onClick={() => setClicked(!clicked)}>
        Toggle
      </button>

      <ImageWithMessage
        id="1"
        src={clic

ng') : red}
        placeholder={clicked ? 'blur' : 'empty'}
        width="256"
        height="256"
        idToCount={idToCount}
        setIdToCount={setIdToCount}
      />

      <ImageWithMessage
        id="3"
        src={clicked ? '/test.svg' : re

ked ? '/test.jpg' : red}
        width="128"
        height="128"
        idToCount={idToCount}
        setIdToCount={setIdToCount}
      />

      <ImageWithMessage
        id="2"
        src={clicked ? require('../public/test.p