mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-10 22:20:14 +00:00
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
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { initRuntimeAnalytics, emitAnalyticsEvent, emitPerformanceMetric } from "./analytics";
|
||||
import { initRuntimeAnalytics, emitAnalyticsEvent } from "./analytics";
|
||||
|
||||
describe("runtime analytics", () => {
|
||||
let postMessage: ReturnType<typeof vi.fn>;
|
||||
@@ -58,94 +58,3 @@ describe("runtime analytics", () => {
|
||||
expect(postMessage).toHaveBeenCalledTimes(events.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("runtime performance metrics", () => {
|
||||
let postMessage: ReturnType<typeof vi.fn>;
|
||||
|
||||
beforeEach(() => {
|
||||
postMessage = vi.fn();
|
||||
initRuntimeAnalytics(postMessage);
|
||||
// Clean up DevTools marks between tests to avoid cross-test interference.
|
||||
if (typeof performance !== "undefined" && typeof performance.clearMarks === "function") {
|
||||
performance.clearMarks();
|
||||
}
|
||||
});
|
||||
|
||||
it("emits a perf metric via postMessage", () => {
|
||||
emitPerformanceMetric("player_scrub_latency", 12.5);
|
||||
expect(postMessage).toHaveBeenCalledWith({
|
||||
source: "hf-preview",
|
||||
type: "perf",
|
||||
name: "player_scrub_latency",
|
||||
value: 12.5,
|
||||
tags: {},
|
||||
});
|
||||
});
|
||||
|
||||
it("passes tags through", () => {
|
||||
emitPerformanceMetric("player_decoder_count", 3, {
|
||||
composition_id: "abc123",
|
||||
mode: "isolated",
|
||||
});
|
||||
expect(postMessage).toHaveBeenCalledWith({
|
||||
source: "hf-preview",
|
||||
type: "perf",
|
||||
name: "player_decoder_count",
|
||||
value: 3,
|
||||
tags: { composition_id: "abc123", mode: "isolated" },
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes missing tags to an empty object", () => {
|
||||
emitPerformanceMetric("player_playback_fps", 60);
|
||||
expect(postMessage).toHaveBeenCalledWith(expect.objectContaining({ tags: {} }));
|
||||
});
|
||||
|
||||
it("supports zero and negative values", () => {
|
||||
emitPerformanceMetric("player_dropped_frames", 0);
|
||||
emitPerformanceMetric("player_media_sync_drift", -8.3);
|
||||
expect(postMessage).toHaveBeenNthCalledWith(1, expect.objectContaining({ value: 0 }));
|
||||
expect(postMessage).toHaveBeenNthCalledWith(2, expect.objectContaining({ value: -8.3 }));
|
||||
});
|
||||
|
||||
it("does not throw when postMessage is not set", () => {
|
||||
initRuntimeAnalytics(null as unknown as (payload: unknown) => void);
|
||||
expect(() => emitPerformanceMetric("player_load_time", 250)).not.toThrow();
|
||||
});
|
||||
|
||||
it("does not throw when postMessage throws", () => {
|
||||
postMessage.mockImplementation(() => {
|
||||
throw new Error("channel closed");
|
||||
});
|
||||
expect(() => emitPerformanceMetric("player_scrub_latency", 12)).not.toThrow();
|
||||
});
|
||||
|
||||
it("does not throw when performance.mark throws", () => {
|
||||
const original = performance.mark;
|
||||
// Vitest provides a real performance API; replace mark with a thrower for this test.
|
||||
performance.mark = vi.fn(() => {
|
||||
throw new Error("mark failed");
|
||||
}) as typeof performance.mark;
|
||||
try {
|
||||
expect(() => emitPerformanceMetric("player_load_time", 100)).not.toThrow();
|
||||
// Even though performance.mark threw, the bridge should still receive the metric.
|
||||
expect(postMessage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ type: "perf", name: "player_load_time", value: 100 }),
|
||||
);
|
||||
} finally {
|
||||
performance.mark = original;
|
||||
}
|
||||
});
|
||||
|
||||
it("writes a User Timing mark with detail for DevTools visibility", () => {
|
||||
if (typeof performance.getEntriesByName !== "function") {
|
||||
// Older test environments — skip the DevTools assertion but don't fail.
|
||||
return;
|
||||
}
|
||||
emitPerformanceMetric("player_composition_switch", 42, { from: "a", to: "b" });
|
||||
const entries = performance.getEntriesByName("player_composition_switch", "mark");
|
||||
expect(entries.length).toBeGreaterThan(0);
|
||||
const mark = entries[entries.length - 1] as PerformanceMark;
|
||||
expect(mark.detail).toEqual({ value: 42, tags: { from: "a", to: "b" } });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user