diff --git a/packages/client/src/relewise.client.ts b/packages/client/src/relewise.client.ts index e9bdbf5..8b30c02 100644 --- a/packages/client/src/relewise.client.ts +++ b/packages/client/src/relewise.client.ts @@ -6,7 +6,10 @@ export interface RelewiseClientOptions { } export interface RelewiseRequestOptions { + /** Cancels the request when the provided abort signal is triggered. */ abortSignal?: AbortSignal; + /** Allows the request to outlive the page, such as when tracking events during page unload or navigation. */ + keepalive?: boolean; } export class ProblemDetailsError extends Error { @@ -68,6 +71,7 @@ export abstract class RelewiseClient { }, body: JSON.stringify(data), signal: options?.abortSignal, + keepalive: options?.keepalive, cache: this.cache, }); @@ -152,4 +156,4 @@ export abstract class RelewiseClient { return undefined; } } -} \ No newline at end of file +} diff --git a/packages/client/tests/unit-tests/relewiseRequestOptions.unit.test.ts b/packages/client/tests/unit-tests/relewiseRequestOptions.unit.test.ts new file mode 100644 index 0000000..3edd049 --- /dev/null +++ b/packages/client/tests/unit-tests/relewiseRequestOptions.unit.test.ts @@ -0,0 +1,33 @@ +import { Tracker } from '../../src/tracker'; + +describe('RelewiseRequestOptions', () => { + const originalFetch = global.fetch; + + afterEach(() => { + global.fetch = originalFetch; + jest.restoreAllMocks(); + }); + + test('passes keepalive to fetch when tracking events', async () => { + const fetchMock = jest.fn().mockResolvedValue({ + ok: true, + json: jest.fn().mockRejectedValue(new Error('No content')), + } as unknown as Response); + + global.fetch = fetchMock; + + const tracker = new Tracker('dataset-id', 'api-key'); + + await tracker.trackProductView({ + productId: 'product-id', + user: { + temporaryId: 'temporary-id', + }, + }, { keepalive: true }); + + expect(fetchMock).toHaveBeenCalledTimes(1); + expect(fetchMock).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({ + keepalive: true, + })); + }); +});