11import { expect } from '@playwright/test'
22import { nextVersionSatisfies } from '../utils/next-version-helpers.mjs'
33import { test } from '../utils/playwright-helpers.js'
4+ import { join } from 'node:path'
5+ import { readdir } from 'node:fs/promises'
46
57export function waitFor ( millis : number ) {
68 return new Promise ( ( resolve ) => setTimeout ( resolve , millis ) )
@@ -614,6 +616,34 @@ test.describe('Simple Page Router (no basePath, no i18n)', () => {
614616 / ( s - m a x a g e | m a x - a g e ) / ,
615617 )
616618 } )
619+
620+ test . describe ( 'static assets and function invocations' , ( ) => {
621+ test ( 'should return 200 for an existing static asset without invoking a function' , async ( {
622+ page,
623+ pageRouter,
624+ } ) => {
625+ // Since assets are hashed, we can't hardcode anything here. Find something to fetch.
626+ const [ staticAsset ] = await readdir (
627+ join ( pageRouter . isolatedFixtureRoot , '.next' , 'static' , 'chunks' ) ,
628+ )
629+ expect ( staticAsset ) . toBeDefined ( )
630+
631+ const response = await page . goto ( `${ pageRouter . url } /_next/static/chunks/${ staticAsset } ` )
632+
633+ expect ( response ?. status ( ) ) . toBe ( 200 )
634+ expect ( response ?. headers ( ) ) . not . toHaveProperty ( 'x-nf-function-type' )
635+ } )
636+
637+ test ( 'should return 404 for a nonexistent static asset without invoking a function' , async ( {
638+ page,
639+ pageRouter,
640+ } ) => {
641+ const response = await page . goto ( `${ pageRouter . url } /_next/static/stale123abcdef.js` )
642+
643+ expect ( response ?. status ( ) ) . toBe ( 404 )
644+ expect ( response ?. headers ( ) ) . not . toHaveProperty ( 'x-nf-function-type' )
645+ } )
646+ } )
617647} )
618648
619649test . describe ( 'Page Router with basePath and i18n' , ( ) => {
@@ -1352,13 +1382,15 @@ test.describe('Page Router with basePath and i18n', () => {
13521382
13531383 test ( 'requesting a non existing page route that needs to be fetched from the blob store like 404.html' , async ( {
13541384 page,
1355- pageRouter ,
1385+ pageRouterBasePathI18n ,
13561386 } ) => {
1357- const response = await page . goto ( new URL ( 'non-existing' , pageRouter . url ) . href )
1387+ const response = await page . goto (
1388+ new URL ( 'base/path/non-existing' , pageRouterBasePathI18n . url ) . href ,
1389+ )
13581390 const headers = response ?. headers ( ) || { }
13591391 expect ( response ?. status ( ) ) . toBe ( 404 )
13601392
1361- expect ( await page . textContent ( 'p' ) ) . toBe ( 'Custom 404 page' )
1393+ expect ( await page . textContent ( 'p' ) ) . toBe ( 'Custom 404 page for locale: en ' )
13621394
13631395 // https://github.com/vercel/next.js/pull/69802 made changes to returned cache-control header,
13641396 // after that 404 pages would have `private` directive, before that it would not
@@ -1375,13 +1407,15 @@ test.describe('Page Router with basePath and i18n', () => {
13751407
13761408 test ( 'requesting a non existing page route that needs to be fetched from the blob store like 404.html (notFound: true)' , async ( {
13771409 page,
1378- pageRouter ,
1410+ pageRouterBasePathI18n ,
13791411 } ) => {
1380- const response = await page . goto ( new URL ( 'static/not-found' , pageRouter . url ) . href )
1412+ const response = await page . goto (
1413+ new URL ( 'base/path/static/not-found' , pageRouterBasePathI18n . url ) . href ,
1414+ )
13811415 const headers = response ?. headers ( ) || { }
13821416 expect ( response ?. status ( ) ) . toBe ( 404 )
13831417
1384- expect ( await page . textContent ( 'p' ) ) . toBe ( 'Custom 404 page' )
1418+ expect ( await page . textContent ( 'p' ) ) . toBe ( 'Custom 404 page for locale: en ' )
13851419
13861420 expect ( headers [ 'debug-netlify-cdn-cache-control' ] ) . toBe (
13871421 nextVersionSatisfies ( '>=15.0.0-canary.187' )
@@ -1390,4 +1424,36 @@ test.describe('Page Router with basePath and i18n', () => {
13901424 )
13911425 expect ( headers [ 'cache-control' ] ) . toBe ( 'public,max-age=0,must-revalidate' )
13921426 } )
1427+
1428+ test . describe ( 'static assets and function invocations' , ( ) => {
1429+ test ( 'should return 200 for an existing static asset without invoking a function' , async ( {
1430+ page,
1431+ pageRouterBasePathI18n,
1432+ } ) => {
1433+ // Since assets are hashed, we can't hardcode anything here. Find something to fetch.
1434+ const [ staticAsset ] = await readdir (
1435+ join ( pageRouterBasePathI18n . isolatedFixtureRoot , '.next' , 'static' , 'chunks' ) ,
1436+ )
1437+ expect ( staticAsset ) . toBeDefined ( )
1438+
1439+ const response = await page . goto (
1440+ `${ pageRouterBasePathI18n . url } /base/path/_next/static/chunks/${ staticAsset } ` ,
1441+ )
1442+
1443+ expect ( response ?. status ( ) ) . toBe ( 200 )
1444+ expect ( response ?. headers ( ) ) . not . toHaveProperty ( 'x-nf-function-type' )
1445+ } )
1446+
1447+ test ( 'should return 404 for a nonexistent static asset without invoking a function' , async ( {
1448+ page,
1449+ pageRouterBasePathI18n,
1450+ } ) => {
1451+ const response = await page . goto (
1452+ `${ pageRouterBasePathI18n . url } /base/path/_next/static/stale123abcdef.js` ,
1453+ )
1454+
1455+ expect ( response ?. status ( ) ) . toBe ( 404 )
1456+ expect ( response ?. headers ( ) ) . not . toHaveProperty ( 'x-nf-function-type' )
1457+ } )
1458+ } )
13931459} )
0 commit comments