mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
prefetching is now controlled with the prefetch export and this option is inert on the instant export. this removes the prefetch option as a valid property on the instant config type. also updates the ts plugin for this export and adds the definition for the previously landed prefetch export
956 lines
48 KiB
TypeScript
956 lines
48 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
import {
|
|
expectNoBuildValidationErrors,
|
|
extractBuildValidationError,
|
|
parseValidationMessages,
|
|
} from 'e2e-utils/instant-validation'
|
|
|
|
describe('instant-validation-build', () => {
|
|
const { next, skipped, isNextStart, isTurbopack } = nextTestSetup({
|
|
files: __dirname,
|
|
skipStart: true,
|
|
skipDeployment: true,
|
|
})
|
|
|
|
if (skipped) {
|
|
return
|
|
}
|
|
if (!isNextStart) {
|
|
it.skip('Build-time only test', () => {})
|
|
return
|
|
}
|
|
if (!isTurbopack) {
|
|
// TODO(instant-validation-build): snapshot tests for webpack
|
|
it.skip('TODO: snapshot tests for webpack', () => {})
|
|
return
|
|
}
|
|
|
|
const prerender = async (pathname: string) => {
|
|
const args = [
|
|
'--experimental-build-mode',
|
|
'generate',
|
|
'--debug-build-paths',
|
|
`app${pathname}/page.tsx`,
|
|
]
|
|
return await next.build({
|
|
args,
|
|
env: {
|
|
NEXT_TEST_LOG_VALIDATION: '1',
|
|
},
|
|
})
|
|
}
|
|
|
|
beforeAll(async () => {
|
|
await next.build({ args: ['--experimental-build-mode', 'compile'] })
|
|
})
|
|
|
|
describe('basic dynamic hole detection', () => {
|
|
// We have extensive tests for this in the instant-validation test suite.
|
|
// This is just a basic test that we can validate a runtime prefetch, which static shell validation can't do.
|
|
describe('valid - suspense around runtime', () => {
|
|
it('should succeed build when cookies are inside Suspense', async () => {
|
|
const result = await prerender(
|
|
'/(default)/valid-suspense-around-runtime'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
})
|
|
|
|
describe('invalid - missing suspense around runtime', () => {
|
|
it('should fail build when cookies are outside Suspense', async () => {
|
|
const result = await prerender(
|
|
'/(default)/invalid-missing-suspense-around-runtime'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/invalid-missing-suspense-around-runtime": Next.js encountered uncached data during the initial render.
|
|
|
|
\`fetch(...)\` or \`connection()\` accessed outside of \`<Suspense>\` blocks navigation, leading to a slower user experience.
|
|
|
|
Ways to fix this:
|
|
- Cache the data access with \`"use cache"\`
|
|
- Move the data access into a child component within a <Suspense> boundary
|
|
- Set \`export const instant = false\` to allow a blocking route
|
|
|
|
Learn more: https://nextjs.org/docs/messages/blocking-route
|
|
at main (<anonymous>)
|
|
at body (<anonymous>)
|
|
at html (<anonymous>)
|
|
Build-time instant validation failed for route "/invalid-missing-suspense-around-runtime".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/invalid-missing-suspense-around-runtime" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('server errors', () => {
|
|
it('valid - ignores server errors that do not surface in SSR', async () => {
|
|
const result = await prerender(
|
|
'/(default)/server-errors/error-passed-to-client-and-ignored'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput)).toBe('')
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('error - server error that blocks page validation with no suspense boundary', async () => {
|
|
const result = await prerender('/(default)/server-errors/page-throws')
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/server-errors/page-throws": Could not validate \`unstable_instant\` because an error prevented the target segment from rendering.
|
|
at main (<anonymous>)
|
|
at body (<anonymous>)
|
|
at html (<anonymous>) {
|
|
[cause]: Error: Kaboom
|
|
at a (app/(default)/server-errors/page-throws/page.tsx:22:9)
|
|
20 | async function Throws(): Promise<never> {
|
|
21 | await cookies()
|
|
> 22 | throw new Error('Kaboom')
|
|
| ^
|
|
23 | }
|
|
24 | {
|
|
digest: '<error-digest>'
|
|
}
|
|
}
|
|
Build-time instant validation failed for route "/server-errors/page-throws".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/server-errors/page-throws" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - server error that blocks page validation with a suspense boundary in a parent segment', async () => {
|
|
const result = await prerender(
|
|
'/(default)/server-errors/page-throws-with-suspense'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/server-errors/page-throws-with-suspense": Could not validate \`unstable_instant\` because an error prevented the target segment from rendering.
|
|
at main (<anonymous>)
|
|
at a (<anonymous>)
|
|
at body (<anonymous>)
|
|
at html (<anonymous>) {
|
|
[cause]: Error: Kaboom
|
|
at b (app/(default)/server-errors/page-throws-with-suspense/page.tsx:22:9)
|
|
20 | async function Throws(): Promise<never> {
|
|
21 | await cookies()
|
|
> 22 | throw new Error('Kaboom')
|
|
| ^
|
|
23 | }
|
|
24 | {
|
|
digest: '<error-digest>'
|
|
}
|
|
}
|
|
Build-time instant validation failed for route "/server-errors/page-throws-with-suspense".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/server-errors/page-throws-with-suspense" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
})
|
|
|
|
describe('client errors', () => {
|
|
it('error - server error that blocks page validation with no suspense boundary', async () => {
|
|
const result = await prerender('/(default)/client-errors/page-throws')
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/client-errors/page-throws": Could not validate \`unstable_instant\` because an error prevented the target segment from rendering.
|
|
at <unknown> (app/(default)/client-errors/page-throws/client.tsx:6:3)
|
|
at main (<anonymous>)
|
|
at body (<anonymous>)
|
|
at html (<anonymous>)
|
|
4 |
|
|
5 | export function ThrowsInClient(): Promise<never> {
|
|
> 6 | useSearchParams()
|
|
| ^
|
|
7 | throw new Error('Kaboom')
|
|
8 | }
|
|
9 | {
|
|
[cause]: Error: Kaboom
|
|
at <unknown> (app/(default)/client-errors/page-throws/client.tsx:7:9)
|
|
5 | export function ThrowsInClient(): Promise<never> {
|
|
6 | useSearchParams()
|
|
> 7 | throw new Error('Kaboom')
|
|
| ^
|
|
8 | }
|
|
9 |
|
|
}
|
|
Build-time instant validation failed for route "/client-errors/page-throws".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/client-errors/page-throws" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - client error that blocks page validation with a suspense boundary in a parent segment', async () => {
|
|
const result = await prerender(
|
|
'/(default)/client-errors/page-throws-with-suspense'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/client-errors/page-throws-with-suspense": Could not validate \`unstable_instant\` because an error prevented the target segment from rendering.
|
|
at <unknown> (app/(default)/client-errors/page-throws-with-suspense/client.tsx:6:3)
|
|
at main (<anonymous>)
|
|
at a (<anonymous>)
|
|
at body (<anonymous>)
|
|
at html (<anonymous>)
|
|
4 |
|
|
5 | export function ThrowsInClient(): Promise<never> {
|
|
> 6 | useSearchParams()
|
|
| ^
|
|
7 | throw new Error('Kaboom')
|
|
8 | }
|
|
9 | {
|
|
[cause]: Error: Kaboom
|
|
at <unknown> (app/(default)/client-errors/page-throws-with-suspense/client.tsx:7:9)
|
|
5 | export function ThrowsInClient(): Promise<never> {
|
|
6 | useSearchParams()
|
|
> 7 | throw new Error('Kaboom')
|
|
| ^
|
|
8 | }
|
|
9 |
|
|
}
|
|
Build-time instant validation failed for route "/client-errors/page-throws-with-suspense".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/client-errors/page-throws-with-suspense" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
})
|
|
|
|
describe('searchParams', () => {
|
|
it('search params are correctly read from samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/search-params/valid-search-params-in-samples'
|
|
)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('error - accessing search param not present in samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/search-params/invalid-undeclared-search-param'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/search-params/invalid-undeclared-search-param" accessed searchParam "undeclared" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`searchParams\` object, or \`{ "undeclared": null }\` if it should be absent.
|
|
at <unknown> (app/(default)/search-params/invalid-undeclared-search-param/page.tsx:29:14)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/search-params/invalid-undeclared-search-param/page.tsx:28:3)
|
|
27 | const sp = await searchParams
|
|
28 | ensureThrows(
|
|
> 29 | () => sp.undeclared,
|
|
| ^
|
|
30 | \`Expected accessing an undeclared search param to throw\`
|
|
31 | )
|
|
32 | return null {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/search-params/invalid-undeclared-search-param".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/search-params/invalid-undeclared-search-param" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('useSearchParams() receives search params from samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/search-params/valid-use-search-params'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('error - accessing search param not present in samples and catching the error', async () => {
|
|
const result = await prerender(
|
|
'/(default)/search-params/invalid-undeclared-search-param-caught'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/search-params/invalid-undeclared-search-param-caught" accessed searchParam "undeclared" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`searchParams\` object, or \`{ "undeclared": null }\` if it should be absent.
|
|
at <unknown> (app/(default)/search-params/invalid-undeclared-search-param-caught/page.tsx:33:16)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/search-params/invalid-undeclared-search-param-caught/page.tsx:32:5)
|
|
31 | try {
|
|
32 | ensureThrows(
|
|
> 33 | () => sp.undeclared,
|
|
| ^
|
|
34 | \`Expected accessing an undeclared search param to throw\`
|
|
35 | )
|
|
36 | } catch (err) { {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/search-params/invalid-undeclared-search-param-caught".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/search-params/invalid-undeclared-search-param-caught" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - accessing undeclared search param via useSearchParams()', async () => {
|
|
const result = await prerender(
|
|
'/(default)/search-params/invalid-undeclared-use-search-params'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/search-params/invalid-undeclared-use-search-params" accessed searchParam "undeclared" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`searchParams\` object, or \`{ "undeclared": null }\` if it should be absent.
|
|
at <unknown> (app/(default)/search-params/invalid-undeclared-use-search-params/search-params-reader.tsx:9:14)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at <unknown> (app/(default)/search-params/invalid-undeclared-use-search-params/search-params-reader.tsx:8:3)
|
|
7 | const sp = useSearchParams()
|
|
8 | ensureThrows(
|
|
> 9 | () => sp.get('undeclared'),
|
|
| ^
|
|
10 | \`Expected accessing an undeclared search param to throw\`
|
|
11 | )
|
|
12 | return null {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/search-params/invalid-undeclared-use-search-params".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/search-params/invalid-undeclared-use-search-params" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - accessing undeclared search param via useSearchParams() and catching the error', async () => {
|
|
const result = await prerender(
|
|
'/(default)/search-params/invalid-undeclared-use-search-params-caught'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/search-params/invalid-undeclared-use-search-params-caught" accessed searchParam "undeclared" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`searchParams\` object, or \`{ "undeclared": null }\` if it should be absent.
|
|
at <unknown> (app/(default)/search-params/invalid-undeclared-use-search-params-caught/search-params-reader.tsx:10:16)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at <unknown> (app/(default)/search-params/invalid-undeclared-use-search-params-caught/search-params-reader.tsx:9:5)
|
|
8 | try {
|
|
9 | ensureThrows(
|
|
> 10 | () => sp.get('undeclared'),
|
|
| ^
|
|
11 | \`Expected accessing an undeclared search param to throw\`
|
|
12 | )
|
|
13 | } catch { {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/search-params/invalid-undeclared-use-search-params-caught".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/search-params/invalid-undeclared-use-search-params-caught" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('valid - awaited search params passed to a cache', async () => {
|
|
const result = await prerender(
|
|
'/(default)/search-params/valid-search-params-passed-to-cache'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('valid - awaited search params passed to a client component', async () => {
|
|
const result = await prerender(
|
|
'/(default)/search-params/valid-search-params-passed-to-client'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
})
|
|
|
|
describe('headers', () => {
|
|
it('headers are correctly read from samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/headers/valid-headers-in-samples'
|
|
)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('error - .get() of header not present in samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/headers/invalid-undeclared-header-get'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/headers/invalid-undeclared-header-get" accessed header "undeclaredheader" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`headers\` array, or \`["undeclaredheader", null]\` if it should be absent.
|
|
at <unknown> (app/(default)/headers/invalid-undeclared-header-get/page.tsx:25:24)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/headers/invalid-undeclared-header-get/page.tsx:24:3)
|
|
23 | const headersStore = await headers()
|
|
24 | ensureThrows(
|
|
> 25 | () => headersStore.get('undeclaredHeader'),
|
|
| ^
|
|
26 | \`Expected get() to throw for undeclared headers\`
|
|
27 | )
|
|
28 | return null {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/headers/invalid-undeclared-header-get".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/headers/invalid-undeclared-header-get" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - .get() of header not present in samples and catching the error', async () => {
|
|
const result = await prerender(
|
|
'/(default)/headers/invalid-undeclared-header-get-caught'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/headers/invalid-undeclared-header-get-caught" accessed header "undeclaredheader" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`headers\` array, or \`["undeclaredheader", null]\` if it should be absent.
|
|
at <unknown> (app/(default)/headers/invalid-undeclared-header-get-caught/page.tsx:28:25)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/headers/invalid-undeclared-header-get-caught/page.tsx:27:5)
|
|
26 | try {
|
|
27 | ensureThrows(
|
|
> 28 | () => headerStore.get('undeclaredHeader'),
|
|
| ^
|
|
29 | \`Expected get() to throw for undeclared headers\`
|
|
30 | )
|
|
31 | } catch (err) { {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/headers/invalid-undeclared-header-get-caught".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/headers/invalid-undeclared-header-get-caught" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - .has() of header not present in samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/headers/invalid-undeclared-header-has'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/headers/invalid-undeclared-header-has" accessed header "undeclaredheader" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`headers\` array, or \`["undeclaredheader", null]\` if it should be absent.
|
|
at <unknown> (app/(default)/headers/invalid-undeclared-header-has/page.tsx:25:23)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/headers/invalid-undeclared-header-has/page.tsx:24:3)
|
|
23 | const headerStore = await headers()
|
|
24 | ensureThrows(
|
|
> 25 | () => headerStore.has('undeclaredHeader'),
|
|
| ^
|
|
26 | \`Expected has() to throw for undeclared headers\`
|
|
27 | )
|
|
28 | return null {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/headers/invalid-undeclared-header-has".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/headers/invalid-undeclared-header-has" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('valid - header value passed to a cache', async () => {
|
|
const result = await prerender(
|
|
'/(default)/headers/valid-headers-passed-to-cache'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('valid - header value passed to a client component', async () => {
|
|
const result = await prerender(
|
|
'/(default)/headers/valid-headers-passed-to-client'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
})
|
|
|
|
describe('cookies', () => {
|
|
it('cookies are correctly read from samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/cookies/valid-cookies-in-samples'
|
|
)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('error - .get() of cookie not present in samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/cookies/invalid-undeclared-cookie-get'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/cookies/invalid-undeclared-cookie-get" accessed cookie "undeclaredCookie" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`cookies\` array, or \`{ name: "undeclaredCookie", value: null }\` if it should be absent.
|
|
at <unknown> (app/(default)/cookies/invalid-undeclared-cookie-get/page.tsx:26:23)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/cookies/invalid-undeclared-cookie-get/page.tsx:25:3)
|
|
24 |
|
|
25 | ensureThrows(
|
|
> 26 | () => cookieStore.get('undeclaredCookie'),
|
|
| ^
|
|
27 | \`Expected get() to throw for undeclared cookies\`
|
|
28 | )
|
|
29 | return null {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/cookies/invalid-undeclared-cookie-get".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/cookies/invalid-undeclared-cookie-get" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - .get() of cookie not present in samples and catching the error', async () => {
|
|
const result = await prerender(
|
|
'/(default)/cookies/invalid-undeclared-cookie-get-caught'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/cookies/invalid-undeclared-cookie-get-caught" accessed cookie "undeclaredCookie" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`cookies\` array, or \`{ name: "undeclaredCookie", value: null }\` if it should be absent.
|
|
at <unknown> (app/(default)/cookies/invalid-undeclared-cookie-get-caught/page.tsx:28:25)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/cookies/invalid-undeclared-cookie-get-caught/page.tsx:27:5)
|
|
26 | try {
|
|
27 | ensureThrows(
|
|
> 28 | () => cookieStore.get('undeclaredCookie'),
|
|
| ^
|
|
29 | \`Expected get() to throw for undeclared cookies\`
|
|
30 | )
|
|
31 | } catch (err) { {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/cookies/invalid-undeclared-cookie-get-caught".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/cookies/invalid-undeclared-cookie-get-caught" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - .has() of cookie not present in samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/cookies/invalid-undeclared-cookie-has'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/cookies/invalid-undeclared-cookie-has" accessed cookie "undeclaredCookie" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`cookies\` array, or \`{ name: "undeclaredCookie", value: null }\` if it should be absent.
|
|
at <unknown> (app/(default)/cookies/invalid-undeclared-cookie-has/page.tsx:25:23)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/cookies/invalid-undeclared-cookie-has/page.tsx:24:3)
|
|
23 | const cookieStore = await cookies()
|
|
24 | ensureThrows(
|
|
> 25 | () => cookieStore.has('undeclaredCookie'),
|
|
| ^
|
|
26 | \`Expected has() to throw for undeclared cookies\`
|
|
27 | )
|
|
28 | return null {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/cookies/invalid-undeclared-cookie-has".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/cookies/invalid-undeclared-cookie-has" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('valid - cookies passed to a cache', async () => {
|
|
const result = await prerender(
|
|
'/(default)/cookies/valid-cookies-passed-to-cache'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
})
|
|
|
|
describe('params', () => {
|
|
it('valid - params are correctly read from samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/params/valid-params-in-samples/[one]/[two]'
|
|
)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('error - reading a param not present in samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/params/invalid-param-not-provided/[one]/[two]'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/params/invalid-param-not-provided/[one]/[two]" accessed param "two" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`params\` object.
|
|
at <unknown> (app/(default)/params/invalid-param-not-provided/[one]/[two]/page.tsx:47:24)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/params/invalid-param-not-provided/[one]/[two]/page.tsx:47:3)
|
|
45 |
|
|
46 | // We're not allowed to access params not in the samples.
|
|
> 47 | ensureThrows(() => p.two)
|
|
| ^
|
|
48 |
|
|
49 | // TODO: test \`in\` and iteration
|
|
50 | // assert.deepStrictEqual( {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/params/invalid-param-not-provided/[one]/[two]".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/params/invalid-param-not-provided/[one]/[two]" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - reading a param not present in samples and catching the error', async () => {
|
|
const result = await prerender(
|
|
'/(default)/params/invalid-param-not-provided-caught/[one]/[two]'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/params/invalid-param-not-provided-caught/[one]/[two]" accessed param "two" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`params\` object.
|
|
at <unknown> (app/(default)/params/invalid-param-not-provided-caught/[one]/[two]/page.tsx:45:26)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at a (app/(default)/params/invalid-param-not-provided-caught/[one]/[two]/page.tsx:45:5)
|
|
43 | try {
|
|
44 | // We're not allowed to access params not in the samples.
|
|
> 45 | ensureThrows(() => p.two, \`Expected accessing an undeclared param to throw\`)
|
|
| ^
|
|
46 | } catch (err) {
|
|
47 | // We swallow the error. It should still be reported and fail the validation.
|
|
48 | } {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/params/invalid-param-not-provided-caught/[one]/[two]".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/params/invalid-param-not-provided-caught/[one]/[two]" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('useParams() receives params from samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/params/valid-use-params/[one]/[two]'
|
|
)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('error - accessing a param not present in samples via useParams()', async () => {
|
|
const result = await prerender(
|
|
'/(default)/params/invalid-undeclared-use-params/[one]/[two]'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/params/invalid-undeclared-use-params/[one]/[two]" accessed param "two" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`params\` object.
|
|
at <unknown> (app/(default)/params/invalid-undeclared-use-params/[one]/[two]/params-reader.tsx:10:18)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at <unknown> (app/(default)/params/invalid-undeclared-use-params/[one]/[two]/params-reader.tsx:9:3)
|
|
8 | // We're not allowed to access params not in the samples.
|
|
9 | ensureThrows(
|
|
> 10 | () => params.two,
|
|
| ^
|
|
11 | \`Expected accessing an undeclared param to throw\`
|
|
12 | )
|
|
13 | return null {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/params/invalid-undeclared-use-params/[one]/[two]".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/params/invalid-undeclared-use-params/[one]/[two]" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - accessing a param not present in samples via useParams() and catching the error', async () => {
|
|
const result = await prerender(
|
|
'/(default)/params/invalid-undeclared-use-params-caught/[one]/[two]'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/params/invalid-undeclared-use-params-caught/[one]/[two]" accessed param "two" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`params\` object.
|
|
at <unknown> (app/(default)/params/invalid-undeclared-use-params-caught/[one]/[two]/params-reader.tsx:11:20)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at <unknown> (app/(default)/params/invalid-undeclared-use-params-caught/[one]/[two]/params-reader.tsx:10:5)
|
|
9 | // We're not allowed to access params not in the samples.
|
|
10 | ensureThrows(
|
|
> 11 | () => params.two,
|
|
| ^
|
|
12 | \`Expected accessing an undeclared param to throw\`
|
|
13 | )
|
|
14 | } catch { {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/params/invalid-undeclared-use-params-caught/[one]/[two]".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/params/invalid-undeclared-use-params-caught/[one]/[two]" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('valid - awaited params passed to a cache', async () => {
|
|
const result = await prerender(
|
|
'/(default)/params/valid-params-passed-to-cache/[slug]'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('valid - awaited params passed to a client component', async () => {
|
|
const result = await prerender(
|
|
'/(default)/params/valid-params-passed-to-client/[slug]'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
})
|
|
|
|
describe('pathname', () => {
|
|
it('valid - usePathname() on a route without params', async () => {
|
|
const result = await prerender(
|
|
'/(default)/pathname/valid-use-pathname-no-params'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('valid - usePathname() on a route with params (all provided in samples)', async () => {
|
|
const result = await prerender(
|
|
'/(default)/pathname/valid-use-pathname-with-params/[one]/[two]'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('valid - usePathname() on a route inside a route group does not include the group segment', async () => {
|
|
const result = await prerender(
|
|
'/(default)/pathname/valid-use-pathname-route-group/(route-group)'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('valid - usePathname() on a catch-all route', async () => {
|
|
const result = await prerender(
|
|
'/(default)/pathname/valid-use-pathname-catch-all/[...catchAll]'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('valid - usePathname() on an optional catch-all route', async () => {
|
|
const result = await prerender(
|
|
'/(default)/pathname/valid-use-pathname-optional-catch-all/[[...optionalCatchAll]]'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('error - usePathname() on a route with params but not all provided in samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/pathname/invalid-use-pathname-missing-params/[one]/[two]'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/pathname/invalid-use-pathname-missing-params/[one]/[two]" called usePathname() but param "two" is not defined in the \`samples\` of \`unstable_instant\`. usePathname() requires all route params to be provided.
|
|
at <unknown> (app/(default)/pathname/invalid-use-pathname-missing-params/[one]/[two]/pathname-reader.tsx:9:11)
|
|
at <unknown> (ensure-error.ts:11:5)
|
|
at <unknown> (app/(default)/pathname/invalid-use-pathname-missing-params/[one]/[two]/pathname-reader.tsx:7:3)
|
|
7 | ensureThrows(
|
|
8 | // eslint-disable-next-line react-hooks/rules-of-hooks
|
|
> 9 | () => usePathname(),
|
|
| ^
|
|
10 | \`Expected usePathname() to throw when not all params are provided in samples\`
|
|
11 | )
|
|
12 | return null {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/pathname/invalid-use-pathname-missing-params/[one]/[two]".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/pathname/invalid-use-pathname-missing-params/[one]/[two]" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
})
|
|
|
|
describe('root params', () => {
|
|
it.each(['static', 'runtime'])(
|
|
'valid - %s - root params are correctly read from samples',
|
|
async (variant) => {
|
|
const result = await prerender(
|
|
`/root-params/[lang]/valid-root-param-in-samples/${variant}`
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
// The page asserts on the values
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
}
|
|
)
|
|
|
|
it('error - reading a root param not present in samples', async () => {
|
|
const result = await prerender(
|
|
'/root-params/[lang]/invalid-root-param-not-provided'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/root-params/[lang]/invalid-root-param-not-provided" accessed root param "lang" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`params\` object.
|
|
at <unknown> (app/root-params/[lang]/invalid-root-param-not-provided/page.tsx:17:11)
|
|
at a (ensure-error.ts:48:11)
|
|
at b (app/root-params/[lang]/invalid-root-param-not-provided/page.tsx:16:9)
|
|
15 |
|
|
16 | await ensureRejects(
|
|
> 17 | () => lang(),
|
|
| ^
|
|
18 | \`Expected lang() to error if sample is not provided\`
|
|
19 | )
|
|
20 | return ( {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/root-params/[lang]/invalid-root-param-not-provided".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/root-params/[lang]/invalid-root-param-not-provided" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
|
|
it('error - reading a root param not present in samples and catching the error', async () => {
|
|
const result = await prerender(
|
|
'/root-params/[lang]/invalid-root-param-not-provided-caught'
|
|
)
|
|
expect(extractBuildValidationError(result.cliOutput))
|
|
.toMatchInlineSnapshot(`
|
|
"Error: Route "/root-params/[lang]/invalid-root-param-not-provided-caught" accessed root param "lang" which is not defined in the \`samples\` of \`unstable_instant\`. Add it to the sample's \`params\` object.
|
|
at <unknown> (app/root-params/[lang]/invalid-root-param-not-provided-caught/page.tsx:18:13)
|
|
at a (ensure-error.ts:48:11)
|
|
at b (app/root-params/[lang]/invalid-root-param-not-provided-caught/page.tsx:17:11)
|
|
16 | try {
|
|
17 | await ensureRejects(
|
|
> 18 | () => lang(),
|
|
| ^
|
|
19 | \`Expected lang() to error if sample is not provided\`
|
|
20 | )
|
|
21 | } catch { {
|
|
digest: 'INSTANT_VALIDATION_ERROR'
|
|
}
|
|
Build-time instant validation failed for route "/root-params/[lang]/invalid-root-param-not-provided-caught".
|
|
To get a more detailed stack trace and pinpoint the issue, try one of the following:
|
|
- Start the app in development mode by running \`next dev\`, then open "/root-params/[lang]/invalid-root-param-not-provided-caught" in your browser to investigate the error.
|
|
- Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.
|
|
Stopping prerender due to instant validation errors."
|
|
`)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
expect(result.exitCode).toBe(1)
|
|
})
|
|
})
|
|
|
|
describe('samples precedence', () => {
|
|
it('page samples override layout samples', async () => {
|
|
const result = await prerender(
|
|
'/(default)/samples-precedence/[slug]/page-overrides'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
|
|
it('page inherits samples from layout when it has none', async () => {
|
|
const result = await prerender(
|
|
'/(default)/samples-precedence/[slug]/page-inherits'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
})
|
|
|
|
describe('generateStaticParams', () => {
|
|
it('valid - page with generateStaticParams and samples only runs validation once', async () => {
|
|
const result = await prerender('/(default)/gsp/[slug]')
|
|
|
|
// If validation ran once, we expect one "validation_start"/"validation_end" pair
|
|
const validationMessages = parseValidationMessages(result.cliOutput)
|
|
expect(validationMessages).toEqual([
|
|
expect.objectContaining({ type: 'validation_start' }),
|
|
expect.objectContaining({ type: 'validation_end' }),
|
|
])
|
|
|
|
expectNoBuildValidationErrors(result)
|
|
expect(result.cliOutput).not.toContain('AssertionError')
|
|
})
|
|
})
|
|
|
|
describe('caches', () => {
|
|
it('valid - static prefetch - awaiting a cache in the static stage does not require a suspense boundary', async () => {
|
|
const result = await prerender(
|
|
'/(default)/valid-await-cache-without-suspense/static'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('valid - runtime prefetch - awaiting a cache in the runtime stage does not require a suspense boundary', async () => {
|
|
const result = await prerender(
|
|
'/(default)/valid-await-cache-without-suspense/runtime'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('valid - runtime prefetch - awaiting a mix of caches in the static and runtime stages does not require a suspense boundary', async () => {
|
|
const result = await prerender(
|
|
'/(default)/valid-await-cache-without-suspense/mixed'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
|
|
it('valid - runtime prefetch - awaiting a private cache in the runtime stage does not require a suspense boundary', async () => {
|
|
const result = await prerender(
|
|
'/(default)/valid-await-cache-without-suspense/private'
|
|
)
|
|
expectNoBuildValidationErrors(result)
|
|
})
|
|
})
|
|
})
|