next.js/test/e2e/app-dir/proxy-missing-export/proxy-missing-export.test.ts
proxy-missing-export.test.ts143 lines4.3 KB
import { nextTestSetup } from 'e2e-utils'
import { join } from 'node:path'
import { writeFile } from 'node:fs/promises'

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

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

To fix it:
- Ensure this file has either a default or "proxy" function export.

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

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

  if (skipped) {
    return
  }

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

    let cliOutput: string

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

    // TODO: Investigate why in dev-turbo, the error is shown in the browser console, not CLI output.
    if (process.env.IS_TURBOPACK_TEST && !isNextDev) {
      expect(cliOutput).toContain(`./proxy.ts
Proxy is missing expected function export name
${errorMessage}`)
    } else {
      expect(cliOutput)
        .toContain(`The file "./proxy.ts" must export a function, either as a default export or as a named "proxy" export.
${errorMessage}`)
    }

    await next.stop()
  })

  it('should NOT error when proxy file has a default function export', async () => {
    await writeFile(
      join(next.testDir, 'proxy.ts'),
      'export default function handler() {}'
    )

    await next.start()

    const browser = await next.browser('/')
    expect(await browser.elementByCss('p').text()).toBe('hello world')

    await next.stop()
  })

  it('should NOT error when proxy file has a default arrow function export', async () => {
    await writeFile(join(next.testDir, 'proxy.ts'), 'export default () => {}')

    await next.start()

    const browser = await next.browser('/')
    expect(await browser.elementByCss('p').text()).toBe('hello world')

    await next.stop()
  })

  it('should NOT error when proxy file has a named declaration function export', async () => {
    await writeFile(
      join(next.testDir, 'proxy.ts'),
      'const proxy = function() {}; export { proxy };'
    )

    await next.start()

    const browser = await next.browser('/')
    expect(await browser.elementByCss('p').text()).toBe('hello world')

    await next.stop()
  })

  it('should NOT error when proxy file has a named declaration arrow function export', async () => {
    await writeFile(
      join(next.testDir, 'proxy.ts'),
      'const proxy = () => {}; export { proxy };'
    )

    await next.start()

    const browser = await next.browser('/')
    expect(await browser.elementByCss('p').text()).toBe('hello world')

    await next.stop()
  })

  it('should error when proxy file has a named export with different name alias', async () => {
    await writeFile(
      join(next.testDir, 'proxy.ts'),
      'const proxy = () => {}; export { proxy as handler };'
    )

    let cliOutput: string

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

    // TODO: Investigate why in dev-turbo, the error is shown in the browser console, not CLI output.
    if (process.env.IS_TURBOPACK_TEST && !isNextDev) {
      expect(cliOutput).toContain(`./proxy.ts
Proxy is missing expected function export name
${errorMessage}`)
    } else {
      expect(cliOutput)
        .toContain(`The file "./proxy.ts" must export a function, either as a default export or as a named "proxy" export.
${errorMessage}`)
    }
    await next.stop()
  })
})
Quest for Codev2.0.0
/
SIGN IN