test: tighten minimax usage coverage

This commit is contained in:
Peter Steinberger 2026-03-13 18:10:40 +00:00
parent 4ed3b62f01
commit 2920d61f18
2 changed files with 141 additions and 105 deletions

View File

@ -2,45 +2,70 @@ import { describe, expect, it } from "vitest";
import { createProviderUsageFetch, makeResponse } from "../test-utils/provider-usage-fetch.js";
import { fetchMinimaxUsage } from "./provider-usage.fetch.minimax.js";
async function expectMinimaxUsageResult(params: {
payload: unknown;
expected: {
plan?: string;
windows: Array<{ label: string; usedPercent: number; resetAt?: number }>;
};
}) {
const mockFetch = createProviderUsageFetch(async (_url, init) => {
const headers = (init?.headers as Record<string, string> | undefined) ?? {};
expect(headers.Authorization).toBe("Bearer key");
expect(headers["MM-API-Source"]).toBe("OpenClaw");
return makeResponse(200, params.payload);
});
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.plan).toBe(params.expected.plan);
expect(result.windows).toEqual(params.expected.windows);
}
describe("fetchMinimaxUsage", () => {
it("returns HTTP errors for failed requests", async () => {
const mockFetch = createProviderUsageFetch(async () => makeResponse(502, "bad gateway"));
it.each([
{
name: "returns HTTP errors for failed requests",
response: () => makeResponse(502, "bad gateway"),
expectedError: "HTTP 502",
},
{
name: "returns invalid JSON when payload cannot be parsed",
response: () => makeResponse(200, "{not-json"),
expectedError: "Invalid JSON",
},
{
name: "returns trimmed API errors from base_resp",
response: () =>
makeResponse(200, {
base_resp: {
status_code: 1007,
status_msg: " auth denied ",
},
}),
expectedError: "auth denied",
},
{
name: "falls back to a generic API error when base_resp message is blank",
response: () =>
makeResponse(200, {
base_resp: {
status_code: 1007,
status_msg: " ",
},
}),
expectedError: "API error",
},
])("$name", async ({ response, expectedError }) => {
const mockFetch = createProviderUsageFetch(async () => response());
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.error).toBe("HTTP 502");
expect(result.error).toBe(expectedError);
expect(result.windows).toHaveLength(0);
});
it("returns invalid JSON when payload cannot be parsed", async () => {
const mockFetch = createProviderUsageFetch(async () => makeResponse(200, "{not-json"));
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.error).toBe("Invalid JSON");
expect(result.windows).toHaveLength(0);
});
it("returns API errors from base_resp", async () => {
const mockFetch = createProviderUsageFetch(async () =>
makeResponse(200, {
base_resp: {
status_code: 1007,
status_msg: " auth denied ",
},
}),
);
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.error).toBe("auth denied");
expect(result.windows).toHaveLength(0);
});
it("derives usage from used/total fields and includes reset + plan", async () => {
const mockFetch = createProviderUsageFetch(async (_url, init) => {
const headers = (init?.headers as Record<string, string> | undefined) ?? {};
expect(headers.Authorization).toBe("Bearer key");
expect(headers["MM-API-Source"]).toBe("OpenClaw");
return makeResponse(200, {
it.each([
{
name: "derives usage from used/total fields and includes reset + plan",
payload: {
data: {
used: 35,
total: 100,
@ -48,52 +73,36 @@ describe("fetchMinimaxUsage", () => {
reset_at: 1_700_000_000,
plan_name: "Pro Max",
},
});
});
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.plan).toBe("Pro Max");
expect(result.windows).toEqual([
{
label: "3h",
usedPercent: 35,
resetAt: 1_700_000_000_000,
},
]);
});
it("supports usage ratio strings with minute windows and ISO reset strings", async () => {
const resetIso = "2026-01-08T00:00:00Z";
const mockFetch = createProviderUsageFetch(async () =>
makeResponse(200, {
expected: {
plan: "Pro Max",
windows: [{ label: "3h", usedPercent: 35, resetAt: 1_700_000_000_000 }],
},
},
{
name: "supports usage ratio strings with minute windows and ISO reset strings",
payload: {
data: {
nested: [
{
usage_ratio: "0.25",
window_minutes: "30",
reset_time: resetIso,
reset_time: "2026-01-08T00:00:00Z",
plan: "Starter",
},
],
},
}),
);
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.plan).toBe("Starter");
expect(result.windows).toEqual([
{
label: "30m",
usedPercent: 25,
resetAt: new Date(resetIso).getTime(),
},
]);
});
it("derives used from total and remaining counts", async () => {
const mockFetch = createProviderUsageFetch(async () =>
makeResponse(200, {
expected: {
plan: "Starter",
windows: [
{ label: "30m", usedPercent: 25, resetAt: new Date("2026-01-08T00:00:00Z").getTime() },
],
},
},
{
name: "derives used from total and remaining counts",
payload: {
data: {
total: "200",
remaining: "50",
@ -101,18 +110,28 @@ describe("fetchMinimaxUsage", () => {
reset_at: 1_700_000_000_000,
plan_name: "Team",
},
}),
);
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.plan).toBe("Team");
expect(result.windows).toEqual([
{
label: "5h",
usedPercent: 75,
resetAt: 1_700_000_000_000,
},
]);
expected: {
plan: "Team",
windows: [{ label: "5h", usedPercent: 75, resetAt: 1_700_000_000_000 }],
},
},
{
name: "falls back to payload-level reset and plan when nested usage records omit them",
payload: {
data: {
plan_name: "Payload Plan",
reset_at: 1_700_000_100,
nested: [{ usage_ratio: 0.4, window_hours: 2 }],
},
},
expected: {
plan: "Payload Plan",
windows: [{ label: "2h", usedPercent: 40, resetAt: 1_700_000_100_000 }],
},
},
])("$name", async ({ payload, expected }) => {
await expectMinimaxUsageResult({ payload, expected });
});
it("returns unsupported response shape when no usage fields are present", async () => {

View File

@ -48,17 +48,21 @@ function createMinimaxOnlyFetch(payload: unknown) {
async function expectMinimaxUsage(
payload: unknown,
expectedUsedPercent: number,
expectedPlan?: string,
expected: {
usedPercent: number;
plan?: string;
label?: string;
},
) {
const mockFetch = createMinimaxOnlyFetch(payload);
const summary = await loadUsageWithAuth([{ provider: "minimax", token: "token-1b" }], mockFetch);
const minimax = summary.providers.find((p) => p.provider === "minimax");
expect(minimax?.windows[0]?.usedPercent).toBe(expectedUsedPercent);
if (expectedPlan !== undefined) {
expect(minimax?.plan).toBe(expectedPlan);
expect(minimax?.windows[0]?.usedPercent).toBe(expected.usedPercent);
expect(minimax?.windows[0]?.label).toBe(expected.label ?? "5h");
if (expected.plan !== undefined) {
expect(minimax?.plan).toBe(expected.plan);
}
expect(mockFetch).toHaveBeenCalled();
}
@ -181,9 +185,10 @@ describe("provider usage loading", () => {
expect(mockFetch).toHaveBeenCalled();
});
it("handles nested MiniMax usage payloads", async () => {
await expectMinimaxUsage(
{
it.each([
{
name: "handles nested MiniMax usage payloads",
payload: {
base_resp: { status_code: 0, status_msg: "ok" },
data: {
plan_name: "Coding Plan",
@ -194,14 +199,11 @@ describe("provider usage loading", () => {
},
},
},
75,
"Coding Plan",
);
});
it("prefers MiniMax count-based usage when percent looks inverted", async () => {
await expectMinimaxUsage(
{
expected: { usedPercent: 75, plan: "Coding Plan" },
},
{
name: "prefers MiniMax count-based usage when percent looks inverted",
payload: {
base_resp: { status_code: 0, status_msg: "ok" },
data: {
prompt_limit: 200,
@ -210,13 +212,11 @@ describe("provider usage loading", () => {
next_reset_time: "2026-01-07T05:00:00Z",
},
},
25,
);
});
it("handles MiniMax model_remains usage payloads", async () => {
await expectMinimaxUsage(
{
expected: { usedPercent: 25 },
},
{
name: "handles MiniMax model_remains usage payloads",
payload: {
base_resp: { status_code: 0, status_msg: "ok" },
model_remains: [
{
@ -229,8 +229,25 @@ describe("provider usage loading", () => {
},
],
},
25,
);
expected: { usedPercent: 25 },
},
{
name: "keeps payload-level MiniMax plan metadata when the usage candidate is nested",
payload: {
base_resp: { status_code: 0, status_msg: "ok" },
data: {
plan_name: "Payload Plan",
nested: {
usage_ratio: "0.4",
window_hours: 2,
next_reset_time: "2026-01-07T05:00:00Z",
},
},
},
expected: { usedPercent: 40, plan: "Payload Plan", label: "2h" },
},
])("$name", async ({ payload, expected }) => {
await expectMinimaxUsage(payload, expected);
});
it("discovers Claude usage from token auth profiles", async () => {