From 1a9f0430bd64e11180157cb45995caacc6ee7390 Mon Sep 17 00:00:00 2001 From: PJ Date: Sat, 6 Jun 2026 12:57:49 +0530 Subject: [PATCH] test(replay-ui): pin metrics formatters and path gap handling --- .../src/__tests__/metrics-format.test.ts | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 replay-ui/src/__tests__/metrics-format.test.ts diff --git a/replay-ui/src/__tests__/metrics-format.test.ts b/replay-ui/src/__tests__/metrics-format.test.ts new file mode 100644 index 0000000..8c36dae --- /dev/null +++ b/replay-ui/src/__tests__/metrics-format.test.ts @@ -0,0 +1,63 @@ +import { describe, it, expect } from "bun:test"; +import { + buildPath, + formatHeap, + formatTime, + fractionFor, +} from "../lib/metrics-format"; + +describe("formatHeap", () => { + const cases: [number, string][] = [ + [0, "0B"], + [-1, "0B"], + [2048, "2K"], + [1024 * 1024, "1M"], + [5 * 1024 * 1024, "5M"], + [2 * 1024 * 1024 * 1024, "2.0G"], + ]; + for (const [bytes, expected] of cases) { + it(`${bytes} -> ${expected}`, () => { + expect(formatHeap(bytes)).toBe(expected); + }); + } +}); + +describe("formatTime", () => { + it("formats mm:ss and clamps negatives", () => { + expect(formatTime(0)).toBe("00:00"); + expect(formatTime(65_000)).toBe("01:05"); + expect(formatTime(-10)).toBe("00:00"); + }); +}); + +describe("fractionFor", () => { + it("centers a lone point and spreads the rest across 0..1", () => { + expect(fractionFor(0, 1)).toBe(0.5); + expect(fractionFor(0, 5)).toBe(0); + expect(fractionFor(4, 5)).toBe(1); + expect(fractionFor(2, 5)).toBe(0.5); + }); +}); + +// Bug class: a missing sample must lift the pen (M) so the chart does not draw +// a straight line bridging the gap, which would imply data that was never +// measured. +describe("buildPath gap handling", () => { + it("starts a new subpath after each undefined value", () => { + const samples = [{ v: 0 }, { v: 100 }, { v: undefined }, { v: 50 }]; + const path = buildPath(samples, (s) => s.v, 100); + const commands = path.match(/[ML]/g); + expect(commands).toEqual(["M", "L", "M"]); + expect(path.startsWith("M0.0000,1.0000")).toBe(true); + }); + + it("emits empty string when every sample is missing", () => { + const samples = [{ v: undefined }, { v: undefined }]; + expect(buildPath(samples, (s) => s.v, 100)).toBe(""); + }); + + it("clamps values above the ceiling to the top of the lane", () => { + const path = buildPath([{ v: 200 }], (s) => s.v, 100); + expect(path).toBe("M0.5000,0.0000"); + }); +});