next.js/test/e2e/app-dir/cache-components-errors/cache-components-errors.prospective-errors.test.ts
cache-components-errors.prospective-errors.test.ts283 lines10.7 KB
import { nextTestSetup } from 'e2e-utils'

const isTurbopack = !!process.env.IS_TURBOPACK_TEST

describe(`Cache Components Prospective Render Errors - Debug Build`, () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname + '/fixtures/prospective-render-errors',
    env: { NEXT_DEBUG_BUILD: 'true' },
    // Accessing cliOutput is only available on the deployment
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  if (isNextDev) {
    // In next dev there really isn't a prospective render but we still assert we error on the first visit to each page
    it('should error on the first visit to each page', async () => {
      let res

      res = await next.fetch('/error')
      expect(res.status).toBe(500)
      res = await next.fetch('/error')
      expect(res.status).toBe(200)
      res = await next.fetch('/error')
      expect(res.status).toBe(200)

      res = await next.fetch('/routes/error')
      expect(res.status).toBe(500)
      res = await next.fetch('/routes/error')
      expect(res.status).toBe(200)
      res = await next.fetch('/routes/error')
      expect(res.status).toBe(200)

      res = await next.fetch('/null')
      expect(res.status).toBe(500)
      res = await next.fetch('/null')
      expect(res.status).toBe(200)
      res = await next.fetch('/null')
      expect(res.status).toBe(200)

      // To make disambiguating cli output in the prod tests I switch from null to undefined
      // for the routes version of this tests. really we're just asserting we get a coherent message
      // when the thrown value is not a string or Error so null or undefined is not very important itself
      res = await next.fetch('/routes/undefined')
      expect(res.status).toBe(500)
      res = await next.fetch('/routes/undefined')
      expect(res.status).toBe(200)
      res = await next.fetch('/routes/undefined')
      expect(res.status).toBe(200)

      res = await next.fetch('/object')
      expect(res.status).toBe(500)
      res = await next.fetch('/object')
      expect(res.status).toBe(200)
      res = await next.fetch('/object')
      expect(res.status).toBe(200)

      res = await next.fetch('/routes/object')
      expect(res.status).toBe(500)
      res = await next.fetch('/routes/object')
      expect(res.status).toBe(200)
      res = await next.fetch('/routes/object')
      expect(res.status).toBe(200)

      res = await next.fetch('/string')
      expect(res.status).toBe(500)
      res = await next.fetch('/string')
      expect(res.status).toBe(200)
      res = await next.fetch('/string')
      expect(res.status).toBe(200)

      res = await next.fetch('/routes/string')
      expect(res.status).toBe(500)
      res = await next.fetch('/routes/string')
      expect(res.status).toBe(200)
      res = await next.fetch('/routes/string')
      expect(res.status).toBe(200)
    })
  } else {
    it('should log an error when the prospective render errors with an Error in a Page', async () => {
      expect(next.cliOutput).toContain(
        'Error: Route /error errored during the prospective render.'
      )
      expect(next.cliOutput).toContain('Original Error: BOOM (Error)')
      if (!isTurbopack) {
        // In turbopack we don't yet support disabling minification so this assertion won't work
        expect(next.cliOutput).toContain('at ErrorFirstTime')
      }
    })

    it('should log an error when the prospective render errors with a string in a Page', async () => {
      expect(next.cliOutput).toContain(
        'Route /string errored during the prospective render.'
      )
      expect(next.cliOutput).toContain('Original Message: BOOM (string)')
    })

    it('should log an error when the prospective render errors with null in a Page', async () => {
      expect(next.cliOutput).toContain(
        'Route /null errored during the prospective render.'
      )
      expect(next.cliOutput).toContain('\nnull\n')
    })

    it('should log an error when the prospective render errors with an object in a Page', async () => {
      expect(next.cliOutput).toContain(
        'Route /object errored during the prospective render.'
      )
      expect(next.cliOutput).toContain("{ boom: '(Object)' }")
    })

    it('should log an error when the prospective render errors with an Error in a route', async () => {
      expect(next.cliOutput).toContain(
        'Error: Route /routes/error errored during the prospective render.'
      )
      expect(next.cliOutput).toContain('Original Error: BOOM (Error route)')
      if (!isTurbopack) {
        // In turbopack we don't yet support disabling minification so this assertion won't work
        expect(next.cliOutput).toContain('at errorFirstTime')
      }
    })

    it('should log an error when the prospective render errors with a string in a route', async () => {
      expect(next.cliOutput).toContain(
        'Route /routes/string errored during the prospective render.'
      )
      expect(next.cliOutput).toContain('Original Message: BOOM (string route)')
    })

    it('should log an error when the prospective render errors with undefined in a route', async () => {
      expect(next.cliOutput).toContain(
        'Route /routes/undefined errored during the prospective render.'
      )
      expect(next.cliOutput).toContain('\nundefined\n')
    })

    it('should log an error when the prospective render errors with an object in a route', async () => {
      expect(next.cliOutput).toContain(
        'Route /routes/object errored during the prospective render.'
      )
      expect(next.cliOutput).toContain("{ boom: '(Object route)' }")
    })
  }
})

