Files
NianAIGC/tests/bailian-client.test.ts
T
2026-10-02 19:56:32 +08:00

86 lines
4.7 KiB
TypeScript

import { afterEach, describe, expect, it } from "vitest";
import {
bailianResultUrls,
bailianOutputVideoSeconds,
bailianStatus,
buildBailianImagePayload,
buildBailianVideoPayload,
deriveBailianNativeBaseUrl
} from "@/lib/bailian/client";
afterEach(() => {
delete process.env.BAILIAN_IMAGE_MODEL;
delete process.env.BAILIAN_VIDEO_MODEL;
delete process.env.BAILIAN_API_KEY;
delete process.env.DASHSCOPE_API_KEY;
});
describe("Bailian client", () => {
it("derives native API base from compatible-mode URL", () => {
expect(deriveBailianNativeBaseUrl("https://workspace.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"))
.toBe("https://workspace.cn-beijing.maas.aliyuncs.com");
});
it("builds Wan 2.7 text-to-image and reference-image payloads", () => {
const text = buildBailianImagePayload("image.generate", { prompt: "海边酒店", width: 2048, height: 2048 });
expect(text).toMatchObject({ model: "wan2.7-image-pro", parameters: { size: "2048*2048", thinking_mode: true, watermark: false } });
const edit = buildBailianImagePayload("image.generate", { prompt: "保持人物一致", imageUrls: ["https://example.com/a.png"], width: 2048, height: 2048 });
expect((edit.input.messages[0].content as Array<Record<string, string>>)[0]).toEqual({ image: "https://example.com/a.png" });
expect(edit.parameters).not.toHaveProperty("thinking_mode");
});
it("preserves a user-selected 9:16 output size for reference images", () => {
const payload = buildBailianImagePayload("image.generate", {
prompt: "x",
imageUrls: ["https://example.com/a.png"],
width: 1440,
height: 2560
});
expect(payload.parameters.size).toBe("1440*2560");
});
it("rejects reference-image output only when total pixels exceed the 2K budget", () => {
expect(() => buildBailianImagePayload("image.generate", { prompt: "x", imageUrls: ["https://example.com/a.png"], width: 2048, height: 2560 }))
.toThrow("总像素");
});
it("maps one or two video images to first and last frames", () => {
const payload = buildBailianVideoPayload({
prompt: "镜头推进",
origin: "https://app.example.com",
materials: [{ type: "image", url: "/first.png" }, { type: "image", url: "/last.png" }],
settings: { duration: 10, resolution: "1080P" }
});
expect(payload.input.media).toEqual([
{ type: "first_frame", url: "https://app.example.com/first.png" },
{ type: "last_frame", url: "https://app.example.com/last.png" }
]);
expect(payload.parameters).toMatchObject({ duration: 10, resolution: "1080P", prompt_extend: true, watermark: false });
expect(payload.parameters).not.toHaveProperty("size");
});
it("maps Wan 3.0 references while retaining optional first and last frames", () => {
const materials = Array.from({ length: 10 }, (_, index) => ({ type: "image" as const, url: `/image-${index}.png` }));
const reference = buildBailianVideoPayload({ model: "wan3.0-video", prompt: "combine", materials, origin: "https://app.test", settings: { duration: 30, resolution: "480P", ratio: "9:16", inputMode: "reference" } });
expect(reference.input.media).toHaveLength(10);
expect(reference.input.media?.every((item) => item.type === "reference_image")).toBe(true);
expect(reference.parameters.ratio).toBe("9:16");
const frames = buildBailianVideoPayload({ model: "wan3.0-video", prompt: "animate", materials: materials.slice(0, 2), origin: "https://app.test", settings: { inputMode: "frames" } });
expect(frames.input.media?.map((item) => item.type)).toEqual(["first_frame", "last_frame"]);
expect(buildBailianVideoPayload({ model: "wan3.0-video", prompt: "landscape", materials: [], origin: "https://app.test", settings: { inputMode: "reference" } }).input).toEqual({ prompt: "landscape" });
expect(() => buildBailianVideoPayload({ model: "wan2.7-i2v-2026-04-25", prompt: "x", materials, origin: "https://app.test", settings: { inputMode: "reference" } })).toThrow("请选择 Wan 3.0");
expect(bailianOutputVideoSeconds({ usage: { output_video_duration: 5.25, duration: 8 } })).toBe(5.25);
});
it("normalizes task state and result URLs", () => {
const response = { output: { task_status: "SUCCEEDED", results: [{ url: "https://example.com/result.png" }] } };
expect(bailianStatus(response)).toBe("succeeded");
expect(bailianResultUrls(response, "image")).toEqual(["https://example.com/result.png"]);
});
it("extracts Wan 2.7 image URLs from choices content", () => {
const response = { output: { task_status: "SUCCEEDED", choices: [{ message: { content: [{ type: "image", image: "https://example.com/choice.png" }] } }] } };
expect(bailianResultUrls(response, "image")).toEqual(["https://example.com/choice.png"]);
});
});