Skip to content
Source
Sign inSign up
Open History to see the last commit

usageProgress.test.ts

120 lines4.0 KB

1import {
2 USAGE_CONTRACT_VERSION,
3 UsageDay,
4 type UsageProviderKind,
5 type UsageSummary,
6} from "@t3tools/contracts";
7import { describe, expect, it } from "vite-plus/test";
8​
9import { usageEnvironmentProgress, usageLoadingState, usageProgress } from "./usageProgress.ts";
10​
11function summary(refreshing: readonly UsageProviderKind[] = []): UsageSummary {
12 return {
13 contractVersion: USAGE_CONTRACT_VERSION,
14 readAt: "2026-09-05T12:00:00Z",
15 timeZone: "UTC",
16 sinceDay: UsageDay.make("2026-09-05"),
17 untilDay: UsageDay.make("2026-09-05"),
18 buckets: [],
19 sources: (["codex", ...refreshing] as const).map((provider) => ({
20 fingerprint: { hostId: "host", provider, resolvedHomePath: "/home", volumeId: "1:1" },
21 status: "ok" as const,
22 scannedFiles: 1,
23 skippedFiles: 0,
24 malformedRecords: 0,
25 distinctSessions: 1,
26 message: null,
27 ...(provider === "codex" ? {} : { refreshing: true as const }),
28 })),
29 pricing: { status: "fresh", source: "test", fetchedAt: null, knownModels: 1 },
30 scanDurationMs: 1,
31 };
33​
34function environment(
35 label: string,
36 overrides: Partial<{
37 isConnected: boolean;
38 isPending: boolean;
39 error: string | null;
40 summary: UsageSummary | null;
41 }> = {},
42) {
43 return {
44 label,
45 isConnected: true,
46 isPending: false,
47 error: null as string | null,
48 summary: summary(),
49 ...overrides,
50 };
52​
53const options = { providerLabel: (provider: UsageProviderKind) => `${provider} label` };
54​
55describe("usageProgress", () => {
56 it("undims once one device answers and names the slow one", () => {
57 const waiting = [environment("a", { isPending: true }), environment("b", { isPending: true })];
58 expect(usageProgress(waiting, options)).toEqual({
59 dimmed: true,
60 label: "Updating 2 environments…",
61 });
62 expect(
63 usageProgress([environment("a"), ...waiting.slice(1), environment("c")], options),
64 ).toEqual({ dimmed: false, label: "Updating b…" });
65 expect(
66 usageProgress(
67 [environment("a"), environment("b", { summary: null, isPending: true })],
68 options,
69 ),
70 ).toEqual({ dimmed: false, label: "Updating b…" });
71 });
72​
73 it("names a slow source without dimming once its environment answers from cache", () => {
74 const partway = environment("a", { isPending: true, summary: summary(["cursor"]) });
75 expect(usageEnvironmentProgress(partway)).toEqual({ phase: "partway", providers: ["cursor"] });
76 expect(usageProgress([partway, environment("b")], options)).toEqual({
77 dimmed: false,
78 label: "Updating cursor label…",
79 });
80 expect(
81 usageProgress(
82 [partway, environment("b", { isPending: true, summary: summary(["cursor", "grok"]) })],
83 options,
84 ),
85 ).toEqual({ dimmed: false, label: "Updating 2 providers…" });
86 expect(usageProgress([{ ...partway, isPending: false }], options)).toEqual({
87 dimmed: false,
88 label: null,
89 });
90 });
91​
92 it("ignores reconnecting and failed environments", () => {
93 const ignored = [
94 environment("reconnecting", { isPending: true, isConnected: false }),
95 environment("failed", { error: "Offline", summary: null }),
96 ];
97 expect(usageProgress([environment("a"), ...ignored], options)).toEqual({
98 dimmed: false,
99 label: null,
100 });
101 expect(
102 usageProgress(
103 [environment("a"), ...ignored, environment("slow", { summary: null, isPending: true })],
104 options,
105 ),
106 ).toEqual({ dimmed: false, label: "Updating slow…" });
107 expect(usageEnvironmentProgress(ignored[0]!)).toEqual({ phase: "inactive" });
108 });
109});
110​
111describe("usageLoadingState", () => {
112 it("ignores environments that cannot answer and settles once all have", () => {
113 const state = usageLoadingState([
114 environment("a"),
115 environment("b", { summary: null, isConnected: false }),
116 environment("c", { summary: null, error: "Offline" }),
117 ]);
118 expect(state).toEqual({ partial: false, everyProvider: false, providers: new Set() });
119 });
120});