import { describe, expect, test } from "bun:test"; import { getPrimaryModelNames, getSharePercent, getTokenDisplayName, getTokenRowKey, shouldShowTokenTab, sortTokenBreakdown, } from "./token-breakdown"; describe("token breakdown helpers", () => { const rows = [ { name: "beta", calls: 2, total_tokens: 100, quota: 500, models: [{ name: "gpt-4o", calls: 1, total_tokens: 70, quota: 300 }], }, { name: "alpha", calls: 5, total_tokens: 300, quota: 300, models: [{ name: "claude-sonnet-4", calls: 1, total_tokens: 200, quota: 200 }], }, ]; test("sorts token rows without mutating nested model data", () => { const sorted = sortTokenBreakdown(rows, "total_tokens", false); expect(sorted.map((row) => row.name)).toEqual(["alpha", "beta"]); expect(sorted[0].models[0].name).toBe("claude-sonnet-4"); expect(rows.map((row) => row.name)).toEqual(["beta", "alpha"]); }); test("uses a localized label for unnamed tokens", () => { expect(getTokenDisplayName("", "未命名令牌")).toBe("未命名令牌"); expect(getTokenDisplayName("prod-key", "未命名令牌")).toBe("prod-key"); }); test("keeps unnamed token row keys stable", () => { expect(getTokenRowKey("")).toBe("__unnamed_token__"); expect(getTokenRowKey("prod-key")).toBe("prod-key"); }); test("shows the token tab only for user details", () => { expect(shouldShowTokenTab("user")).toBe(true); expect(shouldShowTokenTab("model")).toBe(false); expect(shouldShowTokenTab("channel")).toBe(false); }); test("calculates share percentages and handles empty totals", () => { expect(getSharePercent(25, 100)).toBe(25); expect(getSharePercent(25, 0)).toBe(0); }); test("formats a compact primary model preview", () => { expect(getPrimaryModelNames([ { name: "a", calls: 1, total_tokens: 1, quota: 1 }, { name: "b", calls: 1, total_tokens: 1, quota: 1 }, { name: "c", calls: 1, total_tokens: 1, quota: 1 }, { name: "d", calls: 1, total_tokens: 1, quota: 1 }, ])).toBe("a, b, c"); }); });