Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ✨ queue zaraz method calls until initialised #2

Merged
merged 1 commit into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 57 additions & 3 deletions src/helpers/get-zaraz.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@ declare global {

let windowObj: Window & typeof globalThis;

const logSpy = jest.spyOn(console, 'log');

beforeAll(() => {
windowObj = window;

logSpy.mockImplementation();
});

afterAll(() => {
window = windowObj;
Object.defineProperty(global, 'window', {
value: windowObj,
});

logSpy.mockRestore();
});

describe('getZaraz()', () => {
Expand All @@ -36,11 +44,57 @@ describe('getZaraz()', () => {
});
});

it('should throw when zaraz does not exist on the window', () => {
it('should queue events when zaraz is not defined', () => {
window.zaraz = undefined;

// getZaraz() returns a queue.
getZaraz().track('page_view', {
page_location: 'https://example.com',
page_path: '/',
page_title: 'Home',
});

expect(logSpy).toHaveBeenCalledWith(
`Zaraz Web API is not initialized. Queueing events...`,
);

window.zaraz = {
track: trackMock,
set: setMock,
ecommerce: ecommerceMock,
};

// Triggers the flush.
getZaraz().track('button clicked', { userId: 'ABC-123', value: 200 });

expect(logSpy).toHaveBeenCalledWith(
`Zaraz Web API is initialized. Flushing queue...`,
);

// Calls the queued events.
expect(trackMock).toHaveBeenCalledWith('page_view', {
page_location: 'https://example.com',
page_path: '/',
page_title: 'Home',
});

// Calls the actual event.
expect(trackMock).toHaveBeenCalledWith('button clicked', {
userId: 'ABC-123',
value: 200,
});

expect(logSpy).toHaveBeenCalledWith(`Zaraz Web API queue flushed.`);
});

it('should throw when window is not defined', () => {
// Set window to undefined.
Object.defineProperty(global, 'window', {
value: undefined,
});

expect(() => getZaraz()).toThrow(
`Cannot use Zaraz Web API, because window.zaraz is not defined.`,
`Cannot use Zaraz Web API, because window is not defined.`,
);
});
});
49 changes: 43 additions & 6 deletions src/helpers/get-zaraz.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,49 @@
type QueueItem = {
method: 'track' | 'set' | 'ecommerce';
arguments: unknown;
};

let queue: QueueItem[] = [];

/**
* A utility that checks if zaraz exists on the window object. If not it throws
* an error. Else returns the zaraz object.
* A utility that checks if zaraz exists on the window object. If not it queues
* the events until zaraz is initialized. If zaraz is initialized, it flushes
* the queue.
*/
export function getZaraz() {
if (typeof window !== 'undefined' && !window?.zaraz) {
throw new Error(
`Cannot use Zaraz Web API, because window.zaraz is not defined.`,
);
if (typeof window === 'undefined') {
throw new Error(`Cannot use Zaraz Web API, because window is not defined.`);
}

if (!window?.zaraz) {
// eslint-disable-next-line no-console
console.log(`Zaraz Web API is not initialized. Queueing events...`);

return {
track: (...args: unknown[]) => {
queue.push({ method: 'track', arguments: args });
},
set: (...args: unknown[]) => {
queue.push({ method: 'set', arguments: args });
},
ecommerce: (...args: unknown[]) => {
queue.push({ method: 'ecommerce', arguments: args });
},
};
}

if (queue.length > 0) {
// eslint-disable-next-line no-console
console.log(`Zaraz Web API is initialized. Flushing queue...`);

queue.forEach((event) => {
window.zaraz[event.method](...(event.arguments as []));
});

// eslint-disable-next-line no-console
console.log(`Zaraz Web API queue flushed.`);

queue = []; // Clear the queue
}

return window.zaraz;
Expand Down