@@ -12,6 +12,8 @@ import {
1212 cacheId ,
1313 cacheHistory ,
1414 cacheSince ,
15+ cacheGogFragments ,
16+ cacheGogGlosses ,
1517 cacheStats ,
1618 cacheClear
1719} from './middleware.js'
@@ -471,3 +473,194 @@ describe('Cache Statistics', () => {
471473 expect ( cache . cache . size ) . toBe ( 1 )
472474 } )
473475} )
476+
477+ describe ( 'GOG Endpoint Cache Middleware' , ( ) => {
478+ let mockReq
479+ let mockRes
480+ let mockNext
481+
482+ beforeEach ( ( ) => {
483+ // Clear cache before each test
484+ cache . clear ( )
485+
486+ // Reset mock request
487+ mockReq = {
488+ method : 'POST' ,
489+ body : { } ,
490+ query : { } ,
491+ params : { }
492+ }
493+
494+ // Reset mock response
495+ mockRes = {
496+ statusCode : 200 ,
497+ headers : { } ,
498+ set : jest . fn ( function ( key , value ) {
499+ if ( typeof key === 'object' ) {
500+ Object . assign ( this . headers , key )
501+ } else {
502+ this . headers [ key ] = value
503+ }
504+ return this
505+ } ) ,
506+ json : jest . fn ( function ( data ) {
507+ this . jsonData = data
508+ return this
509+ } )
510+ }
511+
512+ // Reset mock next
513+ mockNext = jest . fn ( )
514+ } )
515+
516+ afterEach ( ( ) => {
517+ cache . clear ( )
518+ } )
519+
520+ describe ( 'cacheGogFragments middleware' , ( ) => {
521+ it ( 'should pass through when ManuscriptWitness is missing' , ( ) => {
522+ mockReq . body = { }
523+
524+ cacheGogFragments ( mockReq , mockRes , mockNext )
525+
526+ expect ( mockNext ) . toHaveBeenCalled ( )
527+ expect ( mockRes . json ) . not . toHaveBeenCalled ( )
528+ } )
529+
530+ it ( 'should pass through when ManuscriptWitness is invalid' , ( ) => {
531+ mockReq . body = { ManuscriptWitness : 'not-a-url' }
532+
533+ cacheGogFragments ( mockReq , mockRes , mockNext )
534+
535+ expect ( mockNext ) . toHaveBeenCalled ( )
536+ expect ( mockRes . json ) . not . toHaveBeenCalled ( )
537+ } )
538+
539+ it ( 'should return cache MISS on first request' , ( ) => {
540+ mockReq . body = { ManuscriptWitness : 'https://example.org/manuscript/1' }
541+ mockReq . query = { limit : '50' , skip : '0' }
542+
543+ cacheGogFragments ( mockReq , mockRes , mockNext )
544+
545+ expect ( mockRes . headers [ 'X-Cache' ] ) . toBe ( 'MISS' )
546+ expect ( mockNext ) . toHaveBeenCalled ( )
547+ } )
548+
549+ it ( 'should return cache HIT on second identical request' , ( ) => {
550+ mockReq . body = { ManuscriptWitness : 'https://example.org/manuscript/1' }
551+ mockReq . query = { limit : '50' , skip : '0' }
552+
553+ // First request - populate cache
554+ cacheGogFragments ( mockReq , mockRes , mockNext )
555+ mockRes . json ( [ { '@id' : 'fragment1' , '@type' : 'WitnessFragment' } ] )
556+
557+ // Reset mocks for second request
558+ mockRes . headers = { }
559+ mockRes . json = jest . fn ( )
560+ mockNext = jest . fn ( )
561+
562+ // Second request - should hit cache
563+ cacheGogFragments ( mockReq , mockRes , mockNext )
564+
565+ expect ( mockRes . headers [ 'X-Cache' ] ) . toBe ( 'HIT' )
566+ expect ( mockRes . json ) . toHaveBeenCalledWith ( [ { '@id' : 'fragment1' , '@type' : 'WitnessFragment' } ] )
567+ expect ( mockNext ) . not . toHaveBeenCalled ( )
568+ } )
569+
570+ it ( 'should cache based on pagination parameters' , ( ) => {
571+ const manuscriptURI = 'https://example.org/manuscript/1'
572+
573+ // Request with limit=50, skip=0
574+ mockReq . body = { ManuscriptWitness : manuscriptURI }
575+ mockReq . query = { limit : '50' , skip : '0' }
576+
577+ cacheGogFragments ( mockReq , mockRes , mockNext )
578+ mockRes . json ( [ { '@id' : 'fragment1' } ] )
579+
580+ // Request with different pagination - should be MISS
581+ mockRes . headers = { }
582+ mockRes . json = jest . fn ( )
583+ mockNext = jest . fn ( )
584+ mockReq . query = { limit : '100' , skip : '0' }
585+
586+ cacheGogFragments ( mockReq , mockRes , mockNext )
587+
588+ expect ( mockRes . headers [ 'X-Cache' ] ) . toBe ( 'MISS' )
589+ expect ( mockNext ) . toHaveBeenCalled ( )
590+ } )
591+ } )
592+
593+ describe ( 'cacheGogGlosses middleware' , ( ) => {
594+ it ( 'should pass through when ManuscriptWitness is missing' , ( ) => {
595+ mockReq . body = { }
596+
597+ cacheGogGlosses ( mockReq , mockRes , mockNext )
598+
599+ expect ( mockNext ) . toHaveBeenCalled ( )
600+ expect ( mockRes . json ) . not . toHaveBeenCalled ( )
601+ } )
602+
603+ it ( 'should pass through when ManuscriptWitness is invalid' , ( ) => {
604+ mockReq . body = { ManuscriptWitness : 'not-a-url' }
605+
606+ cacheGogGlosses ( mockReq , mockRes , mockNext )
607+
608+ expect ( mockNext ) . toHaveBeenCalled ( )
609+ expect ( mockRes . json ) . not . toHaveBeenCalled ( )
610+ } )
611+
612+ it ( 'should return cache MISS on first request' , ( ) => {
613+ mockReq . body = { ManuscriptWitness : 'https://example.org/manuscript/1' }
614+ mockReq . query = { limit : '50' , skip : '0' }
615+
616+ cacheGogGlosses ( mockReq , mockRes , mockNext )
617+
618+ expect ( mockRes . headers [ 'X-Cache' ] ) . toBe ( 'MISS' )
619+ expect ( mockNext ) . toHaveBeenCalled ( )
620+ } )
621+
622+ it ( 'should return cache HIT on second identical request' , ( ) => {
623+ mockReq . body = { ManuscriptWitness : 'https://example.org/manuscript/1' }
624+ mockReq . query = { limit : '50' , skip : '0' }
625+
626+ // First request - populate cache
627+ cacheGogGlosses ( mockReq , mockRes , mockNext )
628+ mockRes . json ( [ { '@id' : 'gloss1' , '@type' : 'Gloss' } ] )
629+
630+ // Reset mocks for second request
631+ mockRes . headers = { }
632+ mockRes . json = jest . fn ( )
633+ mockNext = jest . fn ( )
634+
635+ // Second request - should hit cache
636+ cacheGogGlosses ( mockReq , mockRes , mockNext )
637+
638+ expect ( mockRes . headers [ 'X-Cache' ] ) . toBe ( 'HIT' )
639+ expect ( mockRes . json ) . toHaveBeenCalledWith ( [ { '@id' : 'gloss1' , '@type' : 'Gloss' } ] )
640+ expect ( mockNext ) . not . toHaveBeenCalled ( )
641+ } )
642+
643+ it ( 'should cache based on pagination parameters' , ( ) => {
644+ const manuscriptURI = 'https://example.org/manuscript/1'
645+
646+ // Request with limit=50, skip=0
647+ mockReq . body = { ManuscriptWitness : manuscriptURI }
648+ mockReq . query = { limit : '50' , skip : '0' }
649+
650+ cacheGogGlosses ( mockReq , mockRes , mockNext )
651+ mockRes . json ( [ { '@id' : 'gloss1' } ] )
652+
653+ // Request with different pagination - should be MISS
654+ mockRes . headers = { }
655+ mockRes . json = jest . fn ( )
656+ mockNext = jest . fn ( )
657+ mockReq . query = { limit : '100' , skip : '0' }
658+
659+ cacheGogGlosses ( mockReq , mockRes , mockNext )
660+
661+ expect ( mockRes . headers [ 'X-Cache' ] ) . toBe ( 'MISS' )
662+ expect ( mockNext ) . toHaveBeenCalled ( )
663+ } )
664+ } )
665+ } )
666+
0 commit comments