import { describe, expect, it } from "vitest"; import { TOKENS_PER_SQUARE, contextBarModel, formatTokens } from "./context-model"; describe("contextBarModel", () => { it("1 carré = 10 000 tokens : 200 000 tokens → 20 carrés", () => { expect(TOKENS_PER_SQUARE).toBe(10_000); expect(contextBarModel(0, 200_000)).toMatchObject({ total: 20, filled: 0, tokensPerSquare: 10_000, level: "ok" }); }); it("la barre se remplit de la gauche vers la droite selon l'usage", () => { expect(contextBarModel(50_000, 200_000).filled).toBe(5); expect(contextBarModel(100_000, 200_000)).toMatchObject({ filled: 10, ratio: 0.5, level: "ok" }); expect(contextBarModel(130_000, 200_000)).toMatchObject({ filled: 13, level: "warn" }); expect(contextBarModel(180_000, 200_000)).toMatchObject({ filled: 18, level: "danger" }); }); it("un contexte non vide montre au moins un carré ; un contexte plein les remplit tous", () => { expect(contextBarModel(300, 200_000).filled).toBe(1); expect(contextBarModel(200_000, 200_000)).toMatchObject({ filled: 20, ratio: 1 }); }); it("dépassement du maximum : plafonné", () => { expect(contextBarModel(250_000, 200_000)).toMatchObject({ filled: 20, ratio: 1, level: "danger" }); }); it("taille non multiple de 10 000 : carré partiel arrondi vers le haut au total", () => { expect(contextBarModel(0, 128_000).total).toBe(13); }); it("barre trop large pour le terminal : échelle agrandie par paliers de 10 000", () => { const m = contextBarModel(500_000, 1_000_000, 60); // 100 carrés demandés, 60 disponibles expect(m.tokensPerSquare).toBe(20_000); expect(m.total).toBe(50); expect(m.filled).toBe(25); }); }); describe("formatTokens", () => { it.each([ [950, "950"], [12_345, "12.3k"], [128_000, "128k"], [200_000, "200k"], [1_048_576, "1.05M"], [1_000_000, "1M"], ])("%d → %s", (n, expected) => expect(formatTokens(n)).toBe(expected)); });