Files
ttstd-infinite-canvas/web/test/canvas-video-regeneration.test.ts
爱笑的毛毛虫 d33c6389d4 feat(canvas): 视频节点截取重生成 - 支持多段/时间线导入并调用视频模型批量重生成 (#197)
* feat(canvas): 视频节点截取重生成 - 支持多段/时间线导入并调用视频模型批量重生成

* test(canvas): 视频节点时间线导入 - 修正旧数据标题回退测试

* style(canvas): 视频节点截取重生成 - 格式化新增文件并修正测试

---------

Co-authored-by: sikongyue <3155157671@qq.com>
2026-08-10 00:13:02 +08:00

129 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test } from "bun:test";
import { listVideoReferenceModels, validateVideoSegmentBatch, videoReferenceOperationError, videoReferenceRegenerationError, videoReferenceSegmentError } from "../src/lib/canvas/canvas-video-regeneration";
import { defaultModelCapabilityConfig } from "../src/lib/model-capabilities";
import { defaultConfig, type AiConfig, type ModelChannel } from "../src/stores/use-config-store";
function supportedVideoConfig(overrides: { model?: string; maxVideos?: number; maxVideoDurationSeconds?: number; operations?: string[]; baseUrl?: string } = {}): AiConfig {
const model = overrides.model || "seedance-1.0-pro";
const capability = defaultModelCapabilityConfig("newapi-channel-2", model);
if (capability.video) {
capability.video.references.maxVideos = overrides.maxVideos ?? 3;
capability.video.references.maxVideoDurationSeconds = overrides.maxVideoDurationSeconds ?? 15;
capability.video.operations = overrides.operations ?? ["text_to_video", "image_to_video", "extend"];
}
const channel: ModelChannel = {
id: "test",
name: "测试渠道",
baseUrl: overrides.baseUrl || "https://api.example.com",
apiKey: "test-key",
apiFormat: "openai",
interfaceType: "newapi-channel-2",
models: [model],
scope: "user",
modelCosts: [
{
model,
capability: "video",
protocol: "newapi-channel-2",
billingMode: "per_second",
unitPriceMicrocredits: 1,
capabilityConfig: capability,
},
],
};
return {
...defaultConfig,
model: `test::${model}`,
videoModel: `test::${model}`,
models: [`test::${model}`],
videoModels: [`test::${model}`],
channels: [channel],
baseUrl: channel.baseUrl,
};
}
describe("videoReferenceRegenerationError", () => {
test("模型不支持参考视频时返回提示", () => {
const config: AiConfig = { ...defaultConfig, model: "default::grok-imagine-video", videoModel: "default::grok-imagine-video" };
expect(videoReferenceRegenerationError(config)).toContain("不支持参考视频");
});
test("模型没有可用生成模式时返回提示", () => {
const config = supportedVideoConfig({ operations: [] });
expect(videoReferenceRegenerationError(config)).toContain("没有可用的视频生成模式");
});
test("模型支持参考视频且有可用模式时无错误", () => {
expect(videoReferenceRegenerationError(supportedVideoConfig())).toBe("");
});
});
describe("videoReferenceOperationError", () => {
test("所选模式不在模型能力中时返回提示", () => {
const config = supportedVideoConfig({ operations: ["text_to_video", "image_to_video", "extend"] });
expect(videoReferenceOperationError(config, "inpaint")).toContain("不支持所选生成模式");
});
test("所选模式在模型能力中时无错误", () => {
expect(videoReferenceOperationError(supportedVideoConfig(), "extend")).toBe("");
});
});
describe("listVideoReferenceModels", () => {
test("默认配置没有可用的参考视频模型", () => {
const config: AiConfig = { ...defaultConfig, model: "default::grok-imagine-video", videoModel: "default::grok-imagine-video" };
expect(listVideoReferenceModels(config)).toEqual([]);
});
test("只返回支持参考视频且有可用模式的模型", () => {
expect(listVideoReferenceModels(supportedVideoConfig())).toEqual(["test::seedance-1.0-pro"]);
});
test("过滤掉没有可用生成模式的模型", () => {
const config = supportedVideoConfig({ operations: [] });
expect(listVideoReferenceModels(config)).toEqual([]);
});
test("过滤掉未配置 API Key 的渠道模型", () => {
const config = supportedVideoConfig();
config.channels[0].apiKey = "";
expect(listVideoReferenceModels(config)).toEqual([]);
});
});
describe("videoReferenceSegmentError", () => {
test("片段超过模型参考视频上限时返回提示", () => {
const config = supportedVideoConfig({ maxVideoDurationSeconds: 15 });
expect(videoReferenceSegmentError(config, 16000)).toContain("不能超过当前模型参考视频上限(15 秒)");
});
test("Seedance 单段少于 2 秒时返回提示", () => {
const config = supportedVideoConfig({ model: "seedance-1.0-pro" });
expect(videoReferenceSegmentError(config, 1500)).toContain("至少 2 秒");
});
test("合法片段时长无错误", () => {
expect(videoReferenceSegmentError(supportedVideoConfig(), 5000)).toBe("");
});
});
describe("validateVideoSegmentBatch", () => {
test("模型、模式与片段时长都合法时无错误", () => {
expect(validateVideoSegmentBatch(supportedVideoConfig(), [{ startMs: 2000, endMs: 5000 }], "extend")).toBe("");
});
test("模型不支持参考视频时返回首个错误", () => {
const config: AiConfig = { ...defaultConfig, model: "default::grok-imagine-video", videoModel: "default::grok-imagine-video" };
expect(validateVideoSegmentBatch(config, [{ startMs: 2000, endMs: 5000 }], "extend")).toContain("不支持参考视频");
});
test("模式不在模型能力中时返回操作错误", () => {
expect(validateVideoSegmentBatch(supportedVideoConfig(), [{ startMs: 2000, endMs: 5000 }], "inpaint")).toContain("不支持所选生成模式");
});
test("片段超过模型时长上限时返回片段错误", () => {
expect(validateVideoSegmentBatch(supportedVideoConfig({ maxVideoDurationSeconds: 15 }), [{ startMs: 0, endMs: 16000 }], "extend")).toContain("不能超过当前模型参考视频上限");
});
});