@@ -90,6 +90,93 @@ describe('A cache provider that uses stale values while revalidating the cache',
9090 expect ( mockCache . set ) . toHaveBeenCalledWith ( 'key' , expectedEntry ) ;
9191 } ) ;
9292
93+ it ( 'should expire entries according to the specified logic' , async ( ) => {
94+ const now = Instant . ofEpochMilli ( 12345 ) ;
95+ const clock = FixedClock . of ( now , TimeZone . UTC ) ;
96+
97+ const cachedEntry : TimestampedCacheEntry < string > = {
98+ value : 'cachedValue' ,
99+ timestamp : now . plusSeconds ( - 11 ) ,
100+ } ;
101+
102+ mockCache . get . mockResolvedValue ( cachedEntry ) ;
103+
104+ let resolveSet : ( ) => void = jest . fn ( ) ;
105+ const setPromise = new Promise < void > ( resolve => { resolveSet = resolve ; } ) ;
106+
107+ mockCache . set . mockImplementation ( ( ) => {
108+ resolveSet ( ) ;
109+
110+ return setPromise ;
111+ } ) ;
112+
113+ let resolveloader : ( value : string ) => any = jest . fn ( ) ;
114+
115+ const loader = jest . fn ( ) . mockReturnValueOnce (
116+ new Promise ( resolve => { resolveloader = resolve ; } ) ,
117+ ) ;
118+
119+ const cache = new StaleWhileRevalidateCache ( {
120+ cacheProvider : mockCache ,
121+ freshPeriod : ( ) : number => 10 ,
122+ clock : clock ,
123+ } ) ;
124+
125+ await expect ( cache . get ( 'key' , loader ) ) . resolves . toBe ( 'cachedValue' ) ;
126+
127+ expect ( mockCache . get ) . toHaveBeenCalledWith ( 'key' , expect . any ( Function ) ) ;
128+
129+ expect ( loader ) . toHaveBeenCalledWith ( 'key' ) ;
130+
131+ expect ( mockCache . set ) . not . toHaveBeenCalled ( ) ;
132+
133+ const expectedEntry : TimestampedCacheEntry < string > = {
134+ value : 'loaderValue' ,
135+ timestamp : now ,
136+ } ;
137+
138+ resolveloader ( 'loaderValue' ) ;
139+
140+ await setPromise ;
141+
142+ expect ( mockCache . set ) . toHaveBeenCalledWith ( 'key' , expectedEntry ) ;
143+ } ) ;
144+
145+ it ( 'should handle errors while revalidating expired entries' , async ( ) => {
146+ const now = Instant . ofEpochMilli ( 12345 ) ;
147+ const clock = FixedClock . of ( now , TimeZone . UTC ) ;
148+
149+ const cachedEntry : TimestampedCacheEntry < string > = {
150+ value : 'cachedValue' ,
151+ timestamp : now . plusSeconds ( - 11 ) ,
152+ } ;
153+
154+ mockCache . get . mockResolvedValue ( cachedEntry ) ;
155+
156+ const error = new Error ( 'error' ) ;
157+
158+ const loader = jest . fn ( ) . mockRejectedValueOnce ( error ) ;
159+
160+ const errorHandler = jest . fn ( ) ;
161+
162+ const cache = new StaleWhileRevalidateCache ( {
163+ cacheProvider : mockCache ,
164+ freshPeriod : 10 ,
165+ clock : clock ,
166+ errorHandler : errorHandler ,
167+ } ) ;
168+
169+ await expect ( cache . get ( 'key' , loader ) ) . resolves . toBe ( 'cachedValue' ) ;
170+
171+ expect ( mockCache . get ) . toHaveBeenCalledWith ( 'key' , expect . any ( Function ) ) ;
172+
173+ expect ( loader ) . toHaveBeenCalledWith ( 'key' ) ;
174+
175+ expect ( mockCache . set ) . not . toHaveBeenCalled ( ) ;
176+
177+ expect ( errorHandler ) . toHaveBeenCalledWith ( 'key' , error ) ;
178+ } ) ;
179+
93180 it ( 'should returned non-expired entries' , async ( ) => {
94181 const now = Instant . ofEpochMilli ( 12345 ) ;
95182 const clock = FixedClock . of ( now , TimeZone . UTC ) ;
0 commit comments