Files
vercel__next.js/test/e2e/api-resolver-query-writeable/api-resolver-query-writeable.test.ts
Jamiboy Mohammad 77fa82756a test: enable verified pages-router deploy tests (#98526)
## Summary

Enable the same 12 previously selected deployment-test scopes across 12
pages-router test files, now in a stack rooted on canary. Remove 11
`skipDeployment` options and their obsolete skip guards. Remove the
selected suite’s deploy-only placeholder return. Other mode, bundler,
middleware, and Cache Components exclusions remain in place.

This preserves the selection with passing evidence from the previous
deployment runs. No additional candidate scopes are enabled; excluded
variants are not counted as deployment coverage.

## Verification

- All selected test registration names and assertion bodies match the
previous enabled revision, checked by AST comparison.
- Verified that the canary diff contains only the inventoried exclusions
and their obsolete skip plumbing; other exclusions are preserved.
- Formatting and lint passed; 77 gate infrastructure unit tests passed.
- Full local bootstrap was blocked by missing package-level dependencies
in the temporary worktree. Fresh deployment execution on these rewritten
commits remains to be verified in CI.

<details>
<summary>Preserved scope inventory (12)</summary>

- ID 222: `test/e2e/404-page-custom-error/404-page-custom-error.test.ts`
— `describe('Default 404 Page with custom _error', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should respond to 404 correctly', async () => {
    const res = await next.fetch('/404')
    expect(res.status).toBe(404)
    expect(await res.text()).toContain('This page could not be found')
  })

  it('should render error correctly', async () => {
    const text = await next.render('/err')
    expect(text).toContain(isNextDev ? 'oops' : 'Internal Server Error')
  })

  it('should render index page normal', async () => {
    const html = await next.render('/')
    expect(html).toContain('hello from index')
  })
  ;(isNextStart ? it : it.skip)(
    'should set pages404 in routes-manifest correctly',
    async () => {
const data = JSON.parse(await
next.readFile('.next/routes-manifest.json'))
      expect(data.pages404).toBe(true)
    }
  )
;(isNextStart ? it : it.skip)('should have output 404.html', async () =>
{
    const pagesManifest = await next.readJSON(
      '.next/server/pages-manifest.json'
    )
    const page = pagesManifest['/404']
    expect(page.endsWith('.html')).toBe(true)
  })
})`
- ID 223: `test/e2e/404-page/404-page.test.ts` — `describe('404 Page
Support', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  const gip404Err =
    /`pages\/404` can not have getInitialProps\/getServerSideProps/

  it('should use pages/404', async () => {
    const html = await next.render('/abc')
    expect(html).toContain('custom 404 page')
  })

  it('should set correct status code with pages/404', async () => {
    const res = await next.fetch('/abc')
    expect(res.status).toBe(404)
  })

  it('should use pages/404 for .d.ts file', async () => {
    const html = await next.render('/invalidExtension')
    expect(html).toContain('custom 404 page')
  })

  it('should not error when visited directly', async () => {
    const res = await next.fetch('/404')
    expect(res.status).toBe(404)
    expect(await res.text()).toContain('custom 404 page')
  })

  it('should render _error for a 500 error still', async () => {
    const html = await next.render('/err')
    expect(html).not.toContain('custom 404 page')
    expect(html).toContain(isNextDev ? 'oops' : 'Internal Server Error')
  })

  if (isNextStart) {
    it('should output 404.html during build', async () => {
const manifest = await next.readJSON('.next/server/pages-manifest.json')
      const page = manifest['/404']
      expect(page.endsWith('.html')).toBe(true)
    })

    it('should still output 404.js anyway', async () => {
      expect(await next.hasFile('.next/server/pages/404.js')).toBe(true)
    })

    it('should add /404 to pages-manifest correctly', async () => {
const manifest = await next.readJSON('.next/server/pages-manifest.json')
      expect('/404' in manifest).toBe(true)
    })
  }

  if (isNextDev) {
    it('falls back to _error correctly without pages/404', async () => {
      const original404 = await next.readFile('pages/404.js')
      try {
        await next.deleteFile('pages/404.js')
        await retry(async () => {
          const res = await next.fetch('/abc')
          expect(res.status).toBe(404)
expect(await res.text()).toContain('This page could not be found')
        })
      } finally {
        await next.patchFile('pages/404.js', original404)
      }
    })

it('shows error with getInitialProps in pages/404 dev', async () => {
      const original404 = await next.readFile('pages/404.js')
      try {
        await next.patchFile(
          'pages/404.js',
          `
          const page = () => 'custom 404 page'
          page.getInitialProps = () => ({ a: 'b' })
          export default page
        `
        )
        await next.render('/abc')
        await retry(async () => {
          expect(next.cliOutput).toMatch(gip404Err)
        })
      } finally {
        await next.patchFile('pages/404.js', original404)
      }
    })

it('does not show error with getStaticProps in pages/404 dev', async ()
=> {
      const original404 = await next.readFile('pages/404.js')
      const getOutput = next.getCliOutputFromHere()
      try {
        await next.patchFile(
          'pages/404.js',
          `
          const page = () => 'custom 404 page'
          export const getStaticProps = () => ({ props: { a: 'b' } })
          export default page
        `
        )
        await next.render('/abc')
        await retry(async () => {
          const html = await next.render('/abc')
          expect(html).toContain('custom 404 page')
        })
        expect(getOutput()).not.toMatch(gip404Err)
      } finally {
        await next.patchFile('pages/404.js', original404)
      }
    })

it('shows error with getServerSideProps in pages/404 dev', async () => {
      const original404 = await next.readFile('pages/404.js')
      try {
        await next.patchFile(
          'pages/404.js',
          `
          const page = () => 'custom 404 page'
export const getServerSideProps = () => ({ props: { a: 'b' } })
          export default page
        `
        )
        await next.render('/abc')
        await retry(async () => {
          expect(next.cliOutput).toMatch(gip404Err)
        })
      } finally {
        await next.patchFile('pages/404.js', original404)
      }
    })
  }
})`
- ID 225: `test/e2e/500-page/500-page.test.ts` — `describe('500 Page
Support', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should use pages/500', async () => {
    const html = await next.render('/500')
    expect(html).toContain('custom 500 page')
  })

  it('should set correct status code with pages/500', async () => {
    const res = await next.fetch('/500')
    expect(res.status).toBe(500)
  })

  it('should not error when visited directly', async () => {
    const res = await next.fetch('/500')
    expect(res.status).toBe(500)
    expect(await res.text()).toContain('custom 500 page')
  })

  if (isNextStart) {
    it('should output 500.html during build', async () => {
const manifest = await next.readJSON('.next/server/pages-manifest.json')
      const page = manifest['/500']
      expect(page.endsWith('.html')).toBe(true)
    })

    it('should add /500 to pages-manifest correctly', async () => {
const manifest = await next.readJSON('.next/server/pages-manifest.json')
      expect('/500' in manifest).toBe(true)
    })
  }

  if (isNextDev) {
it('shows error with getInitialProps in pages/500 dev', async () => {
      const original500 = await next.readFile('pages/500.js')
      try {
        await next.patchFile(
          'pages/500.js',
          `
          const page = () => 'custom 500 page'
          page.getInitialProps = () => ({ a: 'b' })
          export default page
        `
        )
        await next.render('/500')
        await retry(async () => {
          expect(next.cliOutput).toMatch(
/`pages\/500` can not have getInitialProps\/getServerSideProps/
          )
        })
      } finally {
        await next.patchFile('pages/500.js', original500)
      }
    })

it('does not show error with getStaticProps in pages/500 dev', async ()
=> {
      const original500 = await next.readFile('pages/500.js')
      const outputBefore = next.cliOutput.length
      try {
        await next.patchFile(
          'pages/500.js',
          `
          const page = () => 'custom 500 page'
          export const getStaticProps = () => ({ props: { a: 'b' } })
          export default page
        `
        )
        await next.render('/abc')
        await retry(async () => {
          expect(next.cliOutput.slice(outputBefore)).not.toMatch(
/`pages\/500` can not have getInitialProps\/getServerSideProps/
          )
        })
      } finally {
        await next.patchFile('pages/500.js', original500)
      }
    })

it('shows error with getServerSideProps in pages/500 dev', async () => {
      const original500 = await next.readFile('pages/500.js')
      try {
        await next.patchFile(
          'pages/500.js',
          `
          const page = () => 'custom 500 page'
export const getServerSideProps = () => ({ props: { a: 'b' } })
          export default page
        `
        )
        await next.render('/500')
        await retry(async () => {
          expect(next.cliOutput).toMatch(
/`pages\/500` can not have getInitialProps\/getServerSideProps/
          )
        })
      } finally {
        await next.patchFile('pages/500.js', original500)
      }
    })
  }
})`
- ID 227:
`test/e2e/api-resolver-query-writeable/api-resolver-query-writeable.test.ts`
— `describe('api-resolver-query-writeable', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    startCommand: 'node server.js',
    serverReadyPattern: /Next mode: (production|development)/,
    dependencies: {
      'get-port': '5.1.1',
      express: '5.1.0',
    },
  })

it('should allow req.query to be writable and reflect changes made in
the API handler', async () => {
    const res = await next.fetch('/api?hello=yes', {
      headers: {
        'Content-Type': 'application/json; charset=utf-8',
      },
    })
    if (!res.ok) {
      throw new Error('Fetch failed')
    }
    const data = await res.json()
    expect(data).toEqual({ query: { hello: 'yes', changed: 'yes' } })
  })
})`
- ID 230: `test/e2e/app-document/client.test.ts` — `describe('Document
and App - Client side', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  it('should share module state with pages', async () => {
    const browser = await next.browser('/shared')

    const text = await browser.elementByCss('#currentstate').text()
    expect(text).toBe('UPDATED CLIENT')
  })

  if (isNextDev) {
it('should detect the changes to pages/_app.js and display it', async ()
=> {
      const appPath = 'pages/_app.js'
      const originalContent = await next.readFile(appPath)
      try {
        const browser = await next.browser('/')
        const text = await browser.elementByCss('#hello-hmr').text()
        expect(text).toBe('Hello HMR')

        // change the content
const editedContent = originalContent.replace('Hello HMR', 'Hi HMR')
        await next.patchFile(appPath, editedContent)

        await retry(async () =>
expect(await browser.elementByCss('body').text()).toContain('Hi HMR')
        )

        // add the original content
        await next.patchFile(appPath, originalContent)

        await retry(async () =>
          expect(await browser.elementByCss('body').text()).toContain(
            'Hello HMR'
          )
        )
      } finally {
        await next.patchFile(appPath, originalContent)
      }
    })

it('should detect the changes to pages/_document.js and display it',
async () => {
      const appPath = 'pages/_document.js'
      const originalContent = await next.readFile(appPath)
      try {
        const browser = await next.browser('/')
        const text = await browser.elementByCss('#hello-hmr').text()
        expect(text).toBe('Hello HMR')

        const editedContent = originalContent.replace(
          'Hello Document HMR',
          'Hi Document HMR'
        )

        // change the content
        await next.patchFile(appPath, editedContent)

        await retry(async () =>
          expect(await browser.elementByCss('body').text()).toContain(
            'Hi Document HMR'
          )
        )

        // add the original content
        await next.patchFile(appPath, originalContent)

        await retry(async () =>
          expect(await browser.elementByCss('body').text()).toContain(
            'Hello Document HMR'
          )
        )
      } finally {
        await next.patchFile(appPath, originalContent)
      }
    })

    it('should keep state between page navigations', async () => {
      const browser = await next.browser('/')

const randomNumber = await browser.elementByCss('#random-number').text()

      const switchedRandomNumer = await browser
        .elementByCss('#about-link')
        .click()
        .waitForElementByCss('.page-about')
        .elementByCss('#random-number')
        .text()

      expect(switchedRandomNumer).toBe(randomNumber)
      await browser.close()
    })
  }
})`
- ID 250: `test/e2e/disable-js/disable-js.test.ts` — `describe('disabled
runtime JS', () => {
  const { next, isNextDev, isNextStart } = nextTestSetup({
    files: __dirname,
  })

  it('should render the page', async () => {
    const html = await next.render('/')
    expect(html).toMatch(/Hello World/)
  })

  it('should not have __NEXT_DATA__ script', async () => {
    const html = await next.render('/')

    const $ = cheerio.load(html)
    if (isNextStart) {
      expect($('script#__NEXT_DATA__').length).toBe(0)
    }
    if (isNextDev) {
      expect($('script#__NEXT_DATA__').length).toBe(1)
    }
  })

  if (isNextStart) {
    it('should not have scripts', async () => {
      const html = await next.render('/')
      const $ = cheerio.load(html)
      expect($('script[src]').length).toBe(0)
    })

    it('should not have preload links', async () => {
      const html = await next.render('/')
      const $ = cheerio.load(html)
      expect($('link[rel=preload]').length).toBe(0)
    })
  }

  if (isNextDev) {
    it('should have a script for each preload link', async () => {
      const html = await next.render('/')
      const $ = cheerio.load(html)
      const preloadLinks = $('link[rel=preload]')
      preloadLinks.each((idx, element) => {
        const url = $(element).attr('href')
        expect($(`script[src="${url}"]`).length).toBe(1)
      })
    })
  }
})`
- ID 255: `test/e2e/gip-identifier/gip-identifier.test.ts` —
`describe('gip identifiers', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  const getNextData = async () => {
    const html = await next.render('/')
    const $ = cheerio.load(html)
    return JSON.parse($('#__NEXT_DATA__').text())
  }

it('should not have gip or appGip in NEXT_DATA for page without
getInitialProps', async () => {
    const data = await getNextData()
    expect(data.gip).toBe(undefined)
    expect(data.appGip).toBe(undefined)
  })

  if (isNextDev) {
it('should have gip in NEXT_DATA for page with getInitialProps', async
() => {
      await next.patchFile(
        'pages/index.js',
        `
        const Page = () => 'hi'
        Page.getInitialProps = () => ({ hello: 'world' })
        export default Page
      `
      )
      await retry(async () => {
        const data = await getNextData()
        expect(data.gip).toBe(true)
      })
    })

it('should have gip and appGip in NEXT_DATA for page with
getInitialProps and _app with getInitialProps', async () => {
      await next.patchFile(
        'pages/_app.js',
        `
const App = ({ Component, pageProps }) => <Component {...pageProps} />
        App.getInitialProps = async (ctx) => {
          let pageProps = {}
          if (ctx.Component.getInitialProps) {
            pageProps = await ctx.Component.getInitialProps(ctx.ctx)
          }
          return { pageProps }
        }
        export default App
      `
      )
      await retry(async () => {
        const data = await getNextData()
        expect(data.gip).toBe(true)
        expect(data.appGip).toBe(true)
      })
    })

it('should only have appGip in NEXT_DATA for page without
getInitialProps and _app with getInitialProps', async () => {
await next.patchFile('pages/index.js', `export default () => 'hi'\n`)
      await retry(async () => {
        const data = await getNextData()
        expect(data.gip).toBe(undefined)
        expect(data.appGip).toBe(true)
      })
    })
  }
})`
- ID 258:
`test/e2e/i18n-data-fetching-redirect/redirect-from-context.test.ts` —
`describe('i18n-data-fetching-redirect', () => {
  const { next } = nextTestSetup({
    files: {
      pages: new FileRef(join(__dirname, 'app/pages')),
'next.config.js': new FileRef(join(__dirname, 'app/next.config.js')),
    },
    dependencies: {},
  })

  describe('Redirect to locale from context', () => {
    test.each`
      path                       | locale
      ${'gssp-redirect'}         | ${'en'}
      ${'gssp-redirect'}         | ${'sv'}
      ${'gsp-blocking-redirect'} | ${'en'}
      ${'gsp-blocking-redirect'} | ${'sv'}
      ${'gsp-fallback-redirect'} | ${'en'}
      ${'gsp-fallback-redirect'} | ${'sv'}
    `('$path $locale', async ({ path, locale }) => {
      const browser = await next.browser(`/${locale}/${path}/from-ctx`)

      await check(
        () => browser.eval('window.location.pathname'),
        `/${locale}/home`
      )
expect(await browser.elementByCss('#router-locale').text()).toBe(locale)
expect(await browser.elementByCss('#router-pathname').text()).toBe(
        '/home'
      )
expect(await
browser.elementByCss('#router-as-path').text()).toBe('/home')
    })

    test.each`
      path                       | locale
      ${'gssp-redirect'}         | ${'en'}
      ${'gssp-redirect'}         | ${'sv'}
      ${'gsp-blocking-redirect'} | ${'en'}
      ${'gsp-blocking-redirect'} | ${'sv'}
      ${'gsp-fallback-redirect'} | ${'en'}
      ${'gsp-fallback-redirect'} | ${'sv'}
    `('next/link $path $locale', async ({ path, locale }) => {
      const browser = await next.browser(`/${locale}`)
      await browser.eval('window.beforeNav = 1')

      await browser.elementByCss(`#to-${path}-from-ctx`).click()

      await check(
        () => browser.eval('window.location.pathname'),
        `/${locale}/home`
      )

      expect(await browser.eval('window.beforeNav')).toBe(1)
expect(await browser.elementByCss('#router-locale').text()).toBe(locale)
expect(await browser.elementByCss('#router-pathname').text()).toBe(
        '/home'
      )
expect(await
browser.elementByCss('#router-as-path').text()).toBe('/home')
    })
  })
})`
- ID 261:
`test/e2e/i18n-ignore-rewrite-source-locale/rewrites-with-basepath.test.ts`
— `describe('i18n-ignore-rewrite-source-locale with basepath', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  test.each(locales)(
    'get public file by skipping locale in rewrite, locale: %s',
    async (locale) => {
      const res = await renderViaHTTP(
        next.url,
        `/basepath${locale}/rewrite-files/file.txt`
      )
      expect(res).toContain('hello from file.txt')
    }
  )

  test.each(locales)(
    'call api by skipping locale in rewrite, locale: %s',
    async (locale) => {
      const res = await renderViaHTTP(
        next.url,
        `/basepath${locale}/rewrite-api/hello`
      )
      expect(res).toContain('hello from api')
    }
  )

  // build artifacts aren't available on deploy
  if (!(global as any).isNextDeploy) {
    // chunks are not written to disk with TURBOPACK
    ;(process.env.IS_TURBOPACK_TEST ? it.skip.each : it.each)(locales)(
'get _next/static/ files by skipping locale in rewrite, locale: %s',
      async (locale) => {
        const chunks = (
          await fs.readdir(
            path.join(next.testDir, next.distDir, 'static', 'chunks')
          )
        ).filter((f) => f.endsWith('.js'))

        await Promise.all(
          chunks.map(async (file) => {
            const res = await fetchViaHTTP(
              next.url,
`/basepath${locale}/rewrite-files/_next/static/chunks/${file}`
            )
            // eslint-disable-next-line jest/no-standalone-expect
            expect(res.status).toBe(200)
          })
        )
      }
    )
  }
})`
- ID 267: `test/e2e/legacy-link-behavior/index.test.ts` —
`describe('Link with legacyBehavior', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  describe('if the child is an <a> tag', () => {
    it('forwards the href attribute', async () => {
      const $ = await next.render$('/')
      const $a = $('a[href="/about"]')

      expect($a.text()).toBe('About')
      expect($a.attr('href')).toBe('/about')
    })

    it('navigates correctly', async () => {
      const browser = await next.browser('/')
      await browser.elementByCss('a[href="/about"]').click()
      const title = await browser.elementByCss('#about-page').text()

      expect(title).toBe('About Page')
    })
  })

  it('works if the child is a number', async () => {
    const browser = await next.browser('/child-is-a-number')
    await browser.elementByCss('a[href="/about"]').click()
    const title = await browser.elementByCss('h1').text()

    expect(title).toBe('About Page')
  })

  it('works if the child is a string', async () => {
    const browser = await next.browser('/child-is-a-string')
    await browser.elementByCss('a[href="/about"]').click()
    const title = await browser.elementByCss('h1').text()

    expect(title).toBe('About Page')
  })

  it('errors when calling onClick without the event', async () => {
    const browser = await next.browser('/invalid-onclick')
    expect(await browser.elementByCss('#errors').text()).toBe('0')
    await browser.elementByCss('#custom-button').click()
    expect(await browser.elementByCss('#errors').text()).toBe('1')
  })

  it('should show a deprecation warning', async () => {
    const browser = await next.browser('/')

    await retry(async () => {
      const logs = await browser.log()
      const errors = logs.filter((log) => log.source === 'error')

      if (isNextDev) {
        expect(errors).toEqual([
          {
            message:
'`legacyBehavior` is deprecated and will be removed in a future release.
A codemod is available to upgrade your components:\n\n' +
              'npx @next/codemod@latest new-link .\n\n' +
'Learn more:
https://nextjs.org/docs/app/building-your-application/upgrading/codemods#remove-a-tags-from-link-components',
            source: 'error',
          },
        ])
      } else {
        expect(errors).toEqual([])
      }
    })
  })

  describe('passHref', () => {
    const expectHrefToBeForwardedInSSR = async (path: string) => {
      const $ = await next.render$(path)
      const $a = $('a[href="/about"]')
      expect($a.text()).toBe('About')
      expect($a.attr('href')).toBe('/about')
    }

    const expectLinkClickToNavigate = async (path: string) => {
      const browser = await next.browser(path)

      if (isNextDev) {
// We expect a deprecation warning (in a collapsed redbox), but no other
errors (e.g. no errors thrown by Link)
        await openRedbox(browser)
        expect(await createRedboxSnapshot(browser, next)).toEqual(
          expect.objectContaining<Partial<ErrorSnapshot>>({
            label: 'Console Error',
            description: expect.stringContaining(
`\`legacyBehavior\` is deprecated and will be removed in a future
release.`
            ),
          })
        )
await browser.locateRedbox().press('Escape') // Close redbox so we can
click the link
      }

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

      const title = await browser.elementByCss('h1').text()
      expect(title).toBe('About Page')
    }

    describe('with no prefech config', () => {
      it('forwards the href attribute', async () => {
        await expectHrefToBeForwardedInSSR('/passHref/default')
      })

      it('navigates correctly (failing)', async () => {
        if (isNextDev) {
// FIXME(NAR-876): false positive due to debug info blocking the child
          // await expectLinkClickToNavigate('/passHref/default')

          const browser = await next.browser('/passHref/default')
          await expect(browser).toDisplayRedbox(`
           {
"description": "\`<Link legacyBehavior>\` received a direct child that
is either a Server Component, or JSX that was loaded with React.lazy().
This is not supported. Either remove legacyBehavior, or make the direct
child a Client Component that renders the Link's \`<a>\` tag.",
             "environmentLabel": null,
             "label": "Runtime Error",
             "source": "app/passHref/default/page.tsx (7:7) @ Page
           >  7 |       <Link href="/about" legacyBehavior passHref>
                |       ^",
             "stack": [
               "Page app/passHref/default/page.tsx (7:7)",
             ],
           }
          `)
        } else {
          await expectLinkClickToNavigate('/passHref/default')
        }
      })
    })

    describe('with runtime prefetch', () => {
      it('forwards the href attribute', async () => {
        await expectHrefToBeForwardedInSSR('/passHref/runtime')
      })

      it('navigates correctly (failing)', async () => {
        if (isNextDev) {
// FIXME(NAR-876): false positive due to debug info blocking the child
          // await expectLinkClickToNavigate('/passHref/runtime')

          const browser = await next.browser('/passHref/runtime')
          await expect(browser).toDisplayRedbox(`
           {
"description": "\`<Link legacyBehavior>\` received a direct child that
is either a Server Component, or JSX that was loaded with React.lazy().
This is not supported. Either remove legacyBehavior, or make the direct
child a Client Component that renders the Link's \`<a>\` tag.",
             "environmentLabel": null,
             "label": "Runtime Error",
             "source": "app/passHref/runtime/page.tsx (9:7) @ Page
           >  9 |       <Link href="/about" legacyBehavior passHref>
                |       ^",
             "stack": [
               "Page app/passHref/runtime/page.tsx (9:7)",
             ],
           }
          `)
        } else {
          await expectLinkClickToNavigate('/passHref/runtime')
        }
      })
    })

    describe('in dynamic code', () => {
      it('forwards the href attribute', async () => {
        await expectHrefToBeForwardedInSSR('/passHref/dynamic')
      })

      it('navigates correctly', async () => {
        await expectLinkClickToNavigate('/passHref/dynamic')
      })
    })
  })
})`
- ID 270: `test/e2e/next-link-errors/next-link-errors.test.ts` —
`describe('next-link', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  it('errors on invalid href', async () => {
    const browser = await next.browser('/invalid-href')

    if (isNextDev) {
      await expect(browser).toDisplayRedbox(`
       {
"description": "Failed prop type: The prop \`href\` expects a \`string\`
or \`object\` in \`<Link>\`, but got \`undefined\` instead.
       Open your browser's console to view the Component stack trace.",
         "environmentLabel": null,
         "label": "Runtime Error",
         "source": "app/invalid-href/page.js (6:10) @ Hello
       > 6 |   return <Link>Hello, Dave!</Link>
           |          ^",
         "stack": [
           "Hello app/invalid-href/page.js (6:10)",
         ],
       }
      `)
    }
    // Client errors show "This page couldn\u2019t load"
    expect(await browser.elementByCss('body').text()).toContain(
      'This page couldn\u2019t load'
    )
  })

  it('invalid `prefetch` causes runtime error (dev-only)', async () => {
    const browser = await next.browser('/invalid-prefetch')

    if (isNextDev) {
      await expect(browser).toDisplayRedbox(`
       {
"description": "Failed prop type: The prop \`prefetch\` expects a
\`boolean | "auto"\` in \`<Link>\`, but got \`string\` instead.
       Open your browser's console to view the Component stack trace.",
         "environmentLabel": null,
         "label": "Runtime Error",
         "source": "app/invalid-prefetch/page.js (7:5) @ Hello
       >  7 |     <Link prefetch="unknown" href="https://nextjs.org/">
            |     ^",
         "stack": [
           "Hello app/invalid-prefetch/page.js (7:5)",
         ],
       }
      `)
      // Client errors show "This page couldn\u2019t load"
      expect(await browser.elementByCss('body').text()).toContain(
        'This page couldn\u2019t load'
      )
    } else {
expect(await browser.elementByCss('body').text()).toMatchInlineSnapshot(
        `"Link with unknown \`prefetch\` renders in prod."`
      )
    }
  })
})`
- ID 273: `test/e2e/pages-performance-mark/index.test.ts` —
`describe('pages performance mark', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

it('should render the page correctly without crashing with performance
mark', async () => {
    const browser = await next.browser('/')
    expect(await browser.elementByCss('h1').text()).toBe('home')
  })
})`

</details>

<details>
<summary>Deployment evidence for the additional scopes</summary>

- `test/e2e/404-page-custom-error/404-page-custom-error.test.ts` —
`describe('Default 404 Page with custom _error', () => {`:
[normal](https://github.com/vercel/next.js/actions/runs/34426785205/job/102715905641),
[cache](https://github.com/vercel/next.js/actions/runs/34426785205/job/102715905524).
- `test/e2e/404-page/404-page.test.ts` — `describe('404 Page Support',
() => {`:
[normal](https://github.com/vercel/next.js/actions/runs/34426785205/job/102715905631),
[cache](https://github.com/vercel/next.js/actions/runs/34426785205/job/102715905599).
-
`test/e2e/i18n-ignore-rewrite-source-locale/rewrites-with-basepath.test.ts`
— `describe('i18n-ignore-rewrite-source-locale with basepath', () => {`:
[normal](https://github.com/vercel/next.js/actions/runs/34426785205/job/102715905696),
[cache](https://github.com/vercel/next.js/actions/runs/34426785205/job/102715905562).

</details>

<!-- NEXT_JS_LLM -->
2026-09-15 10:29:06 -07:00

27 lines
756 B
TypeScript

import { nextTestSetup } from 'e2e-utils'
describe('api-resolver-query-writeable', () => {
const { next } = nextTestSetup({
files: __dirname,
startCommand: 'node server.js',
serverReadyPattern: /Next mode: (production|development)/,
dependencies: {
'get-port': '5.1.1',
express: '5.1.0',
},
})
it('should allow req.query to be writable and reflect changes made in the API handler', async () => {
const res = await next.fetch('/api?hello=yes', {
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
})
if (!res.ok) {
throw new Error('Fetch failed')
}
const data = await res.json()
expect(data).toEqual({ query: { hello: 'yes', changed: 'yes' } })
})
})