@@ -390,6 +390,63 @@ test.describe('Simple Page Router (no basePath, no i18n)', () => {
390390 expect ( beforeFetch . localeCompare ( date2 ) ) . toBeLessThan ( 0 )
391391 } )
392392
393+ test ( 'Background SWR invocations can store fresh responses in CDN cache' , async ( {
394+ page,
395+ pageRouter,
396+ } ) => {
397+ const slug = Date . now ( )
398+ const pathname = `/revalidate-60/${ slug } `
399+
400+ const beforeFirstFetch = new Date ( ) . toISOString ( )
401+
402+ const response1 = await page . goto ( new URL ( pathname , pageRouter . url ) . href )
403+ expect ( response1 ?. status ( ) ) . toBe ( 200 )
404+ expect ( response1 ?. headers ( ) [ 'cache-status' ] ) . toMatch (
405+ / " N e t l i f y ( E d g e | D u r a b l e ) " ; f w d = ( u r i - m i s s ( ; s t o r e d ) ? | m i s s ) / m,
406+ )
407+ expect ( response1 ?. headers ( ) [ 'netlify-cdn-cache-control' ] ) . toMatch (
408+ / s - m a x a g e = 6 0 , s t a l e - w h i l e - r e v a l i d a t e = [ 0 - 9 ] + , d u r a b l e / ,
409+ )
410+
411+ // ensure response was NOT produced before invocation
412+ const date1 = ( await page . textContent ( '[data-testid="date-now"]' ) ) ?? ''
413+ expect ( date1 . localeCompare ( beforeFirstFetch ) ) . toBeGreaterThan ( 0 )
414+
415+ // allow page to get stale
416+ await page . waitForTimeout ( 60_000 )
417+
418+ const response2 = await page . goto ( new URL ( pathname , pageRouter . url ) . href )
419+ expect ( response2 ?. status ( ) ) . toBe ( 200 )
420+ expect ( response2 ?. headers ( ) [ 'cache-status' ] ) . toMatch (
421+ / " N e t l i f y ( E d g e | D u r a b l e ) " ; h i t , f w d = s t a l e / m,
422+ )
423+ expect ( response2 ?. headers ( ) [ 'netlify-cdn-cache-control' ] ) . toMatch (
424+ / s - m a x a g e = 6 0 , s t a l e - w h i l e - r e v a l i d a t e = [ 0 - 9 ] + , d u r a b l e / ,
425+ )
426+
427+ const date2 = ( await page . textContent ( '[data-testid="date-now"]' ) ) ?? ''
428+ expect ( date2 ) . toBe ( date1 )
429+
430+ // wait a bit to ensure background work has a chance to finish
431+ // (it should take at least 5 seconds to regenerate, so we should wait at least that much to get fresh response)
432+ await page . waitForTimeout ( 10_000 )
433+
434+ // subsequent request should be served with fresh response from cdn cache, as previous request
435+ // should result in background SWR invocation that serves fresh response that was stored in CDN cache
436+ const response3 = await page . goto ( new URL ( pathname , pageRouter . url ) . href )
437+ expect ( response3 ?. status ( ) ) . toBe ( 200 )
438+ expect ( response3 ?. headers ( ) [ 'cache-status' ] ) . toMatch (
439+ // hit, without being followed by ';fwd=stale'
440+ / " N e t l i f y ( E d g e | D u r a b l e ) " ; h i t (? ! ; f w d = s t a l e ) / m,
441+ )
442+ expect ( response3 ?. headers ( ) [ 'netlify-cdn-cache-control' ] ) . toMatch (
443+ / s - m a x a g e = 6 0 , s t a l e - w h i l e - r e v a l i d a t e = [ 0 - 9 ] + , d u r a b l e / ,
444+ )
445+
446+ const date3 = ( await page . textContent ( '[data-testid="date-now"]' ) ) ?? ''
447+ expect ( date3 . localeCompare ( date2 ) ) . toBeGreaterThan ( 0 )
448+ } )
449+
393450 test ( 'should serve 404 page when requesting non existing page (no matching route)' , async ( {
394451 page,
395452 pageRouter,
0 commit comments