@@ -2,57 +2,107 @@ import { expect } from '@playwright/test'
22import { test } from '../utils/playwright-helpers.js'
33
44test . 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 - m a x a g e = 3 1 5 3 6 0 0 0 , ( s t a l e - w h i l e - r e v a l i d a t e = 3 1 5 3 6 0 0 0 , ) ? d u r a b l e / ,
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- / " N e x t .j s " ; h i t , " N e t l i f y D u r a b l e " ; f w d = s t a l e ; t t l = [ 0 - 9 ] + ; s t o r e d , " N e t l i f y E d g e " ; f w d = ( s t a l e | m i s s ) / ,
33- )
34- expect ( headers2 [ 'netlify-cache-tag' ] ) . toEqual ( '_n_t_/content/blog' )
35- expect ( headers2 [ 'netlify-cdn-cache-control' ] ) . toMatch (
36- / s - m a x a g e = 3 1 5 3 6 0 0 0 , ( s t a l e - w h i l e - r e v a l i d a t e = 3 1 5 3 6 0 0 0 , ) ? d u r a b l e / ,
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- / " N e x t .j s " ; f w d = m i s s , " N e t l i f y D u r a b l e " ; f w d = s t a l e ; t t l = [ 0 - 9 ] + ; s t o r e d , " N e t l i f y E d g e " ; f w d = ( s t a l e | m i s s ) / ,
52- )
53- expect ( headers3 [ 'netlify-cache-tag' ] ) . toEqual ( '_n_t_/content/blog' )
54- expect ( headers3 [ 'netlify-cdn-cache-control' ] ) . toMatch (
55- / s - m a x a g e = 3 1 5 3 6 0 0 0 , ( s t a l e - w h i l e - r e v a l i d a t e = 3 1 5 3 6 0 0 0 , ) ? d u r a b l e / ,
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 - m a x a g e = 3 1 5 3 6 0 0 0 , ( s t a l e - w h i l e - r e v a l i d a t e = 3 1 5 3 6 0 0 0 , ) ? d u r a b l e / ,
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+ / " N e x t .j s " ; h i t , " N e t l i f y D u r a b l e " ; f w d = s t a l e ; t t l = [ 0 - 9 ] + ; s t o r e d , " N e t l i f y E d g e " ; f w d = ( s t a l e | m i s s ) / ,
81+ )
82+ expect ( headers2 [ 'netlify-cache-tag' ] ) . toEqual ( expectedCacheTag )
83+ expect ( headers2 [ 'netlify-cdn-cache-control' ] ) . toMatch (
84+ / s - m a x a g e = 3 1 5 3 6 0 0 0 , ( s t a l e - w h i l e - r e v a l i d a t e = 3 1 5 3 6 0 0 0 , ) ? d u r a b l e / ,
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+ / " N e x t .j s " ; f w d = m i s s , " N e t l i f y D u r a b l e " ; f w d = s t a l e ; t t l = [ 0 - 9 ] + ; s t o r e d , " N e t l i f y E d g e " ; f w d = ( s t a l e | m i s s ) / ,
100+ )
101+ expect ( headers3 [ 'netlify-cache-tag' ] ) . toEqual ( expectedCacheTag )
102+ expect ( headers3 [ 'netlify-cdn-cache-control' ] ) . toMatch (
103+ / s - m a x a g e = 3 1 5 3 6 0 0 0 , ( s t a l e - w h i l e - r e v a l i d a t e = 3 1 5 3 6 0 0 0 , ) ? d u r a b l e / ,
104+ )
105+ } )
106+ }
57107 } )
58108} )
0 commit comments