@@ -90,11 +90,15 @@ describe('WeatherService', () => {
9090 temperature : { value : 15 , unit : IWeatherUnits . C } ,
9191 conditions : { value : 'Sunny' , unit : IWeatherUnits . string } ,
9292 provider : 'nws' ,
93+ cached : false ,
94+ // cachedAt is undefined when data is freshly fetched
9395 } ;
9496
9597 const weather = await weatherService . getWeather ( lat , lng ) ;
9698
9799 expect ( weather ) . toEqual ( expectedWeatherData ) ;
100+ expect ( weather . cached ) . toBe ( false ) ;
101+ expect ( weather . cachedAt ) . toBeUndefined ( ) ;
98102 } ) ;
99103
100104 it ( 'should fallback to the next provider if the first provider does not support the location' , async ( ) => {
@@ -114,6 +118,7 @@ describe('WeatherService', () => {
114118 temperature : { value : 18 , unit : IWeatherUnits . C } ,
115119 conditions : { value : 'Cloudy' , unit : IWeatherUnits . string } ,
116120 provider : 'openweather' ,
121+ cached : false ,
117122 } ;
118123
119124 const weather = await weatherService . getWeather ( lat , lng ) ;
@@ -144,12 +149,14 @@ describe('WeatherService', () => {
144149 } ) ;
145150
146151 it ( 'should use cached weather data if available' , async ( ) => {
147- const cachedWeatherData = {
152+ const cachedWeatherData : IWeatherData = {
148153 dewPoint : { value : 11 , unit : IWeatherUnits . C } ,
149154 humidity : { value : 75 , unit : IWeatherUnits . percent } ,
150155 temperature : { value : 16 , unit : IWeatherUnits . C } ,
151156 conditions : { value : 'Overcast' , unit : IWeatherUnits . string } ,
152157 provider : 'nws' ,
158+ cached : true ,
159+ cachedAt : '2023-10-15T12:00:00Z' ,
153160 } ;
154161
155162 const cacheGetMock = jest
@@ -167,6 +174,8 @@ describe('WeatherService', () => {
167174 const weather = await weatherService . getWeather ( lat , lng ) ;
168175
169176 expect ( weather ) . toEqual ( cachedWeatherData ) ;
177+ expect ( weather . cached ) . toBe ( true ) ;
178+ expect ( weather . cachedAt ) . toBe ( '2023-10-15T12:00:00Z' ) ;
170179 expect ( cacheGetMock ) . toHaveBeenCalled ( ) ;
171180 expect ( cacheSetMock ) . not . toHaveBeenCalled ( ) ;
172181 } ) ;
@@ -252,6 +261,8 @@ describe('WeatherService', () => {
252261 temperature : { value : 18 , unit : IWeatherUnits . C } ,
253262 conditions : { value : 'Partly Cloudy' , unit : IWeatherUnits . string } ,
254263 provider : 'openweather' ,
264+ cached : false ,
265+ // cachedAt is undefined when data is freshly fetched
255266 } ;
256267
257268 const mockProvider : IWeatherProvider = {
@@ -275,6 +286,8 @@ describe('WeatherService', () => {
275286 expect ( mockProvider . getWeather ) . toHaveBeenCalledWith ( latitude , longitude ) ;
276287 expect ( result ) . toEqual ( mockWeatherData ) ;
277288 expect ( result . provider ) . toBe ( 'openweather' ) ; // Verify provider name
289+ expect ( result . cached ) . toBe ( false ) ;
290+ expect ( result . cachedAt ) . toBeUndefined ( ) ;
278291 } ) ;
279292
280293 it ( 'should bypass cache when bypassCache option is true' , async ( ) => {
@@ -283,9 +296,19 @@ describe('WeatherService', () => {
283296 set : jest . fn ( ) ,
284297 } ;
285298
299+ const mockWeatherData : IWeatherData = {
300+ dewPoint : { value : 15 , unit : IWeatherUnits . C } ,
301+ humidity : { value : 60 , unit : IWeatherUnits . percent } ,
302+ temperature : { value : 25 , unit : IWeatherUnits . C } ,
303+ conditions : { value : 'Clear' , unit : IWeatherUnits . string } ,
304+ provider : 'mockProvider' ,
305+ cached : false ,
306+ // cachedAt is undefined when data is freshly fetched
307+ } ;
308+
286309 const mockProvider : IWeatherProvider = {
287310 name : 'mockProvider' ,
288- getWeather : jest . fn ( ) . mockResolvedValue ( { temperature : 25 } ) ,
311+ getWeather : jest . fn ( ) . mockResolvedValue ( mockWeatherData ) ,
289312 } ;
290313
291314 const weatherService = new WeatherService ( {
@@ -309,10 +332,58 @@ describe('WeatherService', () => {
309332 // Expect provider.getWeather to be called
310333 expect ( mockProvider . getWeather ) . toHaveBeenCalledWith ( latitude , longitude ) ;
311334
312- // Expect cache.set to be called with new data
313- expect ( mockCache . set ) . toHaveBeenCalledWith ( expect . any ( String ) , JSON . stringify ( result ) ) ;
335+ // Expect cache.set to be called with new data including cached: true and cachedAt
336+ expect ( mockCache . set ) . toHaveBeenCalled ( ) ;
337+
338+ // Capture the arguments passed to cache.set
339+ const [ cacheKey , cacheValue ] = mockCache . set . mock . calls [ 0 ] ;
340+
341+ // Verify that the cache key is a string
342+ expect ( cacheKey ) . toEqual ( expect . any ( String ) ) ;
343+
344+ // Parse the cached value
345+ const cachedData = JSON . parse ( cacheValue ) ;
346+
347+ // Verify the cached data
348+ expect ( cachedData ) . toEqual ( {
349+ ...mockWeatherData ,
350+ cached : true ,
351+ cachedAt : expect . any ( String ) ,
352+ } ) ;
314353
315354 // Verify the result
316- expect ( result ) . toEqual ( { temperature : 25 } ) ;
355+ expect ( result ) . toEqual ( mockWeatherData ) ;
356+ expect ( result . cached ) . toBe ( false ) ;
357+ expect ( result . cachedAt ) . toBeUndefined ( ) ;
358+ } ) ;
359+
360+ // Add a test to verify cachedAt when data is fetched from cache
361+ it ( 'should have valid cachedAt when data is retrieved from cache' , async ( ) => {
362+ const cachedWeatherData : IWeatherData = {
363+ dewPoint : { value : 11 , unit : IWeatherUnits . C } ,
364+ humidity : { value : 75 , unit : IWeatherUnits . percent } ,
365+ temperature : { value : 16 , unit : IWeatherUnits . C } ,
366+ conditions : { value : 'Overcast' , unit : IWeatherUnits . string } ,
367+ provider : 'nws' ,
368+ cached : true ,
369+ cachedAt : '2023-10-15T12:00:00Z' ,
370+ } ;
371+
372+ const cacheGetMock = jest
373+ . fn ( )
374+ . mockResolvedValue ( JSON . stringify ( cachedWeatherData ) ) ;
375+
376+ // Replace cache methods with mocks
377+ ( weatherService as any ) . cache . get = cacheGetMock ;
378+
379+ const lat = 38.8977 ;
380+ const lng = - 77.0365 ;
381+
382+ const weather = await weatherService . getWeather ( lat , lng ) ;
383+
384+ expect ( weather ) . toEqual ( cachedWeatherData ) ;
385+ expect ( weather . cached ) . toBe ( true ) ;
386+ expect ( weather . cachedAt ) . toBe ( '2023-10-15T12:00:00Z' ) ;
387+ expect ( cacheGetMock ) . toHaveBeenCalled ( ) ;
317388 } ) ;
318389} ) ;
0 commit comments