Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  provider-usage.fetch.minimax.test.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

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: "treats MiniMax current_interval_usage_count as remaining quota (not consumed)",
      payload: {
        data: {
          current_interval_total_count: 100,
          current_interval_usage_count: 98,
          plan_name: "Coding Plan",
        },
      },
      expected: {
        plan: "Coding Plan",
        windows: [{ label: "5h", usedPercent: 2, resetAt: undefined }],
      },
    },
    {
      name: "inverts usage_percent when no count fields are present (remaining to used)",
      payload: {
        data: {
          usage_percent: 98,
          plan_name: "Coding Plan",
        },
      },
      expected: {
        plan: "Coding Plan",
        windows: [{ label: "5h", usedPercent: 2, resetAt: undefined }],
      },
    },
    {
      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: "prefers chat model entries from model_remains and derives window labels from timestamps",
      payload: {
        data: {
          model_remains: [
            {
              model_name: "speech-hd",
              current_interval_total_count: 0,
              current_interval_usage_count: 0,
              start_time: 1_774_180_800_000,
              end_time: 1_774_195_200_000,
            },
            {
              model_name: "MiniMax-M*",
              current_interval_total_count: 600,
              current_interval_usage_count: 595,
              start_time: 1_774_180_800_000,
              end_time: 1_774_195_200_000,
            },
            {
              model_name: "image-01",
              current_interval_total_count: 0,
              current_interval_usage_count: 0,
              start_time: 1_774_180_800_000,
              end_time: 1_774_195_200_000,
            },
          ],
        },
      },
      expected: {
        plan: "Coding Plan · MiniMax-M*",
        windows: [{ label: "4h", usedPercent: 0.8333333333333334, resetAt: 1_774_195_200_000 }],
      },
    },
    {
      name: "falls back to the first non-zero model_remains record when no MiniMax chat entry exists",
      payload: {
        data: {
          model_remains: [
            {
              model_name: "speech-hd",
              current_interval_total_count: 0,
              current_interval_usage_count: 0,
            },
            {
              model_name: "video-01",
              current_interval_total_count: 200,
              current_interval_usage_count: 150,
              start_time: 1_774_180_800_000,
              end_time: 1_774_195_200_000,
            },
          ],
        },
      },
      expected: {
        plan: "Coding Plan · video-01",
        windows: [{ label: "4h", usedPercent: 25, resetAt: 1_774_195_200_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 }]);
  });
});

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge