Skip to content

Commit 13cb002

Browse files
authored
test: expand test fixture and cases for dynamic-cms tests with added i18n to fixture and testing i18n cases and json requests (#2813)
1 parent b6794be commit 13cb002

File tree

5 files changed

+119
-61
lines changed

5 files changed

+119
-61
lines changed

tests/e2e/dynamic-cms.test.ts

+102-52
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,107 @@ import { expect } from '@playwright/test'
22
import { test } from '../utils/playwright-helpers.js'
33

44
test.describe('Dynamic CMS', () => {
5-
test('Invalidates 404 pages from durable cache', async ({ page, dynamicCms }) => {
6-
// 1. Verify the status and headers of the dynamic page
7-
const response1 = await page.goto(new URL('/content/blog', dynamicCms.url).href)
8-
const headers1 = response1?.headers() || {}
9-
10-
expect(response1?.status()).toEqual(404)
11-
expect(headers1['cache-control']).toEqual('public,max-age=0,must-revalidate')
12-
expect(headers1['cache-status']).toEqual(
13-
'"Next.js"; fwd=miss, "Netlify Durable"; fwd=uri-miss; stored, "Netlify Edge"; fwd=miss',
14-
)
15-
expect(headers1['netlify-cache-tag']).toEqual('_n_t_/content/blog')
16-
expect(headers1['netlify-cdn-cache-control']).toMatch(
17-
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
18-
)
19-
20-
// 2. Publish the blob, revalidate the dynamic page, and wait to regenerate
21-
await page.goto(new URL('/cms/publish', dynamicCms.url).href)
22-
await page.goto(new URL('/api/revalidate?path=/content/blog', dynamicCms.url).href)
23-
await page.waitForTimeout(1000)
24-
25-
// 3. Verify the status and headers of the dynamic page
26-
const response2 = await page.goto(new URL('/content/blog', dynamicCms.url).href)
27-
const headers2 = response2?.headers() || {}
28-
29-
expect(response2?.status()).toEqual(200)
30-
expect(headers2['cache-control']).toEqual('public,max-age=0,must-revalidate')
31-
expect(headers2['cache-status']).toMatch(
32-
/"Next.js"; hit, "Netlify Durable"; fwd=stale; ttl=[0-9]+; stored, "Netlify Edge"; fwd=(stale|miss)/,
33-
)
34-
expect(headers2['netlify-cache-tag']).toEqual('_n_t_/content/blog')
35-
expect(headers2['netlify-cdn-cache-control']).toMatch(
36-
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
37-
)
38-
39-
// 4. Unpublish the blob, revalidate the dynamic page, and wait to regenerate
40-
await page.goto(new URL('/cms/unpublish', dynamicCms.url).href)
41-
await page.goto(new URL('/api/revalidate?path=/content/blog', dynamicCms.url).href)
42-
await page.waitForTimeout(1000)
43-
44-
// 5. Verify the status and headers of the dynamic page
45-
const response3 = await page.goto(new URL('/content/blog', dynamicCms.url).href)
46-
const headers3 = response3?.headers() || {}
47-
48-
expect(response3?.status()).toEqual(404)
49-
expect(headers3['cache-control']).toEqual('public,max-age=0,must-revalidate')
50-
expect(headers3['cache-status']).toMatch(
51-
/"Next.js"; fwd=miss, "Netlify Durable"; fwd=stale; ttl=[0-9]+; stored, "Netlify Edge"; fwd=(stale|miss)/,
52-
)
53-
expect(headers3['netlify-cache-tag']).toEqual('_n_t_/content/blog')
54-
expect(headers3['netlify-cdn-cache-control']).toMatch(
55-
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
56-
)
5+
test.describe('Invalidates 404 pages from durable cache', () => {
6+
// using postFix allows to rerun tests without having to redeploy the app because paths/keys will be unique for each test run
7+
const postFix = Date.now()
8+
for (const { label, contentKey, expectedCacheTag, urlPath, pathToRevalidate } of [
9+
{
10+
label: 'Invalidates 404 html from durable cache (implicit default locale)',
11+
urlPath: `/content/html-implicit-default-locale-${postFix}`,
12+
contentKey: `html-implicit-default-locale-${postFix}`,
13+
expectedCacheTag: `_n_t_/en/content/html-implicit-default-locale-${postFix}`,
14+
},
15+
{
16+
label: 'Invalidates 404 html from durable cache (explicit default locale)',
17+
urlPath: `/en/content/html-explicit-default-locale-${postFix}`,
18+
contentKey: `html-explicit-default-locale-${postFix}`,
19+
expectedCacheTag: `_n_t_/en/content/html-explicit-default-locale-${postFix}`,
20+
},
21+
// json paths don't have implicit locale routing
22+
{
23+
label: 'Invalidates 404 json from durable cache (default locale)',
24+
urlPath: `/_next/data/build-id/en/content/json-default-locale-${postFix}.json`,
25+
// for html, we can use html path as param for revalidate,
26+
// for json we can't use json path and instead use one of html paths
27+
// let's use implicit default locale here, as we will have another case for
28+
// non-default locale which will have to use explicit one
29+
pathToRevalidate: `/content/json-default-locale-${postFix}`,
30+
contentKey: `json-default-locale-${postFix}`,
31+
expectedCacheTag: `_n_t_/en/content/json-default-locale-${postFix}`,
32+
},
33+
{
34+
label: 'Invalidates 404 html from durable cache (non-default locale)',
35+
urlPath: `/fr/content/html-non-default-locale-${postFix}`,
36+
contentKey: `html-non-default-locale-${postFix}`,
37+
expectedCacheTag: `_n_t_/fr/content/html-non-default-locale-${postFix}`,
38+
},
39+
{
40+
label: 'Invalidates 404 json from durable cache (non-default locale)',
41+
urlPath: `/_next/data/build-id/fr/content/json-non-default-locale-${postFix}.json`,
42+
pathToRevalidate: `/fr/content/json-non-default-locale-${postFix}`,
43+
contentKey: `json-non-default-locale-${postFix}`,
44+
expectedCacheTag: `_n_t_/fr/content/json-non-default-locale-${postFix}`,
45+
},
46+
]) {
47+
test(label, async ({ page, dynamicCms }) => {
48+
const routeUrl = new URL(urlPath, dynamicCms.url).href
49+
const revalidateAPiUrl = new URL(
50+
`/api/revalidate?path=${pathToRevalidate ?? urlPath}`,
51+
dynamicCms.url,
52+
).href
53+
54+
// 1. Verify the status and headers of the dynamic page
55+
const response1 = await page.goto(routeUrl)
56+
const headers1 = response1?.headers() || {}
57+
58+
expect(response1?.status()).toEqual(404)
59+
expect(headers1['cache-control']).toEqual('public,max-age=0,must-revalidate')
60+
expect(headers1['cache-status']).toEqual(
61+
'"Next.js"; fwd=miss, "Netlify Durable"; fwd=uri-miss; stored, "Netlify Edge"; fwd=miss',
62+
)
63+
expect(headers1['netlify-cache-tag']).toEqual(expectedCacheTag)
64+
expect(headers1['netlify-cdn-cache-control']).toMatch(
65+
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
66+
)
67+
68+
// 2. Publish the blob, revalidate the dynamic page, and wait to regenerate
69+
await page.goto(new URL(`/cms/publish/${contentKey}`, dynamicCms.url).href)
70+
await page.goto(revalidateAPiUrl)
71+
await page.waitForTimeout(1000)
72+
73+
// 3. Verify the status and headers of the dynamic page
74+
const response2 = await page.goto(routeUrl)
75+
const headers2 = response2?.headers() || {}
76+
77+
expect(response2?.status()).toEqual(200)
78+
expect(headers2['cache-control']).toEqual('public,max-age=0,must-revalidate')
79+
expect(headers2['cache-status']).toMatch(
80+
/"Next.js"; hit, "Netlify Durable"; fwd=stale; ttl=[0-9]+; stored, "Netlify Edge"; fwd=(stale|miss)/,
81+
)
82+
expect(headers2['netlify-cache-tag']).toEqual(expectedCacheTag)
83+
expect(headers2['netlify-cdn-cache-control']).toMatch(
84+
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
85+
)
86+
87+
// 4. Unpublish the blob, revalidate the dynamic page, and wait to regenerate
88+
await page.goto(new URL(`/cms/unpublish/${contentKey}`, dynamicCms.url).href)
89+
await page.goto(revalidateAPiUrl)
90+
await page.waitForTimeout(1000)
91+
92+
// 5. Verify the status and headers of the dynamic page
93+
const response3 = await page.goto(routeUrl)
94+
const headers3 = response3?.headers() || {}
95+
96+
expect(response3?.status()).toEqual(404)
97+
expect(headers3['cache-control']).toEqual('public,max-age=0,must-revalidate')
98+
expect(headers3['cache-status']).toMatch(
99+
/"Next.js"; fwd=miss, "Netlify Durable"; fwd=stale; ttl=[0-9]+; stored, "Netlify Edge"; fwd=(stale|miss)/,
100+
)
101+
expect(headers3['netlify-cache-tag']).toEqual(expectedCacheTag)
102+
expect(headers3['netlify-cdn-cache-control']).toMatch(
103+
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
104+
)
105+
})
106+
}
57107
})
58108
})

tests/fixtures/dynamic-cms/netlify/functions/cms.ts renamed to tests/fixtures/dynamic-cms/netlify/functions/cms.mts

+8-4
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,25 @@ import { Context } from '@netlify/functions'
44
// publish or unpublish "cms content" depending on the sent operation
55
export default async function handler(_request: Request, context: Context) {
66
const store = getDeployStore({ name: 'cms-content', consistency: 'strong' })
7-
const BLOB_KEY = 'key'
87

98
const operation = context.params['operation']
109

10+
// root of optional catch-all route in Next.js sets 'index.html' as param
11+
// while it's undefined in the Netlify function, because we need to declare
12+
// path without wildcard
13+
const contentKey = context.params['0'] ?? 'index.html'
14+
1115
if (operation === 'publish') {
12-
await store.setJSON(BLOB_KEY, { content: true })
16+
await store.setJSON(contentKey, { content: true })
1317
}
1418

1519
if (operation === 'unpublish') {
16-
await store.delete(BLOB_KEY)
20+
await store.delete(contentKey)
1721
}
1822

1923
return Response.json({ ok: true })
2024
}
2125

2226
export const config = {
23-
path: '/cms/:operation',
27+
path: ['/cms/:operation/*', '/cms/:operation'],
2428
}

tests/fixtures/dynamic-cms/next.config.js

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ const nextConfig = {
44
eslint: {
55
ignoreDuringBuilds: true,
66
},
7+
i18n: {
8+
locales: ['en', 'fr'],
9+
defaultLocale: 'en',
10+
},
711
generateBuildId: () => 'build-id',
812
}
913

tests/fixtures/dynamic-cms/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
"dependencies": {
1111
"@netlify/blobs": "^8.1.0",
1212
"@netlify/functions": "^2.7.0",
13-
"@netlify/plugin-nextjs": "^5.10.1",
1413
"netlify-cli": "^19.0.3",
1514
"next": "latest",
1615
"react": "18.2.0",

tests/fixtures/dynamic-cms/pages/content/[...slug].js

+5-4
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ const Content = ({ value }) => (
88
</div>
99
)
1010

11-
export async function getStaticProps() {
11+
export async function getStaticProps({ params }) {
12+
const contentKey = params.slug.join('/')
13+
1214
const store = getDeployStore({ name: 'cms-content', consistency: 'strong' })
13-
const BLOB_KEY = 'key'
1415

15-
const value = await store.get(BLOB_KEY, { type: 'json' })
16+
const value = await store.get(contentKey, { type: 'json' })
1617

1718
if (!value) {
1819
return {
@@ -22,7 +23,7 @@ export async function getStaticProps() {
2223

2324
return {
2425
props: {
25-
value: value,
26+
value,
2627
},
2728
}
2829
}

0 commit comments

Comments
 (0)