describe(`Cache Components Prospective Render Errors - Standard Build`, () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname + '/fixtures/prospective-render-errors',
  })

  if (skipped) {
    return
  }

  if (isNextDev) {
    // In next dev there really isn't a prospective render but we still assert we error on the first visit to each page
    it('should error on the first visit to each page', async () => {
      let res

      res = await next.fetch('/error')
      expect(res.status).toBe(500)
      res = await next.fetch('/error')
      expect(res.status).toBe(200)
      res = await next.fetch('/error')
      expect(res.status).toBe(200)

      res = await next.fetch('/routes/error')
      expect(res.status).toBe(500)
      res = await next.fetch('/routes/error')
      expect(res.status).toBe(200)
      res = await next.fetch('/routes/error')
      expect(res.status).toBe(200)

      res = await next.fetch('/null')
      expect(res.status).toBe(500)
      res = await next.fetch('/null')
      expect(res.status).toBe(200)
      res = await next.fetch('/null')
      expect(res.status).toBe(200)

      // To make disambiguating cli output in the prod tests I switch from null to undefined
      // for the routes version of this tests. really we're just asserting we get a coherent message
      // when the thrown value is not a string or Error so null or undefined is not very important itself
      res = await next.fetch('/routes/undefined')
      expect(res.status).toBe(500)
      res = await next.fetch('/routes/undefined')
      expect(res.status).toBe(200)
      res = await next.fetch('/routes/undefined')
      expect(res.status).toBe(200)

      res = await next.fetch('/object')
      expect(res.status).toBe(500)
      res = await next.fetch('/object')
      expect(res.status).toBe(200)
      res = await next.fetch('/object')
      expect(res.status).toBe(200)

      res = await next.fetch('/routes/object')
      expect(res.status).toBe(500)
      res = await next.fetch('/routes/object')
      expect(res.status).toBe(200)
      res = await next.fetch('/routes/object')
      expect(res.status).toBe(200)

      res = await next.fetch('/string')
      expect(res.status).toBe(500)
      res = await next.fetch('/string')
      expect(res.status).toBe(200)
      res = await next.fetch('/string')
      expect(res.status).toBe(200)

      res = await next.fetch('/routes/string')
      expect(res.status).toBe(500)
      res = await next.fetch('/routes/string')
      expect(res.status).toBe(200)
      res = await next.fetch('/routes/string')
      expect(res.status).toBe(200)
    })
  } else {
    it('should not log an error when the prospective render errors with an Error in a Page', async () => {
      expect(next.cliOutput).not.toContain(
        'Error: Route /error errored during the prospective render.'
      )
      expect(next.cliOutput).not.toContain('Original Error: BOOM (Error)')
      expect(next.cliOutput).not.toContain('at ErrorFirstTime')
    })

    it('should not log an error when the prospective render errors with a string in a Page', async () => {
      expect(next.cliOutput).not.toContain(
        'Route /string errored during the prospective render.'
      )
      expect(next.cliOutput).not.toContain('Original Message: BOOM (string)')
    })

    it('should not log an error when the prospective render errors with null in a Page', async () => {
      expect(next.cliOutput).not.toContain(
        'Route /null errored during the prospective render.'
      )
      expect(next.cliOutput).not.toContain('\nnull\n')
    })

    it('should not log an error when the prospective render errors with an object in a Page', async () => {
      expect(next.cliOutput).not.toContain(
        'Route /object errored during the prospective render.'
      )
      expect(next.cliOutput).not.toContain("{ boom: '(Object)' }")
    })

    it('should not log an error when the prospective render errors with an Error in a route', async () => {
      expect(next.cliOutput).not.toContain(
        'Error: Route /routes/error errored during the prospective render.'
      )
      expect(next.cliOutput).not.toContain('Original Error: BOOM (Error route)')
      expect(next.cliOutput).not.toContain('at errorFirstTime')
    })

    it('should not log an error when the prospective render errors with a string in a route', async () => {
      expect(next.cliOutput).not.toContain(
        'Route /routes/string errored during the prospective render.'
      )
      expect(next.cliOutput).not.toContain(
        'Original Message: BOOM (string route)'
      )
    })

    it('should not log an error when the prospective render errors with undefined in a route', async () => {
      expect(next.cliOutput).not.toContain(
        'Route /routes/undefined errored during the prospective render.'
      )
      expect(next.cliOutput).not.toContain('\nundefined\n')
    })

    it('should not log an error when the prospective render errors with an object in a route', async () => {
      expect(next.cliOutput).not.toContain(
        'Route /routes/object errored during the prospective render.'
      )
      expect(next.cliOutput).not.toContain("{ boom: '(Object route)' }")
    })
  }
})
Quest for Codev2.0.0
/
SIGN IN