import { describe, expect, it } from "vitest"; import { ASPECT_PRESETS, blankingInsets, findAspectPreset, isFullFrame, letterboxRect, } from "./aspect-overlays"; describe("letterboxRect", () => { it("pillarboxes a 16:9 source in a squarer box", () => { const rect = letterboxRect(1000, 1000, 1920, 1080)!; expect(rect.width).toBeCloseTo(1000, 6); expect(rect.height).toBeCloseTo(562.5, 6); expect(rect.top).toBeCloseTo(218.75, 6); expect(rect.left).toBeCloseTo(0, 6); }); it("letterboxes a 16:9 source in a wider box", () => { const rect = letterboxRect(2000, 500, 1920, 1080)!; expect(rect.height).toBeCloseTo(500, 6); expect(rect.width).toBeCloseTo(888.888, 2); expect(rect.left).toBeCloseTo(555.555, 2); expect(rect.top).toBeCloseTo(0, 6); }); it("fills exactly when the box matches the source shape", () => { const rect = letterboxRect(1280, 720, 1920, 1080)!; expect(rect).toEqual({ left: 0, top: 0, width: 1280, height: 720 }); }); it("returns null before metadata gives the video a size", () => { expect(letterboxRect(1000, 500, 0, 0)).toBeNull(); expect(letterboxRect(0, 0, 1920, 1080)).toBeNull(); }); }); describe("blankingInsets", () => { const hd = { left: 0, top: 0, width: 1920, height: 1080 }; it("blanks top and bottom for a wider delivery ratio", () => { const insets = blankingInsets(hd, 2.39); // 1920 / 2.39 = 803.35 tall, so 138.32 above and below. expect(insets.top).toBeCloseTo(138.3, 1); expect(insets.bottom).toBeCloseTo(138.3, 1); expect(insets.left).toBe(0); expect(insets.right).toBe(0); }); it("blanks left and right for a taller delivery ratio", () => { const insets = blankingInsets(hd, 4 / 3); // 1080 * 1.333 = 1440 wide, so 240 either side. expect(insets.left).toBeCloseTo(240, 4); expect(insets.right).toBeCloseTo(240, 4); expect(insets.top).toBe(0); expect(insets.bottom).toBe(0); }); it("draws nothing when the target matches the source", () => { expect(isFullFrame(blankingInsets(hd, 16 / 9))).toBe(true); }); it("suppresses a sub-pixel hairline rather than drawing one", () => { // 1.7777... vs a 1.778 label: a real ratio difference, but under half a pixel. expect(isFullFrame(blankingInsets(hd, 1.778))).toBe(true); }); it("keeps the blanked area at the requested ratio", () => { const insets = blankingInsets(hd, 2.39); const visibleHeight = hd.height - insets.top - insets.bottom; expect(hd.width / visibleHeight).toBeCloseTo(2.39, 3); }); it("blanks a letterboxed picture rect, not the element box", () => { // 16:9 source shown in a tall panel: the picture is 1000x562.5 at y=218.75. const rect = letterboxRect(1000, 1000, 1920, 1080)!; const insets = blankingInsets(rect, 2.39); const visibleHeight = rect.height - insets.top - insets.bottom; expect(rect.width / visibleHeight).toBeCloseTo(2.39, 3); // Bars stay inside the picture, never spilling into the letterbox. expect(insets.top).toBeLessThan(rect.height / 2); }); it("is inert for a zero-size rect", () => { expect(isFullFrame(blankingInsets({ left: 0, top: 0, width: 0, height: 0 }, 2.39))).toBe(true); }); }); describe("ASPECT_PRESETS", () => { it("has unique ids and positive ratios", () => { const ids = ASPECT_PRESETS.map((p) => p.id); expect(new Set(ids).size).toBe(ids.length); for (const p of ASPECT_PRESETS) expect(p.ratio).toBeGreaterThan(0); }); it("runs widest to tallest", () => { const ratios = ASPECT_PRESETS.map((p) => p.ratio); expect([...ratios].sort((a, b) => b - a)).toEqual(ratios); }); it("looks up by id and ignores unknown ids", () => { expect(findAspectPreset("2.39")?.ratio).toBe(2.39); expect(findAspectPreset("off")).toBeNull(); expect(findAspectPreset("nonsense")).toBeNull(); }); });