str) {
  return (
    str &&
    str.replace(/^ +(?:at|in) ([\S]+)[^\n]*/gm, function (m, name) {
      const dot = name.lastIndexOf('.')
      if (dot !== -1) {
        name = name.slice(dot + 1)
      }
      return '    at ' + name + (/\d/.test(m) ? ' (**)' : '')
    })
  )
}

describe.each(['default', 'babelrc'] as const)(
  'react-compiler %s',
  (variant) => {
    const dependencies = (global as any).isNextDeploy
      ? // `link` is incompatible with the npm version used when this test is deployed

        variant === 'babelrc'
          ? __dirname
          : {
              app: new FileRef(join(__dirname, 'app')),
              pages: new FileRef(join(__dirname, 'pages')),
              'next.config.js': new FileRef(join(__dirname, 'next.config.

      {
          'reference-library': 'file:./reference-library',
        }
      : {
          'reference-library': 'link:./reference-library',
        }
    const { next, isNextDev, isTurbopack } = nextTestSetup({
      files:


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

describe('browserslist-extends', () => {
  const { next } = nextTestSetup({
    files: {
      'pages/index.js': `
        import styles from './index.module.css'

        export default function Page() {
          return
hello world

        }
      `,
      'pages/index.module.css': `
        .hello {
          color: pink;
        }
      `,
    },
    dependencies: {
      '

onfig-google': '^3.0.1',
    },
    packageJson: {
      browserslist: ['extends browserslist-config-google'],
    },
  })

  it('should work', async () => {
    const html = await renderViaHTTP(next.url, '/')
    expect(html).toContain('hello world')
  })


 readFixtureText,
} from './utils'

describe('metadata-files-static-output-intercepting-route', () => {
  if (process.env.__NEXT_CACHE_COMPONENTS) {
    // Cache Components build fails when metadata files are inside a dynamic route.
    //
    // Route "/dynamic/[id]": Next.js encountered uncached or runtime data in `generateMetadata()`.
    //
    // This prevents the page from being prerendered, leading to a slower user experience.
    //
    // Ways to fix this:
    //   - Use a static metadata export in

rt const instant = false` to allow a blocking route
    //
    // Learn more: https://nextjs.org/docs/messages/next-prerender-dynamic-metadata
    // Error occurred prerendering page "/dynamic/[id]". Read more: https://nextjs.org/docs/messages/prerender-er

stead of `generateMetadata()`
    //   - Cache the metadata with `"use cache"` in `generateMetadata()`
    //   - Add a dynamic data access (e.g. `await connection()`) to the page to render it at request time
    //   - Set `expo


ver as HttpServer } from 'node:http'
import { SavedSpan } from './constants'

export interface Collector {
  getSpans: () => SavedSpan[]
  shutdown: () => Promise<void>
}

export async function connectCollector({
  port,
}: {
  port: number
}): Promise<Collector> {
  const spans: SavedSpan[] = []

  const server = new HttpServer(async (req, res) => {
    if (req.method !== 'POST') {
      res.writeHead(405)
      res.end()
      return
    }

    const body = await new Promise<Buffer>((resolve, reject) => {

ewSpans = JSON.parse(body.toString('utf-8')) as SavedSpan[]
    spans.push(...newSpans)
    res.statusCode = 202
    res.end()
  })

  await new Promise<void>((resolve, reject) => {
    server.listen(port, (err?: Error) => {
      if (err) {
        reject

      const acc: Buffer[] = []
      req.on('data', (chunk: Buffer) => {
        acc.push(chunk)
      })
      req.on('end', () => {
        resolve(Buffer.concat(acc))
      })
      req.on('error', reject)
    })

    const n


('app-dir assetPrefix with basePath handling', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should redirect route when requesting it directly', async () => {
    const res = await next.fetch('/custom-base-path/a/', {
      redirect: 'manual',
    })
    expect(res.status).toBe(308)
    expect(new URL(res.headers.get('location'), next.url).pathname).toBe(
      '/custom-base-path/a'
    )
  })

  it('should render link', async () => {
    const $ = await next.render$('/custom-

ase-path/a')
    expect(await browser.waitForElementByCss('#a-page').text()).toBe('A page')
  })

  it('should redirect route when clicking link', async () => {
    const browser = await next.browser('/custom-base-path')
    await browser
      .elementByC

base-path')
    expect($('#to-a-trailing-slash').attr('href')).toBe('/custom-base-path/a')
  })

  it('should redirect route when requesting it directly by browser', async () => {
    const browser = await next.browser('/custom-b


ndling - next export', () => {
  const { next, isNextStart, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
    dependencies: {
      nanoid: '4.0.1',
      'server-only': 'latest',
    },
  })
  if (skipped) return

  if (!isNextStart) {
    it('skip test for development mode', () => {})
    return
  }

  beforeAll(async () => {
    await next.stop()
    await next.patchFile(
      'next.config.js',
      `
      module.exports = {
        output: 'export'

also not supported with export
    await next.remove('app/interception-routes')
    try {
      await next.start()
    } catch {}
  })

  it('should error when use export output for server actions', async () => {
    expect(next.cliOutput).toContain(

     }
      `
    )
    // interception routes are


ort { nextTestSetup } from 'e2e-utils'
import { retry, waitForRedbox, getRedboxSource } from 'next-test-utils'

// Webpack specific config test.
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
  'devtool set in development mode in next config',
  () => {
    const { next } = nextTestSetup({
      files: __dirname,
    })

    it('should warn and revert when a devtool is set in development mode', async () => {
      await retry(async () => {
        expect(next.cliOutput).toMatch(/Reverting webp

   "pages/index.js (5:11) @ Index.useEffect

            3 | export default function Index(props) {
            4 |   useEffect(() => {
          > 5 |     throw new Error('this should render')
              |           ^
            6 |   }, [])

ack devtool to /)
      })

      const browser = await next.browser('/')
      await waitForRedbox(browser)
      if (process.platform !== 'win32') {
        expect(await getRedboxSource(browser)).toMatchInlineSnapshot(`


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

describe('app dir - css', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    dependencies: {
      sass: 'latest',
    },
  })

  if (skipped) {
    return
  }

  describe('sass support', () => {
    ;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)(
      'error handling',
      () => {
        it('should use original source points for sass errors', async () => {
          const browser =

lineSnapshot(`
           "./app/global.scss.css (45:1)
           Parsing CSS source code failed
             43 | }
             44 |
           > 45 | input.defaultCheckbox::before path {
                | ^
             46 |   fill: currentColor;

 await next.browser('/sass-error')

          await waitForRedbox(browser)
          const source = await getRedboxSource(browser)

          // css-loader does not report an error for this case
          expect(source).toMatchIn


n } from 'path'
import { nextTestSetup, FileRef } from 'e2e-utils'

describe('i18-default-locale-redirect', () => {
  const { next } = nextTestSetup({
    files: {
      pages: new FileRef(join(__dirname, './app/pages')),
      'next.config.js': new FileRef(join(__dirname, './app/next.config.js')),
    },
  })

  it('should not request a path prefixed with default locale', async () => {
    const browser = await next.browser('/')
    let requestedDefaultLocalePath = false
    browser.on('request', (request:

ct(await browser.elementByCss('#new').text()).toBe('New')
    expect(requestedDefaultLocalePath).toBe(false)
  })

  it('should request a path prefixed with non-default locale', async () => {
    const browser = await next.browser('/')
    let requestedNon

 any) => {
      if (new URL(request.url(), 'http://n').pathname === '/en/to-new') {
        requestedDefaultLocalePath = true
      }
    })

    await browser.elementByCss('#to-new').click().waitForElementByCss('#new')
    expe


tTestSetup, type Playwright } from 'e2e-utils'

const getPathname = (url: string) => {
  const urlObj = new URL(url)
  return urlObj.pathname
}

const createRequestsListener = async (browser: Playwright) => {
  // wait for network idle
  await browser.waitForIdleNetwork()

  let requests = []

  browser.on('request', (req) => {
    requests.push([req.url(), !!req.headers()['next-router-prefetch']])
  })

  await browser.refresh()

  return {
    getRequests: () => requests,
    clearRequests: () => {

e {
    it('should avoid double-fetching when optimistic navigation fails', async () => {
      const browser = await next.browser('/foo')
      const { getRequests } = await createRequestsListener(browser)

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

requests = []
    },
  }
}

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

  if (isNextDev) {
    it.skip('should skip test in development mode', () => {})
  } els


 readFixtureText,
} from './utils'

describe('metadata-files-static-output-root-route', () => {
  if (process.env.__NEXT_CACHE_COMPONENTS) {
    // Cache Components build fails when metadata files are inside a dynamic route.
    //
    // Route "/dynamic/[id]": Next.js encountered uncached or runtime data in `generateMetadata()`.
    //
    // This prevents the page from being prerendered, leading to a slower user experience.
    //
    // Ways to fix this:
    //   - Use a static metadata export instead of

 instant = false` to allow a blocking route
    //
    // Learn more: https://nextjs.org/docs/messages/next-prerender-dynamic-metadata
    // Error occurred prerendering page "/dynamic/[id]". Read more: https://nextjs.org/docs/messages/prerender-error

 `generateMetadata()`
    //   - Cache the metadata with `"use cache"` in `generateMetadata()`
    //   - Add a dynamic data access (e.g. `await connection()`) to the page to render it at request time
    //   - Set `export const


import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
import {
  SimpleSpanProcessor,
  SpanExporter,
  ReadableSpan,
  BasicTracerProvider,
} from '@opentelemetry/sdk-trace-base'
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks'
import {
  ExportResult,
  ExportResultCode,
  hrTimeToMicroseconds,
} from '@opentelemetry/core'

import { SavedSpan } from './constants'

const serializeSpan = (span: ReadableSpan): SavedSpan => ({
  runtime: process.

oMicroseconds(span.duration),
  attributes: span.attributes,
  status: span.status,
})

class TestExporter implements SpanExporter {
  constructor(private port: number) {}

  async export(
    spans: ReadableSpan[],
    resultCallback: (result: ExportResul

env.NEXT_RUNTIME,
  traceId: span.spanContext().traceId,
  parentId: span.parentSpanId,
  name: span.name,
  id: span.spanContext().spanId,
  kind: span.kind,
  timestamp: hrTimeToMicroseconds(span.startTime),
  duration: hrTimeT


from 'e2e-utils'
import { check, renderViaHTTP } from 'next-test-utils'
import stripAnsi from 'strip-ansi'

describe('typescript-auto-install', () => {
  const { next } = nextTestSetup({
    files: {
      'pages/index.js': `
        export default function Page() {
          return
hello world

        }
      `,
    },
    env: {
      // unset CI env as this skips the auto-install behavior
      // being tested
      CI: '',
      CIRCLECI: '',
      GITHUB_ACTIONS: '',
      CONTINUOUS_INTEGRATION

 detect TypeScript being added and auto setup', async () => {
    const browser = await next.browser('/')
    const pageContent = await next.readFile('pages/index.js')

    await check(
      () => browser.eval('document.documentElement.innerHTML'),

: '',
      RUN_ID: '',
      BUILD_NUMBER: '',
    },
    dependencies: {},
  })

  it('should work', async () => {
    const html = await renderViaHTTP(next.url, '/')
    expect(html).toContain('hello world')
  })

  it('should


nder native module', () => {
  const { next } = nextTestSetup({
    files: {
      pages: new FileRef(path.join(__dirname, 'prerender-native-module/pages')),
      'data.sqlite': new FileRef(
        path.join(__dirname, 'prerender-native-module/data.sqlite')
      ),
    },
    dependencies: {
      sqlite: '4.0.22',
      sqlite3: '5.0.2',
    },
    packageJson: {
      pnpm: {
        onlyBuiltDependencies: ['sqlite3'],
      },
    },
  })

  it('should render index correctly', async () => {
    const

ld render /blog/first correctly', async () => {
    const browser = await next.browser('/blog/first')

    expect(await browser.elementByCss('#blog').text()).toBe('blog page')
    expect(JSON.parse(await browser.elementByCss('#props').text())).toEqual({

browser = await next.browser('/')
    expect(await browser.elementByCss('#index').text()).toBe('index page')
    expect(JSON.parse(await browser.elementByCss('#props').text())).toEqual({
      index: true,
    })
  })

  it('shou


{ unstable_cache } from 'next/cache'
import { headers as nextHeaders, draftMode } from 'next/headers'

const getCachedValue = unstable_cache(
  async () => Math.random().toString(),
  ['middleware-cache-probe']
)

/**
 * @param {import('next/server').NextRequest} request
 */
export async function middleware(request) {
  const headersFromRequest = new Headers(request.headers)
  // It should be able to import and use `headers` inside middleware
  const headersFromNext = await nextHeaders()
  headersFromReques

rsFromRequest.get('x-from-client')
  ) {
    throw new Error('Expected headers from client to match')
  }

  if (request.nextUrl.searchParams.get('draft')) {
    ;(await draftMode()).enable()
  }

  const removeHeaders = request.nextUrl.searchParams.get('r

t.set('x-from-middleware', 'hello-from-middleware')

  // make sure headers() from `next/headers` is behaving properly
  if (
    headersFromRequest.get('x-from-client') &&
    headersFromNext.get('x-from-client') !==
      heade


import { createSandbox } from 'development-sandbox'
import path from 'path'
import { outdent } from 'outdent'

const middlewarePath = 'middleware.js'
const middlewareWarning = `A middleware can not alter response's body`

describe('middlewares', () => {
  const { next } = nextTestSetup({
    files: new FileRef(
      path.join(__dirname, '..', 'acceptance', 'fixtures', 'default-template')
    ),
    skipStart: true,
  })

  it.each([
    {
      title: 'returning response with literal string',
      code: o

rt default function middleware() {
          return new Response(10);
        }
      `,
    },
    {
      title: 'returning response with JSON.stringify',
      code: outdent`
        export default function middleware() {
          return new Response(J

utdent`
        export default function middleware() {
          return new Response('this is not allowed');
        }
      `,
    },
    {
      title: 'returning response with literal number',
      code: outdent`
        expo


tTestSetup } from 'e2e-utils'

describe('i18n-disallow-multiple-locales', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it.each([
    ['/non-existent'],
    ['/es/non-existent'],
    ['/first/non-existent'],
    ['/es/first/non-existent'],
    ['/first/second/non-existent'],
    ['/es/first/second/non-existent'],
  ])(
    'should 404 properly for fallback: false non-prerendered %s',
    async (pathname) => {
      const res = await next.fetch(pathname)
      expect(res.status).to

th: '/first/second/third/fourth',
      page: '/[first]/[second]/[third]/[fourth]',
    },
  ])(
    'should render properly for fallback: false prerendered $urlPath',
    async ({ urlPath, page }) => {
      const res = await next.fetch(urlPath)
      exp

Be(404)
    }
  )

  it.each([
    { urlPath: '/first', page: '/[first]' },
    { urlPath: '/first/second', page: '/[first]/[second]' },
    { urlPath: '/first/second/third', page: '/[first]/[second]/[third]' },
    {
      urlPa


ype Playwright } from 'e2e-utils'
import { check } from 'next-test-utils'

describe('app a11y features', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    packageJson: {},
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  describe('route announcer', () => {
    async function getAnnouncerContent(browser: Playwright) {
      return browser.eval(
        `document.getElementsByTagName('next-route-announcer')[0]?.shadowRoot.childNodes[0]?.innerHTML`
      )
    }

ges', async () => {
      const browser = await next.browser('/page-with-h1')
      await browser.elementById('page-with-title').click()
      await check(() => getAnnouncerContent(browser), 'page-with-title')
    })

    it('should announce h1 changes', a

   it('should not announce the initital title', async () => {
      const browser = await next.browser('/page-with-h1')
      await check(() => getAnnouncerContent(browser), '')
    })

    it('should announce document.title chan


ierContext } from './internal-context'

export interface CacheIdentifier {}
const cacheById = new WeakMap<CacheIdentifier, DataCache>()

export type DataCache = Map<string, Promise<unknown>>

function createDataCache(): DataCache {
  return new Map()
}

export function useDataCache() {
  const id = use(CacheIdentifierContext)
  if (id === null) {
    throw new Error('Missing DataCacheProvider')
  }

  let cache = cacheById.get(id)
  if (!cache) {
    cacheById.set(id, (cache = createDataCache()))
  }
  retu

se<T>): Promise<T> {
      let promise = cache.get(key) as Promise<T> | undefined
      if (!promise) {
        console.log('client-data-fetching-lib :: MISS', key)
        cache.set(key, (promise = func()))
      } else {
        console.log('client-data-

rn {
    getOrLoad<T>(key: string, func: () => Promi


{ cacheLife } from 'next/cache'
import Link from 'next/link'
import { setTimeout } from 'timers/promises'

export function DebugLinks({ href }: { href: string }) {
  return (

      {href}{' '}
      <Link data-link-type="soft" href={href}>
        [SPA]
      </Link>{' '}

        [MPA]

  )
}

export async function uncachedIO() {
  await setTimeout(0)
}

export async function cachedDelay(key: any) {
  'use cache'
  ca

-render/work-unit-async-storage.external')
  const workUnitStore = workUnitAsyncStorage.getStore()!
  return (
    <div>
      workUnitStore.type: {workUnitStore.type}
      {(() => {
        switch (workUnitStore.type) {
          case 'prerender':

cheLife('minutes')
  await setTimeout(1)
}

export function DebugRenderKind() {
  const { workUnitAsyncStorage } =
    require('next/dist/server/app-render/work-unit-async-storage.external') as typeof import('next/dist/server/app


{ ReactNode, Suspense } from 'react'

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    // We're mostly interested in checking client navigations,
    // so to avoid having to give each test case a valid static shell,
    // we put a Suspense above the body.
    <Suspense fallback={
Root suspense boundary...
}>

          {children}

      </h

turn (

      Home{' '}
      <Suspense fallback="...">

          <Now />

      </Suspense>

  )
}

async function Now() {
  await connection()
  return Date.n

tml>
    </Suspense>
  )
}

function Header() {
  re


nd-params/123" />

          <DebugLinks href="/suspense-in-root/runtime/valid-no-suspense-around-search-params?foo=bar" />

          <DebugLinks href="/suspense-in-root/runtime/missing-suspense-around-dynamic" />

          <DebugLinks href="/suspense-in-root/runtime/missing-suspense-around-dynamic-layout" />

          <DebugLinks href="/suspense-in-root/runtime/suspense-too-high" />

          <DebugLinks href="/suspense-in-root/runtime/invalid-sync-io" />

          <DebugLinks href="/suspense-in-root/runtime/valid-blocking-inside-runtime" />

          <DebugLinks href="

          <DebugLinks href="/suspense-in-root/static/invalid-blocking-inside-static" />

          <DebugLinks href="/suspense-in-root/runtime/invalid-blocking-inside-runtime" />


'
import { cookies } from 'next/headers'
import { connection } from 'next/server'
import { Suspense } from 'react'

export const unstable_instant = { level: 'experimental-error' }
export const unstable_prefetch = 'force-runtime'

// Note that we're inside a root layout with suspense, so we skip the static shell
export async function generateViewport(): Promise<Viewport> {
  await connection()
  return {
    themeColor: 'aliceblue',
  }
}

export default async function Page() {
  await cookies()
  return (

iewport

        We also access dynamic data in the page itself, because a static page
        with a dynamic viewport is not allowed.

      <Suspense>
        <Dynamic />
      </Suspense>

  )
}

async function Dynamic(

   <main>
      <p>This page has a dynamic generateV


rom 'next/server'
import { Suspense } from 'react'

export const unstable_instant = { level: 'experimental-error' }
export const unstable_prefetch = 'force-runtime'

export async function generateMetadata(): Promise<Metadata> {
  await connection()
  return {
    title: 'Blocked by connection',
  }
}

export default async function Page() {
  await cookies()
  return (
    <main>
      <p>
        This page has a generateMetadata that accesses connection. It's
        runtime-prefetchable, but metadata doesn

 We also access connection in the page itself, because a runtime page
        with dynamic metadata is not allowed.
      </p>
      <Suspense>
        <Dynamic />
      </Suspense>
    </main>
  )
}

async function Dynamic() {
  await connection()
  retur

't block, so it's fine.
      </p>
      <p>


import { cookies } from 'next/headers'

// This would be valid if it used a runtime prefetch (because then it wouldn't block navigation),
// but it's static, so it's invalid. As an extra sanity check, we put a runtime prefetch on the
// layout above, and that should not make this error go away.
export const unstable_instant = { level: 'experimental-error' }

export async function generateViewport(): Promise<Viewport> {
  await cookies()
  return {
    themeColor: 'aliceblue',
  }
}

export default function

s a runtime generateViewport

        We also access runtime data in the page itself, because a fully static
        page with a runtime vieport is not allowed.

      <Suspense>
        <Runtime />
      </Suspense>

  )

Page() {
  return (
    <main>
      <p>This page ha


le_instant = {
  level: 'experimental-error',
  unstable_samples: [{ cookies: [], searchParams: { foo: 'bar' } }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page({
  searchParams,
}: {
  searchParams: Promise<Record<string, string | string[]>>
}) {
  const search = await searchParams
  return (

Params don't need a suspense boundary when runtime-prefetched:

Search: {JSON.stringify(search)}

nt does:

        <Suspense fallback={
Loading...
}>
          <Dynamic />
        </Suspense>

  )
}

async function Dynamic() {
  await connection()
  return
Dynamic content from page

}


{ Suspense } from 'react'

export const unstable_instant = {
  level: 'experimental-error',
  unstable_samples: [{ cookies: [], params: { param: '123' } }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page({
  params,
}: {
  params: Promise<{ param: string }>
}) {
  const { param } = await params
  return (

Params don't need a suspense boundary when runtime-prefetched:

Param value: {param}


kies } from 'next/headers'

export const unstable_instant = { level: 'experimental-error' }
export const unstable_prefetch = 'force-runtime'

// This page HAS runtime prefetch enabled. cookies() is passed as a promise
// input to a public "use cache" function. The cache doesn't read the cookies
// in its body — they're only part of the cache key. After the cache resolves,
// Date.now() is sync IO that should error because we're in a
// runtime-prefetchable segment where cookies() has resolved at EarlyRuntim

would
// resolve later, and Date.now() would happen at the Runtime stage where
// canSyncInterrupt returns false — missing the error.

async function cachedFn(cookiePromise: Promise<string>) {
  'use cache'
  // Intentionally not reading the cookie promise

e.
//
// This test validates that the cache input encoding resolves in the correct
// runtime stage (EarlyRuntime for prefetchable segments). If the cache input
// abort signal incorrectly waited for the Runtime stage, the cache


} from 'next/headers'
import { Suspense } from 'react'

// This layout does NOT have runtime prefetch — it's a static segment.
// The RuntimeContent component accesses cookies() then Date.now().
// In a static prefetch the render would never get past cookies() so the
// sync IO is unreachable. In a runtime prefetch, cookies() would resolve
// but this layout is not runtime-prefetchable — only the child page is.
// So the sync IO here should not error.

async function RuntimeContent() {
  await cookies()
  c

sync IO after cookies: {now}

}

export default function StaticLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (

      <Suspense fallback={
Loading...
}>
        <RuntimeContent />
      </Suspense>

onst now = Date.now()
  return <p>Static layout with


'next/headers'
import { connection } from 'next/server'
import { Suspense } from 'react'

export const unstable_instant = { level: 'experimental-error' }
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (

Runtime content doesn't need a suspense boundary:

        <Runtime />

But dynamic content does:

        <Suspense fallback={
Loading...
}>
          <Dynamic />
        <

  )
}

async function Runtime() {
  await cookies()
  return
Runtime content from page

}

async function Dynamic() {
  await connection()
  return
Dynamic content from page</di


t { Suspense, type ReactNode } from 'react'
import { ErrorInSSR } from './client'
import { connection } from 'next/server'

// Make sure that the holes from this layout aren't factored in for validation
// (otherwise, we'd check a navigation into it from the root layout and fail)
export const unstable_instant = false

export default async function Layout({ children }: { children: ReactNode }) {
  await connection() // Prevent the error from failing the prerender in build
  return (
    <>
      <div>

  This layout errors in SSR, and the errors is caught by a Suspense
          boundary, but it blocks the children slot so it prevents validation.
        </p>
        <Suspense>
          <ErrorInSSR>{children}</ErrorInSSR>
        </Suspense>
      </div


omPackage } from 'my-pkg'
import { connection } from 'next/server'

// Make sure that the holes from this layout aren't factored in for validation
// (otherwise, we'd check a navigation into it from the root layout and fail)
export const unstable_instant = false

export default async function Layout({ children }: { children: ReactNode }) {
  await connection() // Prevent the error from failing the prerender in build
  return (
    <>

          This layout errors in SSR, and the error

 blocks the children slot so it prevents validation.
          The error is thrown in a component from node_modules, which means that
          the component is ignore-listed away.
        </p>
        <Suspense>
          <ErrorInSSRFromPackage>{children}

s is caught by a Suspense
          boundary, but it


ype { ReactNode } from 'react'
import { LazyClientWrapperWithNoSSR } from './lazy-client'
import { connection } from 'next/server'

// Make sure that the holes from this layout aren't factored in for validation
// (otherwise, we'd check a navigation into it from the root layout and fail)
export const unstable_instant = false

export default async function Layout({ children }: { children: ReactNode }) {
  await connection() // Prevent the error from failing the prerender in build
  return (
    <>
      <div

ent wrapped in next/dynamic with ssr:
          false around the children slot. This blocks the children slot so it
          prevents validation.
        </p>
        <LazyClientWrapperWithNoSSR>{children}</LazyClientWrapperWithNoSSR>
      </div>
    </>

>
        <p>
          This layout renders a compon


import { cookies } from 'next/headers'
import { connection } from 'next/server'
import { Suspense } from 'react'

export const unstable_instant = { level: 'experimental-error' }

export default async function Page() {
  return (

        This page wraps all runtime/dynamic components in suspense, so it
        wouldn't block a navigation and should pass validation.

Runtime content with a suspense boundary

        <Suspense fallback={
Loading...</

  )
}

async function Runtime() {
  await cookies()
  return
Runtime content from page

}

async function Dynamic() {
  await connection()
  return
Dynamic content from page</div

div>}>
          <Runtime />
        </Suspense>

Dynamic content with a suspense boundary

        <Suspense fallback={
Loading...
}>
          <Dynamic />
        </Suspense>


rt { Suspense, type ReactNode } from 'react'
import { ErrorInSSR } from './client'
import { connection } from 'next/server'

// Make sure that the holes from this layout aren't factored in for validation
// (otherwise, we'd check a navigation into it from the root layout and fail)
export const unstable_instant = false

export default async function Layout({ children }: { children: ReactNode }) {
  await connection() // Prevent the error from failing the prerender in build
  return (
    <>
      <div>

error is wrapped in Suspense and
          does not block the children slot, so it does not prevent us from
          validating the page.
        </p>
        <Suspense>
          <ErrorInSSR />
        </Suspense>
        {children}
      </div>
    </>

   <p>
          This layout errors in SSR, but the


ort { cookies } from 'next/headers'
import { connection } from 'next/server'

export const unstable_instant = { level: 'experimental-error' }

export default async function Page() {
  return (
    <main>
      <p>
        This page doesn't wrap runtime/dynamic components in suspense, but it
        has a loading.tsx above it. However, the page is inside a route group
        and the loading.tsx is on the parent URL segment. Validation considers
        the route group as a potential shared boundary where th

y report an error.

        <Runtime />

        <Dynamic />

  )
}

async function Runtime() {
  await cookies()
  return
Runtime content from page

}

as

e loading.tsx
        Suspense would already be revealed. In a more advanced system we would
        analyze siblings of the route group to determine if such a navigation is
        actually possible, but for now we conservativel


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

  // Recursively read all .js files in a directory
  function getAllServerFiles(dir: string): string[] {
    const results: string[] = []
    try {
      const entries = fs.readdirSync(dir, { withFileTypes: true })
      for (const entry of entries) {
        const fullPath = path.join(dir, entry.name)
        if (entry.isDirectory()) {
          results.push(...getAllServerFiles(fullPath))
        } else if (entry.name.endsWith('.

t.testDir, '.next/server')
    const files = getAllServerFiles(serverDir)
    const contents = await Promise.all(
      files.map((f) => fs.promises.readFile(f, 'utf8'))
    )
    return contents.join('\n')
  }

  // Verify that each page renders correctly

js')) {
          results.push(fullPath)
        }
      }
    } catch {
      // directory doesn't exist
    }
    return results
  }

  async function getAllServerContent(): Promise<string> {
    const serverDir = path.join(nex


assetPrefix', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    nextConfig: {
      assetPrefix: 'https://example.vercel.sh/',
    },
  })

  it('bundles should return 200 on served assetPrefix', async () => {
    const $ = await next.render$('/')

    let bundles = []
    for (const script of $('script').toArray()) {
      const { src } = script.attribs
      if (
        src?.includes('https://example.vercel.sh/_next/static') ||
        src?.includes('https://example.vercel.sh/_next/sta

      }
    }

    expect(bundles.length).toBeGreaterThan(0)

    for (const src of bundles) {
      // Remove hostname to check if pathname is still used for serving the bundles
      const bundlePathWithoutHost = decodeURI(new URL(src).href)
      const

tic/immutable')
      ) {
        bundles.push(src)


ort { nextTestSetup } from 'e2e-utils'

describe('app-dir absolute assetPrefix', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    nextConfig: {
      assetPrefix: 'https://example.vercel.sh/custom-asset-prefix',
    },
  })

  it('bundles should return 200 on served assetPrefix', async () => {
    const $ = await next.render$('/')

    let bundles = []
    for (const script of $('script').toArray()) {
      const { src } = script.attribs
      if (
        src?.startsWith(
          'htt

    }

    expect(bundles.length).toBeGreaterThan(0)

    for (const src of bundles) {
      // Remove hostname to check if pathname is still used for serving the bundles
      const bundlePathWithoutHost = decodeURI(new URL(src).href)
      const { statu

ps://example.vercel.sh/custom-asset-prefix/_next/static'
        ) ||
        src?.startsWith(
          'https://example.vercel.sh/custom-asset-prefix/_next/static/immutable'
        )
      ) {
        bundles.push(src)
      }


r$(
      '/top-level?foo=foosearch',
      {},
      {
        headers: {
          fooheader: 'foo header value',
          cookie: 'foocookie=foo cookie value',
        },
      }
    )
    if (isNextDev) {
      // in dev we expect the entire page to be rendered at runtime
      expect($('#layout').text()).toBe('at runtime')
      expect($('#page').text()).toBe('at runtime')
    } else if (process.env.__NEXT_CACHE_COMPONENTS) {
      // in PPR we expect the shell to be rendered at build and the page to

 expect($('#layout').text()).toBe('at runtime')
      expect($('#page').text()).toBe('at runtime')
    }

    expect($('#headers .fooheader').text()).toBe('foo header value')
    expect($('#cookies .foocookie').text()).toBe('foo cookie value')
    expect($

be rendered at runtime
      expect($('#layout').text()).toBe('at buildtime')
      expect($('#page').text()).toBe('at runtime')
    } else {
      // in static generation we expect the entire page to be rendered at runtime


aders'
import { unstable_cache as cache } from 'next/cache'

const cookies = cache(() => nextCookies())

export default async function Page({ searchParams }) {
  return (

        This example uses `cookies()` but is configured with `dynamic = 'error'`
        which should cause the page to fail to build

cookies

        {(await cookies()).getAll().map((cookie) => {
          const key = cookie.name
          let value =

value = value.slice(0, 10) + '...'
          }
          return (

{key}

{value}

          )
        })}

cookie.value

          if (key === 'userCache') {


{ headers as nextHeaders } from 'next/headers'
import { unstable_cache as cache } from 'next/cache'

const headers = cache(() => nextHeaders())

export default async function Page() {
  return (

        This example uses `headers()` but is configured with `dynamic = 'error'`
        which should cause the page to fail to build

headers

        {Array.from(await headers())
          .entries()
          .map(([key, value

if (key === 'cookie') return null
            return (

{key}

{value}

            )
          })}

  )
}


} from 'next/headers'
import { connection } from 'next/server'

import { PageSentinel } from '../getSentinelValue'

export const dynamic = 'force-static'

export default async function Page({ searchParams }) {
  await connection()
  return (

      <PageSentinel />

        This example uses headers/cookies/connection/searchParams directly in a
        Page configured with `dynamic = 'force-static'`. This should cause the
        page to always statically render but without exposing

{key}

{value}

          )
        })}

cookies

        {(await cookies()).getAll().map((coo

dynamic data

headers

        {Array.from((await headers()).entries()).map(([key, value]) => {
          if (key === 'cookie') return null
          return (


use client'

import { PageSentinel } from '../getSentinelValue'

export default async function Page({ searchParams }) {
  return (

      <PageSentinel />

        This example uses headers/cookies/searchParams directly in a Page
        configured with `dynamic = 'force-dynamic'`. This should cause the page
        to always render dynamically regardless of dynamic APIs used

headers

This is a client Page so `h

searchParams

        {Object.entries(await searchParams).map(([key, value]) => {
          return (

{key}

{value}

          )

eaders()` is not available

cookies
{' '}

This is a client Page so `cookies()` is not available


} from 'next/headers'
import { connection } from 'next/server'

import { PageSentinel } from '../getSentinelValue'

export default async function Page({ searchParams }) {
  await connection()
  return (

      <PageSentinel />

        This example uses headers/cookies/searchParams directly. In static
        generation we'd expect this to bail out to dynamic. In PPR we expect
        this to partially render the root layout only

className={key}>{value}

          )
        })}

cookies

        {(await cookies()).getAll().map((cookie) => {
          const key = cookie.name
          let value = c

headers

        {Array.from((await headers()).entries()).map(([key, value]) => {
          if (key === 'cookie') return null
          return (

{key}

              <pre


} from 'next/headers'
import { connection } from 'next/server'

import { PageSentinel } from '../getSentinelValue'

export const dynamic = 'force-dynamic'

export default async function Page({ searchParams }) {
  await connection()
  return (

      <PageSentinel />

        This example uses headers/cookies/connection/searchParams directly in a
        Page configured with `dynamic = 'force-dynamic'`. This should cause the
        page to always render dynamically regardless of dyn

{key}

{value}

          )
        })}

cookies

        {(await cookies()).getAll().map((co

amic APIs used

headers

        {Array.from((await headers()).entries()).map(([key, value]) => {
          if (key === 'cookie') return null
          return (


tal-not-affect-parent', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should not affect parent display', async () => {
    const browser = await next.browser('/')
    const rect = await browser.eval(
      // https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
      `document.querySelector('#div2').getBoundingClientRect()`
    )
    // Since the <body> has `space-between`, if the shadow root takes up
    // the space, the x of #div2 will be 100 as is

not take up the space, as the total width of
    // the <body> is 300 and as is a space-between, the #div2 will be placed
    // at the end of the <body> and the x will be 200.

    // Before: <#div1 100> <#div2 100> <nextjs-portal 100>
    // After: <#div

 the width of #div1.
    // If the shadow root does


s } from 'child_process'
import { isNextDev, isNextStart, nextTestSetup } from 'e2e-utils'
import { findPort, killApp, retry } from 'next-test-utils'

describe('interception-routes-output-export', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    // Vercel deployment fails to build/deploy this fixture in CI; skip in deploy mode.
    skipDeployment: true,
  })

  it('should error when using interception routes with static export', async () => {
    if (isNextStart) {

   let stderr = ''
      let child: ChildProcess | undefined
      const port = await findPort()
      const exit = next.runCommand(['dev', '-p', String(port)], {
        onStderr(msg) {
          stderr += msg || ''
        },
        instance: (p) => {

     const { exitCode, cliOutput } = await next.build()
      expect(cliOutput).toContain(
        'Intercepting routes are not supported with static export.'
      )
      expect(exitCode).toBe(1)
    } else if (isNextDev) {


 { nextTestSetup } from 'e2e-utils'

describe('with-exported-function-config', () => {
  const { next, isNextStart } = nextTestSetup({
    files: __dirname,
  })

  it('should have correct values in function config manifest', async () => {
    if (isNextStart) {
      const functionsConfigManifest = JSON.parse(
        await next.readFile('.next/server/functions-config-manifest.json')
      )

      expect(functionsConfigManifest).toEqual({
        functions: {
          '/api/page-route': {
            max

   },
          '/app-route-edge': {
            maxDuration: 2,
          },
          '/app-ssr': {
            maxDuration: 3,
          },
          '/app-ssr-edge': {
            maxDuration: 4,
          },
          '/page': {
            maxDuratio

Duration: 1,
          },
          '/app-layout': {
            maxDuration: 1,
          },
          '/app-layout/inner': {
            maxDuration: 2,
          },
          '/app-route': {
            maxDuration: 1,


import { nextTestSetup } from 'e2e-utils'

describe('resuming-head-runtime-search-param', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should not show resumable slots error when using runtime search params', async () => {
    const browser = await next.browser('/?foo=bar&test=123')

    // Check that the page renders correctly
    await browser.waitForElementByCss('p')
    const text = await browser.elementByCss('p').text()
    expect(text).toContain('hello world')

    // Wa

le')

    // Check server logs for the specific error message
    expect(next.cliOutput).not.toContain(
      "Couldn't find all resumable slots by key/index during replaying. The tree doesn't match so React will fallback to client rendering."
    )
  })
}

it for dynamic content to load (it's rendered inside the first p element)
    await browser.waitForElementByCss('p p')
    const dynamicText = await browser.elementByCss('p p').text()
    expect(dynamicText).toContain('Dynamic Ho


lient'

import { useState } from 'react'
import { streamData } from './actions'

export default function Page() {
  const [chunks, setChunks] = useState<string[] | null>(null)
  const [isStreaming, setIsStreaming] = useState(false)

  const handleClick = async () => {
    setChunks(null)
    setIsStreaming(true)

    const stream = await streamData(window.location.origin)
    const reader = stream.getReader()
    const decoder = new TextDecoder()

    try {
      while (true) {
        const { done, value }

der.releaseLock()
      setIsStreaming(false)
    }
  }

  return (
    <div>
      <button disabled={isStreaming} onClick={handleClick} id="stream-button">
        {isStreaming ? 'Streaming...' : 'Start Stream'}
      </button>

      {chunks && (

 = await reader.read()
        if (done) {
          break
        }
        const chunk = decoder.decode(value, { stream: true })
        setChunks((prev) => (prev ? [...prev, chunk] : [chunk]))
      }
    } finally {
      rea


['--experimental-build-mode', 'compile'] })
    })
    afterEach(async () => {
      await next.stop()
    })
  } else {
    beforeAll(async () => {
      await next.start()
    })
  }

  let currentCliOutputIndex = 0
  beforeEach(() => {
    currentCliOutputIndex = next.cliOutput.length
  })

  function getCliOutputSinceMark(): string {
    if (next.cliOutput.length < currentCliOutputIndex) {
      currentCliOutputIndex = 0
    }
    return next.cliOutput.slice(currentCliOutputIndex)
  }

  const prerender

LIDATION_ERRORS_WAIT: Parameters<typeof waitForNoErrorToast>[1] = {
    waitInMs: 500,
  }

  async function expectNoDevValidationErrors(
    browser: Playwright,
    url: string
  ): Promise<void> {
    await waitForValidation(url, getCliOutputSinceMark)

 = async (pathname: string) => {
    const args = [
      '--experimental-build-mode',
      'generate',
      '--debug-build-paths',
      `app${pathname}/page.tsx`,
    ]
    return await next.build({ args })
  }

  const NO_VA


tion.

         \`cookies()\`, \`headers()\`, \`params\`, or \`searchParams\` accessed outside of \`<Suspense>\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.

         Ways to fix this:
           - Provide a placeholder with \`<Suspense fallback={...}>\` around the data access
           - If the runtime data is \`params\` and they're known, prerender them with \`generateStaticParams\`
           - Set \`export const instant = false\`

idation failed for route "/suspense-in-root/static/missing-suspense-around-runtime".
         To get a more detailed stack trace and pinpoint the issue, try one of the following:
           - Start the app in development mode by running \`next dev\`, then

to allow a blocking route

         Learn more: https://nextjs.org/docs/messages/blocking-route
             at body (<anonymous>)
             at html (<anonymous>)
             at a (<anonymous>)
         Build-time instant val


uspense } from 'react'

export default async function Layout({
  children,
  params,
}: {
  children: React.ReactNode
  params: Promise<{
    layoutPaddingWidth: string
    layoutPaddingHeight: string
    pageWidth: string
    pageHeight: string
  }>
}) {
  const { layoutPaddingHeight, layoutPaddingWidth, pageWidth, pageHeight } =
    await params
  return (
    <div
      style={{
        height: Number(pageHeight),
        width: Number(pageWidth),
        paddingTop: Number(layoutPaddingHeight),

paddingLeft: Number(layoutPaddingWidth),
        paddingRight: Number(layoutPaddingWidth),
        background: 'pink',
        display: 'flex',
      }}
    >
      <Suspense fallback={
loading...
}>
        {children}
      </Suspens


describe('actions-unused-args', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    // No access to runtime logs when deployed.
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should not call server actions with unused arguments', async () => {
    const browser = await next.browser('/')
    const cliOutputLength = next.cliOutput.length
    await browser.elementById('action-button').click()

    await retry(async () => {
      const actionLog = next.cliOutp

n')
        .find((line) => line.includes('Action called'))

      // We expect only 1 argument because the click event from the onClick
      // handler should be omitted as an unused argument.
      expect(actionLog).toBe('Action called with value: 42 (t

ut
        .slice(cliOutputLength)
        .split('\


iousLogs = () => {
    currentCliOutputIndex = next.cliOutput.length
  }

  const getLogs = () => {
    return next.cliOutput.slice(currentCliOutputIndex)
  }

  beforeEach(() => {
    ignorePreviousLogs()
  })

  let buildLogs: string
  beforeAll(async () => {
    if (!isNextDev) {
      await next.build()
      buildLogs = next.cliOutput
    } else {
      buildLogs = '(no build logs in dev)'
    }
    await next.start()
  })

  describe('request APIs inside after()', () => {
    // TODO(after): test unaw

'cannot be called in a dynamic page', async () => {
      const path = '/request-apis/page-dynamic'
      await next.render(path)
      await retry(() => {
        const logs = getLogs()

        expect(logs).not.toContain(`[${path}] headers(): ok`)

aited calls, like this
    //
    // export default function Page() {
    //   const promise = headers()
    //   after(async () => {
    //     const headerStore = await promise
    //   })
    //   return null
    // }

    it(


kies, headers } from 'next/headers'
import { after, connection } from 'next/server'

export function testRequestAPIs(/** @type {string} */ route) {
  after(async () => {
    try {
      await headers()
      console.log(`[${route}] headers(): ok`)
    } catch (err) {
      console.error(`[${route}] headers(): error:`, err)
    }
  })

  after(() =>
    after(async () => {
      try {
        await headers()
        console.log(`[${route}] nested headers(): ok`)
      } catch (err) {
        console.error(`[

r:`, err)
    }
  })

  after(() =>
    after(async () => {
      try {
        await cookies()
        console.log(`[${route}] nested cookies(): ok`)
      } catch (err) {
        console.error(`[${route}] nested cookies(): error:`, err)
      }
    })

${route}] nested headers(): error:`, err)
      }
    })
  )

  after(async () => {
    try {
      await cookies()
      console.log(`[${route}] cookies(): ok`)
    } catch (err) {
      console.error(`[${route}] cookies(): erro


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

  it('should match default and dynamic segment paths before catch-all', async () => {
    let browser = await next.browser('/en/nested')

    // we have a top-level catch-all but the /nested dir doesn't have a default/page until the /[foo]/[bar] segment
    // so we expect the top-level catch-all to render
    expect(await browser.elementById('children').text()).toBe(
      '/[locale]/[[...catchAll]]/page.tsx'
    )

    browser = await next.b

   '/[locale]/nested/[foo]/[bar]/default.tsx'
    )

    // we expect the slot0 to match since there's a page defined at this segment
    expect(await browser.elementById('slot0').text()).toBe(
      '/[locale]/nested/[foo]/[bar]/@slot0/page.tsx'
    )

rowser('/en/nested/foo/bar')

    // we're now at the /[foo]/[bar] segment, so we expect the matched page to be the default (since there's no page defined)
    expect(await browser.elementById('nested-children').text()).toBe(


 { NextResponse } from 'next/server'

export async function middleware(request) {
  if (
    request.nextUrl.pathname.includes('payment') &&
    !request.nextUrl.pathname.includes('whoops')
  ) {
    if (request.nextUrl.searchParams.has('redirect')) {
      return NextResponse.redirect(new URL('/payment/whoops', request.url))
    }
    return NextResponse.rewrite(new URL('/payment/whoops', request.url))
  }
  if (
    request.nextUrl.pathname.includes('anotherRoute') &&
    !request.nextUrl.pathname.include

est.url))
  }
}

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.i

s('whoops')
  ) {
    if (request.nextUrl.searchParams.has('redirect')) {
      return NextResponse.redirect(new URL('/anotherRoute/whoops', request.url))
    }
    return NextResponse.rewrite(new URL('/anotherRoute/whoops', requ


v jest */
import { nextTestSetup } from 'e2e-utils'
import {
  waitForRedbox,
  getRedboxDescription,
} from '../../../../lib/next-test-utils'

describe('after() in generateStaticParams - thrown errors', () => {
  const { next, skipped, isNextDev } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true, // can't access build errors in deploy tests
  })

  if (skipped) return

  if (isNextDev) {
    it('shows the error overlay if an error is thrown inside after', async () => {

y cool error thrown inside after on route "${route}"`
      )
    })
  } else {
    it('fails the build if an error is thrown inside after', async () => {
      const buildResult = await next.build()
      expect(buildResult?.exitCode).toBe(1)

      const

      await next.start()
      const browser = await next.browser('/callback/1')
      await waitForRedbox(browser)
      const route = '/callback/[myParam]'
      expect(await getRedboxDescription(browser)).toContain(
        `M


etup } from 'e2e-utils'
import * as Log from './utils/log'
import { setTimeout } from 'timers/promises'

// This test relies on next.build() so it can't work in dev mode.
const _describe = isNextDev ? describe.skip : describe

_describe('after() in static pages', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true, // reading CLI logs to observe after
    skipStart: true,
  })

  if (skipped) return

  let currentCliOutputIndex = 0
  beforeEach(() => {
    curr

s
      currentCliOutputIndex = 0
    }
    return next.cliOutput.slice(currentCliOutputIndex)
  }

  const resetLogs = () => {
    currentCliOutputIndex = next.cliOutput.length
  }

  it('runs after during build', async () => {
    const buildResult = awa

entCliOutputIndex = next.cliOutput.length
  })

  const getLogs = () => {
    if (next.cliOutput.length < currentCliOutputIndex) {
      // cliOutput shrank since we started the test, so something (like a `sandbox`) reset the log


('TypeScript type expressions in route segment config', () => {
  const { next, isNextStart } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  describe('app directory', () => {
    it('should pick up maxDuration declared with `as` type assertion', async () => {
      const $ = await next.render$('/as')
      expect($('main').text()).toBe('hello')
    })

    it('should pick up maxDuration declared with `as const` assertion', async () => {
      const $ = await next.render$('/as-cons

   })
  })

  describe('pages directory', () => {
    it('should pick up maxDuration from config object declared with `as`', async () => {
      const $ = await next.render$('/config-as')
      expect($('main').text()).toBe('hello')
    })

    it('should

t')
      expect($('main').text()).toBe('hello')
    })

    it('should pick up maxDuration declared with `satisfies`', async () => {
      const $ = await next.render$('/satisfies')
      expect($('main').text()).toBe('hello')


tTestSetup } from 'e2e-utils'

// CSS data urls are only support in Turbopack
;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)(
  'css-modules-data-urls',
  () => {
    const { next } = nextTestSetup({
      files: __dirname,
    })

    it('should apply rsc class name from data url correctly', async () => {
      const browser = await next.browser('/')

      const clientElementClass =
        (await browser.elementByCss('#client').getAttribute('class')) || ''

      expect(clientElementClass).n

ss('font-weight')

      expect(rscElement).toBe('700')
    })

    it('should apply client class name from data url correctly', async () => {
      const browser = await next.browser('/')

      const clientElementClass =
        (await browser.elementByC

ot.toBe('')
    })

    it('should apply rsc styles from data url correctly', async () => {
      const browser = await next.browser('/')

      const rscElement = await browser
        .elementByCss('#rsc')
        .getComputedC


check } from 'next-test-utils'

describe('interception-middleware-rewrite', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    // TODO: remove after deployment handling is updated
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should support intercepting routes with a middleware rewrite', async () => {
    const browser = await next.browser('/')

    await check(() => browser.elementByCss('#children').text(), 'root')

    await check(
      () =>
        br

     'not intercepted'
    )

    await check(() => browser.elementByCss('#modal').text(), 'default')
  })

  it('should continue to work after using browser back button and following another intercepting route', async () => {
    const browser = await nex

owser
          .elementByCss('[href="/feed"]')
          .click()
          .elementByCss('#modal')
          .text(),
      'intercepted'
    )

    await check(
      () => browser.refresh().elementByCss('#children').text(),


import { nextTestSetup } from 'e2e-utils'

describe('next-image-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', async () => {
    if (isNextDev) {
      await next.start()
      await next.browser('/')
      expect(next.cliOutput).toContain(
        'Image with src "/te

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-localpatterns'
      )
    }

st.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 { cliOutput } = await next.


/lib/next-test-utils'
import { createRedboxSnapshot } from '../../../lib/add-redbox-matchers'

describe('instant validation - server errors', () => {
  const { next, skipped, isNextDev, isNextStart, isTurbopack } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
    env: {
      NEXT_TEST_LOG_VALIDATION: '1',
    },
  })
  if (skipped) return

  if (isNextStart && !isTurbopack) {
    it.skip('TODO: snapshot tests for webpack', () => {})
    return
  }

  if (isNextStart)

tart()
    })
  }

  let currentCliOutputIndex = 0
  beforeEach(() => {
    currentCliOutputIndex = next.cliOutput.length
  })

  function getCliOutputSinceMark(): string {
    if (next.cliOutput.length < currentCliOutputIndex) {
      currentCliOutputInde

 {
    beforeAll(async () => {
      await next.build({ args: ['--experimental-build-mode', 'compile'] })
    })
    afterEach(async () => {
      await next.stop()
    })
  } else {
    beforeAll(async () => {
      await next.s


       // Should inject global css for .green selectors
        await check(
          async () =>
            await browser.eval(
              `window.getComputedStyle(document.querySelector('.green')).color`
            ),
          'rgb(0, 128, 0)'
        )
      })

      it('should support css modules inside server layouts', async () => {
        const browser = await next.browser('/css/css-nested')
        await check(
          async () =>
            await browser.eval(
              `window.getCo

ss/css-external')
        await check(
          async () =>
            await browser.eval(
              `window.getComputedStyle(document.querySelector('main')).paddingTop`
            ),
          '80px'
        )
      })
    })

    describe('server

mputedStyle(document.querySelector('#server-cssm')).color`
            ),
          'rgb(0, 128, 0)'
        )
      })

      it('should support external css imports', async () => {
        const browser = await next.browser('/c


from 'e2e-utils'

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

  describe('multi-param catch-all', () => {
    it('should intercept when navigating to the same path with route interception', async () => {
      const browser = await next.browser('/templates/multi/slug')
      await browser.elementByCss("[href='/showcase/multi/slug']").click()
      await browser.waitForElementByCss('#intercepting-page')
    })

    it('should interc

ByCss('#intercepting-page')
    })

    it('should intercept when navigating to a multi-param path', async () => {
      const browser = await next.browser('/templates/multi/slug')
      await browser.elementByCss("[href='/showcase/another/slug']").click()

ept when navigating to a single param path', async () => {
      const browser = await next.browser('/templates/multi/slug')
      await browser.elementByCss("[href='/showcase/single']").click()
      await browser.waitForElement


ort { isNextDev, nextTestSetup } from 'e2e-utils'

// This test relies on next.build() so it can't work in dev mode.
const _describe = isNextDev ? describe.skip : describe

_describe('after() in static pages - thrown errors', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true, // can't access build errors in deploy tests
  })

  if (skipped) return

  it('fails the build if an error is thrown inside after', async () => {
    const buildRes

    expect(next.cliOutput).toContain(
        `My cool error thrown inside after on route "${path}"`
      )
    }

    {
      const path = '/page-throws-in-after/promise'
      expect(next.cliOutput).toContain(
        `Error occurred prerendering page "

ult = await next.build()
    expect(buildResult?.exitCode).toBe(1)

    {
      const path = '/page-throws-in-after/callback'
      expect(next.cliOutput).toContain(
        `Error occurred prerendering page "${path}"`
      )


tTestSetup } from 'e2e-utils'

// TODO(NAR-423): Migrate to Cache Components.
describe.skip('ppr build errors', () => {
  ;(isNextStart ? describe : describe.skip)('production only', () => {
    const { next } = nextTestSetup({
      files: __dirname,
      skipStart: true,
    })

    let cliOutput: string

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

    describe('within a suspense boundary', () => {
      it('should fail the build for unca

prerendering page "/re-throwing-error".'
        )
      })
    })

    describe('outside of a suspense boundary', () => {
      it('should fail the build for uncaught errors', async () => {
        expect(cliOutput).toContain(
          'Error occurred pr

ught prerender errors', async () => {
        expect(cliOutput).toContain(
          'Error occurred prerendering page "/regular-error-suspense-boundary".'
        )
        expect(cliOutput).toContain(
          'Error occurred


estSetup } from 'e2e-utils'

describe('Undefined default export', () => {
  const { next, isNextDev } = nextTestSetup({
    files: path.join(__dirname),
    skipStart: isNextStart,
    skipDeployment: true,
  })

  if (isNextDev) {
    it('should error if page component does not have default export', async () => {
      const browser = await next.browser('/specific-path/1')

      await expect(browser).toDisplayRedbox(`
       {
         "code": "E45",
         "description": "The default export is not a Re

es not have default export', async () => {
      const browser = await next.browser('/specific-path/2')

      await expect(browser).toDisplayRedbox(`
       {
         "code": "E45",
         "description": "The default export is not a React Component in

act Component in "/specific-path/1/page"",
         "environmentLabel": null,
         "label": "Runtime Error",
         "source": null,
         "stack": [],
       }
      `)
    })

    it('should error if layout component do


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

describe('css-modules-pure-no-check', () => {
  const { isNextStart, next } = nextTestSetup({
    files: __dirname,
  })

  it('should apply styles correctly', async () => {
    const browser = await next.browser('/')

    const elementWithGlobalStyles = await browser
      .elementByCss('#my-div')
      .getComputedCss('font-weight')

    expect(elementWithGlobalStyles).toBe('700')
  })

  if (isNextStart) {
    it('should have emitte

nk[0].attribs['href']

      const res = await next.fetch(cssHref)
      const cssCode = await res.text()

      expect(cssCode).toInclude(`.global{font-weight:700}`)
      expect(cssCode).toInclude(
        `::view-transition-old(root){animation-duration:

d a CSS file', async () => {
      const html = await next.render('/')
      const $html = cheerio.load(html)

      const cssLink = $html('link[rel="stylesheet"]')
      expect(cssLink.length).toBe(1)
      const cssHref = cssLi


mport { nextTestSetup } from 'e2e-utils'

describe('Root Suspense Dynamic Rendering', () => {
  const { next, isNextStart } = nextTestSetup({
    files: __dirname + '/fixtures/default',
    skipDeployment: true,
  })

  // TODO: remove when there is a test for isNextDev === false
  it('placeholder to satisfy at least one test when isNextDev is false', async () => {
    expect(true).toBe(true)
  })

  if (isNextStart) {
    it('should handle dynamic content wrapped in Suspense above HTML structure', async ()

cted build to succeed for Suspense wrapping dynamic content above HTML',
          { cause: error }
        )
      }
    })

    it('should correctly mark route as dynamic', async () => {
      // The route should be marked as dynamic (ƒ) not static (○)

 => {
      try {
        // Should render the page successfully
        const $ = await next.render$('/')
        expect($('body').text()).toContain('Hello World')
      } catch (error) {
        throw new Error(
          'Expe


from 'e2e-utils'

describe('app-dir - middleware rewrite with catch-all and parallel routes', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  describe('payment route', () => {
    it('should rewrite to the specific page instead of the catch-all with parallel route', async () => {
      const browser = await next.browser('/payment/test')
      const text = await browser.elementByCss('#specific-page').text()

      expect(text).toBe('payment whoops')
      expect(await browser.url()).

t text = await browser.elementByCss('#specific-page').text()

      expect(text).toBe('payment whoops')
      expect(await browser.url()).toBe(next.url + '/payment/whoops')
    })
  })

  describe('anotherRoute', () => {
    it('should rewrite to the speci

toBe(next.url + '/payment/test')
    })

    it('should redirect to the specific page instead of the catch-all with parallel route', async () => {
      const browser = await next.browser('/payment/test?redirect=true')
      cons


 'e2e-utils'
import * as Log from './utils/log'
import { waitForNoRedbox, retry } from '../../../../lib/next-test-utils'

describe('after() in generateStaticParams', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true, // reading CLI logs to observe after
    skipStart: true,
  })

  if (skipped) return

  let currentCliOutputIndex = 0
  beforeEach(() => {
    currentCliOutputIndex = next.cliOutput.length
  })

  const getLogs = () => {
    if (next.

tIndex)
  }

  if (isNextDev) {
    it('runs after callbacks when visiting a page in dev', async () => {
      await next.start()
      const browser = await next.browser('/one/a')

      expect(await browser.elementByCss('body').text()).toBe('Param: a')

cliOutput.length < currentCliOutputIndex) {
      // cliOutput shrank since we started the test, so something (like a `sandbox`) reset the logs
      currentCliOutputIndex = 0
    }
    return next.cliOutput.slice(currentCliOutpu


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

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

  describe('actions returning a ReadableStream', () => {
    it('should properly stream the response without buffering', async () => {
      const browser = await next.browser('/readable-stream')
      await browser.elementById('stream-button').click()

      expect(await browser.elementById('stream-button').text()).toBe(

ect(await browser.elementById('chunks').text()).toInclude(
        'Lorem ipsum dolor sit'
      )

      // Finally, wait for the response to finish streaming.
      await waitFor(5000)
      await retry(
        async () => {
          expect(await brows

 'Streaming...'
      )

      // If we're streaming properly, we should see the first chunks arrive
      // quickly.
      expect(await browser.elementByCss('h3').text()).toMatch(
        /Received \d+ chunks/
      )
      exp


import { Suspense } from 'react'
import { connection } from 'next/server'
import { HydrationIndicator } from '../../hydration-indicator'
import waitForMarkerFile from '../../../waitForMarkerFile'

export default async function Page() {
  // Trigger the Suspense-around-body in the root layout so that no static shell is produced
  await connection()

  return (

This is a page with no static shell + no streaming metadata

Dynamic shell

        <Hyd

SlowServerComponent() {
  await connection()
  await waitForMarkerFile()
  const randomValue = Math.floor(Math.random() * 1000)
  return (

{`Random value: ${randomValue}`}

      <HydrationIndicator id="dynamic-hydrat

rationIndicator id="shell-hydrated" />

        <Suspense fallback={
Loading...
}>
          <SlowServerComponent />
        </Suspense>

  )
}

async function


 { Suspense } from 'react'
import { connection } from 'next/server'
import { HydrationIndicator } from '../../hydration-indicator'
import waitForMarkerFile from '../../../waitForMarkerFile'
import type { Metadata } from 'next'

export async function generateMetadata(): Promise<Metadata> {
  await connection()
  return {
    title: 'Resume test',
  }
}

export default async function Page() {
  // Trigger the Suspense-around-body in the root layout so that no static shell is produced
  await connection()

  r

se fallback={
Loading...
}>
          <SlowServerComponent />
        </Suspense>

  )
}

async function SlowServerComponent() {
  await connection()
  await waitForMarkerFile()
  const randomValue = M

eturn (

This is a page with no static shell + with streaming metadata

Dynamic shell

        <HydrationIndicator id="shell-hydrated" />

        <Suspen


configuration is NOT realistic — it's set up to exercise the clamp
 * logic in both dev and build. In practice, users might tune
 * `experimental.useCacheTimeout` up (e.g. for slower dev-time backends) or
 * down (e.g. for faster feedback while iterating); what's unusual here is
 * the very low `staticPageGenerationTimeout`.
 *
 * Setup:
 *   - `staticPageGenerationTimeout: 10` → build-time clamp = 9s, with a
 *     1s buffer before the build worker kills the page at 10s.
 *   - Dev `useCacheTimeout: 15` →

eeps 17s (above 15s).
 *
 * This way:
 *   - Dev `/below-dev-timeout` succeeds (proves no clamp; if we clamped, it
 *     would time out at 9s < 11s).
 *   - Dev `/above-dev-timeout` times out at 15s (proves the configured dev
 *     value is actually appl

would be clamped to 9s if we clamped in
 *     dev. We don't, so the raw 15s applies.
 *   - Build `useCacheTimeout: 60` → clamped to 9s.
 *   - `/below-dev-timeout` sleeps 11s (between 9s and 15s).
 *   - `/above-dev-timeout` sl


ripAnsi from 'strip-ansi'

const expectedTimeoutErrorMessage =
  'Filling a cache during prerender timed out, likely because request-specific arguments such as params, searchParams, cookies() or dynamic data were used inside "use cache".'

describe('use-cache-configured-timeout', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
    skipStart: process.env.NEXT_TEST_MODE !== 'dev',
  })

  if (skipped) {
    return
  }

  if (isNextDev) {
    descr

h
        const browser = await next.browser('/below-dev-timeout')

        await expect(browser.elementByCss('#result').text()).resolves.toBe(
          'cached'
        )

        const cliOutput = stripAnsi(next.cliOutput.slice(outputIndex))

        ex

ibe('when a "use cache" fill is below the configured dev `useCacheTimeout`', () => {
      it('should not clamp the dev timeout and allow the cache fill to complete', async () => {
        const outputIndex = next.cliOutput.lengt


: any) {
  let result = ''
  onData = onData || (() => {})

  for await (const chunk of response.body) {
    result += chunk.toString()
    onData(chunk.toString(), result)
  }
  return result
}

describe('use-server-inserted-html', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    dependencies: {
      // TODO: Temporarily pinned due to https://github.com/styled-components/styled-components/issues/5667
      // which is breaking deployment tests
      'styled-components': '6.3.9',

x

    expect(head).toMatch(/{color:(\s*)purple;?}/) // styled-jsx/style
    expect(head).toMatch(/{color:(\s*)(?:hotpink|#ff69b4);?}/) // styled-jsx/css

    // from styled-components
    expect(head).toMatch(/{color:(\s*)(?:blue|#00f);?}/)
  })

  it('sh

'server-only': 'latest',
    },
  })

  it('should render initial styles of css-in-js in nodejs SSR correctly', async () => {
    const $ = await next.render$('/css-in-js')
    const head = $('head').html()

    // from styled-js


import React from 'react'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
import { useServerInsertedHTML } from 'next/navigation'
import { useState } from 'react'

export default function RootStyleRegistry({ children }) {
  const [jsxStyleRegistry] = useState(() => createStyleRegistry())
  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
  const styledJsxFlushEffect = () => {
    const styles

nstance.clearTag()
    return <>{styles}</>
  }

  // Allow multiple useServerInsertedHTML
  useServerInsertedHTML(() => {
    return <>{styledJsxFlushEffect()}</>
  })

  useServerInsertedHTML(() => {
    return <>{styledComponentsFlushEffect()}</>
  })

 = jsxStyleRegistry.styles()
    jsxStyleRegistry.flush()
    return <>{styles}</>
  }
  const styledComponentsFlushEffect = () => {
    const styles = styledComponentsStyleSheet.getStyleElement()
    styledComponentsStyleSheet.i


import { Suspense } from 'react'
import styled from 'styled-components'

export function createDataFetcher(data, { timeout = 0, expire = 10 }) {
  let result
  let promise
  return function Data() {
    if (result) return result
    if (!promise)
      promise = new Promise((resolve) => {
        setTimeout(() => {
          result = data
          setTimeout(() => {
            result = undefined
            promise = undefined
          }, expire)
          resolve()
        }, timeout)
      })
    thr

pire: 4000,
})

function SuspenseyFooter() {
  readData()
  // generate large chunk of text to let the suspensey styling be inserted before the suspense script
  return (
    <FootInner id="footer-inner">
      {'(generate-large-footer-text)'.repeat(30)}

ow promise
  }
}

const Footer = styled.div`
  border: 1px solid orange;
  color: blue;
`

const FootInner = styled.span`
  padding: 2px;
  color: orange;
`

const readData = createDataFetcher('streaming', {
  timeout: 4000,
  ex


t } from 'next/server'

// We use this in combination with fallback rewrites to redirect all /:teamSlug URLs to /app-future/[locale]/:teamSlug
// in order to avoid having to grab all existing pages at build and checking the path in middleware
export async function GET(
  request: NextRequest,
  {
    params,
  }: {
    params: Promise<{
      path: string
    }>
  }
): Promise<Response> {
  request.nextUrl.pathname = `/app-future/en/${(await params).path}`
  return fetch(request.nextUrl, {
    headers: new

  cookie: request.headers.get('cookie') ?? '',
    }),
  }).then(async (res) => {
    const resHeaders = new Headers(res.headers)
    resHeaders.delete('content-encoding')
    return new Response(res.body, { status: res.status, headers: resHeaders })
  })


tDev } from 'e2e-utils'
import { waitForRedbox, getRedboxSource, retry } from 'next-test-utils'
import * as Log from './utils/log'

// using after is a compile-time error in build mode.
const _describe = isNextDev ? describe : describe.skip

_describe('after() - pages', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  let currentCliOutputIndex = 0
  beforeEach(() => {
    currentCliOutputIndex = next.cliOutput.length
  })

  const getLogs = () => {
    return Log.readCliLogs(next.cli

  redirect: 'follow',
        headers: {
          cookie: 'testCookie=testValue',
        },
      }
    )

    expect(res.status).toBe(200)
    await retry(() => {
      expect(getLogs()).toContainEqual({
        source: '[middleware] /middleware/redirec

Output.slice(currentCliOutputIndex))
  }

  it('runs in middleware', async () => {
    const requestId = `${Date.now()}`
    const res = await next.fetch(
      `/middleware/redirect-source?requestId=${requestId}`,
      {


getRedboxSource } from 'next-test-utils'

describe('CSS Import from node_modules', () => {
  const { next, skipped, isTurbopack, isRspack } = nextTestSetup({
    files: __dirname,
    skipStart: isNextStart,
    skipDeployment: true,
    dependencies: { sass: '1.54.0' },
  })

  if (skipped) {
    return
  }

  if (isNextStart) {
    it('should fail the build', async () => {
      const { exitCode, cliOutput } = await next.build()
      expect(exitCode).not.toBe(0)
      if (isRspack) {
        expect(cliOu

(/Build failed|Build error occurred/)
    })
  } else {
    it('should show a build error', async () => {
      const browser = await next.browser('/')

      await waitForRedbox(browser)
      const errorSource = await getRedboxSource(browser)

      if (

tput).toMatch(
          /RspackResolver\(NotFound\(\\?"nprogress\/nprogress.css\\?"\)\)/
        )
      } else {
        expect(cliOutput).toMatch(/Can't resolve '[^']*?nprogress[^']*?'/)
      }
      expect(cliOutput).toMatch


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

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'Nested @import() Global Support ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirname,
      dependencies,
      nextConfig,
    })

const browser = await next.browser('/')
      expect(
        await browser.elementByCss('.red-text').getComputedCss('color')
      ).toBe(colorToRgb('red'))
      expect(
        await browser.elementByCss('.blue-text').getComputedCss('color')
      ).toB

it('should render the page', async () => {


v jest */

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

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  '3rd Party CSS Module Support ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirname,
      dependencies,
      n

Css('background-color')
      ).toBe(colorToRgb('blue'))

      // Baz
      expect(
        await browser
          .elementByCss('#verify-div .baz')
          .getComputedCss('background-color')
      ).toBe(colorToRgb('blue'))

      // Lol
      expect

extConfig,
    })

    it('should render the module', async () => {
      const browser = await next.browser('/')
      // Bar
      expect(
        await browser
          .elementByCss('#verify-div .bar')
          .getComputed


v jest */

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

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'SCSS Support loader handling Preprocessor loader order ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirname,

ies,
      nextConfig,
    })
    it('should render the module', async () => {
      const browser = await next.browser('/')
      expect(
        await browser.elementByCss('.red-text').getComputedCss('color')
      ).toBe(colorToRgb('red'))
    })
  }
)


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

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'SCSS Support loader handling Data Urls ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirname,
      dependencies,
      nextConfig,

 {
      const browser = await next.browser('/')
      const redText = await browser.elementByCss('.red-text')
      expect(await redText.getComputedCss('color')).toBe(colorToRgb('red'))
      expect(await redText.getComputedCss('background-image')).toMatc

  })

    it('should render the module', async () =>


* eslint-env jest */

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

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'Ordering with styled-jsx ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirname,
      dependencies,

ig,
    })

    it('should have the correct color (css ordering)', async () => {
      const browser = await next.browser('/')
      expect(
        await browser.elementByCss('.my-text').getComputedCss('color')
      ).toBe(colorToRgb('green'))
    })
  }


port { nextTestSetup } from 'e2e-utils'
import { colorToRgb, getUrlFromBackgroundImage } from 'next-test-utils'

// TODO: Skipped as this test should set up the server to handle assetPrefix which it currently does not do.
describe.skip('SCSS Support loader handling', () => {
  describe.each([
    { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
    {
      dependencies: { 'sass-embedded': '1.75.0' },
      nextConfig: {
        sassOptions: {
          implementation: 'sass-embedded',
        },

extConfig,
      })

      it('should render the page', async () => {
        const browser = await next.browser('/')
        expect(
          await browser.elementByCss('.red-text').getComputedCss('color')
        ).toBe(colorToRgb('red'))

        const

      },
    },
  ])(
    'CSS URL via `file-loader` and asset prefix (2) ($dependencies)',
    ({ dependencies, nextConfig }) => {
      const { next } = nextTestSetup({
        files: __dirname,
        dependencies,
        n


port { nextTestSetup } from 'e2e-utils'

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])('unused scss', ({ dependencies, nextConfig }) => {
  describe('Body is not hidden when unused in Development ($dependencies)', () => {
    const { next, isNextDev } = nextTestSetup({
      files: __dirname,
      dependencies,
      ne

wser.eval(
          `window.getComputedStyle(document.querySelector('body')).display`
        )
        expect(currentDisplay).toBe('block')
      })
    })
  })

  describe('Body is not hidden when broken in Development', () => {
    const { next, isNext

xtConfig,
    })

    ;(isNextDev ? describe : describe.skip)('development only', () => {
      it('should have body visible', async () => {
        const browser = await next.browser('/')
        const currentDisplay = await bro


nv jest */

import { nextTestSetup } from 'e2e-utils'

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'Good CSS Import from node_modules ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirname,
      dependencies: {
        ...dependencies,
        nprogress:

should render the page', async () => {
      const browser = await next.browser('/')
      expect(
        await browser
          .elementByCss('#nprogress .bar')
          .getComputedCss('background-color')
      ).toBe('rgb(34, 153, 221)')
    })
  }
)


/* eslint-env jest */

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

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'Valid CSS Module Usage from within node_modules ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirna

ndencies,
      nextConfig,
    })

    it('should render the page', async () => {
      const browser = await next.browser('/')
      expect(
        await browser.elementByCss('#nm-div').getComputedCss('color')
      ).toBe(colorToRgb('red'))
    })
  }


ext-test-utils'

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'CSS Module Composes Usage (Basic) ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirname,
      dependencies,
      nextConfig,
    })

    it('should render the module', async () => {
      con

       await browser.elementByCss('#verify-yellow').getComputedCss('color')
      ).toBe(colorToRgb('yellow'))
      expect(
        await browser
          .elementByCss('#verify-yellow')
          .getComputedCss('background-color')
      ).toBe(colorToR

st browser = await next.browser('/')
      expect(


int-env jest */

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

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'Valid Nested CSS Module Usage from within node_modules ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirn

     ).toBe(colorToRgb('red'))
      expect(
        await browser.elementByCss('#other3').getComputedCss('color')
      ).toBe(colorToRgb('black'))
      expect(
        await browser.elementByCss('#subclass').getComputedCss('color')
      ).toBe(colorToR

ame,
      dependencies,
      nextConfig,
    })

    it('should render the page', async () => {
      const browser = await next.browser('/')
      expect(
        await browser.elementByCss('#other2').getComputedCss('color')


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

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'Good Nested CSS Import from node_modules ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } = nextTestSetup({
      files: __dirname,
      dependencies,
      nextConfig,

 {
      const browser = await next.browser('/')
      expect(
        await browser.elementByCss('.red-text').getComputedCss('color')
      ).toBe(colorToRgb('red'))
      expect(
        await browser.elementByCss('.blue-text').getComputedCss('color')

    })

    it('should render the page', async () =>


v jest */

import { nextTestSetup } from 'e2e-utils'
import { colorToRgb, getUrlFromBackgroundImage } from 'next-test-utils'

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'SCSS Support loader handling ($dependencies)',
  ({ dependencies, nextConfig }) => {
    describe('CSS URL via `file-loader`', () => {
      const

await browser.elementByCss('.red-text').getComputedCss('color')
        ).toBe(colorToRgb('red'))

        const background = await browser
          .elementByCss('.red-text')
          .getComputedCss('background-image')
        expect(background).toMatc

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

      it('should render the page', async () => {
        const browser = await next.browser('/')
        expect(


port { isNextStart, nextTestSetup } from 'e2e-utils'
import { waitForRedbox, getRedboxSource } from 'next-test-utils'

// Importing module CSS in _document is allowed in Turbopack
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
  'Invalid SCSS in _document',
  () => {
    const { next, skipped, isRspack } = nextTestSetup({
      files: __dirname,
      skipStart: isNextStart,
      skipDeployment: true,
      dependencies: { sass: '1.54.0' },
    })

    if (skipped) {
      return
    }

    i

ect(cliOutput).toContain('styles.module.scss')
        expect(cliOutput).toMatch(
          /CSS.*cannot.*be imported within.*pages[\\/]_document\.js/
        )
        // Skip: Rspack loaders cannot access module issuer info for location details
        i

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


Invalid CSS Global Module Usage in node_modules', () => {
  ;(isNextStart ? describe : describe.skip)('production only', () => {
    const { next } = nextTestSetup({
      files: __dirname,
      skipStart: true,
    })

    it('should fail to build', async () => {
      const { exitCode, cliOutput } = await next.build()
      expect(exitCode).not.toBe(0)
      expect(cliOutput).toContain('Failed to compile')
      expect(cliOutput).toContain('node_modules/example/index.scss')
      expect(cliOutput).toMatc

hin.*node_modules/
      )
      // Skip: Rspack loaders cannot access module issuer info for location details
      if (!process.env.NEXT_RSPACK) {
        expect(cliOutput).toMatch(
          /Location:.*node_modules[\\/]example[\\/]index\.mjs/
        )

h(
        /Global CSS.*cannot.*be imported from wit


stSetup } from 'e2e-utils'
import { waitForRedbox, getRedboxSource } from 'next-test-utils'

describe('Invalid Global CSS', () => {
  const { next, skipped, isTurbopack, isRspack } = nextTestSetup({
    files: __dirname,
    skipStart: isNextStart,
    skipDeployment: true,
    dependencies: { sass: '1.54.0' },
  })

  if (skipped) {
    return
  }

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

orts.*?pages(\/|\\)_app/
      )
      // Skip: Rspack loaders cannot access module issuer info for location details
      if (!process.env.NEXT_RSPACK) {
        expect(cliOutput).toMatch(/Location:.*pages[\\/]index\.js/)
      }
    })
  } else {
    it(

    if (!isTurbopack) {
        expect(cliOutput).toContain('Failed to compile')
      }
      expect(cliOutput).toContain('styles/global.scss')
      expect(cliOutput).toMatch(
        /Please move all first-party global CSS imp


v jest */

import { nextTestSetup } from 'e2e-utils'
import { colorToRgb, getUrlFromBackgroundImage } from 'next-test-utils'

describe('SCSS Support loader handling', () => {
  describe.each([
    { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
    {
      dependencies: { 'sass-embedded': '1.75.0' },
      nextConfig: {
        sassOptions: {
          implementation: 'sass-embedded',
        },
      },
    },
  ])(
    'CSS URL via file-loader sass partial ($dependencies)',
    ({ dependencie

r('/')
        expect(
          await browser.elementByCss('.red-text').getComputedCss('color')
        ).toBe(colorToRgb('red'))

        const background = await browser
          .elementByCss('.red-text')
          .getComputedCss('background-image')

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

      it('should render the page', async () => {
        const browser = await next.browse


t */
import { nextTestSetup } from 'e2e-utils'
import { colorToRgb } from 'next-test-utils'

const sassOptions = {
  loadPaths: ['./styles'],
}

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: { sassOptions } },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        ...sassOptions,
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'Basic Module Include Paths Support ($dependencies)',
  ({ dependencies, nextConfig }) => {
    co

e,
      dependencies,
      nextConfig,
    })

    it('should render the module', async () => {
      const browser = await next.browser('/')
      expect(
        await browser.elementByCss('#verify-red').getComputedCss('color')
      ).toBe(colorToRgb(

nst { next } = nextTestSetup({
      files: __dirnam


m 'e2e-utils'
import { colorToRgb, retry } from 'next-test-utils'

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: undefined },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        implementation: 'sass-embedded',
      },
    },
  },
])('SCSS Support ($dependencies)', ({ dependencies, nextConfig }) => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
    dependencies,
    nextConfig,
  })
  describe('Has CSS in computed st

(colorToRgb('blue'))
    })
  })

  if (isNextDev) {
    describe('Can hot reload CSS without losing state', () => {
      it('should update CSS color without remounting <input>', async () => {
        const browser = await next.browser('/page1')

yles in Production', () => {
    it('should have CSS for page', async () => {
      const browser = await next.browser('/page2')

      expect(
        await browser.elementByCss('.blue-text').getComputedCss('color')
      ).toBe


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

const sassOptions = {
  additionalData: `
    $var: red;
  `,
}

describe.each([
  { dependencies: { sass: '1.54.0' }, nextConfig: { sassOptions } },
  {
    dependencies: { 'sass-embedded': '1.75.0' },
    nextConfig: {
      sassOptions: {
        ...sassOptions,
        implementation: 'sass-embedded',
      },
    },
  },
])(
  'Basic Module Additional Data Support ($dependencies)',
  ({ dependencies, nextConfig }) => {
    const { next } =

dencies,
      nextConfig,
    })

    it('should render the module', async () => {
      const browser = await next.browser('/')
      expect(
        await browser.elementByCss('#verify-red').getComputedCss('color')
      ).toBe(colorToRgb('red'))
    })

 nextTestSetup({
      files: __dirname,
      depen


nst path = require('path')

module.exports = async function (content) {
  let dir = path.dirname(this.resourcePath)

  let read1 = await new Promise((res, rej) =>
    this.fs.readFile(path.join(dir, 'test.txt'), (err, data) => {
      if (err) return rej(err)
      res(data)
    })
  )
  let read2 = await new Promise((res, rej) =>
    this.fs.readFile(path.join(dir, 'test.txt'), 'utf8', (err, data) => {
      if (err) return rej(err)
      res(data)
    })
  )
  let read3 = await new Promise((res, rej) =>

dFile(path.join(dir, 'test.mp4'), (err, data) => {
      if (err) return rej(err)
      res(data)
    })
  )
  return `module.exports = "Buffer read: ${read1 instanceof Buffer ? read1.length : 0}, string read: '${read2.trim()}', binary read: ${read3.length


 and over again'
    foo =
      'This is the other repeating string. It should be about the same length'
    foo =
      'I should just alternately repeat this and another string over and over again'
    foo =
      'This is the other repeating string. It should be about the same length'
    foo =
      'I should just alternately repeat this and another string over and over again'
    foo =
      'This is the other repeating string. It should be about the same length'
    foo =
      'I should just alterna


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

describe('app-dir trailingSlash handling', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
    buildArgs: [
      '--debug-build-paths',
      isCacheComponentsEnabled
        ? '!app/[lang]/legacy/page.js'
        : '!app/[lang]/cache-components/page.js',
    ],
  })

  it('should redirect route when requesting it directly', async () => {
    const res = await next.fetch('/a', {
      redirect: 'manual',
    })
    ex

o-a-trailing-slash').attr('href')).toBe('/a/')
  })

  it('should contain trailing slash to canonical url', async () => {
    const $ = await next.render$('/')
    expect($(`link[rel="canonical"]`).attr('href')).toBe(
      'http://trailingslash.com/'

pect(res.status).toBe(308)
    expect(new URL(res.headers.get('location'), next.url).pathname).toBe('/a/')
  })

  it('should render link with trailing slash', async () => {
    const $ = await next.render$('/')

    expect($('#t


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

describe('global-not-found - basic', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  it('should render global-not-found for 404', async () => {
    const browser = await next.browser('/does-not-exist')
    if (isNextDev) {
      await waitForNoRedbox(browser)
    }

    const errorTitle = await browser.elementByCss('#global-error-title').text()
    expect(errorTitle).toBe('global-not-found')
    const not

next.render$('/does-not-exist')
    const errorTitle = $('#global-error-title').text()
    expect(errorTitle).toBe('global-not-found')
    const notFoundHtmlProp = $('html').attr('data-global-not-found')
    expect(notFoundHtmlProp).toBe('true')
  })

  it

FoundHtmlProp = await browser
      .elementByCss('html')
      .getAttribute('data-global-not-found')
    expect(notFoundHtmlProp).toBe('true')
  })

  it('should ssr global-not-found for 404', async () => {
    const $ = await