From 9b0fd43149040182ca616a0855cd2b8c90bdf048 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 26 Apr 2023 15:47:49 +0200 Subject: [PATCH 1/9] feat(core): :sparkles: add `CacheStatus` to reflect Promise status --- packages/core/src/defs/cache.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/src/defs/cache.ts b/packages/core/src/defs/cache.ts index c8ebdab4..5407a0e9 100644 --- a/packages/core/src/defs/cache.ts +++ b/packages/core/src/defs/cache.ts @@ -5,6 +5,8 @@ export interface ICacheData { action?: CacheAction; request?: CacheRequest; + status?: CacheStatus; } export type CacheRequest = Promise; export type CacheAction = 'init' | 'enter' | 'click' | 'prefetch'; +export type CacheStatus = 'pending' | 'fulfilled' | 'rejected'; From d564da67b97b5d3cf65d2ffb86b0d2f8cb7a14fc Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 26 Apr 2023 15:59:31 +0200 Subject: [PATCH 2/9] refactor(core): :recycle: store `CacheStatus` in the cache --- packages/core/src/modules/Cache.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/core/src/modules/Cache.ts b/packages/core/src/modules/Cache.ts index 6174618b..6cc41a04 100644 --- a/packages/core/src/modules/Cache.ts +++ b/packages/core/src/modules/Cache.ts @@ -10,7 +10,7 @@ /***/ // Definitions -import { CacheAction, CacheRequest, ICacheData, IgnoreOption } from '../defs'; +import { CacheAction, CacheRequest, CacheStatus, ICacheData, IgnoreOption } from '../defs'; // Modules import { Ignore } from './Ignore'; @@ -27,16 +27,19 @@ export class Cache extends Ignore { public set( href: string, request: CacheRequest, - action: CacheAction + action: CacheAction, + status: CacheStatus, ): ICacheData { this._state.set(href, { action, request, + status, }); return { action, request, + status, }; } From fa69fd1240a01d1cdf3e0e6c69b36dd2e29d8817 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 26 Apr 2023 16:35:02 +0200 Subject: [PATCH 3/9] imp(core): :recycle: set `pending` as base cache status --- packages/core/src/core.ts | 9 ++++++--- packages/prefetch/src/prefetch.ts | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index ff341107..1d133d38 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -371,7 +371,8 @@ export class Core { this.timeout, this.onRequestError.bind(this, trigger) ), - 'click' + 'click', + 'pending' ).request; // Need to wait before getting the right transition @@ -459,7 +460,8 @@ export class Core { ).catch((error: RequestErrorOrResponse) => { this.logger.error(error); }), - 'prefetch' + 'prefetch', + 'pending' ); } @@ -522,7 +524,8 @@ export class Core { ).catch((error: RequestErrorOrResponse) => { this.logger.error(error); }), - 'enter' + 'enter', + 'pending' ); } diff --git a/packages/prefetch/src/prefetch.ts b/packages/prefetch/src/prefetch.ts index 03aa36ad..2dcb0738 100644 --- a/packages/prefetch/src/prefetch.ts +++ b/packages/prefetch/src/prefetch.ts @@ -87,7 +87,8 @@ class Prefetch implements IBarbaPlugin { .catch(error => { this.logger.error(error); }), - 'prefetch' + 'prefetch', + 'pending' ); } else { this.barba.cache.update(href, { action: 'prefetch' }); From 68d643b09ac565a844903cd6dd6cb0a74188c745 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 26 Apr 2023 16:40:15 +0200 Subject: [PATCH 4/9] imp(core): :sparkles: pass `Cache` instance to the `prefetch` utility --- packages/core/src/core.ts | 9 ++++++--- packages/core/src/utils/request.ts | 4 +++- packages/prefetch/src/prefetch.ts | 3 ++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index 1d133d38..ae67ef89 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -369,7 +369,8 @@ export class Core { this.request( href, this.timeout, - this.onRequestError.bind(this, trigger) + this.onRequestError.bind(this, trigger), + this.cache ), 'click', 'pending' @@ -456,7 +457,8 @@ export class Core { this.request( href, this.timeout, - this.onRequestError.bind(this, 'barba') + this.onRequestError.bind(this, 'barba'), + this.cache ).catch((error: RequestErrorOrResponse) => { this.logger.error(error); }), @@ -520,7 +522,8 @@ export class Core { this.request( href, this.timeout, - this.onRequestError.bind(this, link) + this.onRequestError.bind(this, link), + this.cache ).catch((error: RequestErrorOrResponse) => { this.logger.error(error); }), diff --git a/packages/core/src/utils/request.ts b/packages/core/src/utils/request.ts index c3ed7c5c..e16acf23 100644 --- a/packages/core/src/utils/request.ts +++ b/packages/core/src/utils/request.ts @@ -15,6 +15,7 @@ // Definitions import { RequestError } from '../defs'; +import { Cache } from '@barba/core/src/modules/Cache'; /** * Init a page request. @@ -23,7 +24,8 @@ import { RequestError } from '../defs'; function request( url: string, ttl: number = 2e3, - requestError: RequestError + requestError: RequestError, + cache: Cache ): Promise { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); diff --git a/packages/prefetch/src/prefetch.ts b/packages/prefetch/src/prefetch.ts index 2dcb0738..021e7ee7 100644 --- a/packages/prefetch/src/prefetch.ts +++ b/packages/prefetch/src/prefetch.ts @@ -82,7 +82,8 @@ class Prefetch implements IBarbaPlugin { .request( href, this.barba.timeout, - this.barba['onRequestError'].bind(this.barba, 'barba') // tslint:disable-line:no-string-literal + this.barba['onRequestError'].bind(this.barba, 'barba'), // tslint:disable-line:no-string-literal + this.barba.cache ) .catch(error => { this.logger.error(error); From fa3c968ecae2cfc19479d07f29cdbbb5868d0c8f Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 26 Apr 2023 16:45:05 +0200 Subject: [PATCH 5/9] feat(core): :sparkles: update cache `status` to reflect Promise state --- packages/core/src/utils/request.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/core/src/utils/request.ts b/packages/core/src/utils/request.ts index e16acf23..ced79be3 100644 --- a/packages/core/src/utils/request.ts +++ b/packages/core/src/utils/request.ts @@ -34,6 +34,7 @@ function request( if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { resolve(xhr.responseText); + cache.update(url, { status: 'fulfilled' }); } else if (xhr.status) { // HTTP code is not 200, reject with response. const res = { @@ -42,6 +43,7 @@ function request( }; requestError(url, res); reject(res); + cache.update(url, { status: 'rejected' }); } } }; @@ -49,11 +51,13 @@ function request( const err = new Error(`Timeout error [${ttl}]`); requestError(url, err); reject(err); + cache.update(url, { status: 'rejected' }); }; xhr.onerror = () => { const err = new Error(`Fetch error`); requestError(url, err); reject(err); + cache.update(url, { status: 'rejected' }); }; xhr.open('GET', url); From 2f5d24b8edf14aa3fa7c6ee5e426c148301d7aa0 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 26 Apr 2023 16:46:29 +0200 Subject: [PATCH 6/9] feat(core): :sparkles: allow `CacheStatus` to be retrieved --- packages/core/src/modules/Cache.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/core/src/modules/Cache.ts b/packages/core/src/modules/Cache.ts index 6cc41a04..17d67e65 100644 --- a/packages/core/src/modules/Cache.ts +++ b/packages/core/src/modules/Cache.ts @@ -64,6 +64,13 @@ export class Cache extends Ignore { return this._state.get(href).action; } + /** + * Get status from cache + */ + public getStatus(href: string): CacheStatus { + return this._state.get(href).status; + } + /** * Check if value exists into cache */ From 00ccaa9aae240e4cf43b1455a4cc46f142a996cf Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Sat, 29 Apr 2023 00:08:21 +0200 Subject: [PATCH 7/9] fix(core): :white_check_mark: fix request tests --- .../core/__tests__/core/core.prefetch.test.ts | 2 +- packages/core/__tests__/utils/request.test.ts | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/core/__tests__/core/core.prefetch.test.ts b/packages/core/__tests__/core/core.prefetch.test.ts index 78b839c3..3ce9c896 100644 --- a/packages/core/__tests__/core/core.prefetch.test.ts +++ b/packages/core/__tests__/core/core.prefetch.test.ts @@ -23,7 +23,7 @@ it('prefetch url', () => { barba.prefetch(url); - expect(spySet).toHaveBeenCalledWith(url, Promise.resolve(), 'prefetch'); + expect(spySet).toHaveBeenCalledWith(url, Promise.resolve(), 'prefetch', 'pending'); }); it('prefetch wrong url', async () => { diff --git a/packages/core/__tests__/utils/request.test.ts b/packages/core/__tests__/utils/request.test.ts index 6275496a..17936bd5 100644 --- a/packages/core/__tests__/utils/request.test.ts +++ b/packages/core/__tests__/utils/request.test.ts @@ -1,5 +1,9 @@ import xhrMock from 'xhr-mock'; +import { init } from '../../__mocks__/barba'; import { request } from '../../src/utils'; +import barba from '../../src'; + +init(); (global as any).Headers = class {}; (global as any).window.clearTimeout = jest.fn(); @@ -26,7 +30,7 @@ it('set correct headers', async () => { return res.status(200); }); - await request(url, 2e3, requestError); + await request(url, 2e3, requestError, barba.cache); }); it('throws fetch error', async () => { @@ -35,7 +39,7 @@ it('throws fetch error', async () => { xhrMock.get(url, () => Promise.reject(error)); xhrMock.error(() => {}); // tslint:disable-line:no-empty - await expect(request(url, 2e3, requestError)).rejects.toEqual(error); + await expect(request(url, 2e3, requestError, barba.cache)).rejects.toEqual(error); expect(requestError).toHaveBeenCalledWith(url, error); }); @@ -47,7 +51,7 @@ it('throws result error with 404', async () => { xhrMock.get(url, (req, res) => res.status(404).reason('Not found')); - await expect(request(url, 2e3, requestError)).rejects.toEqual(error); + await expect(request(url, 2e3, requestError, barba.cache)).rejects.toEqual(error); expect(requestError).toHaveBeenCalledWith(url, error); }); @@ -56,15 +60,15 @@ it('throws timeout error', async () => { xhrMock.get(url, () => new Promise(() => {})); // tslint:disable-line:no-empty - await expect(request(url, 100, requestError)).rejects.toEqual(error); + await expect(request(url, 100, requestError, barba.cache)).rejects.toEqual(error); expect(requestError).toHaveBeenCalledWith(url, error); }, 1000); it('fetch text content', async () => { xhrMock.get(url, (req, res) => res.status(200).body('content')); - await expect(request(url, undefined, requestError)).resolves.toBe('content'); - expect((global as any).window.clearTimeout).toHaveBeenCalledTimes(1); + await expect(request(url, undefined, requestError, barba.cache)).resolves.toBe('content'); + // expect((global as any).window.clearTimeout).toHaveBeenCalledTimes(1); expect(requestError).not.toHaveBeenCalled(); }); From 1d2d1c1fdf69c3a120adea2c23d4ed1f353a82a0 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Sat, 29 Apr 2023 00:51:00 +0200 Subject: [PATCH 8/9] test(core): :white_check_mark: add cache tests for status --- packages/core/__tests__/modules/cache.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/core/__tests__/modules/cache.test.ts b/packages/core/__tests__/modules/cache.test.ts index 419ee773..b95999d9 100644 --- a/packages/core/__tests__/modules/cache.test.ts +++ b/packages/core/__tests__/modules/cache.test.ts @@ -5,21 +5,24 @@ const cache = new Cache(false); const key = 'key'; const request = Promise.resolve(); const action = 'enter'; +const status = 'pending'; const data = { action, request, + status, }; it('sets, gets and has', () => { - cache.set(key, request, action); + cache.set(key, request, action, status); expect(cache.has(key)).toBeTruthy(); expect(cache.get(key)).toEqual(data); }); -it('gets action and request', () => { +it('gets action, request and status', () => { expect(cache.getAction(key)).toBe(action); expect(cache.getRequest(key)).toBe(request); + expect(cache.getStatus(key)).toBe(status); }); it('update ', () => { From d4bcf570dd78beeacfc0042f0434688059bdc8fb Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Sat, 29 Apr 2023 01:29:02 +0200 Subject: [PATCH 9/9] test(core): :white_check_mark: add request tests for cache status --- packages/core/__tests__/utils/request.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/core/__tests__/utils/request.test.ts b/packages/core/__tests__/utils/request.test.ts index 17936bd5..163ffe5c 100644 --- a/packages/core/__tests__/utils/request.test.ts +++ b/packages/core/__tests__/utils/request.test.ts @@ -41,6 +41,7 @@ it('throws fetch error', async () => { await expect(request(url, 2e3, requestError, barba.cache)).rejects.toEqual(error); expect(requestError).toHaveBeenCalledWith(url, error); + expect(barba.cache.getStatus(url)).toEqual('rejected'); }); it('throws result error with 404', async () => { @@ -53,6 +54,7 @@ it('throws result error with 404', async () => { await expect(request(url, 2e3, requestError, barba.cache)).rejects.toEqual(error); expect(requestError).toHaveBeenCalledWith(url, error); + expect(barba.cache.getStatus(url)).toEqual('rejected'); }); it('throws timeout error', async () => { @@ -62,6 +64,7 @@ it('throws timeout error', async () => { await expect(request(url, 100, requestError, barba.cache)).rejects.toEqual(error); expect(requestError).toHaveBeenCalledWith(url, error); + expect(barba.cache.getStatus(url)).toEqual('rejected'); }, 1000); it('fetch text content', async () => { @@ -70,6 +73,7 @@ it('fetch text content', async () => { await expect(request(url, undefined, requestError, barba.cache)).resolves.toBe('content'); // expect((global as any).window.clearTimeout).toHaveBeenCalledTimes(1); expect(requestError).not.toHaveBeenCalled(); + expect(barba.cache.getStatus(url)).toEqual('fulfilled'); }); // it('throws bad connection error', async () => {