@@ -278,4 +278,159 @@ describe("cacheInterceptor", () => {
278278
279279 expect ( result ) . toEqual ( event ) ;
280280 } ) ;
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+ } ) ;
281436} ) ;
0 commit comments