Skip to content

Commit

Permalink
Merge pull request #2 from expatfile/@HofmannZ/featture/init-queue
Browse files Browse the repository at this point in the history
feat: ✨ queue zaraz method calls until initialised
  • Loading branch information
HofmannZ authored Jan 17, 2024
2 parents c67e434 + 1edbdd2 commit e15288b
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 9 deletions.
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

0 comments on commit e15288b

Please sign in to comment.