Files
hyperframes/packages/core/src/runtime/analytics.test.ts
T
Miguel Ángel 6f677292ae refactor(core): simplify packages/core — dead code, dedup, type safety (#1413)
- Delete unused mediaPreloader module, 5 dead RuntimeState fields,
  emitPerformanceMetric, lintScriptUrls, 5 variable type guards
- Consolidate compiler utilities: unify CSS URL regex, relative URL
  predicate, MIME map, @import regex, bulk asset rewrite delegation
- Cache extractGsapWindows per script (eliminates 2 redundant recast
  parses per lint run), share stripJsComments and script extraction
- Deduplicate GSAP parser: share serializeValue/safeJsKey, centralize
  converted-id fallback (6 sites), keyframe codegen (3 sites),
  waypoint extraction, insert-after-anchor, script hoisting
- Replace 88 bare any annotations with typed AstNode/AstPath interfaces
- Derive RuntimeBridgeControlAction from HyperframeControlAction,
  alias RuntimePickerElementInfo, share macOS font profiler
- Gate generateHyperframesStyles on includeStyles, collapse 4 GSAP
  property mutation cases into 2
- Extract magic numbers into named constants, replace 5 double casts
  with type guards and typed accessors (runtime/globals.ts),
  reduce function complexity in htmlParser and files route
2026-06-13 18:23:36 -04:00

61 lines
1.8 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from "vitest";
import { initRuntimeAnalytics, emitAnalyticsEvent } from "./analytics";
describe("runtime analytics", () => {
let postMessage: ReturnType<typeof vi.fn>;
beforeEach(() => {
postMessage = vi.fn();
// Reset module state by re-init
initRuntimeAnalytics(postMessage);
});
it("emits analytics event via postMessage", () => {
emitAnalyticsEvent("composition_loaded");
expect(postMessage).toHaveBeenCalledWith({
source: "hf-preview",
type: "analytics",
event: "composition_loaded",
properties: {},
});
});
it("passes properties through", () => {
emitAnalyticsEvent("composition_played", { duration: 10, autoplay: true });
expect(postMessage).toHaveBeenCalledWith({
source: "hf-preview",
type: "analytics",
event: "composition_played",
properties: { duration: 10, autoplay: true },
});
});
it("does not throw when postMessage is not set", () => {
// Re-init with a function that we'll clear
initRuntimeAnalytics(null as unknown as (payload: unknown) => void);
expect(() => emitAnalyticsEvent("composition_paused")).not.toThrow();
});
it("does not throw when postMessage throws", () => {
postMessage.mockImplementation(() => {
throw new Error("channel closed");
});
expect(() => emitAnalyticsEvent("composition_seeked")).not.toThrow();
});
it("emits all event types", () => {
const events = [
"composition_loaded",
"composition_played",
"composition_paused",
"composition_seeked",
"composition_ended",
"element_picked",
] as const;
for (const event of events) {
emitAnalyticsEvent(event);
}
expect(postMessage).toHaveBeenCalledTimes(events.length);
});
});