Files
openclaw/src/infra/provider-usage.fetch.minimax.test.ts
2026-03-13 18:10:40 +00:00

171 lines
5.0 KiB
TypeScript

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.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(expectedError);
expect(result.windows).toHaveLength(0);
});
it.each([
{
name: "derives usage from used/total fields and includes reset + plan",
payload: {
data: {
used: 35,
total: 100,
window_hours: 3,
reset_at: 1_700_000_000,
plan_name: "Pro Max",
},
},
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: "2026-01-08T00:00:00Z",
plan: "Starter",
},
],
},
},
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",
usage_percent: 75,
reset_at: 1_700_000_000_000,
plan_name: "Team",
},
},
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 () => {
const mockFetch = createProviderUsageFetch(async () =>
makeResponse(200, { data: { foo: "bar" } }),
);
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.error).toBe("Unsupported response shape");
expect(result.windows).toHaveLength(0);
});
it("handles repeated nested records while scanning usage candidates", async () => {
const sharedUsage = {
total: 100,
used: 20,
usage_percent: 90,
window_hours: 1,
};
const dataWithSharedReference = {
first: sharedUsage,
nested: [sharedUsage],
};
const mockFetch = createProviderUsageFetch(
async () =>
({
ok: true,
status: 200,
json: async () => ({ data: dataWithSharedReference }),
}) as Response,
);
const result = await fetchMinimaxUsage("key", 5000, mockFetch);
expect(result.windows).toEqual([{ label: "1h", usedPercent: 20, resetAt: undefined }]);
});
});