Files
vercel__next.js/test/e2e/app-dir/use-cache-close-over-function/use-cache-close-over-function.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

132 lines
4.9 KiB
TypeScript

import { nextTestSetup } from 'e2e-utils'
import {
waitForRedbox,
getRedboxDescription,
getRedboxSource,
openRedbox,
} 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('use-cache-close-over-function', () => {
const { next, isNextDev, isTurbopack } = nextTestSetup({
files: __dirname,
skipStart: process.env.NEXT_TEST_MODE !== 'dev',
})
if (isNextDev) {
it('should show an error toast for client-side usage', async () => {
const outputIndex = next.cliOutput.length
const browser = await next.browser('/client')
await openRedbox(browser)
const errorDescription = await getRedboxDescription(browser)
const errorSource = await getRedboxSource(browser)
expect(errorDescription).toMatchInlineSnapshot(`
"Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.
[function fn]
^^^^^^^^^^^"
`)
expect(errorSource).toMatchInlineSnapshot(`
"app/client/page.tsx (8:3) @ createCachedFn
6 | }
7 |
> 8 | return async () => {
| ^
9 | 'use cache'
10 | return Math.random() + fn()
11 | }"
`)
const cliOutput = stripAnsi(next.cliOutput.slice(outputIndex))
expect(cliOutput).toContain(
'' +
'Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.' +
'\n [function fn]' +
'\n ^^^^^^^^^^^' +
'\n at createCachedFn (app/client/page.tsx:8:3)' +
'\n at Page (app/client/page.tsx:15:28)' +
'\n 6 | }' +
'\n 7 |' +
'\n> 8 | return async () => {' +
'\n | ^' +
"\n 9 | 'use cache'" +
'\n 10 | return Math.random() + fn()' +
'\n 11 | }'
)
})
it('should show the error overlay for server-side usage', async () => {
const outputIndex = next.cliOutput.length
const browser = await next.browser('/server')
await waitForRedbox(browser)
const errorDescription = await getRedboxDescription(browser)
const errorSource = await getRedboxSource(browser)
expect(errorDescription).toMatchInlineSnapshot(`
"Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.
[function fn]
^^^^^^^^^^^"
`)
expect(errorSource).toMatchInlineSnapshot(`
"app/server/page.tsx (6:3) @ createCachedFn
4 | }
5 |
> 6 | return async () => {
| ^
7 | 'use cache'
8 | return Math.random() + fn()
9 | }"
`)
const cliOutput = stripAnsi(next.cliOutput.slice(outputIndex))
expect(cliOutput).toContain(
isTurbopack
? '' +
'Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.' +
'\n [function fn]' +
'\n ^^^^^^^^^^^' +
'\n at createCachedFn (app/server/page.tsx:6:3)' +
'\n at module evaluation (app/server/page.tsx:12:24)'
: '' +
'Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.' +
'\n [function fn]' +
'\n ^^^^^^^^^^^' +
'\n at createCachedFn (app/server/page.tsx:6:3)' +
'\n at eval (app/server/page.tsx:12:24)' +
// TODO(veil): Should be source-mapped.
'\n at <unknown> (rsc)'
)
expect(cliOutput).toContain(
'' +
'\n> 6 | return async () => {' +
'\n | ^' +
"\n 7 | 'use cache'"
)
})
} else {
it('should fail the build with an error', async () => {
const { cliOutput } = await next.build()
expect(cliOutput).toInclude(`
Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.
[function]
^^^^^^^^`)
expect(cliOutput).toMatch(
/Error occurred prerendering page "\/(client|server)"/
)
})
}
})