@@ -38,6 +38,8 @@ type MockResponse = {
3838 statusCode : number
3939 json ?: ( payload : any ) => void
4040 send ?: ( body : any ) => void
41+ sendStatus ?: ( statusCode : number ) => void
42+ end ?: ( ) => void
4143 _json ?: string
4244 _send ?: string
4345 headers : Record < string , string >
@@ -48,8 +50,8 @@ type MockResponse = {
4850
4951const mockResponse = ( ) => {
5052 const res : MockResponse = {
51- status : 404 ,
52- statusCode : 404 ,
53+ status : undefined as any ,
54+ statusCode : undefined as any ,
5355 headers : { } ,
5456 }
5557 res . json = ( payload ) => {
@@ -60,6 +62,14 @@ const mockResponse = () => {
6062 res . statusCode = 200
6163 res . _send = body
6264 }
65+ res . end = ( ) => {
66+ // Mock end method
67+ }
68+ res . sendStatus = ( statusCode ) => {
69+ res . status = statusCode
70+ res . statusCode = statusCode
71+ // Mock sendStatus method
72+ }
6373 res . set = ( key , value ) => {
6474 if ( typeof key === 'string' ) {
6575 res . headers [ key . toLowerCase ( ) ] = value
@@ -75,6 +85,12 @@ const mockResponse = () => {
7585 res . hasHeader = ( key ) => {
7686 return key in res . headers
7787 }
88+ // Add Express-style status method that supports chaining
89+ ; ( res as any ) . status = ( code : number ) => {
90+ res . status = code
91+ res . statusCode = code
92+ return res
93+ }
7894 return res
7995}
8096
@@ -178,7 +194,12 @@ describe('archived enterprise static assets', () => {
178194 } )
179195 nock ( 'https://github.github.com' )
180196 . get ( '/docs-ghes-2.3/_next/static/fourofour.css' )
181- . reply ( 404 , 'Not found' , {
197+ . reply ( 404 , 'not found' , {
198+ 'content-type' : 'text/plain' ,
199+ } )
200+ nock ( 'https://github.github.com' )
201+ . get ( '/docs-ghes-3.5/assets/images/some-image.png' )
202+ . reply ( 404 , 'not found' , {
182203 'content-type' : 'text/plain' ,
183204 } )
184205 nock ( 'https://github.github.com' )
@@ -251,7 +272,6 @@ describe('archived enterprise static assets', () => {
251272 }
252273 setDefaultFastlySurrogateKey ( req , res , next )
253274 await archivedEnterpriseVersionsAssets ( req as any , res as any , next )
254- expect ( res . statusCode ) . toBe ( 404 )
255275 // It didn't exit in that middleware but called next() to move on
256276 // with any other middlewares.
257277 expect ( nexted ) . toBe ( true )
@@ -274,4 +294,87 @@ describe('archived enterprise static assets', () => {
274294 // tried "our disk" and it's eventually there.
275295 expect ( nexted ) . toBe ( true )
276296 } )
297+
298+ describe . each ( [
299+ {
300+ name : 'Next.js chunk assets from archived enterprise referrer (legacy format)' ,
301+ path : '/_next/static/chunks/9589-81283b60820a85f5.js' ,
302+ referrer : '/en/enterprise/3.5/authentication/connecting-to-github-with-ssh' ,
303+ expectStatus : 204 ,
304+ shouldCallNext : false ,
305+ } ,
306+ {
307+ name : 'Next.js chunk assets from archived enterprise referrer (new format)' ,
308+ path : '/_next/static/chunks/pages/[versionId]-40812da083876691.js' ,
309+ referrer :
'/en/[email protected] /authentication/connecting-to-github-with-ssh' , 310+ expectStatus : 204 ,
311+ shouldCallNext : false ,
312+ } ,
313+ {
314+ name : 'Next.js build manifest from archived enterprise referrer' ,
315+ path : '/_next/static/NkhGE2zLVuDHVh7pXdtVC/_buildManifest.js' ,
316+ referrer :
'/[email protected] /admin/configuration' , 317+ expectStatus : 204 ,
318+ shouldCallNext : false ,
319+ } ,
320+ ] ) (
321+ 'should return $expectStatus for $name' ,
322+ ( { name, path, referrer, expectStatus, shouldCallNext } ) => {
323+ test ( name , async ( ) => {
324+ const req = mockRequest ( path , {
325+ headers : {
326+ Referrer : referrer ,
327+ } ,
328+ } )
329+ const res = mockResponse ( )
330+ let nexted = false
331+ const next = ( ) => {
332+ if ( ! shouldCallNext ) {
333+ throw new Error ( 'should not call next() for suppressed assets' )
334+ }
335+ nexted = true
336+ }
337+ setDefaultFastlySurrogateKey ( req , res , ( ) => { } )
338+ await archivedEnterpriseVersionsAssets ( req as any , res as any , next )
339+ expect ( res . statusCode ) . toBe ( expectStatus )
340+ if ( shouldCallNext ) {
341+ expect ( nexted ) . toBe ( true )
342+ }
343+ } )
344+ } ,
345+ )
346+
347+ describe . each ( [
348+ {
349+ name : 'Next.js assets from non-enterprise referrer' ,
350+ path : '/_next/static/chunks/main-abc123.js' ,
351+ referrer : '/en/actions/using-workflows' ,
352+ expectStatus : undefined ,
353+ shouldCallNext : true ,
354+ } ,
355+ {
356+ name : 'non-Next.js assets from archived enterprise referrer' ,
357+ path : '/assets/images/some-image.png' ,
358+ referrer :
'/en/[email protected] /some/page' , 359+ expectStatus : undefined ,
360+ shouldCallNext : true ,
361+ } ,
362+ ] ) ( 'should not suppress $name' , ( { name, path, referrer, expectStatus, shouldCallNext } ) => {
363+ test ( name , async ( ) => {
364+ const req = mockRequest ( path , {
365+ headers : {
366+ Referrer : referrer ,
367+ } ,
368+ } )
369+ const res = mockResponse ( )
370+ let nexted = false
371+ const next = ( ) => {
372+ nexted = true
373+ }
374+ setDefaultFastlySurrogateKey ( req , res , ( ) => { } )
375+ await archivedEnterpriseVersionsAssets ( req as any , res as any , next )
376+ expect ( nexted ) . toBe ( shouldCallNext )
377+ expect ( res . statusCode ) . toBe ( expectStatus )
378+ } )
379+ } )
277380} )
0 commit comments