/** * Ticket #54 F2 — pure download-progress formatting for the model-server overlay. * These lock the wire→display mapping independently of React: byte formatting, * the determinate/indeterminate split, and the "no fake %" rule. */ import { describe, it, expect } from "vitest"; import type { ModelServerStatus } from "@/domain"; import { formatBytes, describeModelServerDownload, modelServerOverlayText, } from "./modelServerLaunch"; function downloading( fields: Partial<{ downloadedBytes: number | null; totalBytes: number | null; percent: number | null; source: string | null; }> = {}, ): ModelServerStatus { return { state: "downloading", downloadedBytes: null, totalBytes: null, percent: null, source: null, ...fields, }; } describe("formatBytes", () => { it("shows whole bytes and SI-scaled larger units", () => { expect(formatBytes(0)).toBe("0 o"); expect(formatBytes(512)).toBe("512 o"); expect(formatBytes(1000)).toBe("1 Ko"); expect(formatBytes(1_500_000)).toBe("1.5 Mo"); expect(formatBytes(4_200_000_000)).toBe("4.2 Go"); }); it("guards non-finite / negative", () => { expect(formatBytes(-5)).toBe("0 o"); expect(formatBytes(Number.NaN)).toBe("0 o"); }); }); describe("describeModelServerDownload", () => { it("returns null for every non-downloading state", () => { expect(describeModelServerDownload(undefined)).toBeNull(); expect(describeModelServerDownload({ state: "probing" })).toBeNull(); expect(describeModelServerDownload({ state: "starting" })).toBeNull(); expect( describeModelServerDownload({ state: "ready", reused: false }), ).toBeNull(); }); it("exposes percent + a 'X / Y' bytes label when both bounds are known", () => { const p = describeModelServerDownload( downloading({ downloadedBytes: 1_500_000, totalBytes: 3_000_000, percent: 50, source: "unsloth/Qwen3-Coder-30B", }), ); expect(p).toEqual({ percent: 50, bytesLabel: "1.5 Mo / 3 Mo", source: "unsloth/Qwen3-Coder-30B", }); }); it("clamps percent to 0..100", () => { expect(describeModelServerDownload(downloading({ percent: 137 }))?.percent).toBe( 100, ); expect(describeModelServerDownload(downloading({ percent: -3 }))?.percent).toBe( 0, ); }); it("is indeterminate (percent null) when the total is unknown", () => { const p = describeModelServerDownload( downloading({ downloadedBytes: 800_000, totalBytes: null, percent: null }), ); expect(p).toEqual({ percent: null, bytesLabel: "800 Ko", source: null }); }); it("has no bytes label when nothing about size is known", () => { expect(describeModelServerDownload(downloading())).toEqual({ percent: null, bytesLabel: null, source: null, }); }); }); describe("modelServerOverlayText (unchanged F1 titles)", () => { it("keeps the download / loading titles", () => { expect(modelServerOverlayText(downloading())).toBe( "Téléchargement du modèle…", ); expect(modelServerOverlayText({ state: "starting" })).toBe( "Chargement du serveur…", ); expect(modelServerOverlayText({ state: "ready", reused: true })).toBeNull(); }); });