fix: fixed isCacheValid function and added tests

This commit is contained in:
Hazork 2021-10-25 15:58:04 -03:00
parent 6ec1b5722b
commit 6e6100b86a
5 changed files with 65 additions and 13 deletions

View File

@ -11,7 +11,7 @@ export class MemoryStorage implements CacheStorage {
return { state: 'empty' };
}
if (!isCacheValid(value)) {
if (isCacheValid(value) === false) {
this.remove(key);
return { state: 'empty' };
}

View File

@ -32,6 +32,10 @@ export type StorageValue = CachedStorageValue | LoadingStorageValue | EmptyStora
export type CachedStorageValue = {
data: CachedResponse;
/**
* The number in milliseconds to wait after createdAt before the
* value is considered stale.
*/
ttl: number;
createdAt: number;
state: 'cached';

View File

@ -2,18 +2,15 @@ import type { StorageValue } from './types';
/**
* Returns true if a storage value can still be used by checking his
* createdAt and ttl values.
* createdAt and ttl values. Returns `'unknown'` when the cache.state
* is different from `'cached'`
*
* @param value The stored value
* @returns True if the cache can still be used
* @returns True if the cache can still be used of falsy otherwise
*/
export function isCacheValid(value: StorageValue): boolean {
if (!value) {
return false;
}
if (value.state !== 'cached') {
return false;
export function isCacheValid(value: StorageValue): boolean | 'unknown' {
if (!value || value.state !== 'cached') {
return 'unknown';
}
return value.createdAt + value.ttl > Date.now();

View File

@ -1,10 +1,26 @@
import type { CacheStorage, StorageValue } from './types';
import { isCacheValid } from './util';
/**
* The key prefix used in WindowStorageWrapper to prevent key
* collisions with other code.
*/
export const DEFAULT_KEY_PREFIX = 'axios-cache-interceptor';
/**
* A storage that uses any {@link Storage} as his storage.
*
* **Note**: All storage keys used are prefixed with `prefix` value.
*/
export abstract class WindowStorageWrapper implements CacheStorage {
/**
* Creates a new instance of WindowStorageWrapper
*
* @param storage The storage to interact
* @param prefix The prefix to use for all keys or
* `DEFAULT_KEY_PREFIX` if not provided.
* @see DEFAULT_KEY_PREFIX
*/
constructor(readonly storage: Storage, readonly prefix: string = DEFAULT_KEY_PREFIX) {}
get = async (key: string): Promise<StorageValue> => {
@ -17,7 +33,7 @@ export abstract class WindowStorageWrapper implements CacheStorage {
const parsed = JSON.parse(json);
if (!isCacheValid(parsed)) {
if (isCacheValid(parsed) === false) {
this.storage.removeItem(prefixedKey);
return { state: 'empty' };
}
@ -48,5 +64,3 @@ export class SessionCacheStorage extends WindowStorageWrapper {
super(window.sessionStorage, prefix);
}
}
export const DEFAULT_KEY_PREFIX = 'axios-cache-interceptor';

37
test/storage/util.test.ts Normal file
View File

@ -0,0 +1,37 @@
import { isCacheValid } from '../../src/storage/util';
describe('tests common storages', () => {
it('tests isCacheValid with empty state', () => {
const invalid = isCacheValid({ state: 'empty' });
expect(invalid).toBe('unknown');
});
it('tests isCacheValid with loading state', () => {
const invalid = isCacheValid({ state: 'loading' });
expect(invalid).toBe('unknown');
});
it('tests isCacheValid with overdue cached state', () => {
const isValid = isCacheValid({
state: 'cached',
data: {} as any, // doesn't matter
createdAt: Date.now() - 2000, // 2 seconds in the past
ttl: 1000 // 1 second
});
expect(isValid).toBe(false);
});
it('tests isCacheValid with overdue cached state', () => {
const isValid = isCacheValid({
state: 'cached',
data: {} as any, // doesn't matter
createdAt: Date.now(),
ttl: 1000 // 1 second
});
expect(isValid).toBe(true);
});
});