diff --git a/src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts b/src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts index 0502defe..55dc888f 100644 --- a/src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts +++ b/src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts @@ -44,16 +44,36 @@ export class ApiPlugin implements WorkboxPlugin { request, response, }) => { - if (this.options.type === 'list' || this.options.type === 'item') { - if (response.status !== 200) { - return response; - } + if (response.status !== 200) { + return response; + } + if (this.options.type === 'list' || this.options.type === 'item') { const tableName = this.options.tableName; const body = (await response.clone().json()) as DocsResponse | Doc; await DocsDB.cacheResponse(request.url, body, tableName); } + if (this.options.type === 'update') { + const db = await DocsDB.open(); + const storedResponse = await db.get('doc-item', request.url); + + if (!storedResponse || !this.initialRequest) { + return response; + } + + const bodyMutate = (await this.initialRequest + .clone() + .json()) as Partial; + + const newResponse = { + ...storedResponse, + ...bodyMutate, + }; + + await DocsDB.cacheResponse(request.url, newResponse, 'doc-item'); + } + return response; }; diff --git a/src/frontend/apps/impress/src/features/service-worker/__tests__/ApiPlugin.test.tsx b/src/frontend/apps/impress/src/features/service-worker/__tests__/ApiPlugin.test.tsx index 491d77b6..4285e00e 100644 --- a/src/frontend/apps/impress/src/features/service-worker/__tests__/ApiPlugin.test.tsx +++ b/src/frontend/apps/impress/src/features/service-worker/__tests__/ApiPlugin.test.tsx @@ -30,17 +30,34 @@ jest.mock('idb', () => ({ describe('ApiPlugin', () => { afterEach(() => jest.clearAllMocks()); - ['doc-item', 'doc-list'].forEach((type) => { + [ + { type: 'item', table: 'doc-item' }, + { type: 'list', table: 'doc-list' }, + { type: 'update', table: 'doc-item' }, + ].forEach(({ type, table }) => { it(`calls fetchDidSucceed with type ${type} and status 200`, async () => { + const mockedSync = jest.fn().mockResolvedValue({}); const apiPlugin = new ApiPlugin({ - tableName: type as any, - type: 'list', - syncManager: jest.fn() as any, + tableName: table as any, + type: type as any, + syncManager: { + sync: () => mockedSync(), + } as any, }); const body = { lastName: 'Doe' }; const bodyBuffer = RequestSerializer.objectToArrayBuffer(body); + const requestInit = { + request: { + url: 'test-url', + clone: () => mockedClone(), + json: () => body, + } as unknown as Request, + } as any; + const mockedClone = jest.fn().mockReturnValue(requestInit.request); + await apiPlugin.requestWillFetch?.(requestInit); + const response = await apiPlugin.fetchDidSucceed?.({ request: { url: 'test-url', @@ -55,15 +72,15 @@ describe('ApiPlugin', () => { }), } as any); - expect(mockedPut).toHaveBeenCalledWith(type, body, 'test-url'); + expect(mockedPut).toHaveBeenCalledWith(table, body, 'test-url'); expect(mockedClose).toHaveBeenCalled(); expect(response?.status).toBe(200); }); it(`calls fetchDidSucceed with type ${type} and status other that 200`, async () => { const apiPlugin = new ApiPlugin({ - tableName: type as any, - type: 'list', + tableName: table as any, + type: type as any, syncManager: jest.fn() as any, });