Files
vercel__next.js/test/e2e/app-dir/app-custom-cache-handler-errors/app-custom-cache-handler-errors.test.ts
Josh Story e0966df114 test: migrate caching deploy exclusions to force gates (#98154)
## Summary

- migrate Cache Components, PPR, prefetching, prerendering,
revalidation, and SSG deployment exclusions to `@force-gate`
- remove the corresponding `skipDeployment` options and `skipped`
control flow while preserving each suite's rationale

This keeps caching-related exclusions together so their deployed
semantics can be reviewed by the same owners.

## Verification

- verified on the combined top-of-stack tree with `pnpm typescript`
- compared ordinary-mode collection before and after: all 4,670 existing
test names matched
- collected all 510 affected files in deploy mode: 4,578 skipped tests,
zero failures

<!-- NEXT_JS_LLM -->
2026-09-09 08:25:36 -07:00

134 lines
4.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { nextTestSetup } from 'e2e-utils'
import { hasErrorToast, retry, waitFor, waitForNoRedbox } from 'next-test-utils'
import stripAnsi from 'strip-ansi'
// TODO(deploy-test-completion): Re-enable this suite in deploy mode.
// It likely asserts local CLI or runtime output that deploy tests do not expose.
// @force-gate !deploy
describe('app-custom-cache-handler-errors - get throws', () => {
const { next, isNextDev, isTurbopack } = nextTestSetup({
files: __dirname,
env: { CACHE_HANDLER_THROW_ON: 'get' },
})
it('surfaces the cache handler error', async () => {
const outputIndex = next.cliOutput.length
const browser = await next.browser('/?input=x')
if (isNextDev) {
if (isTurbopack) {
await expect(browser).toDisplayRedbox(`
{
"description": "CustomCacheHandler.get failed",
"environmentLabel": "Prefetch",
"label": "Runtime Error",
"source": "app/page.tsx (19:14) @ CachedData
> 19 | return <p>{await getCachedData(input)}</p>
| ^",
"stack": [
"Object.get throwing-cache-handler.js (24:13)",
"CachedData app/page.tsx (19:14)",
],
}
`)
} else {
// TODO(veil): Webpack renders the cache handler frame as a file://
// URL, which the redbox matcher flags as unintended.
await expect(browser).toDisplayRedbox(`
{
"description": "CustomCacheHandler.get failed",
"environmentLabel": "Prefetch",
"label": "Runtime Error",
"source": "app/page.tsx (19:14) @ CachedData
> 19 | return <p>{await getCachedData(input)}</p>
| ^",
"stack": [
"<FIXME-file-protocol>",
"CachedData app/page.tsx (19:14)",
],
}
`)
}
}
await retry(async () => {
expect(next.cliOutput.slice(outputIndex)).toContain(
' Error: CustomCacheHandler.get failed'
)
})
// Give a potential unhandled rejection a chance to be reported before
// asserting its absence.
await waitFor(1000)
const cliOutput = stripAnsi(next.cliOutput.slice(outputIndex))
const errorBlock = isNextDev
? 'Error: CustomCacheHandler.get failed' +
'\n at Object.get (throwing-cache-handler.js:24:13)' +
'\n at async CachedData (app/page.tsx:19:14)' +
"\n 17 | const { input = 'default' } = await searchParams" +
'\n 18 |' +
'\n> 19 | return <p>{await getCachedData(input)}</p>' +
'\n | ^' +
'\n 20 | }' +
'\n 21 |' +
'\n 22 | export default function Page({ {' +
"\n digest: '"
: // In production, the frames below the cache handler frame are bundled
// code, and are therefore not stable across bundlers and builds.
'Error: CustomCacheHandler.get failed' +
'\n at Object.get (throwing-cache-handler.js:24:13)' +
'\n at '
expect(cliOutput).toContain(' ' + errorBlock)
if (!isNextDev) {
expect(cliOutput).toContain(" digest: '")
}
// The error must be logged exactly once, as a rendering error, and in
// particular not additionally as an unhandled rejection.
expect(cliOutput).not.toContain('unhandledRejection')
expect(cliOutput.split(errorBlock).length - 1).toBe(1)
})
})
// TODO(deploy-test-completion): Re-enable this suite in deploy mode.
// It likely asserts local CLI or runtime output that deploy tests do not expose.
// @force-gate !deploy
describe('app-custom-cache-handler-errors - set throws', () => {
const { next, isNextDev } = nextTestSetup({
files: __dirname,
env: { CACHE_HANDLER_THROW_ON: 'set' },
})
it('renders the page successfully', async () => {
const outputIndex = next.cliOutput.length
const browser = await next.browser('/?input=x')
expect(await browser.elementByCss('p').text()).toBe(
'cached data for input: x'
)
if (isNextDev) {
// A throwing set() is currently completely silent in dev: the cache
// handler is called and its rejection is swallowed without being logged
// or reported to the dev overlay.
await waitForNoRedbox(browser)
expect(await hasErrorToast(browser)).toBe(false)
expect(next.cliOutput.slice(outputIndex)).not.toContain(
'CustomCacheHandler.set failed'
)
} else {
await retry(async () => {
expect(stripAnsi(next.cliOutput.slice(outputIndex))).toContain(
'Error: CustomCacheHandler.set failed' +
'\n at Object.set (throwing-cache-handler.js:50:13)' +
'\n at <unknown> ('
)
})
}
})
})