feat(ajax): add an option to initialize the cache interceptors even when useCache is turned off in the global options

This commit is contained in:
Martin Pool 2022-04-26 16:48:33 +02:00 committed by Thijs Louisse
parent a28686ee72
commit 56af96f1da
6 changed files with 64 additions and 18 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ajax': minor
---
Add an option "addCaching" to the Ajax config, in order to add cache interceptors when useCache is turned off. In this situation, all requests are cached proactively.

View file

@ -23,11 +23,12 @@ export class Ajax {
*/
constructor(config = {}) {
/**
* @type {Partial<AjaxConfig>}
* @type {AjaxConfig}
* @private
*/
this.__config = {
addAcceptLanguage: true,
addCaching: false,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
jsonPrefix: '',
@ -53,7 +54,7 @@ export class Ajax {
}
const { cacheOptions } = this.__config;
if (cacheOptions?.useCache) {
if (cacheOptions.useCache || this.__config.addCaching) {
const { cacheRequestInterceptor, cacheResponseInterceptor } = createCacheInterceptors(
cacheOptions.getCacheIdentifier,
cacheOptions,
@ -65,7 +66,7 @@ export class Ajax {
/**
* Configures the Ajax instance
* @param {Partial<AjaxConfig>} config configuration for the Ajax instance
* @param {AjaxConfig} config configuration for the Ajax instance
*/
set options(config) {
this.__config = config;

View file

@ -10,6 +10,15 @@ import {
isCurrentSessionId,
} from '../cacheManager.js';
/**
* Tests whether the request method is supported according to the `cacheOptions`
* @param {ValidatedCacheOptions} cacheOptions
* @param {string} method
* @returns {boolean}
*/
const isMethodSupported = (cacheOptions, method) =>
cacheOptions.methods.includes(method.toLowerCase());
/**
* Request interceptor to return relevant cached requests
* @param {function(): string} getCacheId used to invalidate cache if identifier is changed
@ -36,9 +45,8 @@ const createCacheRequestInterceptor =
}
const requestId = cacheOptions.requestIdFunction(request);
const isMethodSupported = cacheOptions.methods.includes(request.method.toLowerCase());
if (!isMethodSupported) {
if (!isMethodSupported(cacheOptions, request.method)) {
invalidateMatchingCache(requestId, cacheOptions);
return request;
}
@ -81,12 +89,9 @@ const createCacheResponseInterceptor =
...response.request.cacheOptions,
});
const requestId = cacheOptions.requestIdFunction(response.request);
const isAlreadyFromCache = !!response.fromCache;
const isCacheActive = cacheOptions.useCache;
const isMethodSupported = cacheOptions.methods.includes(response.request?.method.toLowerCase());
if (!response.fromCache && isMethodSupported(cacheOptions, response.request.method)) {
const requestId = cacheOptions.requestIdFunction(response.request);
if (!isAlreadyFromCache && isCacheActive && isMethodSupported) {
if (isCurrentSessionId(response.request.cacheSessionId)) {
// Cache the response
ajaxCache.set(requestId, response.clone());
@ -95,6 +100,7 @@ const createCacheResponseInterceptor =
// Mark the pending request as resolved
pendingRequestStore.resolve(requestId);
}
return response;
};

View file

@ -43,6 +43,7 @@ describe('Ajax', () => {
};
const expected = {
addAcceptLanguage: true,
addCaching: false,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
jsonPrefix: ")]}',",
@ -303,6 +304,44 @@ describe('Ajax', () => {
getCacheIdentifier = () => String(cacheId);
});
it('does not add cache interceptors when useCache is turned off', () => {
const customAjax = new Ajax({
cacheOptions: {
maxAge: 100,
getCacheIdentifier,
},
});
expect(customAjax._requestInterceptors.length).to.equal(2);
expect(customAjax._responseInterceptors.length).to.equal(0);
});
it('adds cache interceptors when useCache is turned on', () => {
const customAjax = new Ajax({
cacheOptions: {
useCache: true,
maxAge: 100,
getCacheIdentifier,
},
});
expect(customAjax._requestInterceptors.length).to.equal(3);
expect(customAjax._responseInterceptors.length).to.equal(1);
});
it('adds cache interceptors when addCaching is turned on', () => {
const customAjax = new Ajax({
addCaching: true,
cacheOptions: {
maxAge: 100,
getCacheIdentifier,
},
});
expect(customAjax._requestInterceptors.length).to.equal(3);
expect(customAjax._responseInterceptors.length).to.equal(1);
});
describe('caching interceptors', async () => {
/**
* @type {Ajax}

View file

@ -150,14 +150,12 @@ describe('cache interceptors', () => {
expect(fetchStub.callCount).to.equal(1);
});
// TODO: Check if this is the behaviour we want
it('all calls with non-default `maxAge` are cached proactively', async () => {
it('all calls are cached proactively', async () => {
// Given
newCacheId();
addCacheInterceptors(ajax, {
useCache: false,
maxAge: 100,
});
// When
@ -169,11 +167,7 @@ describe('cache interceptors', () => {
expect(fetchStub.callCount).to.equal(1);
// When
await ajax.fetch('/test', {
cacheOptions: {
useCache: true,
},
});
await ajax.fetch('/test');
// Then
expect(fetchStub.callCount).to.equal(2);

View file

@ -12,6 +12,7 @@ export interface LionRequestInit extends Omit<RequestInit, 'body'> {
export interface AjaxConfig {
addAcceptLanguage: boolean;
addCaching: boolean;
xsrfCookieName: string | null;
xsrfHeaderName: string | null;
cacheOptions: CacheOptionsWithIdentifier;