h'
import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils'

describe('useDefineForClassFields SWC option', () => {
  const { next } = nextTestSetup({
    files: join(__dirname, 'fixture'),
    dependencies: {
      mobx: '6.3.7',
      typescript: 'latest',
      '@types/react': 'latest',
      '@types/node': 'latest',
      'mobx-react': '7.2.1',
    },
  })

  it('tsx should compile with useDefineForClassFields enabled', async () => {
    const browser = await next.browser('/')

n with useDefineForClassFields enabled", async () => {
    const browser = await next.browser('/animal')
    expect(await browser.elementByCss('#dog').text()).toBe('undefined')
    expect(await browser.elementByCss('#dogDecl').text()).toBe('dog')
  })

  a

   await browser.elementByCss('#action').click()
    await check(
      () => browser.elementByCss('#name').text(),
      /this is my name: next/
    )
  })

  it("Initializes resident to undefined after the call to 'super()' whe


 React from 'react'

interface Animal {
  animalStuff: any
}
interface Dog extends Animal {
  dogStuff: any
}

class AnimalHouse {
  resident: Animal
  constructor(animal: Animal) {
    this.resident = animal
  }
}
class DogHouse extends AnimalHouse {
  // Initializes 'resident' to 'undefined'
  // after the call to 'super()' when
  // using 'useDefineForClassFields'!
  // @ts-ignore
  resident: Dog
  // useless constructor only for type checker
  /* eslint-disable @typescript-eslint/no-useless-constructor

or */
  constructor(dog: Dog) {
    super(dog)
  }
}

export default function AnimalView() {
  const dog = new DogHouse({
    animalStuff: 'animal',
    dogStuff: 'dog',
  })
  const dogDeclare = new DogHouseWithDeclare({
    animalStuff: 'animal',
    dog

*/
  constructor(dog: Dog) {
    super(dog)
  }
}

class DogHouseWithDeclare extends AnimalHouse {
  declare resident: Dog
  // useless constructor only for type checker
  /* eslint-disable @typescript-eslint/no-useless-construct


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

describe('asset-prefix', () => {
  const { next } = nextTestSetup({
    files: join(__dirname, 'fixture'),
  })

  it('should load the app properly without reloading', async () => {
    const browser = await next.browser('/')
    await browser.eval(`window.__v = 1`)

    expect(await browser.elementByCss('#text').text()).toBe('Hello World')

    await check(async () => {
      const logs = await browser.log()

vigate to another page without hard navigating', async () => {
    const browser = await next.browser('/')
    await browser.eval(`window.__v = 1`)
    await browser.elementByCss('[href="/page2"]').click()
    await retry(async () => {
      expect(await b

const hasError = logs.some((log) =>
        log.message.includes('Failed to fetch')
      )
      return hasError ? 'error' : 'success'
    }, 'success')

    expect(await browser.eval(`window.__v`)).toBe(1)
  })

  it('should na


rypto'
import vm from 'vm'
import constants from 'constants'
import domain from 'domain'
import http from 'http'
import https from 'https'
import os from 'os'
// TODO: These are accidentally polyfilled in edge runtime currently.
// import punycode from 'punycode'
// import process from 'process'
// import querystring from 'querystring'
// import stringDecoder from 'string_decoder'
import sys from 'sys'
import timers from 'timers'
import tty from 'tty'
import zlib from 'zlib'
import 'setimmediate'
// Support

leware(request) {
  if (request.nextUrl.pathname !== '/middleware-test') {
    return
  }
  const response = NextResponse.next()

  let emitted = false
  class MyEmitter extends EventEmitter {}
  const myEmitter = new MyEmitter()
  // Only do this once so

ed in edge
import { Buffer } from 'buffer'
import assert from 'assert'
import util from 'util'
import { EventEmitter } from 'events'

// Other imports
import { NextResponse } from 'next/server'

export default async function midd


rt path from 'path'
import crypto from 'crypto'
import { Buffer } from 'buffer'
import vm from 'vm'
import assert from 'assert'
import constants from 'constants'
import { useEffect, useState } from 'react'
import domain from 'domain'
import http from 'http'
import https from 'https'
import os from 'os'
import punycode from 'punycode'
import process from 'process'
import querystring from 'querystring'
import stringDecoder from 'string_decoder'
import sys from 'sys'
import timers from 'timers'
import tty from

t writable = new Writable({
      write(_chunk, _encoding, callback) {
        callback()
      },
    })

    writable.on('finish', () => {
      closedStream = true
    })

    writable.end()

    assert.ok(true)

    assert.ok(!!domain)
    assert.ok(!!

 'tty'
import util from 'util'
import zlib from 'zlib'
import 'setimmediate'

export default function NodeBrowserPolyfillPage() {
  const [state, setState] = useState({})
  useEffect(() => {
    let closedStream = false

    cons


ck
// Import a .txt file using a raw loader via turbopackLoader
// turbopackAs tells turbopack to treat the loader output as JavaScript
import rawText from '../data.txt' with { turbopackLoader: 'test-raw-loader', turbopackAs: '*.js' }
// Import a .js file with a replace loader via turbopackLoader with options
import replacedValue from '../data-with-placeholder.js' with { turbopackLoader: 'test-replace-loader', turbopackLoaderOptions: '{"search":"PLACEHOLDER","replace":"turbopackUse works!"}' }
// Import a .

port a non-.json file and treat it as JSON via turbopackModuleType
import jsonData from '../data.jsonlike' with { turbopackLoader: 'test-identity-loader', turbopackModuleType: 'json' }
// Normal rules should still work at the same time
import jsonData2 fro

txt file using turbopackModuleType to treat loader output as ecmascript
import rawTextViaModuleType from '../data2.txt' with { turbopackLoader: '../node_modules/test-raw-loader/index.js', turbopackModuleType: 'ecmascript' }
// Im


ort { FileRef, nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils'
import path from 'path'

const envFile = '.env.development.local'

describe(`app-dir hmr-env`, () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
    patchFileDelay: 1000,
  })

  it.each(['node', 'node-module-var', 'edge', 'edge-module-var'])(
    'should update server components pages when env files is changed (%s)',
    async (page) => {
      const

ect(await browser.elementByCss('p').text()).toBe('ipad')
        })
      })

      // ensure it's restored back to "mac" before the next test
      await retry(async () => {
        expect(await browser.elementByCss('p').text()).toBe('mac')
      })

 browser = await next.browser(`/env/${page}`)
      expect(await browser.elementByCss('p').text()).toBe('mac')

      await next.patchFile(envFile, 'MY_DEVICE="ipad"', async () => {
        await retry(async () => {
          exp


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

describe('app-dir server restart', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
    patchFileDelay: 1000,
    forcedPort: 'random',
  })

  it('should reload the page when the server restarts', async () => {
    const browser = await next.browser('/')
    await retry(async () => {
      expect(await browser.elementByCss('body').text()).toMatch(/hello world/)

ick()
    expect(await browser.elementById('counter-value').text()).toBe('Count: 1')

    // Click again to make it 2
    await browser.elementById('increment-button').click()
    expect(await browser.elementById('counter-value').text()).toBe('Count: 2')

   })

    // Verify the counter is at 0 initially
    expect(await browser.elementById('counter-value').text()).toBe('Count: 0')

    // Click increment button to change state
    await browser.elementById('increment-button').cl


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

describe('Invalid Image Import (dev)', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: __dirname,
  })

  it('should show error', async () => {
    const browser = await next.browser('/')
    await waitForRedbox(browser)
    const description = await getRedboxDescription(browser)
    if (isTurbopack) {
      expect(description).toContain('Processing image failed')
    } else if

cription).toContain(
        'Image import "../public/invalid.svg" is not a valid image file. The image may be corrupted or an unsupported format.'
      )
    }
    const source = await getRedboxSource(browser)
    if (isTurbopack) {
      expect(source).

(process.env.NEXT_RSPACK) {
      expect(description).toContain(
        'Image import "../public/invalid.svg" is not a valid image file. The image may be corrupted or an unsupported format.'
      )
    } else {
      expect(des


rt { useSearchParams, usePathname, useParams } from 'next/navigation'

function Box({
  label,
  children,
}: {
  label: string
  children: React.ReactNode
}) {
  return (
    <div
      style={{
        background: '#fff',
        border: '1px solid #ddd',
        borderRadius: 8,
        padding: '1rem',
        marginBottom: '0.75rem',
      }}
    >
      <div
        style={{
          fontSize: '0.7rem',
          textTransform: 'uppercase',
          letterSpacing: '0.05em',
          color: '#888',

ode>{pathname}

  )
}

function ParamsDisplay() {
  const params = useParams()

  return (

      slug={String(params.slug ?? '(none)')}

  )
}

function SearchPar

          marginBottom: '0.5rem',
        }}
      >
        {label}
      </div>
      {children}
    </div>
  )
}

function PathnameDisplay() {
  const pathname = usePathname()

  return (
    <p style={{ margin: 0 }}>
      <c


 { nextTestSetup, FileRef } from 'e2e-utils'
import { waitForRedbox, waitForNoRedbox } from 'next-test-utils'
import { waitForHydration } from 'development-sandbox'

describe('hmr-deleted-page', () => {
  const { next } = nextTestSetup({
    files: {
      app: new FileRef(join(__dirname, 'app')),
    },
  })

  it('should not show errors for a deleted page', async () => {
    const browser = await next.browser('/page')
    expect(await browser.elementByCss('p').text()).toBe('nested hello world')

    await

.deleteFile('app/page/style.css')
    await waitForHydration(browser)

    await waitForRedbox(browser)

    await next.deleteFile('app/page')
    await waitForHydration(browser)

    await waitForNoRedbox(browser)
    expect(await browser.elementByCss('h1

 next.deleteFile('app/page/test.tsx')
    await next


from 'e2e-utils'
import { join } from 'path'
import { existsSync } from 'fs'
import { parseTraceFile } from '../../../lib/parse-trace-file'

describe('render-path tracing', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  if (!isNextDev) {
    it('should be skipped in production', () => {})
    return
  }

  it('should record render-path events for page requests', async () => {
    const tracePath = join(next.testDir, '.next/dev/trace')

    // Trigger page request if trac

RM')
      await new Promise((resolve) => setTimeout(resolve, 500))
    }

    const traceStructure = parseTraceFile(tracePath)

    // Check for render-path events
    const renderPathEvents = traceStructure.eventsByName.get('render-path')
    expect(rend

e doesn't exist yet
    if (!existsSync(tracePath)) {
      const browser = await next.browser('/')
      expect(await browser.elementByCss('p').text()).toBe('hello world')
      await browser.close()
      await next.stop('SIGTE


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

describe('hmr-app-and-pages', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should do HMR when app router and pages router have shared CSS', async () => {
    let browser = await next.browser('/')
    await browser.eval('window.notReloaded = true')

    expect(
      await browser.elementByCss('body').getComputedCss('background-color')
    ).toEqual('rgb(255, 255, 255)')

    await next.patchFile('app/styles.c

'body').getComputedCss('background-color')
    ).toEqual('rgb(255, 0, 0)')
    expect(await browser.eval('window.notReloaded')).toBe(true)

    browser = await next.browser('/pages-router')
    await browser.eval('window.notReloaded = true')

    expect(

ss', (content) =>
      content.replace(
        'background-color: rgb(255, 255, 255);',
        'background-color: rgb(255, 0, 0);'
      )
    )

    await waitForNoRedbox(browser)
    expect(
      await browser.elementByCss(


tTestSetup } from 'e2e-utils'

describe('hook-function-names', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should show readable hook names in stacks', async () => {
    const browser = await next.browser('/button')

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

    await expect(browser).toDisplayCollapsedRedbox(`
     {
       "description": "Kaputt!",
       "environmentLabel": null,
       "label": "Runtime Error",
       "source": "app/button/page.tsx (7:11) @ Button.

app/button/page.tsx (11:5)",
         "Page app/button/page.tsx (18:10)",
       ],
     }
    `)
  })

  it('should show readable hook names in stacks for default-exported components', async () => {
    const browser = await next.browser('/')

    await e

useCallback[handleClick]
     >  7 |     throw new Error(message)
          |           ^",
       "stack": [
         "Button.useCallback[handleClick] app/button/page.tsx (7:11)",
         "button <anonymous>",
         "Button


} from 'e2e-utils'
import { getDevIndicatorPosition } from './utils'

describe('devtools-position-persistence', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    nextConfig: {
      devIndicators: {
        position: 'top-right',
      },
    },
  })

  it('should maintain devtools indicator position after navigation', async () => {
    const browser = await next.browser('/')

    let style = await getDevIndicatorPosition(browser)

    expect(style).toContain('top: 20px')
    expect(style

k devtools indicator position is maintained
    await browser.refresh()
    await browser.waitForIdleNetwork()

    style = await getDevIndicatorPosition(browser)

    expect(style).toContain('top: 20px')
    expect(style).toContain('right: 20px')
  })
})

).toContain('right: 20px')

    // Navigate and chec


from 'e2e-utils'

// This only works for Turbopack HMR builds
;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)(
  'hmr-intercept-routes',
  () => {
    const { next } = nextTestSetup({
      files: __dirname,
    })

    it('should update intercept routes via HMR', async () => {
      const browser = await next.browser('/')
      expect(await browser.elementByCss('h1').text()).toBe('Main Page')

      const parallelDefaultContent = await next.readFile(
        'fixtures/@intercept/default.js'

ercept/default.js', parallelDefaultContent)
      await next.patchFile(
        'app/@intercept/(.)intercept/page.js',
        parallelInterceptContent
      )

      // Read the original code of the root layout page
      const rootLayoutContent = await n

   )

      const parallelInterceptContent = await next.readFile(
        'fixtures/@intercept/(.)intercept/page.js'
      )

      // Write the fixture files to the associated output location
      await next.patchFile('app/@int


v jest */
import { nextTestSetup } from 'e2e-utils'
import * as Log from './basic/utils/log'
import { waitForRedbox, getRedboxSource } from '../../../lib/next-test-utils'
import { join } from 'path'

describe('after() - invalid usages', () => {
  const { next } = nextTestSetup({
    files: join(__dirname, 'basic'),
  })

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

  const getAfterLogs = () => {
    if (next.cliOutput.length < currentCliOutputI

errors at compile time when used in a client module', async () => {
    const session = await next.browser('/invalid-in-client')

    await waitForRedbox(session)
    expect(await getRedboxSource(session)).toMatch(
      /You're importing a module that dep

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

  it('


Count,
  hasErrorToast,
  retry,
} from 'next-test-utils'

describe('app-dir - missing required html tags', () => {
  const { next } = nextTestSetup({ files: __dirname })

  if (process.env.__NEXT_CACHE_COMPONENTS === 'true') {
    // TODO(restart-on-cache-miss): reenable once the bug is fixed in:
    // https://github.com/vercel/next.js/pull/85818
    it.skip('currently broken in Cache Components', () => {})
    return
  }

  it('should display correct error count in dev indicator', async () => {
    const

w error overlay', async () => {
    const browser = await next.browser('/')

    await waitForRedbox(browser)
    await expect(browser).toDisplayRedbox(`
     {
       "code": "E394",
       "description": "Missing <html> and <body> tags in the root layout

 browser = await next.browser('/')
    await waitForRedbox(browser)
    retry(async () => {
      expect(await hasErrorToast(browser)).toBe(true)
    })
    expect(await getToastErrorCount(browser)).toBe(1)
  })

  it('should sho


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

describe('app-dir assetPrefix full URL', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    forcedPort: 'random',
  })

  beforeAll(async () => {
    const port = next.forcedPort
    await next.patchFile(
      'next.config.js',
      `module.exports = { assetPrefix: 'http://localhost:${port}' }`
    )
    await next.start()
  })

  it('should not break HMR when asset prefix set to full URL', async () => {
    const brows

browser.elementByCss('p').text()
    expect(text).toBe('before edit')

    await next.patchFile('app/page.tsx', (content) => {
      return content.replace('before', 'after')
    })

    await retry(async () => {
      expect(await browser.elementByCss('p'

er = await next.browser('/')
    const text = await


'with turbopack.ignoreIssue config', () => {
    const { next, skipped, isTurbopack } = nextTestSetup({
      files: __dirname,
      // turbopack.ignoreIssue is turbopack-only
      nextConfig: {
        turbopack: {
          ignoreIssue: [
            {
              // glob string pattern for path
              path: '**/with-warning/**',
            },
            {
              path: '**/with-error/**',
            },
            {
              path: '**/server-with-warning/**',
            },

    ],
        },
      },
    })

    if (skipped) return
    if (!isTurbopack) {
      it('should skip tests since turbopack.ignoreIssue only works with Turbopack', () => {})
      return
    }

    it('should suppress ignored warning from cli output', a

       {
              path: '**/server-with-error/**',
            },
            {
              path: '**/route-with-warning/**',
            },
            {
              path: '**/route-with-error/**',
            },


tTestSetup } from 'e2e-utils'

describe('experimental-lightningcss with default mode', () => {
  describe('in dev server', () => {
    const { isTurbopack, next } = nextTestSetup({
      files: __dirname,
      dependencies: { lightningcss: '^1.23.0' },
      packageJson: {
        browserslist: ['chrome 100'],
      },
    })

    it('should support css modules', async () => {
      // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
      const $ = await next.ren

ngcss does.
        expect($('p').attr('class')).toBe(
          'search-keyword style-module__hlQ3RG__blue'
        )
      } else {
        // We remove hash from the class name in test mode using env var because it is not deterministic.
        expect($

der$('/')
      expect($('p').text()).toBe('hello world')

      // lightningcss produces different class names in turbo mode
      if (isTurbopack) {
        // swc_css does not include `-module` in the class name, while lightni


port path from 'path'

const envFile = '.env.development.local'

describe(`app-dir-hmr`, () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
    patchFileDelay: 1000,
  })

  describe('filesystem changes', () => {
    it('should not continously poll when hitting a not found page', async () => {
      let requestCount = 0

      const browser = await next.browser('/does-not-exist', {
        beforePageLoad(page) {
          page.on('request

lementByCss('body').text()
      expect(body).toContain('404')

      await waitFor(3000)

      expect(requestCount).toBe(1)
    })

    it('should not break when renaming a folder', async () => {
      const browser = await next.browser('/folder')

', (request) => {
            const url = new URL(request.url())
            if (url.pathname === '/does-not-exist') {
              requestCount++
            }
          })
        },
      })
      const body = await browser.e


tTestSetup } from 'e2e-utils'

// Only implemented in Turbopack
import { getRedboxSource, waitForRedbox } from 'next-test-utils'
;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)(
  'report-system-env-var-inlining',
  () => {
    const { next } = nextTestSetup({
      files: __dirname,
    })

    it('should report when inlining system env vars', async () => {
      const browser = await next.browser('/')
      await waitForRedbox(browser)

      const error = await getRedboxSource(browser)

           |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         3 | }
         4 |

       This variable changes frequently, causing slower deploy times and worse browser client-side caching. Consider using \`process.env.NEXT_DEPLOYMENT_ID

expect(error).toMatchInlineSnapshot(`
       "./app/foo.tsx (2:14)
       TP1202 The commit hash is being inlined.
         1 | export function Foo() {
       > 2 |   return <p>{process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA}</p>


xport const unstable_prefetch = 'force-runtime'

function Box({
  label,
  children,
}: {
  label: string
  children: React.ReactNode
}) {
  return (
    <div
      style={{
        background: '#fff',
        border: '1px solid #ddd',
        borderRadius: 8,
        padding: '1rem',
        marginBottom: '0.75rem',
      }}
    >
      <div
        style={{
          fontSize: '0.7rem',
          textTransform: 'uppercase',
          letterSpacing: '0.05em',
          color: '#888',
          marginBottom

o', value: '456' },
    { label: 'Stat three', value: '789' },
  ]

  return (

      {stats.map((s) => (

: '0.5rem',
        }}
      >
        {label}
      </div>
      {children}
    </div>
  )
}

async function DynamicStats() {
  await connection()

  const stats = [
    { label: 'Stat one', value: '123' },
    { label: 'Stat tw


-test-utils'

describe('app-dir - capture-console-error-owner-stack', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should capture browser console error and format the error message', async () => {
    const browser = await next.browser('/browser/event')
    await browser.elementByCss('button').click()

    await expect(browser).toDisplayCollapsedRedbox(`
     {
       "code": "E394",
       "description": "trigger an console <error>",
       "environmentLabel": null,
       "

rowser/event/page.js (7:17)",
         "button <anonymous>",
         "Page app/browser/event/page.js (5:5)",
       ],
     }
    `)
  })

  it('should capture browser console error in render and dedupe if necessary', async () => {
    const browser = awa

label": "Console Error",
       "source": "app/browser/event/page.js (7:17) @ onClick
     >  7 |         console.error('trigger an console <%s>', 'error')
          |                 ^",
       "stack": [
         "onClick app/b


 install
 * reorganizes `node_modules` while the Next.js dev server is running.
 *
 * Specifically, when `next` (re)moves under `node_modules` mid-HMR, Turbopack
 * fails to resolve `next/package.json` and emits a `MissingNextFolderIssue`.
 * The dev server must:
 *   - surface the issue (recoverable, not Fatal)
 *   - NOT crash with a `TurbopackInternalError` / "FATAL" log
 *   - recover once `node_modules/next` is restored
 */
const describeMaybe = process.env.NEXT_SKIP_ISOLATE ? describe.skip : describe

t nextPath = path.join(next.testDir, 'node_modules', 'next')
    // sanity check
    await fs.lstat(nextPath)
    return nextPath
  }

  async function moveNextAside(): Promise<{ original: string; stash: string }> {
    const original = await getNextPath()

describeMaybe('concurrent-install', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: __dirname,
  })

  const itTurbopack = isTurbopack ? it : it.skip

  async function getNextPath(): Promise<string> {
    cons


            This App is made up of a number of sub-pages which exercise the
            Cache Components validation performed in dev to ensure it matches up
            with the validation performed during the build.

            When Building routes with dynamic params we validate that the
            prerender produces an acceptable static shell. If we do not have a
            complete set of params for any given page we will use a special kind
            of param cal

alues for that param.
          </p>
          <p>
            In Dev, our validation needs to match and the way we do this is we
            look at the current route and determine the most specific set of
            params that would be availalbe during

led a fallback param which suspends as dynamic and is
            required to be wrapped in Suspense if accessed so we can ensure
            there is still an acceptable shell even when we don't know about
            specific v


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

import cheerio from 'cheerio'

describe('dev-fetch-hmr', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should retain module level fetch patching', async () => {
    const html = await next.render('/')
    expect(html).toContain('monkey patching is fun')

    const magicNumber = cheerio.load(html)('#magic-number').text()

    const html2 = await next.render('/')
    expect(html2).toContain('monkey patching is fun')
    c

 to trigger HMR')

    await next.patchFile('app/page.tsx', (content) =>
      content.replace('touch to trigger HMR', 'touch to trigger HMR 2')
    )
    // For server hmr, we must touch the exact module to trigger re-evaluation
    await next.patchFile('

onst magicNumber2 = cheerio.load(html2)('#magic-number').text()
    // Module was not re-evaluated
    expect(magicNumber2).toBe(magicNumber)
    const update = cheerio.load(html2)('#update').text()
    expect(update).toBe('touch


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

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

  describe('bad lowercase exports', () => {
    it.each([
      ['get'],
      ['head'],
      ['options'],
      ['post'],
      ['put'],
      ['delete'],
      ['patch'],
    ])(
      'should print an error when using lowercase %p in dev',
      async (method: string) => {
        await next.fetch('/lowercase/' +

method.toUpperCase()}' method name to fix this error.`
          )
          expect(next.cliOutput).toMatch(
            /Detected lowercase method '.+' in '.+\/route\.js'\. Export the uppercase '.+' method name to fix this error\./
          )
          r

method)

        await check(() => {
          expect(next.cliOutput).toContain(
            `Detected lowercase method '${method}' in`
          )
          expect(next.cliOutput).toContain(
            `Export the uppercase '${


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

  it('is none on initial load', async () => {
    const browser = await next.browser('/')

    const badge = await browser.elementByCss('[data-next-badge]')
    const cacheStatus = await badge.getAttribute('data-status')
    expect(cacheStatus).toBe('none')
  })

  if (enableCacheComponents) {
    it('renders the cache warming indicator when navigating to a page that needs to warm the cache', async () => {
      const browser = await next.browser('/')

data-next-badge]')
        const cacheStatus = await badge.getAttribute('data-status')
        expect(cacheStatus).toBe('prerendering')
      })

      await retry(async () => {
        const text = await browser.elementByCss('#navigation-page').text()

      // navigate to the navigation page
      const link = await browser.waitForElementByCss('a[href="/navigation"]')
      await link.click()

      await retry(async () => {
        const badge = await browser.elementByCss('[


tTestSetup } from 'e2e-utils'

describe('serialize-circular-error', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should serialize the object from server component in console correctly', async () => {
    const browser = await next.browser('/')

    await expect(browser).toDisplayRedbox(`
     {
       "code": "E394",
       "description": "An error occurred but serializing the error message failed.",
       "environmentLabel": "Server",
       "label": "Runtime Error",

ject from client component in console correctly', async () => {
    const browser = await next.browser('/client')

    // TODO: Format arbitrary messages in Redbox
    await expect(browser).toDisplayRedbox(`
     {
       "code": "E394",
       "descriptio

 "source": null,
       "stack": [],
     }
    `)
    const output = next.cliOutput
    expect(output).toContain(
      'Error: {"objA":{"other":{"a":"[Circular]"}},"objB":"[Circular]"}'
    )
  })

  it('should serialize the ob


waitForNoRedbox, retry } from 'next-test-utils'

// This tests file symlinks, but not directory symlinks. Directory symlinks are
// known to break route manifest generation:
// https://github.com/vercel/next.js/discussions/77463
describe('HMR symlinks', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('tracks updates to symlinked target', async () => {
    const browser = await next.browser('/symlink-link')

    expect(await browser.elementByCss('h1').text()).toBe(
      'This is

     await waitForNoRedbox(browser)
          expect(await browser.elementByCss('h1').text()).toBe(
            'This is the updated symlink target'
          )
        })
      }
    )
  })

  /* eslint-disable jest/no-standalone-expect */
  // This works

the symlink target'
    )

    await next.patchFile(
      'app/symlink-target/page.tsx',
      (content) => content.replace('symlink target', 'updated symlink target'),
      async () => {
        await retry(async () => {


eact from 'react'
import { ReactNode } from 'react'

const magicNumber = Math.random()
const originalFetch = globalThis.fetch

if (originalFetch.name === 'monkeyPatchedFetch') {
  throw new Error(
    'Patching over already patched fetch. This creates a memory leak.'
  )
}

globalThis.fetch = async function monkeyPatchedFetch(
  resource: URL | RequestInfo,
  options?: RequestInit
) {
  const request = new Request(resource)

  if (request.url === 'http://fake.url/secret') {
    return new Response('monkey p

fake.url/magic-number') {
    return new Response(magicNumber.toString())
  }

  return originalFetch(resource, options)
}

export default function Root({ children }: { children: ReactNode }) {
  return (
    <html>
      <body>{children}</body>
    </html

atching is fun')
  }

  if (request.url === 'http://


rt { cacheTag } from 'next/cache'
import { Suspense } from 'react'

export default function Page() {
  return (

      Hello navigation page!
      <Suspense fallback={
Loading
}>
        <Component />
      </Suspense>
      <SlowThing />

  )
}

async function Component() {
  const posts = await getBlogPosts()
  return (

      {posts.map((post) => (

{post.content}

      ))}

  )
}

async function getBlogP

 sleep for 2s
  await new Promise((resolve) => setTimeout(resolve, 2000))

  return [{ id: 'foo', content: 'bar' }]
}

async function SlowThing() {
  // sleep for 2s
  await new Promise((resolve) => setTimeout(resolve, 2000))

  return <div>Slow Thing</div

osts() {
  'use cache'
  cacheTag('blog-posts')
  //


ect to see any errors await params regarless of where there
    // are Suspense boundaries.
    const browser = await next.browser(
      '/complete/prerendered/wrapped/prerendered'
    )
    await waitForNoRedbox(browser)

    await browser.loadPage(`${next.url}/complete/prerendered/wrapped/novel`)
    await waitForNoRedbox(browser)

    await browser.loadPage(`${next.url}/complete/novel/wrapped/novel`)
    await waitForNoRedbox(browser)

    await browser.loadPage(
      `${next.url}/complete/prerendered/

novel/unwrapped/novel`)
    await waitForNoRedbox(browser)
  })

  it('should warn about missing Suspense when accessing params if static params are partially known at build time', async () => {
    // when the params are partially complete we don't expect

unwrapped/prerendered`
    )
    await waitForNoRedbox(browser)

    await browser.loadPage(`${next.url}/complete/prerendered/unwrapped/novel`)
    await waitForNoRedbox(browser)

    await browser.loadPage(`${next.url}/complete/


ipStart: true,
    dependencies: {
      'styled-components': '6.1.16',
      '@next/mdx': 'canary',
      '@mdx-js/loader': '2.2.1',
      '@mdx-js/react': '2.2.1',
    },
  })

  // https://github.com/vercel/next.js/issues/12422
  test('styled-components hydration mismatch', async () => {
    const files = new Map([
      [
        'pages/_document.js',
        outdent`
          import Document from 'next/document'
          import { ServerStyleSheet } from 'styled-components'

          export default

  ctx.renderPage = () =>
                  originalRenderPage({
                    enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
                  })

                const initialProps = await Document.getInitialProps(ctx)

 class MyDocument extends Document {
            static async getInitialProps(ctx) {
              const sheet = new ServerStyleSheet()
              const originalRenderPage = ctx.renderPage

              try {


bkit } from 'playwright'
import type { Browser } from 'playwright'

describe('mcp-server get_errors tool', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
  })

  async function callGetErrors(id: string) {
    const response = await fetch(`${next.url}/_next/mcp`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json, text/event-stream',
      },
      body: JSON.stringify

  const result = JSON.parse(match![1])
    return result.result?.content?.[0]?.text
  }

  it('should handle no browser sessions gracefully', async () => {
    const errorsText = await callGetErrors('test-no-session')
    const errors = JSON.parse(errorsTe

({
        jsonrpc: '2.0',
        id,
        method: 'tools/call',
        params: { name: 'get_errors', arguments: {} },
      }),
    })

    const text = await response.text()
    const match = text.match(/data: ({.*})/s)


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

describe('get-logs MCP tool', () => {
  const { next, skipped } = nextTestSetup({
    files: path.join(__dirname, 'fixtures', 'log-file-app'),
  })

  if (skipped) {
    return
  }

  async function callGetLogs(id: string): Promise<string> {
    const response = await fetch(`${next.url}/_next/mcp`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/jso

.text()
    const match = text.match(/data: ({.*})/s)
    const result = JSON.parse(match![1])
    return result.result?.content?.[0]?.text
  }

  it('should return log file path via MCP get_logs tool', async () => {
    // Generate some logs by visiting p

n, text/event-stream',
      },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id,
        method: 'tools/call',
        params: { name: 'get_logs', arguments: {} },
      }),
    })

    const text = await response


adata tool', () => {
  async function callGetPageMetadata(url: string, id: string) {
    const response = await fetch(`${url}/_next/mcp`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json, text/event-stream',
      },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id,
        method: 'tools/call',
        params: { name: 'get_page_metadata', arguments: {} },
      }),
    })

    const text = await response.text()
    const m

 path.join(__dirname, 'fixtures', 'parallel-routes-template')
      ),
    })

    it('should return metadata for basic page', async () => {
      await next.browser('/')
      const metadataText = await callGetPageMetadata(next.url, 'test-basic')
      co

atch = text.match(/data: ({.*})/s)
    const result = JSON.parse(match![1])
    return result.result?.content?.[0]?.text
  }

  describe('app router', () => {
    const { next } = nextTestSetup({
      files: new FileRef(


tSetup } from 'e2e-utils'
import path from 'path'

describe('mcp-server get_project_metadata tool', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
  })
  it('should return correct project metadata via get_project_metadata tool', async () => {
    const mcpEndpoint = `${next.url}/_next/mcp`

    // Call get_project_metadata tool
    const callToolResponse = await fetch(mcpEndpoint, {
      method: 'POST',
      headers: {
        'Cont

    name: 'get_project_metadata',
          arguments: {},
        },
      }),
    })

    const callToolText = await callToolResponse.text()
    const callToolDataMatch = callToolText.match(/data: ({.*})/s)
    expect(callToolDataMatch).toBeTruthy()

ent-Type': 'application/json',
        Accept: 'application/json, text/event-stream',
      },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: 'call-tool-1',
        method: 'tools/call',
        params: {


om 'e2e-utils'

describe('get_routes MCP tool', () => {
  const { next, skipped } = nextTestSetup({
    files: path.join(__dirname, 'fixtures', 'dynamic-routes-app'),
  })

  if (skipped) {
    return
  }

  async function callGetRoutes(
    id: string,
    args: Record<string, unknown> = {}
  ): Promise<string> {
    const response = await fetch(`${next.url}/_next/mcp`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json, text/event-stream'

 match = text.match(/data: ({.*})/s)
    const result = JSON.parse(match![1])
    return result.result?.content?.[0]?.text
  }

  it('should return all routes via MCP get_routes tool without visiting pages', async () => {
    // The tool should discover al

,
      },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id,
        method: 'tools/call',
        params: { name: 'get_routes', arguments: args },
      }),
    })

    const text = await response.text()
    const


 => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'actions-app')),
  })

  it('should return action details via get_server_action_by_id tool', async () => {
    const mcpEndpoint = `${next.url}/_next/mcp`

    // Visit the page to trigger action registration
    await next.render('/')

    // Read the manifest to get a valid action ID
    const manifestPath = path.join(
      next.testDir,
      getDistDir(),
      'server',
      'server-reference-manifest.jso

)[0]
    expect(actionId).toBeTruthy()

    // Call get_server_action_by_id tool
    const callToolResponse = await fetch(mcpEndpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json, t

n'
    )
    const manifestContent = await fs.readFile(manifestPath, 'utf-8')
    const manifest = JSON.parse(manifestContent)

    // Get the first action ID from the manifest
    const actionId = Object.keys(manifest.node || {}


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

describe('mcp-server telemetry tracking', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
    env: {
      NEXT_TELEMETRY_DEBUG: '1',
    },
  })

  async function callMcpTool(
    toolName: string,
    params: Record<string, any> = {}
  ) {
    const response = await fetch(`${next.url}/_next/mcp`, {
      method: 'POST',
      headers: {
        'Content

rams: { name: toolName, arguments: params },
      }),
    })

    const text = await response.text()
    const match = text.match(/data: ({.*})/s)
    if (!match) {
      throw new Error(`Failed to parse response for tool ${toolName}`)
    }
    return JS

-Type': 'application/json',
        Accept: 'application/json, text/event-stream',
      },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: `telemetry-test-${Date.now()}`,
        method: 'tools/call',
        pa


omium, firefox, webkit, type Browser } from 'playwright'

function getFullUrl(appPortOrUrl: string | number, url: string): string {
  const appUrl =
    typeof appPortOrUrl === 'string'
      ? appPortOrUrl
      : `http://localhost:${appPortOrUrl}`
  return url.startsWith('/') ? `${appUrl}${url}` : url
}

/**
 * Minimal standalone browser session launcher for testing multiple concurrent browser tabs.
 * The standard test harness (next.browser) uses a singleton browser instance which doesn't
 * support conc

erName = (process.env.BROWSER_NAME || 'chrome').toLowerCase()
  let browser: Browser
  if (browserName === 'safari') {
    browser = await webkit.launch({ headless })
  } else if (browserName === 'firefox') {
    browser = await firefox.launch({ headless }

urrent tabs needed for testing errors across multiple browser sessions.
 */
export async function launchStandaloneSession(
  appPortOrUrl: string | number,
  url: string
) {
  const headless = !!process.env.HEADLESS
  const brows


ent'

import { useEffect } from 'react'

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

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

  console.error('globalThis', globalThis)

  return <p>client page with loggin

bj
    console.log('Client: Complex circular object:


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

  test('can edit a component without losing state', async () => {
    await using sandbox = await createSandbox(next)
    const { session } = sandbox

    await session.patch(
      'index.js',
      outdent`
        import { useCallback, useState } from 'react'
        export default function Index() {
          const [count, setCount] = useState(0)

       )
        }
      `
    )
    await session.evaluate(() => document.querySelector('button').click())
    expect(
      await session.evaluate(() => document.querySelector('p').textContent)
    ).toBe('1')
    await session.patch(
      'index.js',

        const increment = useCallback(() => setCount(c => c + 1), [setCount])
          return (
            <main>
              <p>{count}</p>
              <button onClick={increment}>Increment</button>
            </main>


ble with webpack 5
  test('Node.js builtins', async () => {
    await using sandbox = await createSandbox(
      next,
      new Map([
        [
          'node_modules/my-package/index.js',
          outdent`
            const dns = require('dns')
            module.exports = dns
          `,
        ],
        [
          'node_modules/my-package/package.json',
          outdent`
            {
              "name": "my-package",
              "version": "0.0.1"
            }
          `,
        ],

ded
 :
Package did not load
)
        }
      `
    )
    if (isTurbopack) {
      await expect(browser).toDisplayRedbox(`
       {
         "description": "Module not found: Can't resolve 'dns'",
         "environmentLabel": null,
         "la

])
    )

    const { browser, session } = sandbox

    await session.patch(
      'index.js',
      outdent`
        import pkg from 'my-package'

        export default function Hello() {
          return (pkg ? <h1>Package loa


 'development-sandbox'
import { FileRef, nextTestSetup } from 'e2e-utils'
import path from 'path'
import { outdent } from 'outdent'

// TODO: figure out why snapshots mismatch on GitHub actions
// specifically but work in docker and locally
describe.skip('ReactRefreshLogBox scss app', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
    dependencies: {
      sass: 'latest',
    },
    skipStart: true,
  })

  test('scss syntax errors',

nt`
        import './index.module.scss';
        export default () => {
          return (

Hello World

          )
        }
      `
    )

    await session.waitForNoRedbox()

    // Syntax error

async () => {
    await using sandbox = await createSandbox(next)
    const { session } = sandbox

    await session.write('index.module.scss', `.button { font-size: 5px; }`)
    await session.patch(
      'index.js',
      outde


import * as React from 'react';
        class ClassDefault extends React.Component {
          render() {
            return
Default Export
;
          }
        }
        export default ClassDefault;
      `
    )

    expect(
      await session.evaluate(() => document.querySelector('h1').textContent)
    ).toBe('Default Export')

    // Add a throw in module init phase:
    await session.patch(
      'index.js',
      outdent`
        // top offset for snapshot
        import * as React from

)

    if (isTurbopack) {
      await expect(browser).toDisplayRedbox(`
       {
         "description": "no",
         "environmentLabel": null,
         "label": "Runtime Error",
         "source": "index.js (3:7) @ module evaluation
       > 3 | throw n

'react';
        throw new Error('no')
        class ClassDefault extends React.Component {
          render() {
            return
Default Export
;
          }
        }
        export default ClassDefault;
      `


import path from 'path'
import { outdent } from 'outdent'

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

  test('server-side only compilation errors', async () => {
    await using sandbox = await createSandbox(next)
    const { browser, session } = sandbox

    await session.patch(
      'app/page.js',
      outdent`
        'use client'
        im

unction Hello(props) {
          return <h1>{props.result}</h1>
        }
      `
    )

    if (isTurbopack) {
      await expect(browser).toDisplayRedbox(`
       {
         "description": ""getStaticProps" is not supported in app/. Read more: https://ne

port myLibrary from 'my-non-existent-library'
        export async function getStaticProps() {
          return {
            props: {
              result: myLibrary()
            }
          }
        }
        export default f


 { FileRef, nextTestSetup } from 'e2e-utils'
import path from 'path'
import { createSandbox } from 'development-sandbox'
import { outdent } from 'outdent'

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

  it('should allow any variable names', async () => {
    await using sandbox = await createSandbox(next, new Map([]))
    const { session } = sandbox
    await session.wait

/page.js',
        outdent`
          'use client'
          import { default as ${variable} } from 'next/link'
          console.log({ ${variable} })
          export default function Page() {
            return null
          }
        `
      )
      aw

ForNoRedbox()

    const variables = [
      '_a',
      '_b',
      'currentExports',
      'prevExports',
      'isNoLongerABoundary',
    ]

    for await (const variable of variables) {
      await session.patch(
        'app


 'styled-components': '6.1.16',
      '@next/mdx': 'canary',
      '@mdx-js/loader': '2.2.1',
      '@mdx-js/react': '2.2.1',
    },
    skipStart: true,
  })

  // https://github.com/vercel/next.js/issues/12422
  // TODO-APP: port to app directory
  test.skip('styled-components hydration mismatch', async () => {
    const files = new Map()
    files.set(
      'pages/_document.js',
      outdent`
        import Document from 'next/document'
        import { ServerStyleSheet } from 'styled-components'

        ctx.renderPage = () =>
                originalRenderPage({
                  enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
                })

              const initialProps = await Document.getInitialProps(ctx)

    export default class MyDocument extends Document {
          static async getInitialProps(ctx) {
            const sheet = new ServerStyleSheet()
            const originalRenderPage = ctx.renderPage

            try {


w.log.push('init FooV1'); require('./bar');`
    )
    await session.write(
      './bar.js',
      `window.log.push('init BarV1'); export default function Bar() { return null; };`
    )

    await session.evaluate(() => ((window as any).log = []))
    await session.patch(
      'index.js',
      `require('./foo'); export default function Noop() { return null; };`
    )
    expect(await session.evaluate(() => (window as any).log)).toEqual([
      'init FooV1',
      'init BarV1',
    ])

    // We only edit

n Bar() { return null; };`
    )
    expect(await session.evaluate(() => (window as any).log)).toEqual([
      'init BarV2',
    ])

    // We only edited Bar, and it accepted.
    // So we expect it to re-run alone.
    await session.evaluate(() => ((wind

ed Bar, and it accepted.
    // So we expect it to re-run alone.
    await session.evaluate(() => ((window as any).log = []))
    await session.patch(
      './bar.js',
      `window.log.push('init BarV2'); export default functio


'path'
import crypto from 'crypto'
import { Buffer } from 'buffer'
import vm from 'vm'
import assert from 'assert'
import constants from 'constants'
import domain from 'domain'
import http from 'http'
import https from 'https'
import os from 'os'
import punycode from 'punycode'
import process from 'process'
import querystring from 'querystring'
import stringDecoder from 'string_decoder'
import sys from 'sys'
import timers from 'timers'
import tty from 'tty'
import util from 'util'
import zlib from 'zlib'

i

        callback()
      },
    })

    writable.on('finish', () => {
      closedStream = true
    })

    writable.end()

    assert.ok(true)

    assert.ok(!!domain)
    assert.ok(!!http)
    assert.ok(!!https)
    assert.ok(!!punycode)
    assert.ok(!

mport '_http_common'
import 'setimmediate'

async function getData() {
  const result = await new Promise((resolve) => {
    let closedStream = false

    const writable = new Writable({
      write(_chunk, _encoding, callback) {


'path'
import crypto from 'crypto'
import { Buffer } from 'buffer'
import vm from 'vm'
import assert from 'assert'
import constants from 'constants'
import { useEffect, useState } from 'react'
import domain from 'domain'
import http from 'http'
import https from 'https'
import os from 'os'
import punycode from 'punycode'
import process from 'process'
import querystring from 'querystring'
import stringDecoder from 'string_decoder'
import sys from 'sys'
import timers from 'timers'
import tty from 'tty'
import

new Writable({
      write(_chunk, _encoding, callback) {
        callback()
      },
    })

    writable.on('finish', () => {
      closedStream = true
    })

    writable.end()

    assert.ok(true)

    assert.ok(!!domain)
    assert.ok(!!http)
    ass

 util from 'util'
import zlib from 'zlib'
import 'setimmediate'

export default function NodeBrowserPolyfillPage() {
  const [state, setState] = useState({})
  useEffect(() => {
    let closedStream = false

    const writable =


from 'node:path'
import crypto from 'node:crypto'
import { Buffer } from 'node:buffer'
import vm from 'node:vm'
import assert from 'node:assert'
import constants from 'node:constants'
import domain from 'node:domain'
import http from 'node:http'
import https from 'node:https'
import os from 'node:os'
import punycode from 'node:punycode'
import process from 'node:process'
import querystring from 'node:querystring'
import stringDecoder from 'node:string_decoder'
import sys from 'node:sys'
import timers from '

onst writable = new Writable({
      write(_chunk, _encoding, callback) {
        callback()
      },
    })

    writable.on('finish', () => {
      closedStream = true
    })

    writable.end()

    assert.ok(true)

    assert.ok(!!domain)
    assert.ok

node:timers'
import tty from 'node:tty'
import util from 'node:util'
import zlib from 'node:zlib'

export async function getServerSideProps() {
  const result = await new Promise((resolve) => {
    let closedStream = false

    c


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

  test('can edit a component without losing state', async () => {
    await using sandbox = await createSandbox(next)
    const { session } = sandbox

    await session.patch(
      'index.js',
      outdent`
        import { useCallback, useState } from 'react'

        export default function Index() {
          const [count, setCount] = useState(0)

    )
        }
      `
    )

    await session.evaluate(() => document.querySelector('button').click())
    expect(
      await session.evaluate(() => document.querySelector('p').textContent)
    ).toBe('1')

    await session.patch(
      'index.js',

     const increment = useCallback(() => setCount(c => c + 1), [setCount])
          return (
            <main>
              <p>{count}</p>
              <button onClick={increment}>Increment</button>
            </main>


ack 5
  test('Node.js builtins', async () => {
    await using sandbox = await createSandbox(
      next,
      new Map([
        [
          'node_modules/my-package/index.js',
          outdent`
            const dns = require('dns')
            module.exports = dns
          `,
        ],
        [
          'node_modules/my-package/package.json',
          outdent`
            {
              "name": "my-package",
              "version": "0.0.1"
            }
          `,
        ],
      ])
    )

Package did not load</h1>)
        }
      `
    )

    if (isTurbopack) {
      await expect(browser).toDisplayRedbox(`
       {
         "description": "Module not found: Can't resolve 'dns'",
         "environmentLabel": null,
         "label": "Build E

const { browser, session } = sandbox
    await session.patch(
      'index.js',
      outdent`
        import pkg from 'my-package'

        export default function Hello() {
          return (pkg ?
Package loaded
 :


         "description": "idk",
         "environmentLabel": null,
         "label": "Runtime Error",
         "source": "index.js (8:27) @ onClick
       >  8 |                     throw new Error('idk')
            |                           ^",
         "stack": [
           "onClick index.js (8:27)",
         ],
       }
      `)
    }
  })

  // https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/3#issuecomment-554137807
  test('module init error not shown', async () => {
    // Start here:

sDefault extends React.Component {
          render() {
            return
Default Export
;
          }
        }
        export default ClassDefault;
      `
    )

    expect(
      await session.evaluate(() => document.querySelector('h1').textCo

 await using sandbox = await createSandbox(next)
    const { browser, session } = sandbox

    // We start here.
    await session.patch(
      'index.js',
      outdent`
        import * as React from 'react';
        class Clas


9a6c3/packages/metro/src/lib/polyfills/__tests__/require-test.js#L989-L1048
  test('re-runs accepted modules', async () => {
    await using sandbox = await createSandbox(next)
    const { session } = sandbox

    await session.patch(
      'index.js',
      `export default function Noop() { return null; };`
    )

    await session.write(
      './foo.js',
      `window.log.push('init FooV1'); require('./bar');`
    )
    await session.write(
      './bar.js',
      `window.log.push('init BarV1'); export d

  )
    expect(await session.evaluate(() => (window as any).log)).toEqual([
      'init FooV1',
      'init BarV1',
    ])

    // We only edited Bar, and it accepted.
    // So we expect it to re-run alone.
    await session.evaluate(() => ((window as any

efault function Bar() { return null; };`
    )

    await session.evaluate(() => ((window as any).log = []))
    await session.patch(
      'index.js',
      `require('./foo'); export default function Noop() { return null; };`


tTestSetup } from 'e2e-utils'
import fs from 'fs-extra'
import { waitForNoRedbox } from 'next-test-utils'
import path from 'path'

describe('repeated-dev-edits', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })
  // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
  it('should not break the hydration ', async () => {
    const browser = await next.browser('/')
    expect(await browser.elementByCss('p').text()).toBe('version-1')

    const pageP

it browser.waitForElementByCss('#version-2')
    expect(await browser.elementByCss('p').text()).toBe('version-2')

    // Verify no hydration mismatch:
    await waitForNoRedbox(browser)

    await next.patchFile(
      pagePath,
      pageContent.replaceA

ath = 'pages/index.tsx'
    const pageContent = String(
      await fs.readFile(path.join(__dirname, pagePath))
    )

    await next.patchFile(
      pagePath,
      pageContent.replaceAll('version-1', 'version-2')
    )
    awa


waitFor } from 'next-test-utils'

// When `__NEXT_EXPERIMENTAL_STRICT_ROUTE_TYPES=true` is set in CI, Next.js
// regenerates `next-env.d.ts` with additional `cache-life`/`validator`
// imports. The seed fixture must match that output so the very first read of
// `next-env.d.ts` (before any regeneration is observed) lines up with what
// Next.js will write back during the test.
const strictRouteTypes =
  process.env.__NEXT_EXPERIMENTAL_STRICT_ROUTE_TYPES === 'true'

const nextEnvDts = strictRouteTypes
  ? `/

types/validator.ts";

// NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
`
  : `/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next

// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/dev/types/root-params.d.ts";
import "./.next/dev/types/cache-life.d.ts";
import "./.next/dev/


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

describe('empty-object-getInitialProps', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should show empty object warning on SSR', async () => {
    await next.render('/')
    await retry(() => {
      expect(next.cliOutput).toMatch(
        /returned an empty object from `getInitialProps`/
      )
    })
  })

  it('should not show empty object warning for page without `getInitialProps`', async () => {
    c

om `getInitialProps`/
      )
    })
  })

  it('should show empty object warning during client transition', async () => {
    const browser = await next.browser('/static')
    await browser.eval(`(function() {
      window.gotWarn = false
      const orig

onst outputIndex = next.cliOutput.length
    await next.render('/static')
    await retry(() => {
      const newOutput = next.cliOutput.slice(outputIndex)
      expect(newOutput).not.toMatch(
        /returned an empty object fr


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

describe('watch-config-file', () => {
  const { next } = nextTestSetup({
    files: join(__dirname, 'fixture'),
  })
  it('should output config file change', async () => {
    await check(async () => next.cliOutput, /ready/i)

    await check(async () => {
      await next.patchFile(
        'next.config.js',
        `
            console.log(${Date.now()})
            const nextConfig = {

                    },
                  ]
                },
            }
            module.exports = nextConfig`
      )
      return next.cliOutput
    }, /Found a change in next\.config\.js\. Restarting the server to apply the changes\.\.\./)

    aw

   reactStrictMode: true,
              async redirects() {
                  return [
                    {
                      source: '/about',
                      destination: '/',
                      permanent: false,


const { next, isTurbopack } = nextTestSetup({
    files: {
      pages: new FileRef(join(__dirname, 'pages')),
    },
    env: {
      // Disable the cooldown period for the dev indicator so that hiding the indicator in a test doesn't
      // impact subsequent tests.
      __NEXT_DEV_INDICATOR_COOLDOWN_MS: '0',
    },
  })

  // The `Playwright.hasElementByCssSelector` cannot be used for elements inside a shadow DOM.
  function elementExistsInNextJSPortalShadowDOM(
    browser: Playwright,
    selector: st

nextjs-toast]',
    popover: '[data-nextjs-dev-tools-button]',
    indicator: '[data-next-badge-root]',
    minimizeButton: 'body',
    preferencesButton: '[data-preferences]',
    hideButton: '[data-hide-dev-tools]',
  }
  function getToast(browser: Playw

ring
  ) {
    return browser.eval(
      `!!document.querySelector('nextjs-portal').shadowRoot.querySelector('${selector}')`
    ) as any
  }
  const selectors = {
    fullScreenDialog: '[data-nextjs-dialog]',
    toast: '[data-


from 'e2e-utils'

describe('MDX-rs Plugin support', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    dependencies: {
      '@next/mdx': 'canary',
      '@mdx-js/loader': '*',
      '@mdx-js/react': '*',
    },
  })

  it('should render an MDX page correctly', async () => {
    expect(await next.render('/')).toMatch(/Hello MDX/)
  })

  it('should render an MDX page with component correctly', async () => {
    expect(await next.render('/button')).toMatch(/Look, a button!/)
  })

  it('sho

h mdx transform options', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    dependencies: {
      '@next/mdx': 'canary',
      '@mdx-js/loader': '*',
      '@mdx-js/react': '*',
    },
    skipStart: true,
  })

  beforeAll(async () => {

uld render an MDX page with globally provided components (from `mdx-components.js`) correctly', async () => {
    expect(await next.render('/provider')).toMatch(/Marker was rendered!/)
  })
})

describe('MDX-rs Plugin support wit


e = await fetch(`${url}/_next/mcp`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json, text/event-stream',
    },
    body: JSON.stringify({
      jsonrpc: '2.0',
      id: toolName + '-' + Date.now(),
      method: 'tools/call',
      params: { name: toolName, arguments: args },
    }),
  })
  const text = await response.text()
  const match = text.match(/data: ({.*})/s)
  expect(match).toBeTruthy()
  const envelope = JSON.parse(match![1])
  retu

,
  () => {
    const { next, skipped } = nextTestSetup({
      files: path.join(__dirname, 'fixtures', 'dynamic-routes-app'),
    })

    if (skipped) {
      return
    }

    describe('routeSpecifier input', () => {
      it('should compile a valid app

rn JSON.parse(envelope.result?.content?.[0]?.text)
}

// compile_route is Turbopack-only; it is not registered on webpack dev servers.
;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)(
  'mcp-server compile_route tool'


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

// Skip on Turbopack because it's not supported
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
  'webpack-issuer-deprecation-warning',
  () => {
    const { next } = nextTestSetup({
      files: {
        'pages/index.js': `
          export default function Page() {
            return <p>hello world
          }
        `,
      },
      dependencies: {},
    })

    it('should not appear deprecation war

   const html = await renderViaHTTP(next.url, '/')
      expect(html).toContain('Syntax Error')
      expect(next.cliOutput).not.toContain(
        '[DEP_WEBPACK_MODULE_ISSUER] DeprecationWarning: Module.issuer: Use new ModuleGraph API'
      )
    })
  }

ning about webpack module issuer', async () => {


'path'
import crypto from 'crypto'
import { Buffer } from 'buffer'
import vm from 'vm'
import assert from 'assert'
import constants from 'constants'
import domain from 'domain'
import http from 'http'
import https from 'https'
import os from 'os'
import punycode from 'punycode'
import process from 'process'
import querystring from 'querystring'
import stringDecoder from 'string_decoder'
import sys from 'sys'
import timers from 'timers'
import tty from 'tty'
import util from 'util'
import zlib from 'zlib'
im

    callback()
      },
    })

    writable.on('finish', () => {
      closedStream = true
    })

    writable.end()

    assert.ok(true)

    assert.ok(!!domain)
    assert.ok(!!http)
    assert.ok(!!https)
    assert.ok(!!punycode)
    assert.ok(!!stri

port 'setimmediate'

export async function getServerSideProps() {
  const result = await new Promise((resolve) => {
    let closedStream = false

    const writable = new Writable({
      write(_chunk, _encoding, callback) {


rt: true,
  })

  test('empty _app shows logbox', async () => {
    await using sandbox = await createSandbox(
      next,
      new Map([['pages/_app.js', ``]])
    )
    const { browser, session } = sandbox
    await expect(browser).toDisplayRedbox(`
     {
       "code": "E464",
       "description": "The default export is not a React Component in page: "/_app"",
       "environmentLabel": null,
       "label": "Runtime Error",
       "source": null,
       "stack": [],
     }
    `)

    await session.p

)
  })

  test('empty _document shows logbox', async () => {
    await using sandbox = await createSandbox(
      next,
      new Map([['pages/_document.js', ``]])
    )
    const { browser, session } = sandbox

    await expect(browser).toDisplayRedbox(`

atch(
      'pages/_app.js',
      outdent`
        function MyApp({ Component, pageProps }) {
          return <Component {...pageProps} />;
        }
        export default MyApp
      `
    )
    await session.waitForNoRedbox(


mport { FileRef, nextTestSetup } from 'e2e-utils'
import { createSandbox } from 'development-sandbox'
import path from 'path'

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

  it('should allow any variable names', async () => {
    await using sandbox = await createSandbox(next)
    const { session } = sandbox
    await session.waitForNoRedbox()

    const variables = [
      '

ariable} } from 'next/link'
        console.log({ ${variable} })
        export default function Page() {
          return null
        }`
      )
      await session.waitForNoRedbox()
      expect(next.cliOutput).not.toContain(
        `'${variable}' has

_a',
      '_b',
      'currentExports',
      'prevExports',
      'isNoLongerABoundary',
    ]

    for await (const variable of variables) {
      await session.patch(
        'pages/index.js',
        `import { default as ${v


eState(0)
          const increment = useCallback(() => setCount(c => c + 1), [setCount])
          return (
            <main>
              <p>{count}</p>
              <button onClick={increment}>Increment</button>
            </main>
          )
        }
      `
    )

    await session.evaluate(() => document.querySelector('button').click())
    expect(
      await session.evaluate(() => document.querySelector('p').textContent)
    ).toBe('1')

    await session.patch('index.js', `export default () =>

./index.js (1:27)
       Expected '>', got '<eof>'
       > 1 | export default () => <div/
           |                           ^",
         "stack": [],
       }
      `)
    } else if (isRspack) {
      await expect({ browser, next }).toDisplayRedbox(`

 <div/`)

    if (isTurbopack) {
      await expect(browser).toDisplayRedbox(`
       {
         "description": "Expected '>', got '<eof>'",
         "environmentLabel": null,
         "label": "Build Error",
         "source": "


       expect.stringContaining(
                'https://react.dev/link/hydration-mismatch'
              ),
          source: 'error',
        },
      ])
    )
  })

  it('should show correct hydration error when client and server render different text', async () => {
    await using sandbox = await createSandbox(
      next,
      new Map([
        [
          'index.js',
          outdent`
              const isClient = typeof window !== 'undefined'
              export default function Mismatch() {

    `,
        ],
      ])
    )
    const { session, browser } = sandbox

    // Pages Router uses React version without Owner Stacks hence the empty `stack`
    if (isReact18) {
      await expect(browser).toDisplayRedbox(`
       [
         {

return (

                      {isClient ? "client" : "server"}

                  );
                }


xtTestSetup } from 'e2e-utils'

describe('Custom Document Head Warnings', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('warns when using a <title> in document/head', async () => {
    await next.render('/')
    expect(next.cliOutput).toMatch(
      /.*Warning: <title> should not be used in _document.js's <Head>\..*/
    )
  })

  it('warns when using viewport meta tags in document/head', async () => {
    await next.render('/')
    expect(next.cliOutput).toMatch(
      /.*Warn

ent.js's <Head>\..*/
    )
  })

  it('warns when using a crossOrigin attribute on document/head', async () => {
    await next.render('/')
    expect(next.cliOutput).toMatch(
      /.*Warning: `Head` attribute `crossOrigin` is deprecated\..*/
    )
  })
}

ing: viewport meta tags should not be used in _docum


 'e2e-utils'
import { retry } from '../../lib/next-test-utils'

describe('Replaying internal errors', () => {
  const { next } = nextTestSetup({ files: __dirname })

  it('should not log the internal error thrown by redirect()', async () => {
    const EXPECTED_REPLAYED_MESSAGE = 'This error should get replayed'
    const OMITTED_ERROR_MESSAGE = 'NEXT_REDIRECT'

    const browser = await next.browser('/')

    await browser.elementByCss('a[href="/will-redirect"]').click()
    await retry(async () => {

heck for redbox here,
    // but it seems to disappear the first time we navigate to /target.
    // But checking console errors should be enough because they're closely tied

    const logs = await browser.log()

    expect(logs).toContainEqual(
      exp

 expect(await browser.elementByCss('h1').text()).toBe('Redirected')
    })

    expect(next.cliOutput).toContain(EXPECTED_REPLAYED_MESSAGE)
    expect(next.cliOutput).not.toContain(OMITTED_ERROR_MESSAGE)

    // It'd be good to c


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

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

let counter = 0

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

try again..')
    }
  }

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

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

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

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

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


opack-only feature (requires NAPI project handle)
;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)(
  'mcp-server get_compilation_issues tool',
  () => {
    const { next, skipped } = nextTestSetup({
      files: path.join(__dirname, 'fixtures', 'compilation-errors-app'),
    })

    if (skipped) {
      return
    }

    async function callMcpTool() {
      const response = await fetch(`${next.url}/_next/mcp`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/js

get_compilation_issues', arguments: {} },
        }),
      })

      const text = await response.text()
      const match = text.match(/data: ({.*})/s)
      expect(match).toBeTruthy()
      const result = JSON.parse(match![1])
      return JSON.parse(res

on',
          Accept: 'application/json, text/event-stream',
        },
        body: JSON.stringify({
          jsonrpc: '2.0',
          id: 'get-compilation-issues',
          method: 'tools/call',
          params: { name: '


frames } from '@emotion/react'
import styled from '@emotion/styled'

export const globalStyles = (
  <Global
    styles={css`
      html,
      body {
        padding: 3rem 1rem;
        margin: 0;
        background: papayawhip;
        min-height: 100%;
        font-family: Helvetica, Arial, sans-serif;
        font-size: 24px;
      }
    `}
  />
)

export const basicStyles = css({
  backgroundColor: 'white',
  color: 'cornflowerblue',
  border: '1px solid lightgreen',
  borderRight: 'none',
  borderBott

ckground-color: lightgray;
    border-color: aqua;
    box-shadow:
      -15px -15px 0 0 aqua,
      -30px -30px 0 0 cornflowerblue;
  }
`
export const bounce = keyframes`
  from {
    transform: scale(1.01);
  }
  to {
    transform: scale(0.99);
  }
`

e

om: 'none',
  boxShadow: '5px 5px 0 0 lightgreen, 10px 10px 0 0 lightyellow',
  transition: 'all 0.1s linear',
  margin: '3rem 0',
  padding: '1rem 0.5rem',
})

export const hoverStyles = css`
  &:hover {
    color: white;
    ba


export default function Page() { return <Comp /> }
    `,
  ],
  [
    'components/Comp.js',
    outdent`
      export default function Comp() {
        return
Hello world

      }
    `,
  ],
])

describe('Error Overlay for server components compiler errors in pages', () => {
  const { next } = nextTestSetup({
    files: {},
    skipStart: true,
  })

  test("importing 'next/headers' in pages", async () => {
    await using sandbox = await createSandbox(next, initialFiles)
    const { session

)

    await session.waitForRedbox()
    await expect(session.getRedboxSource()).resolves.toMatch(
      /This API is only available in Server Components/
    )

    if (process.env.IS_TURBOPACK_TEST) {
      expect(next.normalizeTestDirContent(await sessi

} = sandbox

    await session.patch(
      'components/Comp.js',
      outdent`
        import { cookies } from 'next/headers'

        export default function Page() {
          return
hello world

        }
      `


getRedboxHeader, retry } from 'next-test-utils'

describe('TypeScript HMR', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: __dirname,
  })

  describe('delete a page and add it back', () => {
    it('should detect the changes to typescript pages and display it', async () => {
      const browser = await next.browser('/hello')
      await retry(async () => {
        expect(await browser.elementByCss('body').text()).toMatch(/Hello World/)
      })

      const originalContent = await next.

'pages/hello.tsx', editedContent)
      await retry(async () => {
        expect(await browser.elementByCss('body').text()).toMatch(/COOL page/)
      })

      await next.patchFile('pages/hello.tsx', originalContent)
      await retry(async () => {

readFile('pages/hello.tsx')
      const editedContent = originalContent.replace('Hello', 'COOL page')

      if (isTurbopack) {
        await new Promise((resolve) => setTimeout(resolve, 500))
      }

      await next.patchFile(


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

describe('SSG Prerender', () => {
  describe('development mode getStaticPaths', () => {
    const { next } = nextTestSetup({
      files: __dirname,
      dependencies: {
        firebase: '7.14.5',
      },
      nextConfig: {
        experimental: {
          cpus: 1,
        },
      },
    })

    it('should work with firebase import and getStaticPaths', async () => {
      const html = await next.render('/blog/post-1')
      expect(html).toConta

})

    it('should not cache getStaticPaths errors', async () => {
      const errMsg = /The `fallback` key must be returned from getStaticPaths/

      await retry(async () => {
        const html = await next.render('/blog/post-1')
        expect(html).t

in('post-1')
      expect(html).not.toContain('Error: Failed to load')

      const html2 = await next.render('/blog/post-1')
      expect(html2).toContain('post-1')
      expect(html2).not.toContain('Error: Failed to load')


ort { createSandbox } from 'development-sandbox'
import { FileRef, nextTestSetup } from 'e2e-utils'
import path from 'path'

// TODO: figure out why snapshots mismatch on GitHub actions
// specifically but work in docker and locally
describe.skip('ReactRefreshLogBox scss', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
    skipStart: true,
    dependencies: {
      sass: 'latest',
    },
  })

  test('scss syntax errors', async () =>

'./index.module.scss';
        export default () => {
          return (

lol

          )
        }
      `
    )

    await session.waitForNoRedbox()

    // Syntax error
    await session.patch('in

{
    await using sandbox = await createSandbox(next)
    const { session } = sandbox

    await session.write('index.module.scss', `.button { font-size: 5px; }`)
    await session.patch(
      'index.js',
      `
        import


retry } from 'next-test-utils'

describe('_app/_document removal HMR', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should HMR when _app is removed', async () => {
    const indexContent = await next.readFile('pages/index.js')
    try {
      const browser = await next.browser('/')

      const html = await browser.eval('document.documentElement.innerHTML')
      expect(html).toContain('custom _app')

      const appContent = await next.readFile('pages/_app.js')
      await n

m _app')
      })

      await next.patchFile(
        'pages/index.js',
        `
        export default function Page() {
          return
index page updated

        }
      `
      )

      await retry(async () => {
        const html = await bro

ext.deleteFile('pages/_app.js')

      await retry(async () => {
        const html = await browser.eval('document.documentElement.innerHTML')
        expect(html).toContain('index page')
        expect(html).not.toContain('custo


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

jest.setTimeout(240 * 1000)

describe('Error overlay - RSC build errors', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'app-hmr-changes')),
    dependencies: {
      '@next/mdx': 'canary',
      'react-wrap-balancer': '^0.2.4',
      'react-tweet': '^3.2.0',
      '@mdx-js/react': '^2.3.0',
      tailwindcss: '^3.2.6',
      typescript: 'latest',
      '@types/react': '^18.0.28'

S_TURBOPACK_TEST ? describe : describe.skip)(
    'Skipped in webpack',
    () => {
      it('should handle successive HMR changes with errors correctly', async () => {
        await using sandbox = await createSandbox(
          next,
          undefined,

,
      '@types/react-dom': '^18.0.10',
      'image-size': '^1.0.2',
      autoprefixer: '^10.4.13',
    },
    skipStart: true,
  })

  // TODO: The error overlay is not closed when restoring the working code.
  ;(process.env.I


ent } from 'outdent'

async function clickSourceFile(browser: Playwright) {
  await browser.waitForElementByCss(
    '[data-with-open-in-editor-link-source-file]'
  )
  await browser
    .elementByCss('[data-with-open-in-editor-link-source-file]')
    .click()
}

async function clickImportTraceFiles(browser: Playwright) {
  await browser.waitForElementByCss(
    '[data-with-open-in-editor-link-import-trace]'
  )
  const collapsedFrameworkGroups = await browser.elementsByCss(
    '[data-with-open-in-editor-l

 files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
    skipStart: true,
  })

  it('should be possible to open source file on build error', async () => {
    let editorRequestsCount = 0
    await using sandbox = await createSandbox(

ink-import-trace]'
  )
  for (const collapsedFrameworkButton of collapsedFrameworkGroups) {
    await collapsedFrameworkButton.click()
  }
}

describe('Error overlay - editor links', () => {
  const { next } = nextTestSetup({


rement = useCallback(() => setCount(c => c + 1), [setCount])
          return (
            <main>
              <p>{count}</p>
              <button onClick={increment}>Increment</button>
            </main>
          )
        }
      `
    )

    await browser.elementByCss('button').click()
    expect(
      await session.evaluate(() => document.querySelector('p').textContent)
    ).toBe('1')

    await session.patch('index.js', `export default () => <div/`)

    if (isTurbopack) {
      await expect(bro

   > 1 | export default () => <div/
           |                           ^",
         "stack": [],
       }
      `)
    } else if (isRspack) {
      await expect({ browser, next }).toDisplayRedbox(`
       {
         "description": "  ╰─▶   × Error:   x

wser).toDisplayRedbox(`
       {
         "description": "Expected '>', got '<eof>'",
         "environmentLabel": null,
         "label": "Build Error",
         "source": "./index.js (1:27)
       Expected '>', got '<eof>'


nt-only': 'latest',
    },
    skipStart: true,
  })

  it('should show error when using styled-jsx in server component', async () => {
    await using sandbox = await createSandbox(
      next,
      new Map([
        [
          'app/comp1.js',
          outdent`
            import { Comp2 } from './comp2'

            export function Comp1() {
              return <Comp2 />
            }
          `,
        ],
        [
          'app/comp2.js',
          outdent`
            export function Comp2() {

         }
          `,
        ],
        [
          'app/page.js',
          outdent`
            'use client'
            import { Comp1 } from './comp1'

            export default function Page() {
              return <Comp1 />
            }

             return (
                <div>
                  <style jsx>{\`
                    p {
                      color: red;
                    }
                  \`}</style>
                </div>
              )


tdent'
import { FileRef, nextTestSetup } from 'e2e-utils'

describe('Error overlay - RSC runtime errors', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'rsc-runtime-errors')),
  })

  it('should show runtime errors if invalid client API from node_modules is executed', async () => {
    await next.patchFile(
      'app/server/page.js',
      outdent`
      import { callClientApi } from 'client-package'
      export default function Page() {
        callCli

se client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/react-client-hook-in-server-component",
       "environmentLabel": "Server",
       "label": "Runtime TypeError",
       "source": "app/server/page.js (3:16)

entApi()
        return 'page'
      }
    `
    )

    const browser = await next.browser('/server')

    await expect(browser).toDisplayRedbox(`
     {
       "description": "useState only works in Client Components. Add the "u


tup, type Playwright } from 'e2e-utils'
import path from 'path'
import { outdent } from 'outdent'

function getStaleness(browser: Playwright) {
  return browser
    .waitForElementByCss('.nextjs-container-build-error-version-status')
    .text()
}

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

  it('should show version staleness in runtime error', async () => {

   next,
      new Map([
        ['node_modules/next/package.json', JSON.stringify(nextPackageJson)],
      ])
    )
    const { session, browser } = sandbox
    await session.patch(
      'app/page.js',
      outdent`
        "use client"
        import C

  // Set next to outdated version
    const nextPackageJson = JSON.parse(
      await next.readFile('node_modules/next/package.json')
    )
    nextPackageJson.version = '1.0.0'

    await using sandbox = await createSandbox(


import sizeOf from 'image-size'
import { join } from 'path'
import { readFile } from 'fs/promises'
import NextImage from 'next/image'

export async function Image({ src, alt = null, width = null, height = null }) {
  if (!src.startsWith('data:') && (width === null || height === null)) {
    let imageBuffer = null

    if (src.startsWith('http')) {
      imageBuffer = Buffer.from(
        await fetch(src).then((res) => res.arrayBuffer())
      )
    } else {
      imageBuffer = await readFile(
        new UR

tartsWith('data:') ? (

      ) : (
        <NextImage width={width} height={height} alt={alt} src={src} />
      )}

      {alt && (
        {alt}
      )

L(join(import.meta.url, '..', '..', '..', '..', 'public', src))
          .pathname
      )
    }

    ;({ width, height } = sizeOf(imageBuffer))
  }

  return (
    <span className="my-5 flex flex-col items-center">
      {src.s


mport type { ReactNode } from 'react'
import { Tweet as ReactTweet, TweetComponents } from 'react-tweet'
import Image from 'next/image'

import { Caption } from './caption'

const components: TweetComponents = {
  AvatarImg: (props) => <Image {...props} />,
  MediaImg: (props) => <Image {...props} fill unoptimized />,
}

// we import this globally in the top-most layout.tsx file
// until Next.js lands suspense-y CSS support
// import "./tweet.css";

interface TweetArgs {
  id: string
  caption: ReactNode
}

function Tweet({ id, caption }: TweetArgs) {
  return (

        <ReactTweet id={id} components={components} />

      {caption &&
{caption}
}


t { createSandbox } from 'development-sandbox'
import { FileRef, nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils'

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

  it('should error when id is missing in generateImageMetadata', async () => {
    const iconFilePath = 'app/metadata-base/unset/icon.tsx'
    const contentMissingIdProperty = `
    import {

{
          contentType: 'image/png',
          size: { width: 48, height: 48 },
          id: 101,
        },
      ]
    }

    export default function icon() {
      return new ImageResponse(
icon
)
    }
    `
    await using _sandbox = awai

 ImageResponse } from 'next/og'
    export async function generateImageMetadata() {
      return [
        {
          contentType: 'image/png',
          size: { width: 48, height: 48 },
          // id: 100,
        },


  <Next.js Internal Component>
                           <Next.js Internal Component>
                             <Next.js Internal Component>
                             <Next.js Internal Component>
                               <Mismatch params={Promise} searchParams={Promise}>
                                 <div className="parent">
                                   <main className="child">
     +                               client
     -                               server

n if a SSR-ed Client Component used:",
       "environmentLabel": null,
       "label": "Recoverable Error",
       "source": "app/(default)/text-mismatch/page.tsx (8:7) @ Mismatch
     >  8 |       <main className="child">{isClient ? 'client' : 'server'}<

      ...
                         ...
               ...",
       "description": "Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client. This can happe


lt function Page() {
                return (
                  <>
                      <Context.Provider value="hello">

Page

                      </Context.Provider>
                  </>
                )
              }
            `,
          ],
        ])
      )
      const { browser } = sandbox
      await check(async () => {
        expect(
          await browser
            .waitForElementByCss('#nextjs__container_errors_desc')
            .text()
        ).to

 'success'
      }, 'success')

      expect(next.cliOutput).toContain(
        'createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-c

Contain(
          'createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component'
        )
        return


 { A as a } from '#/app/(post)/components/a'
import { P as p } from '#/app/(post)/components/p'
import { H1 as h1 } from '#/app/(post)/components/h1'
import { H2 as h2 } from '#/app/(post)/components/h2'
import { H3 as h3 } from '#/app/(post)/components/h3'
import { OL as ol } from '#/app/(post)/components/ol'
import { UL as ul } from '#/app/(post)/components/ul'
import { LI as li } from '#/app/(post)/components/li'
import { HR as hr } from '#/app/(post)/components/hr'
import { Tweet } from '#/app/(post)/co

nents/callout'
import { Ref, FootNotes, FootNote } from '#/app/(post)/components/footnotes'
import { Blockquote as blockquote } from '#/app/(post)/components/blockquote'

const components = {
  a,
  h1,
  h2,
  h3,
  p,
  ol,
  ul,
  li,
  hr,
  pre: Snipp

mponents/tweet'
import { Image } from '#/app/(post)/components/image'
import { Snippet } from '#/app/(post)/components/snippet'
import { Caption } from '#/app/(post)/components/caption'
import { Callout } from '#/app/(post)/compo


tSetup } from 'e2e-utils'
import path from 'path'
import { createSandbox } from 'development-sandbox'
import { outdent } from 'outdent'

describe('Error overlay - error message urls', () => {
  const { next } = nextTestSetup({
    files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
    skipStart: true,
  })

  it('should be possible to click url in build error', async () => {
    await using sandbox = await createSandbox(next)
    const { session, browser } = sandbox

    const content

s(
      '[data-nextjs-terminal] a, [data-nextjs-codeframe] a'
    )
    const text = await link.text()
    const href = await link.getAttribute('href')
    expect(text).toEqual(
      'https://nextjs.org/docs/app/building-your-application/data-fetching'

 = await next.readFile('app/page.js')

    await session.patch(
      'app/page.js',
      content + '\nexport function getServerSideProps() {}'
    )

    await session.waitForRedbox()

    const link = await browser.elementByCs


from 'node:path'
import crypto from 'node:crypto'
import { Buffer } from 'node:buffer'
import vm from 'node:vm'
import assert from 'node:assert'
import constants from 'node:constants'
import domain from 'node:domain'
import http from 'node:http'
import https from 'node:https'
import os from 'node:os'
import punycode from 'node:punycode'
import process from 'node:process'
import querystring from 'node:querystring'
import stringDecoder from 'node:string_decoder'
import sys from 'node:sys'
import timers from '

w Writable({
      write(_chunk, _encoding, callback) {
        callback()
      },
    })

    writable.on('finish', () => {
      closedStream = true
    })

    writable.end()

    assert.ok(true)

    assert.ok(!!domain)
    assert.ok(!!http)
    asser

node:timers'
import tty from 'node:tty'
import util from 'node:util'
import zlib from 'node:zlib'

async function getData() {
  const result = await new Promise((resolve) => {
    let closedStream = false

    const writable = ne


      'export function getServerSideProps'
    )
    await session.patch(pageFile, uncomment)

    await session.waitForRedbox()
    expect(await session.getRedboxSource()).toInclude(
      '"getServerSideProps" is not supported in app/'
    )
  })

  it('should throw an error when metadata export is used in client components', async () => {
    await using sandbox = await createSandbox(
      next,
      undefined,
      '/client-with-errors/metadata-export'
    )
    const { session } = sandbox
    const

t metadata'
    )
    await session.patch(pageFile, uncomment)
    await session.waitForRedbox()
    expect(await session.getRedboxSource()).toInclude(
      'You are attempting to export "metadata" from a component marked with "use client", which is disal

 pageFile = 'app/client-with-errors/metadata-export/page.js'
    const content = await next.readFile(pageFile)

    // Add `metadata` error
    let uncomment = content.replace(
      '// export const metadata',
      'export cons


('with empty getInitialProps()', () => {
    it('should render a redbox', async () => {
      const pageErrors: unknown[] = []
      const browser = await next.browser('/nav', {
        beforePageLoad: (page) => {
          page.on('pageerror', (error: unknown) => {
            pageErrors.push(error)
          })
        },
      })
      await browser.elementByCss('#empty-props').click()
      await expect(browser).toDisplayRedbox(`
       {
         "code": "E1025",
         "description": ""EmptyInitialP

ect(pageErrors).toEqual([
        expect.objectContaining({
          message:
            '"EmptyInitialPropsPage.getInitialProps()" should resolve to an object. But found "null" instead.',
        }),
      ])
    })
  })

  describe('with the current ur

ropsPage.getInitialProps()" should resolve to an object. But found "null" instead.",
         "environmentLabel": null,
         "label": "Runtime Error",
         "source": null,
         "stack": [],
       }
      `)
      exp


 { nextTestSetup } from 'e2e-utils'

describe('Client Navigation with <Link/>', () => {
  const { next } = nextTestSetup({
    files: path.join(__dirname, 'fixture'),
    env: {
      TEST_STRICT_NEXT_HEAD: String(true),
    },
  })

  it('should navigate the page', async () => {
    const browser = await next.browser('/nav')
    const text = await browser
      .elementByCss('#about-link')
      .click()
      .waitForElementByCss('.nav-about')
      .elementByCss('p')
      .text()

    expect(text).toBe(

wser.waitForElementByCss('.nav-about')
    await browser.refresh()
    await waitFor(3000)
    await browser.back()
    await waitFor(3000)
    const text = await browser.elementByCss('#about-link').text()
    if (browser) await browser.close()
    expect(

'This is the about page.')
    await browser.close()
  })

  it('should navigate back after reload', async () => {
    const browser = await next.browser('/nav')
    await browser.elementByCss('#about-link').click()
    await bro


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

let count = 0

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

  return (

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

        Via A

      <Link href="/nav/hash-changes" id="page-url">
        Page URL
      </Link>
      <Link href="#" id="via-empty-hash">
        Via Empty Hash
      </Link>
      <Link href="

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

COUNT: {count}

      {Array.fr

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


ounter = 0

const linkStyle = {
  marginRight: 10,
}

export default class extends Component {
  increase() {
    counter++
    this.forceUpdate()
  }

  visitQueryStringPage() {
    const href = { pathname: '/nav/querystring', query: { id: 10 } }
    const as = { pathname: '/nav/querystring/10', hash: '10' }
    Router.push(href, as)
  }

  render() {
    return (
      <div className="nav-home">
        <Link href="/nav/about" id="about-link" style={linkStyle}>
          About
        </Link>
        <Lin

       Self Reload
        </Link>
        <Link
          href="/nav/shallow-routing"
          id="shallow-routing-link"
          style={linkStyle}
        >
          Shallow Routing
        </Link>
        <Link href="/nav/redirect" id="redirect-link"

k
          href="/empty-get-initial-props"
          id="empty-props"
          style={linkStyle}
        >
          Empty Props
        </Link>
        <Link href="/nav/self-reload" id="self-reload-link" style={linkStyle}>