Files
paseo/packages/plugin/src/server/usage.test.ts
T
Mohamed Boudra 73d25317a4 fix(usage): derive window names and unify pin selection (#5903)
* fix(usage): derive window names and unify pin selection

Quota slots do not identify a period. Derive numeric windows and IDs from reported duration and quota scope; keep unknown lengths neutral. Resolve source defaults and explicit pins through one model, with a persisted empty selection distinct from defaults.

* fix(plugins): declare the duration helper host requirement

* fix(usage): verify persisted selections at the storage boundary
2026-10-02 11:18:13 +01:00

108 lines
3.2 KiB
TypeScript

import { describe, expect, it, test } from "vitest";
import {
balanceToneFromRemaining,
toneFromUsedPct,
usedPctOf,
windowFromUsedPct,
windowFromReportedDuration,
} from "./usage.js";
test("shared usage tones preserve the app threshold contract", () => {
expect([null, 69.9, 70, 90, 90.1].map(toneFromUsedPct)).toEqual([
"default",
"ok",
"warning",
"warning",
"danger",
]);
expect([null, 0, 0.01].map(balanceToneFromRemaining)).toEqual(["default", "danger", "ok"]);
});
test("shared windows retain percentage and reset time", () => {
expect(windowFromUsedPct({ id: "a", label: "A", utilizationPct: 30 })).toEqual({
id: "a",
label: "A",
usedPct: 30,
remainingPct: 70,
resetsAt: null,
});
expect(windowFromUsedPct({ id: "b", label: "B", utilizationPct: null })).toEqual({
id: "b",
label: "B",
usedPct: null,
remainingPct: null,
resetsAt: null,
});
expect(usedPctOf(25, 100)).toBe(25);
expect(usedPctOf(25, 0)).toBeNull();
});
describe("toneFromUsedPct", () => {
// Thresholds must match deriveTone in the app's provider-usage/tone.ts, which is what
// the client applies when a window arrives without a tone.
it.each([
[0, "ok"],
[69.9, "ok"],
[70, "warning"],
[90, "warning"],
[90.1, "danger"],
[100, "danger"],
[150, "danger"],
])("%s%% used is %s", (usedPct, expected) => {
expect(toneFromUsedPct(usedPct)).toBe(expected);
});
it("is neutral when the percentage is unknown", () => {
expect(toneFromUsedPct(null)).toBe("default");
expect(toneFromUsedPct(undefined)).toBe("default");
});
});
describe("usedPctOf", () => {
it("computes a percentage of the limit", () => {
expect(usedPctOf(15.79, 42.5)).toBeCloseTo(37.15, 2);
});
it("is unknown when either side is missing", () => {
expect(usedPctOf(null, 100)).toBeNull();
expect(usedPctOf(50, null)).toBeNull();
});
// A zero limit would divide to Infinity and render as a full red bar.
it("is unknown when the limit is zero or negative", () => {
expect(usedPctOf(50, 0)).toBeNull();
expect(usedPctOf(50, -1)).toBeNull();
});
});
describe("balanceToneFromRemaining", () => {
// Kept for balances with no limit, where no percentage can be computed. It only
// escalates at exhaustion, which is why anything with a limit should use
// toneFromUsedPct instead.
it("stays ok until nothing is left", () => {
expect(balanceToneFromRemaining(0.01)).toBe("ok");
expect(balanceToneFromRemaining(0)).toBe("danger");
expect(balanceToneFromRemaining(null)).toBe("default");
});
});
test.each([
[18000, "five_hour", "5-hour", "5h"],
[604800, "weekly", "Weekly", "wk"],
[7200, "7200s", "2-hour", "2h"],
[86400, "86400s", "1-day", "1d"],
[90, "90s", "90-second", "90s"],
[null, "primary", "Primary limit", ""],
])(
"duration %s owns the window's identity and both names",
(durationSeconds, id, label, shortLabel) => {
expect(
windowFromReportedDuration({
durationSeconds: durationSeconds as number | null,
unknown: { id: "primary", label: "Primary limit", shortLabel: "" },
utilizationPct: 11,
}),
).toMatchObject({ id, label, shortLabel, usedPct: 11 });
},
);