build / build (pull_request) Successful in 1m10s
trackEvent queues events until the deferred Umami script exists (they were dropped when fired in onMounted) and drops them silently after 10 s. The result page sends purchase-completed with revenue/currency once per order (localStorage guard, set only after sending). The plugin honours Do Not Track and loads recorder.js only on /details/* for Umami heatmaps. bun test utils/trackEvent.test.ts: 4 pass. Netcup #115.
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
import { afterEach, beforeEach, expect, test } from "bun:test";
|
|
|
|
const sent: Array<[string, unknown]> = [];
|
|
beforeEach(() => {
|
|
sent.length = 0;
|
|
(globalThis as any).window = {};
|
|
});
|
|
afterEach(async () => {
|
|
const { __resetTrackQueue } = await import("./trackEvent");
|
|
__resetTrackQueue();
|
|
delete (globalThis as any).window;
|
|
});
|
|
const umami = { track: (e: string, d: unknown) => sent.push([e, d]) };
|
|
const wait = (ms: number) => new Promise((r) => setTimeout(r, ms));
|
|
|
|
test("sends immediately when umami is loaded", async () => {
|
|
const { trackEvent } = await import("./trackEvent");
|
|
(globalThis as any).window.umami = umami;
|
|
trackEvent("a", { x: 1 });
|
|
expect(sent).toEqual([["a", { x: 1 }]]);
|
|
});
|
|
|
|
test("queues until umami appears, then flushes in order and calls onSent", async () => {
|
|
const { trackEvent } = await import("./trackEvent");
|
|
let confirmed = false;
|
|
trackEvent("first");
|
|
trackEvent("purchase-completed", { revenue: 12.5, currency: "EUR" }, () => (confirmed = true));
|
|
expect(sent).toEqual([]);
|
|
await wait(300);
|
|
(globalThis as any).window.umami = umami;
|
|
await wait(400);
|
|
expect(sent.map((s) => s[0])).toEqual(["first", "purchase-completed"]);
|
|
expect(confirmed).toBe(true);
|
|
});
|
|
|
|
test("never throws and drops events when umami never loads", async () => {
|
|
const { trackEvent } = await import("./trackEvent");
|
|
let confirmed = false;
|
|
trackEvent("lost", undefined, () => (confirmed = true));
|
|
await wait(10_500);
|
|
(globalThis as any).window.umami = umami;
|
|
await wait(400);
|
|
expect(sent).toEqual([]);
|
|
expect(confirmed).toBe(false);
|
|
}, 15_000);
|
|
|
|
test("is a no-op on the server", async () => {
|
|
delete (globalThis as any).window;
|
|
const { trackEvent } = await import("./trackEvent");
|
|
expect(() => trackEvent("ssr")).not.toThrow();
|
|
});
|