import { describe, expect, it } from "vitest"; import { driverLabelFor, unassignedGlyphFor } from "./geo"; describe("driverLabelFor", () => { it("returns A for the first driver alphabetically", () => { const drivers = [{ id: "u-1" }, { id: "u-2" }].sort((a, b) => a.id.localeCompare(b.id) ); // u-1 < u-2 lexically, so driver at index 0 is "u-1" expect(driverLabelFor(drivers, drivers[0].id)).toBe("A"); expect(driverLabelFor(drivers, drivers[1].id)).toBe("B"); }); it("returns sequential letters A through Z for the first 26 drivers", () => { const drivers = Array.from({ length: 26 }, (_, i) => ({ id: `driver-${String(i).padStart(2, "0")}`, })); const sorted = [...drivers].sort((a, b) => a.id.localeCompare(b.id)); for (let i = 0; i < 26; i++) { expect(driverLabelFor(sorted, sorted[i].id)).toBe( String.fromCharCode("A".charCodeAt(0) + i) ); } }); it("falls back to digits 1..9 starting at position 27", () => { const drivers = Array.from({ length: 30 }, (_, i) => ({ id: `driver-${String(i).padStart(2, "0")}`, })); const sorted = [...drivers].sort((a, b) => a.id.localeCompare(b.id)); expect(driverLabelFor(sorted, sorted[26].id)).toBe("1"); expect(driverLabelFor(sorted, sorted[27].id)).toBe("2"); expect(driverLabelFor(sorted, sorted[28].id)).toBe("3"); expect(driverLabelFor(sorted, sorted[29].id)).toBe("4"); }); it("clamps at '9' for the 35th driver and beyond (no '0' wrap)", () => { const drivers = Array.from({ length: 40 }, (_, i) => ({ id: `driver-${String(i).padStart(2, "0")}`, })); const sorted = [...drivers].sort((a, b) => a.id.localeCompare(b.id)); // Sorted: driver-00 (A) ... driver-34 (9), then driver-35 clamps to "9". expect(driverLabelFor(sorted, sorted[34].id)).toBe("9"); expect(driverLabelFor(sorted, sorted[35].id)).toBe("9"); expect(driverLabelFor(sorted, sorted[39].id)).toBe("9"); }); it("returns '?' for an unknown driver id", () => { const drivers = [{ id: "u-1" }]; expect(driverLabelFor(drivers, "u-missing")).toBe("?"); }); it("is stable — same input returns the same label on repeated calls", () => { const drivers = [{ id: "u-1" }, { id: "u-2" }, { id: "u-3" }]; const sorted = [...drivers].sort((a, b) => a.id.localeCompare(b.id)); const first = driverLabelFor(sorted, "u-2"); const second = driverLabelFor(sorted, "u-2"); const third = driverLabelFor(sorted, "u-2"); expect(first).toBe(second); expect(second).toBe(third); }); it("is stable when given names instead of ids (alphabetical by name)", () => { const drivers = [ { id: "alice" }, { id: "bob" }, { id: "carol" }, ]; expect(driverLabelFor(drivers, "alice")).toBe("A"); expect(driverLabelFor(drivers, "bob")).toBe("B"); expect(driverLabelFor(drivers, "carol")).toBe("C"); }); }); describe("unassignedGlyphFor", () => { it("returns 'ready' when every item is ready_for_collection=true", () => { expect( unassignedGlyphFor([ { ready_for_collection: true }, { ready_for_collection: true }, ]) ).toBe("ready"); }); it("returns 'unready' when at least one item is not ready", () => { expect( unassignedGlyphFor([ { ready_for_collection: true }, { ready_for_collection: false }, ]) ).toBe("unready"); }); it("returns 'unready' when at least one item has ready_for_collection=undefined", () => { expect( unassignedGlyphFor([ { ready_for_collection: true }, {}, ]) ).toBe("unready"); }); it("returns 'unready' for an empty array", () => { expect(unassignedGlyphFor([])).toBe("unready"); }); });