@@ -278,4 +278,159 @@ describe("cacheInterceptor", () => {
278
278
279
279
expect ( result ) . toEqual ( event ) ;
280
280
} ) ;
281
+
282
+ it ( "should retrieve route content from cache with text content" , async ( ) => {
283
+ const event = createEvent ( {
284
+ url : "/albums" ,
285
+ } ) ;
286
+ const routeBody = JSON . stringify ( { message : "Hello from API" } ) ;
287
+ incrementalCache . get . mockResolvedValueOnce ( {
288
+ value : {
289
+ type : "route" ,
290
+ body : routeBody ,
291
+ meta : {
292
+ status : 200 ,
293
+ headers : {
294
+ "content-type" : "application/json" ,
295
+ } ,
296
+ } ,
297
+ revalidate : 300 ,
298
+ } ,
299
+ lastModified : new Date ( "2024-01-02T00:00:00Z" ) . getTime ( ) ,
300
+ } ) ;
301
+
302
+ const result = await cacheInterceptor ( event ) ;
303
+
304
+ const body = await fromReadableStream ( result . body ) ;
305
+ expect ( body ) . toEqual ( routeBody ) ;
306
+ expect ( result ) . toEqual (
307
+ expect . objectContaining ( {
308
+ type : "core" ,
309
+ statusCode : 200 ,
310
+ isBase64Encoded : false ,
311
+ headers : expect . objectContaining ( {
312
+ "cache-control" : "s-maxage=300, stale-while-revalidate=2592000" ,
313
+ "content-type" : "application/json" ,
314
+ etag : expect . any ( String ) ,
315
+ "x-opennext-cache" : "HIT" ,
316
+ vary : "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Next-Url" ,
317
+ } ) ,
318
+ } ) ,
319
+ ) ;
320
+ } ) ;
321
+
322
+ it ( "should retrieve route content from cache with binary content" , async ( ) => {
323
+ const event = createEvent ( {
324
+ url : "/albums" ,
325
+ } ) ;
326
+ const routeBody = "randomBinaryData" ;
327
+ incrementalCache . get . mockResolvedValueOnce ( {
328
+ value : {
329
+ type : "route" ,
330
+ body : routeBody ,
331
+ meta : {
332
+ status : 200 ,
333
+ headers : {
334
+ "content-type" : "image/png" ,
335
+ } ,
336
+ } ,
337
+ revalidate : false ,
338
+ } ,
339
+ lastModified : new Date ( "2024-01-02T00:00:00Z" ) . getTime ( ) ,
340
+ } ) ;
341
+
342
+ const result = await cacheInterceptor ( event ) ;
343
+
344
+ const body = await fromReadableStream ( result . body , true ) ;
345
+ expect ( body ) . toEqual ( routeBody ) ;
346
+ expect ( result ) . toEqual (
347
+ expect . objectContaining ( {
348
+ type : "core" ,
349
+ statusCode : 200 ,
350
+ isBase64Encoded : true ,
351
+ headers : expect . objectContaining ( {
352
+ "cache-control" : "s-maxage=31536000, stale-while-revalidate=2592000" ,
353
+ "content-type" : "image/png" ,
354
+ etag : expect . any ( String ) ,
355
+ "x-opennext-cache" : "HIT" ,
356
+ vary : "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Next-Url" ,
357
+ } ) ,
358
+ } ) ,
359
+ ) ;
360
+ } ) ;
361
+
362
+ it ( "should retrieve route content from stale cache" , async ( ) => {
363
+ const event = createEvent ( {
364
+ url : "/albums" ,
365
+ } ) ;
366
+ const routeBody = "API response" ;
367
+ incrementalCache . get . mockResolvedValueOnce ( {
368
+ value : {
369
+ type : "route" ,
370
+ body : routeBody ,
371
+ meta : {
372
+ status : 201 ,
373
+ headers : {
374
+ "content-type" : "text/plain" ,
375
+ "custom-header" : "custom-value" ,
376
+ } ,
377
+ } ,
378
+ revalidate : 60 ,
379
+ } ,
380
+ lastModified : new Date ( "2024-01-01T23:58:00Z" ) . getTime ( ) ,
381
+ } ) ;
382
+
383
+ const result = await cacheInterceptor ( event ) ;
384
+
385
+ const body = await fromReadableStream ( result . body ) ;
386
+ expect ( body ) . toEqual ( routeBody ) ;
387
+ expect ( result ) . toEqual (
388
+ expect . objectContaining ( {
389
+ type : "core" ,
390
+ statusCode : 201 ,
391
+ isBase64Encoded : false ,
392
+ headers : expect . objectContaining ( {
393
+ "cache-control" : "s-maxage=1, stale-while-revalidate=2592000" ,
394
+ "content-type" : "text/plain" ,
395
+ "custom-header" : "custom-value" ,
396
+ etag : expect . any ( String ) ,
397
+ "x-opennext-cache" : "STALE" ,
398
+ vary : "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Next-Url" ,
399
+ } ) ,
400
+ } ) ,
401
+ ) ;
402
+ } ) ;
403
+
404
+ it ( "should retrieve route content with default status code when meta is missing" , async ( ) => {
405
+ const event = createEvent ( {
406
+ url : "/albums" ,
407
+ } ) ;
408
+ const routeBody = "Simple response" ;
409
+ incrementalCache . get . mockResolvedValueOnce ( {
410
+ value : {
411
+ type : "route" ,
412
+ body : routeBody ,
413
+ revalidate : false ,
414
+ } ,
415
+ lastModified : new Date ( "2024-01-02T00:00:00Z" ) . getTime ( ) ,
416
+ } ) ;
417
+
418
+ const result = await cacheInterceptor ( event ) ;
419
+
420
+ const body = await fromReadableStream ( result . body ) ;
421
+ expect ( body ) . toEqual ( routeBody ) ;
422
+ expect ( result ) . toEqual (
423
+ expect . objectContaining ( {
424
+ type : "core" ,
425
+ statusCode : 200 ,
426
+ isBase64Encoded : false ,
427
+ headers : expect . objectContaining ( {
428
+ "cache-control" : "s-maxage=31536000, stale-while-revalidate=2592000" ,
429
+ etag : expect . any ( String ) ,
430
+ "x-opennext-cache" : "HIT" ,
431
+ vary : "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Next-Url" ,
432
+ } ) ,
433
+ } ) ,
434
+ ) ;
435
+ } ) ;
281
436
} ) ;
0 commit comments