Files
WRNexusJS/packages/tracking/test/tracking.test.ts
2026-07-12 15:55:18 +05:30

62 lines
2.2 KiB
TypeScript

import { test, expect } from "bun:test";
import { createContext } from "@wrnexus/core";
import { createTracker, type ErrorEvent, type ErrorSink } from "../src/index.ts";
function collectingSink(): ErrorSink & { events: ErrorEvent[] } {
const events: ErrorEvent[] = [];
return { name: "collect", events, capture: (e) => void events.push(e) };
}
test("capture fans out to sinks with context + timestamp", async () => {
const sink = collectingSink();
const tracker = createTracker({ sinks: [sink], now: () => 123 });
await tracker.capture(new Error("boom"), { userId: "u1" });
expect(sink.events.length).toBe(1);
expect(sink.events[0]!.error.message).toBe("boom");
expect(sink.events[0]!.context.userId).toBe("u1");
expect(sink.events[0]!.timestamp).toBe(123);
});
test("non-Error values are wrapped", async () => {
const sink = collectingSink();
const tracker = createTracker({ sinks: [sink] });
await tracker.capture("just a string");
expect(sink.events[0]!.error.message).toBe("just a string");
});
test("beforeSend can scrub or drop events", async () => {
const sink = collectingSink();
const tracker = createTracker({
sinks: [sink],
beforeSend: (e) => (e.context.secret ? null : e), // drop events tagged secret
});
await tracker.capture(new Error("a"), { secret: true });
await tracker.capture(new Error("b"));
expect(sink.events.map((e) => e.error.message)).toEqual(["b"]);
});
test("middleware captures a thrown request error and re-throws it", async () => {
const sink = collectingSink();
const tracker = createTracker({ sinks: [sink] });
const url = new URL("http://x/api/boom");
const ctx = createContext(new Request(url, { method: "POST" }), url);
await expect(
tracker.middleware()(ctx, () => {
throw new Error("downstream");
}),
).rejects.toThrow("downstream");
expect(sink.events[0]!.context).toMatchObject({ method: "POST", path: "/api/boom" });
});
test("a failing sink never breaks capture", async () => {
const bad: ErrorSink = {
capture: () => {
throw new Error("sink down");
},
};
const good = collectingSink();
const tracker = createTracker({ sinks: [bad, good] });
await tracker.capture(new Error("x")); // must not throw
expect(good.events.length).toBe(1);
});