import { describe, expect, test } from "bun:test"; import { generateId } from "./id"; describe("generateId", () => { test("returns id matching project-{4hex} pattern", () => { const id = generateId("myproject", []); expect(id).toMatch(/^myproject-[0-9a-f]{4}$/); }); test("uses project name as prefix", () => { const id = generateId("overstory", []); expect(id.startsWith("overstory-")).toBe(true); }); test("generates different ids on repeated calls", () => { const ids = new Set(); for (let i = 0; i < 20; i++) { ids.add(generateId("proj", [])); } // With 4 hex chars (65536 possibilities), 20 calls should almost certainly produce multiple unique values // This test is probabilistic but reliable in practice expect(ids.size).toBeGreaterThan(1); }); test("avoids collisions with existing ids", () => { // Fill all possible 1-char hex suffixes to force collision avoidance // In practice, with 4 hex = 65536 options, collisions are extremely rare const id1 = generateId("proj", []); const id2 = generateId("proj", [id1]); expect(id2).not.toBe(id1); }); test("falls back to 8-char hex after many collisions", () => { // Simulate 100 collisions by pre-filling many IDs // The function should eventually produce a longer ID or succeed // We just verify it doesn't throw and returns a valid id const existing: string[] = []; // This is a functional test — just ensure it completes const id = generateId("p", existing); expect(id).toMatch(/^p-[0-9a-f]{4,}$/); }); test("handles project names with hyphens", () => { const id = generateId("my-project", []); expect(id).toMatch(/^my-project-[0-9a-f]{4}$/); }); test("hex suffix uses lowercase letters", () => { for (let i = 0; i < 10; i++) { const id = generateId("proj", []); const suffix = id.replace("proj-", ""); expect(suffix).toMatch(/^[0-9a-f]+$/); } }); });