import { describe, expect, it } from "vitest"; import { curtainEdge, curtainPolygon } from "./curtain"; const ROWS = Array.from({ length: 30 }, (_, row) => row); describe("curtainEdge", () => { it("is fully closed at progress 0 and fully open at progress 1, in every row", () => { for (const row of ROWS) { expect(curtainEdge(row, 0)).toBe(0); expect(curtainEdge(row, 1)).toBe(1); } }); it("never moves backwards as progress grows", () => { for (const row of ROWS) { let last = 0; for (let step = 0; step <= 20; step++) { const edge = curtainEdge(row, step / 20); expect(edge).toBeGreaterThanOrEqual(last); last = edge; } } }); it("is ragged: rows are at different places half way through", () => { const places = new Set(ROWS.map((row) => curtainEdge(row, 0.5).toFixed(3))); expect(places.size).toBeGreaterThan(10); }); it("stays within 0..1 and clamps progress outside 0..1", () => { expect(curtainEdge(3, -1)).toBe(0); expect(curtainEdge(3, 2)).toBe(1); }); it("is deterministic per row", () => { expect(curtainEdge(7, 0.4)).toBe(curtainEdge(7, 0.4)); }); }); describe("curtainPolygon", () => { const box = { width: 200, height: 40, cell: 20 }; it("covers nothing at progress 0 and the whole box at progress 1 (behind the edge)", () => { expect(curtainPolygon("behind", 0, box)).toBe("polygon(0px 0px, 0px 0px, 0px 20px, 0px 20px, 0px 40px, 0px 40px)"); expect(curtainPolygon("behind", 1, box)).toBe( "polygon(0px 0px, 200px 0px, 200px 20px, 200px 20px, 200px 40px, 0px 40px)", ); }); it("is the complement ahead of the edge", () => { expect(curtainPolygon("ahead", 1, box)).toBe( "polygon(200px 0px, 200px 0px, 200px 20px, 200px 20px, 200px 40px, 200px 40px)", ); expect(curtainPolygon("ahead", 0, box)).toBe( "polygon(200px 0px, 0px 0px, 0px 20px, 0px 20px, 0px 40px, 200px 40px)", ); }); it("adds a row for a height that is not a multiple of the cell", () => { const points = curtainPolygon("behind", 1, { width: 100, height: 50, cell: 20 }).split(","); // Two corner points plus two per row, for three rows. expect(points).toHaveLength(8); }); });