Skip to content

Commit 333fd37

Browse files
committed
lets try to annotate some tests to see if it helps with finding common causes
1 parent 1799786 commit 333fd37

File tree

7 files changed

+2250
-2107
lines changed

7 files changed

+2250
-2107
lines changed

tests/e2e/dynamic-cms.test.ts

Lines changed: 104 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,114 @@
11
import { expect } from '@playwright/test'
2-
import { test } from '../utils/playwright-helpers.js'
2+
import { generateTestTags, test } from '../utils/playwright-helpers.js'
33

4-
test.describe('Dynamic CMS', () => {
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
4+
test.describe(
5+
'Dynamic CMS',
6+
{
7+
tag: generateTestTags({ pagesRouter: true, i18n: true }),
8+
},
9+
() => {
10+
test.describe('Invalidates 404 pages from durable cache', () => {
11+
// using postFix allows to rerun tests without having to redeploy the app because paths/keys will be unique for each test run
12+
const postFix = Date.now()
13+
for (const { label, contentKey, expectedCacheTag, urlPath, pathToRevalidate } of [
14+
{
15+
label: 'Invalidates 404 html from durable cache (implicit default locale)',
16+
urlPath: `/content/html-implicit-default-locale-${postFix}`,
17+
contentKey: `html-implicit-default-locale-${postFix}`,
18+
expectedCacheTag: `_n_t_/en/content/html-implicit-default-locale-${postFix}`,
19+
},
20+
{
21+
label: 'Invalidates 404 html from durable cache (explicit default locale)',
22+
urlPath: `/en/content/html-explicit-default-locale-${postFix}`,
23+
contentKey: `html-explicit-default-locale-${postFix}`,
24+
expectedCacheTag: `_n_t_/en/content/html-explicit-default-locale-${postFix}`,
25+
},
26+
// json paths don't have implicit locale routing
27+
{
28+
label: 'Invalidates 404 json from durable cache (default locale)',
29+
urlPath: `/_next/data/build-id/en/content/json-default-locale-${postFix}.json`,
30+
// for html, we can use html path as param for revalidate,
31+
// for json we can't use json path and instead use one of html paths
32+
// let's use implicit default locale here, as we will have another case for
33+
// non-default locale which will have to use explicit one
34+
pathToRevalidate: `/content/json-default-locale-${postFix}`,
35+
contentKey: `json-default-locale-${postFix}`,
36+
expectedCacheTag: `_n_t_/en/content/json-default-locale-${postFix}`,
37+
},
38+
{
39+
label: 'Invalidates 404 html from durable cache (non-default locale)',
40+
urlPath: `/fr/content/html-non-default-locale-${postFix}`,
41+
contentKey: `html-non-default-locale-${postFix}`,
42+
expectedCacheTag: `_n_t_/fr/content/html-non-default-locale-${postFix}`,
43+
},
44+
{
45+
label: 'Invalidates 404 json from durable cache (non-default locale)',
46+
urlPath: `/_next/data/build-id/fr/content/json-non-default-locale-${postFix}.json`,
47+
pathToRevalidate: `/fr/content/json-non-default-locale-${postFix}`,
48+
contentKey: `json-non-default-locale-${postFix}`,
49+
expectedCacheTag: `_n_t_/fr/content/json-non-default-locale-${postFix}`,
50+
},
51+
]) {
52+
test(label, async ({ page, dynamicCms }) => {
53+
const routeUrl = new URL(urlPath, dynamicCms.url).href
54+
const revalidateAPiUrl = new URL(
55+
`/api/revalidate?path=${pathToRevalidate ?? urlPath}`,
56+
dynamicCms.url,
57+
).href
5358

54-
// 1. Verify the status and headers of the dynamic page
55-
const response1 = await page.goto(routeUrl)
56-
const headers1 = response1?.headers() || {}
59+
// 1. Verify the status and headers of the dynamic page
60+
const response1 = await page.goto(routeUrl)
61+
const headers1 = response1?.headers() || {}
5762

58-
expect(response1?.status()).toEqual(404)
59-
expect(headers1['cache-control']).toEqual('public,max-age=0,must-revalidate')
60-
expect(headers1['cache-status']).toMatch(
61-
/"Next.js"; fwd=miss\s*(,|\n)\s*"Netlify Durable"; fwd=uri-miss; stored\s*(, |\n)\s*"Netlify Edge"; fwd=miss/,
62-
)
63-
expect(headers1['debug-netlify-cache-tag']).toEqual(expectedCacheTag)
64-
expect(headers1['debug-netlify-cdn-cache-control']).toMatch(
65-
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
66-
)
63+
expect(response1?.status()).toEqual(404)
64+
expect(headers1['cache-control']).toEqual('public,max-age=0,must-revalidate')
65+
expect(headers1['cache-status']).toMatch(
66+
/"Next.js"; fwd=miss\s*(,|\n)\s*"Netlify Durable"; fwd=uri-miss; stored\s*(, |\n)\s*"Netlify Edge"; fwd=miss/,
67+
)
68+
expect(headers1['debug-netlify-cache-tag']).toEqual(expectedCacheTag)
69+
expect(headers1['debug-netlify-cdn-cache-control']).toMatch(
70+
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
71+
)
6772

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)
73+
// 2. Publish the blob, revalidate the dynamic page, and wait to regenerate
74+
await page.goto(new URL(`/cms/publish/${contentKey}`, dynamicCms.url).href)
75+
await page.goto(revalidateAPiUrl)
76+
await page.waitForTimeout(1000)
7277

73-
// 3. Verify the status and headers of the dynamic page
74-
const response2 = await page.goto(routeUrl)
75-
const headers2 = response2?.headers() || {}
78+
// 3. Verify the status and headers of the dynamic page
79+
const response2 = await page.goto(routeUrl)
80+
const headers2 = response2?.headers() || {}
7681

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\s*(,|\n)\s*"Netlify Durable"; fwd=stale; ttl=[0-9]+; stored\s*(,|\n)\s*"Netlify Edge"; fwd=(stale|miss)/,
81-
)
82-
expect(headers2['debug-netlify-cache-tag']).toEqual(expectedCacheTag)
83-
expect(headers2['debug-netlify-cdn-cache-control']).toMatch(
84-
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
85-
)
82+
expect(response2?.status()).toEqual(200)
83+
expect(headers2['cache-control']).toEqual('public,max-age=0,must-revalidate')
84+
expect(headers2['cache-status']).toMatch(
85+
/"Next.js"; hit\s*(,|\n)\s*"Netlify Durable"; fwd=stale; ttl=[0-9]+; stored\s*(,|\n)\s*"Netlify Edge"; fwd=(stale|miss)/,
86+
)
87+
expect(headers2['debug-netlify-cache-tag']).toEqual(expectedCacheTag)
88+
expect(headers2['debug-netlify-cdn-cache-control']).toMatch(
89+
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
90+
)
8691

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)
92+
// 4. Unpublish the blob, revalidate the dynamic page, and wait to regenerate
93+
await page.goto(new URL(`/cms/unpublish/${contentKey}`, dynamicCms.url).href)
94+
await page.goto(revalidateAPiUrl)
95+
await page.waitForTimeout(1000)
9196

92-
// 5. Verify the status and headers of the dynamic page
93-
const response3 = await page.goto(routeUrl)
94-
const headers3 = response3?.headers() || {}
97+
// 5. Verify the status and headers of the dynamic page
98+
const response3 = await page.goto(routeUrl)
99+
const headers3 = response3?.headers() || {}
95100

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\s*(,|\n)\s*"Netlify Durable"; fwd=stale; ttl=[0-9]+; stored\s*(,|\n)\s*"Netlify Edge"; fwd=(stale|miss)/,
100-
)
101-
expect(headers3['debug-netlify-cache-tag']).toEqual(expectedCacheTag)
102-
expect(headers3['debug-netlify-cdn-cache-control']).toMatch(
103-
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
104-
)
105-
})
106-
}
107-
})
108-
})
101+
expect(response3?.status()).toEqual(404)
102+
expect(headers3['cache-control']).toEqual('public,max-age=0,must-revalidate')
103+
expect(headers3['cache-status']).toMatch(
104+
/"Next.js"; fwd=miss\s*(,|\n)\s*"Netlify Durable"; fwd=stale; ttl=[0-9]+; stored\s*(,|\n)\s*"Netlify Edge"; fwd=(stale|miss)/,
105+
)
106+
expect(headers3['debug-netlify-cache-tag']).toEqual(expectedCacheTag)
107+
expect(headers3['debug-netlify-cdn-cache-control']).toMatch(
108+
/s-maxage=31536000,( stale-while-revalidate=31536000,)? durable/,
109+
)
110+
})
111+
}
112+
})
113+
},
114+
)

