/** * KHAELOR * File: tests/shared/primitives.test.ts * Description: Unit tests for shared primitives — Result, KhaelorError, ULID. * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai */ import { describe, expect, it } from "vitest"; import { KhaelorError, err, isKhaelorError, isUlid, ok, ulid, unwrap } from "../../src/shared/index.js"; describe("Result", () => { it("ok() produces a success result", () => { const r = ok(42); expect(r.ok).toBe(true); expect(r.value).toBe(42); }); it("err() produces a failure result", () => { const e = new KhaelorError("internal", "boom"); const r = err(e); expect(r.ok).toBe(false); expect(r.error).toBe(e); }); it("unwrap returns the value on success", () => { expect(unwrap(ok("x"))).toBe("x"); }); it("unwrap throws the error on failure", () => { const e = new KhaelorError("config-invalid", "bad config"); expect(() => unwrap(err(e))).toThrow(e); }); }); describe("KhaelorError", () => { it("carries code and details", () => { const e = new KhaelorError("session-log-corrupted", "torn", { offset: 12 }); expect(e.code).toBe("session-log-corrupted"); expect(e.details).toEqual({ offset: 12 }); expect(e.message).toBe("torn"); expect(isKhaelorError(e)).toBe(true); expect(isKhaelorError(new Error("x"))).toBe(false); }); }); describe("ulid", () => { it("produces 26-char Crockford base32 ids", () => { const id = ulid(); expect(id).toHaveLength(26); expect(isUlid(id)).toBe(true); expect(isUlid("not a ulid!")).toBe(false); }); it("is unique and monotonic within the same millisecond", () => { const t = 1_700_000_000_000; const ids = Array.from({ length: 1000 }, () => ulid(t)); const set = new Set(ids); expect(set.size).toBe(1000); for (let i = 1; i < ids.length; i++) { expect(ids[i]! > ids[i - 1]!).toBe(true); } }); it("orders by time across milliseconds", () => { const a = ulid(1_700_000_000_000); const b = ulid(1_700_000_000_001); expect(b > a).toBe(true); }); it("rejects out-of-range times", () => { expect(() => ulid(-1)).toThrow(RangeError); expect(() => ulid(2 ** 48)).toThrow(RangeError); }); });