Add caching tests for when getCacheIdentifier is asynchronous
This commit is contained in:
parent
c5ffe9cffc
commit
a8105ec278
2 changed files with 141 additions and 66 deletions
5
.changeset/stupid-pandas-greet.md
Normal file
5
.changeset/stupid-pandas-greet.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@lion/ajax': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add caching tests for when getCacheIdentifier is asynchronous
|
||||||
|
|
@ -451,6 +451,8 @@ describe('Ajax', () => {
|
||||||
let cacheId;
|
let cacheId;
|
||||||
/** @type {() => string} */
|
/** @type {() => string} */
|
||||||
let getCacheIdentifier;
|
let getCacheIdentifier;
|
||||||
|
/** @type {() => Promise<string>} */
|
||||||
|
let getCacheIdentifierAsync;
|
||||||
|
|
||||||
const newCacheId = () => {
|
const newCacheId = () => {
|
||||||
if (!cacheId) {
|
if (!cacheId) {
|
||||||
|
|
@ -463,6 +465,7 @@ describe('Ajax', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
getCacheIdentifier = () => String(cacheId);
|
getCacheIdentifier = () => String(cacheId);
|
||||||
|
getCacheIdentifierAsync = () => Promise.resolve(String(cacheId));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not add cache interceptors when useCache is turned off', () => {
|
it('does not add cache interceptors when useCache is turned off', () => {
|
||||||
|
|
@ -503,7 +506,97 @@ describe('Ajax', () => {
|
||||||
expect(customAjax._responseInterceptors.length).to.equal(1);
|
expect(customAjax._responseInterceptors.length).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Caching interceptors: synchronous getCacheIdentifier tests', async () => {
|
const cachingTests = {};
|
||||||
|
cachingTests.works = async (/** @type {Ajax} */ customAjax) => {
|
||||||
|
await customAjax.fetch('/foo');
|
||||||
|
|
||||||
|
const secondResponse = await customAjax.fetch('/foo');
|
||||||
|
expect(fetchStub.callCount).to.equal(1);
|
||||||
|
expect(await secondResponse.text()).to.equal('mock response');
|
||||||
|
expect(secondResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
||||||
|
expect(secondResponse.headers.get('Content-Type')).to.equal('application/json');
|
||||||
|
};
|
||||||
|
|
||||||
|
cachingTests.resetOnCacheIDChange = async (/** @type {Ajax} */ customAjax) => {
|
||||||
|
/* Three calls to the same endpoint should result in a
|
||||||
|
single fetchStubCall due to caching */
|
||||||
|
await customAjax.fetch('/foo');
|
||||||
|
await customAjax.fetch('/foo');
|
||||||
|
await customAjax.fetch('/foo');
|
||||||
|
expect(fetchStub.callCount).to.equal(1);
|
||||||
|
|
||||||
|
newCacheId();
|
||||||
|
await customAjax.fetch('/foo');
|
||||||
|
|
||||||
|
/* The newCacheId call should reset the cache, thereby adding an
|
||||||
|
extra call to the fetchStub call count. */
|
||||||
|
expect(fetchStub.callCount).to.equal(2);
|
||||||
|
};
|
||||||
|
|
||||||
|
cachingTests.completePendingOnCacheIDChange = async (/** @type {Ajax} */ customAjax) => {
|
||||||
|
const requestOne = customAjax.fetch('/foo').then(() => 'completedRequestOne');
|
||||||
|
newCacheId();
|
||||||
|
const requestTwo = customAjax.fetch('/foo').then(() => 'completedRequestTwo');
|
||||||
|
expect(await requestOne).to.equal('completedRequestOne');
|
||||||
|
expect(await requestTwo).to.equal('completedRequestTwo');
|
||||||
|
};
|
||||||
|
|
||||||
|
cachingTests.worksWithFetchJson = async (/** @type {Ajax} */ customAjax) => {
|
||||||
|
fetchStub.returns(Promise.resolve(new Response('{"a":1,"b":2}', responseInit())));
|
||||||
|
|
||||||
|
const firstResponse = await customAjax.fetchJson('/foo');
|
||||||
|
expect(firstResponse.body).to.deep.equal({ a: 1, b: 2 });
|
||||||
|
expect(firstResponse.response.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
||||||
|
expect(firstResponse.response.headers.get('Content-Type')).to.equal('application/json');
|
||||||
|
|
||||||
|
const secondResponse = await customAjax.fetchJson('/foo');
|
||||||
|
expect(fetchStub.callCount).to.equal(1);
|
||||||
|
expect(secondResponse.body).to.deep.equal({ a: 1, b: 2 });
|
||||||
|
expect(secondResponse.response.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
||||||
|
expect(secondResponse.response.headers.get('Content-Type')).to.equal('application/json');
|
||||||
|
};
|
||||||
|
|
||||||
|
cachingTests.invalidatesOnNonGetMethod = async (/** @type {Ajax} */ customAjax) => {
|
||||||
|
await customAjax.fetch('/foo');
|
||||||
|
|
||||||
|
const secondResponse = await customAjax.fetch('/foo', { method: 'POST' });
|
||||||
|
expect(fetchStub.callCount).to.equal(2);
|
||||||
|
expect(await secondResponse.text()).to.equal('mock response');
|
||||||
|
expect(secondResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
||||||
|
expect(secondResponse.headers.get('Content-Type')).to.equal('application/json');
|
||||||
|
|
||||||
|
const thirdResponse = await customAjax.fetch('/foo');
|
||||||
|
expect(fetchStub.callCount).to.equal(3);
|
||||||
|
expect(await thirdResponse.text()).to.equal('mock response');
|
||||||
|
expect(thirdResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
||||||
|
expect(thirdResponse.headers.get('Content-Type')).to.equal('application/json');
|
||||||
|
};
|
||||||
|
|
||||||
|
cachingTests.invalidatesOnTTLPassed = async (/** @type {Ajax} */ customAjax) => {
|
||||||
|
const clock = useFakeTimers({
|
||||||
|
shouldAdvanceTime: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await customAjax.fetch('/foo');
|
||||||
|
|
||||||
|
const secondResponse = await customAjax.fetch('/foo');
|
||||||
|
expect(fetchStub.callCount).to.equal(1);
|
||||||
|
expect(await secondResponse.text()).to.equal('mock response');
|
||||||
|
expect(secondResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
||||||
|
expect(secondResponse.headers.get('Content-Type')).to.equal('application/json');
|
||||||
|
|
||||||
|
clock.tick(101);
|
||||||
|
|
||||||
|
const thirdResponse = await customAjax.fetch('/foo');
|
||||||
|
expect(fetchStub.callCount).to.equal(2);
|
||||||
|
expect(await thirdResponse.text()).to.equal('mock response');
|
||||||
|
expect(thirdResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
||||||
|
expect(thirdResponse.headers.get('Content-Type')).to.equal('application/json');
|
||||||
|
|
||||||
|
clock.restore();
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Caching interceptors: cache tests with synchronous getCacheIdentifier', async () => {
|
||||||
/**
|
/**
|
||||||
* @type {Ajax}
|
* @type {Ajax}
|
||||||
*/
|
*/
|
||||||
|
|
@ -521,92 +614,69 @@ describe('Ajax', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
await customAjax.fetch('/foo');
|
await cachingTests.works(customAjax);
|
||||||
|
|
||||||
const secondResponse = await customAjax.fetch('/foo');
|
|
||||||
expect(fetchStub.callCount).to.equal(1);
|
|
||||||
expect(await secondResponse.text()).to.equal('mock response');
|
|
||||||
expect(secondResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
|
||||||
expect(secondResponse.headers.get('Content-Type')).to.equal('application/json');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resets the cache if the cache ID changes', async () => {
|
it('resets the cache if the cache ID changes', async () => {
|
||||||
/* Three calls to the same endpoint should result in a
|
await cachingTests.resetOnCacheIDChange(customAjax);
|
||||||
single fetchStubCall due to caching */
|
|
||||||
await customAjax.fetch('/foo');
|
|
||||||
await customAjax.fetch('/foo');
|
|
||||||
await customAjax.fetch('/foo');
|
|
||||||
expect(fetchStub.callCount).to.equal(1);
|
|
||||||
|
|
||||||
newCacheId();
|
|
||||||
await customAjax.fetch('/foo');
|
|
||||||
|
|
||||||
/* The newCacheId call should reset the cache, thereby adding an
|
|
||||||
extra call to the fetchStub call count. */
|
|
||||||
expect(fetchStub.callCount).to.equal(2);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Completes pending requests when the cache ID changes', async () => {
|
it('Completes pending requests when the cache ID changes', async () => {
|
||||||
const requestOne = customAjax.fetch('/foo').then(() => 'completedRequestOne');
|
await cachingTests.completePendingOnCacheIDChange(customAjax);
|
||||||
newCacheId();
|
|
||||||
const requestTwo = customAjax.fetch('/foo').then(() => 'completedRequestTwo');
|
|
||||||
expect(await requestOne).to.equal('completedRequestOne');
|
|
||||||
expect(await requestTwo).to.equal('completedRequestTwo');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works with fetchJson', async () => {
|
it('works with fetchJson', async () => {
|
||||||
fetchStub.returns(Promise.resolve(new Response('{"a":1,"b":2}', responseInit())));
|
await cachingTests.worksWithFetchJson(customAjax);
|
||||||
|
|
||||||
const firstResponse = await customAjax.fetchJson('/foo');
|
|
||||||
expect(firstResponse.body).to.deep.equal({ a: 1, b: 2 });
|
|
||||||
expect(firstResponse.response.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
|
||||||
expect(firstResponse.response.headers.get('Content-Type')).to.equal('application/json');
|
|
||||||
|
|
||||||
const secondResponse = await customAjax.fetchJson('/foo');
|
|
||||||
expect(fetchStub.callCount).to.equal(1);
|
|
||||||
expect(secondResponse.body).to.deep.equal({ a: 1, b: 2 });
|
|
||||||
expect(secondResponse.response.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
|
||||||
expect(secondResponse.response.headers.get('Content-Type')).to.equal('application/json');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('is invalidated on non-get method', async () => {
|
it('is invalidated on non-get method', async () => {
|
||||||
await customAjax.fetch('/foo');
|
await cachingTests.invalidatesOnNonGetMethod(customAjax);
|
||||||
|
|
||||||
const secondResponse = await customAjax.fetch('/foo', { method: 'POST' });
|
|
||||||
expect(fetchStub.callCount).to.equal(2);
|
|
||||||
expect(await secondResponse.text()).to.equal('mock response');
|
|
||||||
expect(secondResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
|
||||||
expect(secondResponse.headers.get('Content-Type')).to.equal('application/json');
|
|
||||||
|
|
||||||
const thirdResponse = await customAjax.fetch('/foo');
|
|
||||||
expect(fetchStub.callCount).to.equal(3);
|
|
||||||
expect(await thirdResponse.text()).to.equal('mock response');
|
|
||||||
expect(thirdResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
|
||||||
expect(thirdResponse.headers.get('Content-Type')).to.equal('application/json');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('is invalidated after TTL has passed', async () => {
|
it('is invalidated after TTL has passed', async () => {
|
||||||
const clock = useFakeTimers({
|
await cachingTests.invalidatesOnTTLPassed(customAjax);
|
||||||
shouldAdvanceTime: true,
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Caching interceptors: cache tests with asynchronous getCacheIdentifier', async () => {
|
||||||
|
/**
|
||||||
|
* @type {Ajax}
|
||||||
|
*/
|
||||||
|
let customAjax;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
newCacheId();
|
||||||
|
customAjax = new Ajax({
|
||||||
|
cacheOptions: {
|
||||||
|
useCache: true,
|
||||||
|
maxAge: 100,
|
||||||
|
getCacheIdentifier: getCacheIdentifierAsync,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
await customAjax.fetch('/foo');
|
it('works', async () => {
|
||||||
|
await cachingTests.works(customAjax);
|
||||||
|
});
|
||||||
|
|
||||||
const secondResponse = await customAjax.fetch('/foo');
|
it('resets the cache if the cache ID changes', async () => {
|
||||||
expect(fetchStub.callCount).to.equal(1);
|
await cachingTests.resetOnCacheIDChange(customAjax);
|
||||||
expect(await secondResponse.text()).to.equal('mock response');
|
});
|
||||||
expect(secondResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
|
||||||
expect(secondResponse.headers.get('Content-Type')).to.equal('application/json');
|
|
||||||
|
|
||||||
clock.tick(101);
|
it('Completes pending requests when the cache ID changes', async () => {
|
||||||
|
await cachingTests.completePendingOnCacheIDChange(customAjax);
|
||||||
|
});
|
||||||
|
|
||||||
const thirdResponse = await customAjax.fetch('/foo');
|
it('works with fetchJson', async () => {
|
||||||
expect(fetchStub.callCount).to.equal(2);
|
await cachingTests.worksWithFetchJson(customAjax);
|
||||||
expect(await thirdResponse.text()).to.equal('mock response');
|
});
|
||||||
expect(thirdResponse.headers.get('X-Custom-Header')).to.equal('y-custom-value');
|
|
||||||
expect(thirdResponse.headers.get('Content-Type')).to.equal('application/json');
|
|
||||||
|
|
||||||
clock.restore();
|
it('is invalidated on non-get method', async () => {
|
||||||
|
await cachingTests.invalidatesOnNonGetMethod(customAjax);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is invalidated after TTL has passed', async () => {
|
||||||
|
await cachingTests.invalidatesOnTTLPassed(customAjax);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue