import { describe, expect, test } from "bun:test"; import { animatedLavaLampSvg, lavaLamp, lavaLampDataUrl, lavaLampSvg, lavaMotion } from "./lava-lamp"; const stripAnimation = (svg: string) => svg.replace(/]*\/>/g, "").replace(/]*)><\/ellipse>/g, ""); describe("lavaLamp", () => { test("is deterministic and case-insensitive", () => { expect(lavaLampSvg("Taigrr")).toBe(lavaLampSvg("taigrr")); expect(lavaLampDataUrl("taigrr")).toBe(lavaLampDataUrl("TAIGRR")); expect(lavaLampDataUrl("taigrr", true)).toBe(lavaLampDataUrl("TAIGRR", true)); }); test("keeps shipped lamps stable", () => { expect(lavaLamp("taigrr").blobs.length).toBeGreaterThanOrEqual(3); expect(Bun.hash(lavaLampSvg("taigrr")).toString(16)).toMatchSnapshot(); }); test("gives distinct handles distinct lamps", () => { const handles = Array.from({ length: 2000 }, (_, i) => `user${i}`); expect(new Set(handles.map(lavaLampSvg)).size).toBe(handles.length); }); test("animated lamp starts and loops on the static frame", () => { for (const handle of ["taigrr", "alice", "x", "gitfor"]) { const animated = animatedLavaLampSvg(handle); expect(animated).toContain(" { for (const handle of Array.from({ length: 200 }, (_, i) => `rise${i}`)) { const moving = lavaLamp(handle).blobs.slice(1); lavaMotion(handle, moving).forEach((motion, index) => { const blob = moving[index]; expect(blob.cy - motion.rise + blob.ry).toBeLessThan(0); expect(motion.seconds).toBeGreaterThanOrEqual(14); expect(motion.seconds).toBeLessThanOrEqual(30); }); } }); test("uses every variety axis somewhere", () => { const lamps = Array.from({ length: 300 }, (_, i) => lavaLamp(`seed${i}`)); expect(lamps.some((lamp) => lamp.wax.length === 2)).toBe(true); expect(lamps.some((lamp) => lamp.blobs.some((blob) => blob.tone === 1))).toBe(true); const FINE_BUBBLE_LAMP = 7; expect(lamps.some((lamp) => lamp.blobs.length >= FINE_BUBBLE_LAMP)).toBe(true); expect(new Set(lamps.map((lamp) => Math.sign(lamp.highlight.angle))).size).toBe(2); }); test("keeps every blob and color well formed", () => { for (const handle of ["a", "gitfor", "x".repeat(64), "名前"]) { const lamp = lavaLamp(handle); for (const blob of lamp.blobs) for (const value of [blob.cx, blob.cy, blob.rx, blob.ry]) expect(Number.isFinite(value)).toBe(true); for (const tone of lamp.wax) expect(tone.core).toMatch(/^hsl\(\d+ \d+% \d+%\)$/); } }); });