Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a2d38ee

Browse files
committed
Add a test case to avoid regression on sequential function calling
After moving the test case for the parent handling to a route that does not have dynamic params, we now need this additional case to ensure that the sequential calling of cached `generateMetadata`/`generateViewport` functions is indeed required to avoid a timeout error.
1 parent cabff96 commit a2d38ee

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Metadata, ResolvingMetadata } from 'next'
2+
3+
export async function generateMetadata(
4+
_: { params: Promise<{ slug: string }> },
5+
parent: ResolvingMetadata
6+
): Promise<Metadata> {
7+
'use cache'
8+
9+
// We're not reading params here, but we do define a canonical URL, which
10+
// leads to the pathname being read under the hood. This should make the
11+
// function dynamic when prerendering the fallback shell, and not lead to a
12+
// timeout error.
13+
14+
const { metadataBase } = await parent
15+
16+
return {
17+
// We can not return a URL instance from a `'use cache'` function.
18+
metadataBase: metadataBase?.replace('/foo', '/bar'),
19+
}
20+
}
21+
22+
export default function Layout({ children }: { children: React.ReactNode }) {
23+
return <>{children}</>
24+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Metadata, ResolvingMetadata } from 'next'
2+
import { connection } from 'next/server'
3+
import { Suspense } from 'react'
4+
5+
export async function generateMetadata(
6+
_: { params: Promise<{ slug: string }> },
7+
parent: ResolvingMetadata
8+
): Promise<Metadata> {
9+
'use cache'
10+
11+
// We're not reading params here, but we do define a canonical URL, which
12+
// leads to the pathname being read under the hood. This should make the
13+
// function dynamic when prerendering the fallback shell, and not lead to a
14+
// timeout error.
15+
16+
const { metadataBase } = await parent
17+
18+
return {
19+
metadataBase: metadataBase?.replace('/bar', '/baz'),
20+
alternates: { canonical: '/qux' },
21+
}
22+
}
23+
24+
export default function Page() {
25+
return (
26+
<Suspense fallback={<p>Loading...</p>}>
27+
<Dynamic />
28+
</Suspense>
29+
)
30+
}
31+
32+
async function Dynamic() {
33+
await connection()
34+
35+
return <p>Dynamic</p>
36+
}

test/e2e/app-dir/use-cache/use-cache.test.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1171,8 +1171,9 @@ describe('use-cache', () => {
11711171
it('can serialize parent metadata as generateMetadata argument', async () => {
11721172
const browser = await next.browser('/generate-metadata-resume/nested')
11731173

1174+
// The metadata must be in the head if it was prerendered.
11741175
const canonicalUrl = await browser
1175-
.elementByCss('link[rel="canonical"]')
1176+
.elementByCss('head link[rel="canonical"]', { state: 'attached' })
11761177
.getAttribute('href')
11771178

11781179
expect(canonicalUrl).toBe('https://example.com/baz/qux')
@@ -1181,6 +1182,35 @@ describe('use-cache', () => {
11811182
await assertNoErrorToast(browser)
11821183
})
11831184

1185+
it('makes a cached generateMetadata function that implicitly depends on params dynamic during prerendering', async () => {
1186+
// First load the page with JavaScript disabled, to ensure that no
1187+
// generateMetadata result was included in the prerendered shell.
1188+
let browser = await next.browser(
1189+
'/generate-metadata-resume/canonical/foo',
1190+
{ disableJavaScript: true }
1191+
)
1192+
1193+
// The metadata would be in the head if it was prerendered.
1194+
expect(
1195+
await browser
1196+
.elementByCss('head', { state: 'attached' })
1197+
.hasElementByCss('link[rel="canonical"]')
1198+
).toBe(false)
1199+
1200+
// However, it should have been added to the body during the resume.
1201+
expect(
1202+
await browser.elementByCss('link[rel="canonical"]').getAttribute('href')
1203+
).toBe('https://example.com/baz/qux')
1204+
1205+
await browser.close()
1206+
1207+
// Load the page again, now with JavaScript enabled.
1208+
browser = await next.browser('/generate-metadata-resume/canonical/foo')
1209+
1210+
// There should be no timeout error.
1211+
await assertNoErrorToast(browser)
1212+
})
1213+
11841214
it('makes a cached generateMetadata function that reads params dynamic during prerendering', async () => {
11851215
// First load the page with JavaScript disabled, to ensure that no
11861216
// generateMetadata result was included in the prerendered shell.

0 commit comments

Comments
 (0)