tests/e2e/export.test.ts

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,85 @@
11
import { expect, type Locator } from '@playwright/test'
2-
import { test } from '../utils/playwright-helpers.js'
2+
import { generateTestTags, test } from '../utils/playwright-helpers.js'
33

44
const expectImageWasLoaded = async (locator: Locator) => {
55
expect(await locator.evaluate((img: HTMLImageElement) => img.naturalHeight)).toBeGreaterThan(0)
66
}
7-
test('Renders the Home page correctly with output export', async ({ page, outputExport }) => {
8-
const response = await page.goto(outputExport.url)
9-
const headers = response?.headers() || {}
107

11-
await expect(page).toHaveTitle('Simple Next App')
8+
test.describe(
9+
'Static export',
10+
{
11+
tag: generateTestTags({ appRouter: true, export: true }),
12+
},
13+
() => {
14+
test('Renders the Home page correctly with output export', async ({ page, outputExport }) => {
15+
const response = await page.goto(outputExport.url)
16+
const headers = response?.headers() || {}
1217

13-
expect(headers['cache-status']).toBe('"Netlify Edge"; fwd=miss')
18+
await expect(page).toHaveTitle('Simple Next App')
1419

15-
const h1 = page.locator('h1')
16-
await expect(h1).toHaveText('Home')
20+
expect(headers['cache-status']).toBe('"Netlify Edge"; fwd=miss')
1721

18-
await expectImageWasLoaded(page.locator('img'))
19-
})
22+
const h1 = page.locator('h1')
23+
await expect(h1).toHaveText('Home')
2024

21-
test('Renders the Home page correctly with output export and publish set to out', async ({
22-
page,
23-
ouputExportPublishOut,
24-
}) => {
25-
const response = await page.goto(ouputExportPublishOut.url)
26-
const headers = response?.headers() || {}
25+
await expectImageWasLoaded(page.locator('img'))
26+
})
2727

28-
await expect(page).toHaveTitle('Simple Next App')
28+
test('Renders the Home page correctly with output export and publish set to out', async ({
29+
page,
30+
outputExportPublishOut,
31+
}) => {
32+
const response = await page.goto(outputExportPublishOut.url)
33+
const headers = response?.headers() || {}
2934

30-
expect(headers['cache-status']).toBe('"Netlify Edge"; fwd=miss')
35+
await expect(page).toHaveTitle('Simple Next App')
3136

32-
const h1 = page.locator('h1')
33-
await expect(h1).toHaveText('Home')
37+
expect(headers['cache-status']).toBe('"Netlify Edge"; fwd=miss')
3438

35-
await expectImageWasLoaded(page.locator('img'))
36-
})
39+
const h1 = page.locator('h1')
40+
await expect(h1).toHaveText('Home')
3741

38-
test('Renders the Home page correctly with output export and custom dist dir', async ({
39-
page,
40-
outputExportCustomDist,
41-
}) => {
42-
const response = await page.goto(outputExportCustomDist.url)
43-
const headers = response?.headers() || {}
42+
await expectImageWasLoaded(page.locator('img'))
43+
})
4444

45-
await expect(page).toHaveTitle('Simple Next App')
45+
test(
46+
'Renders the Home page correctly with output export and custom dist dir',
47+
{
48+
tag: generateTestTags({ customDistDir: true }),
49+
},
50+
async ({ page, outputExportCustomDist }) => {
51+
const response = await page.goto(outputExportCustomDist.url)
52+
const headers = response?.headers() || {}
4653

47-
expect(headers['cache-status']).toBe('"Netlify Edge"; fwd=miss')
54+
await expect(page).toHaveTitle('Simple Next App')
4855

49-
const h1 = page.locator('h1')
50-
await expect(h1).toHaveText('Home')
56+
expect(headers['cache-status']).toBe('"Netlify Edge"; fwd=miss')
5157

52-
await expectImageWasLoaded(page.locator('img'))
53-
})
58+
const h1 = page.locator('h1')
59+
await expect(h1).toHaveText('Home')
5460

55-
test.describe('next/image is using Netlify Image CDN', () => {
56-
test('Local images', async ({ page, outputExport }) => {
57-
const nextImageResponsePromise = page.waitForResponse('**/.netlify/images**')
61+
await expectImageWasLoaded(page.locator('img'))
62+
},
63+
)
5864

59-
await page.goto(`${outputExport.url}/image/local`)
65+
test.describe('next/image is using Netlify Image CDN', () => {
66+
test('Local images', async ({ page, outputExport }) => {
67+
const nextImageResponsePromise = page.waitForResponse('**/.netlify/images**')
6068

61-
const nextImageResponse = await nextImageResponsePromise
62-
expect(nextImageResponse.request().url()).toContain('.netlify/images?url=%2Fsquirrel.jpg')
69+
await page.goto(`${outputExport.url}/image/local`)
6370

64-
expect(nextImageResponse.status()).toBe(200)
65-
// ensure next/image is using Image CDN
66-
// source image is jpg, but when requesting it through Image CDN avif or webp will be returned
67-
expect(['image/avif', 'image/webp']).toContain(
68-
await nextImageResponse.headerValue('content-type'),
69-
)
71+
const nextImageResponse = await nextImageResponsePromise
72+
expect(nextImageResponse.request().url()).toContain('.netlify/images?url=%2Fsquirrel.jpg')
73+
74+
expect(nextImageResponse.status()).toBe(200)
75+
// ensure next/image is using Image CDN
76+
// source image is jpg, but when requesting it through Image CDN avif or webp will be returned
77+
expect(['image/avif', 'image/webp']).toContain(
78+
await nextImageResponse.headerValue('content-type'),
79+
)
7080

71-
await expectImageWasLoaded(page.locator('img'))
72-
})
73-
})
81+
await expectImageWasLoaded(page.locator('img'))
82+
})
83+
})
84+
},
85+
)

0 commit comments

Comments
 (0)