import { afterEach, describe, expect, it, vi } from "vitest"; import { buildMinimaxH3Payload, createMinimaxH3Task, extractMinimaxH3Usage, queryMinimaxH3Task } from "@/lib/minimax/client"; describe("MiniMax H3 V2 client", () => { afterEach(() => { vi.unstubAllGlobals(); delete process.env.MINIMAX_API_KEY; delete process.env.MINIMAX_BASE_URL; }); it("builds text and single first-frame payloads with bounded parameters", () => { expect(buildMinimaxH3Payload({ prompt: "move", materials: [], settings: { duration: 5, resolution: "2K", ratio: "3:4" }, origin: "https://app.test" })).toMatchObject({ model: "MiniMax-H3", duration: 5, resolution: "2K", ratio: "3:4", aigc_watermark: false, content: [{ type: "text", text: "move" }] }); const image = buildMinimaxH3Payload({ prompt: "animate", materials: [{ type: "image", url: "/asset.png", label: "@图片1" }], settings: { duration: 8, resolution: "768p", ratio: "16:9" }, origin: "https://app.test" }); expect(image).toMatchObject({ resolution: "768P", ratio: "adaptive", content: [ { type: "text", text: "animate" }, { type: "image_url", image_url: { url: "https://app.test/asset.png" }, role: "first_frame" } ] }); expect(() => buildMinimaxH3Payload({ prompt: "bad", materials: [{ type: "video", url: "/a.mp4" }], settings: {}, origin: "https://app.test" })).toThrow("只上传 1 张图片"); }); it("submits and queries the official asynchronous endpoints", async () => { process.env.MINIMAX_API_KEY = "test-key"; process.env.MINIMAX_BASE_URL = "https://minimax.test"; const fetchMock = vi.fn() .mockResolvedValueOnce(new Response(JSON.stringify({ task_id: "task-h3" }), { status: 200 })) .mockResolvedValueOnce(new Response(JSON.stringify({ task: { id: "task-h3", status: "succeeded", content: { url: "https://cdn.test/video.mp4" }, usage: { total_seconds: 5, input_seconds: 0, output_seconds: 5, input_image_count: 1 } } }), { status: 200 })); vi.stubGlobal("fetch", fetchMock); const payload = buildMinimaxH3Payload({ prompt: "move", materials: [], settings: {}, origin: "https://app.test" }); await expect(createMinimaxH3Task(payload)).resolves.toMatchObject({ providerTaskId: "task-h3" }); await expect(queryMinimaxH3Task("task-h3")).resolves.toMatchObject({ status: "succeeded", resultUrl: "https://cdn.test/video.mp4", usage: { outputSeconds: 5, inputImageCount: 1 } }); expect(String(fetchMock.mock.calls[0][0])).toBe("https://minimax.test/v2/video_generation"); expect(String(fetchMock.mock.calls[1][0])).toBe("https://minimax.test/v2/query/video_generation/task-h3"); }); it("extracts billable usage", () => { expect(extractMinimaxH3Usage({ total_seconds: 8, input_seconds: 0, output_seconds: 8, input_image_count: 1 })).toEqual({ totalSeconds: 8, inputSeconds: 0, outputSeconds: 8, inputImageCount: 1 }); expect(extractMinimaxH3Usage({ output_seconds: 0 })).toBeUndefined(); }); });