plan/react-rewrite #1

Merged
gnezim merged 138 commits from plan/react-rewrite into main 2026-04-15 12:21:16 +03:00
3 changed files with 74 additions and 0 deletions
Showing only changes of commit e95781a069 - Show all commits
+40
View File
@@ -0,0 +1,40 @@
import { describe, expect, it, beforeEach } from "vitest";
import { emitEvent, getRecordedEvents, resetEvents } from "./sink.js";
import type { AnalyticsEvent } from "./types.js";
describe("analytics sink", () => {
beforeEach(() => {
resetEvents();
});
it("records emitted events", () => {
const event: AnalyticsEvent = {
kind: "track",
name: "test.click",
props: { button: "cta" },
provider: "metrica",
ts: new Date().toISOString(),
};
emitEvent(event);
expect(getRecordedEvents()).toHaveLength(1);
expect(getRecordedEvents()[0]).toEqual(event);
});
it("records multiple events in order", () => {
emitEvent({ kind: "track", name: "a", props: {}, provider: "ctm", ts: "t1" });
emitEvent({ kind: "page", name: "/home", props: {}, provider: "dynatrace", ts: "t2" });
const events = getRecordedEvents();
expect(events).toHaveLength(2);
expect(events[0]?.name).toBe("a");
expect(events[1]?.name).toBe("/home");
});
it("resetEvents clears all recorded events", () => {
emitEvent({ kind: "track", name: "x", props: {}, provider: "variocube", ts: "t" });
expect(getRecordedEvents()).toHaveLength(1);
resetEvents();
expect(getRecordedEvents()).toHaveLength(0);
});
});
+27
View File
@@ -0,0 +1,27 @@
import type { AnalyticsEvent } from "./types.js";
let events: AnalyticsEvent[] = [];
/**
* Emit an analytics event to the test-observable sink.
* In production, this is a no-op ring buffer (capped to prevent memory leaks).
* In test, events are retained for assertion via getRecordedEvents().
*/
export function emitEvent(event: AnalyticsEvent): void {
events.push(event);
// Ring buffer: cap at 1000 events to prevent unbounded growth
if (events.length > 1000) {
events = events.slice(-500);
}
}
/** Returns all recorded events (for test assertions). */
export function getRecordedEvents(): readonly AnalyticsEvent[] {
return events;
}
/** Clears all recorded events (for test teardown). */
export function resetEvents(): void {
events = [];
}
+7
View File
@@ -25,3 +25,10 @@ export interface Analytics {
track(event: string, props?: AnalyticsProps): void;
page(url: string, props?: AnalyticsProps): void;
}
export interface AnalyticsAdapter {
readonly name: AnalyticsEvent["provider"];
load(): Promise<void>;
track(event: string, props?: AnalyticsProps): void;
page(url: string, props?: AnalyticsProps): void;
}