import { readdirSync, readFileSync, statSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, it } from "@suaveplan/testing/runner"; import type { TimersLike } from "@suaveplan/types"; import { AnalyticsTracker } from "../src/tracker/tracker.js"; import { BatchTransport } from "../src/transport/batch.js"; const noopTimers: TimersLike = { setTimer: () => 0, clearTimer: () => {}, }; function* walk(dir: string): Generator { for (const entry of readdirSync(dir)) { const full = join(dir, entry); const st = statSync(full); if (st.isDirectory()) { yield* walk(full); } else if (full.endsWith(".ts") && !full.endsWith(".test.ts")) { yield full; } } } describe("integration", () => { it("tracker → batch transport → in-process endpoint round-trip", { timeout: 5000, }, async () => { const observed: Array<{ events: unknown[] }> = []; const fetchFn: typeof fetch = async (_url, init) => { const body = init?.body as string; observed.push(JSON.parse(body) as { events: unknown[] }); return new Response("", { status: 200 }); }; const transport = new BatchTransport({ endpoint: "/api/analytics", fetchFn, }); const tracker = new AnalyticsTracker(transport, { batchSize: 1, timers: noopTimers, }); const seen: string[] = []; tracker.events.on("track", () => seen.push("track")); tracker.events.on("flush", ({ success }) => seen.push(`flush:${String(success)}`) ); tracker.track("e"); await tracker.flush(); expect(observed.length).toBe(1); expect((observed[0]?.events?.[0] as { name: string }).name).toBe("e"); expect(seen[0]).toBe("track"); expect(seen[seen.length - 1]).toBe("flush:true"); }); it("src/ contains no node: imports", { timeout: 5000 }, () => { const srcDir = join(__dirname, "..", "src"); for (const file of walk(srcDir)) { const text = readFileSync(file, "utf8"); expect(text).not.toMatch(/from\s+["']node:/); } }); });