@@ -38,6 +38,8 @@ type MockResponse = {
38
38
statusCode : number
39
39
json ?: ( payload : any ) => void
40
40
send ?: ( body : any ) => void
41
+ sendStatus ?: ( statusCode : number ) => void
42
+ end ?: ( ) => void
41
43
_json ?: string
42
44
_send ?: string
43
45
headers : Record < string , string >
@@ -48,8 +50,8 @@ type MockResponse = {
48
50
49
51
const mockResponse = ( ) => {
50
52
const res : MockResponse = {
51
- status : 404 ,
52
- statusCode : 404 ,
53
+ status : undefined as any ,
54
+ statusCode : undefined as any ,
53
55
headers : { } ,
54
56
}
55
57
res . json = ( payload ) => {
@@ -60,6 +62,14 @@ const mockResponse = () => {
60
62
res . statusCode = 200
61
63
res . _send = body
62
64
}
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
+ }
63
73
res . set = ( key , value ) => {
64
74
if ( typeof key === 'string' ) {
65
75
res . headers [ key . toLowerCase ( ) ] = value
@@ -75,6 +85,12 @@ const mockResponse = () => {
75
85
res . hasHeader = ( key ) => {
76
86
return key in res . headers
77
87
}
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
+ }
78
94
return res
79
95
}
80
96
@@ -178,7 +194,12 @@ describe('archived enterprise static assets', () => {
178
194
} )
179
195
nock ( 'https://github.github.com' )
180
196
. 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' , {
182
203
'content-type' : 'text/plain' ,
183
204
} )
184
205
nock ( 'https://github.github.com' )
@@ -251,7 +272,6 @@ describe('archived enterprise static assets', () => {
251
272
}
252
273
setDefaultFastlySurrogateKey ( req , res , next )
253
274
await archivedEnterpriseVersionsAssets ( req as any , res as any , next )
254
- expect ( res . statusCode ) . toBe ( 404 )
255
275
// It didn't exit in that middleware but called next() to move on
256
276
// with any other middlewares.
257
277
expect ( nexted ) . toBe ( true )
@@ -274,4 +294,87 @@ describe('archived enterprise static assets', () => {
274
294
// tried "our disk" and it's eventually there.
275
295
expect ( nexted ) . toBe ( true )
276
296
} )
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
+ } )
277
380
} )
0 commit comments