197 lines
5.5 KiB
TypeScript
197 lines
5.5 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import {
|
|
buildVideoCanvasImageCreationParams,
|
|
buildVideoCanvasVideoCreationParams,
|
|
defaultVideoCanvasNodeCreationConfig,
|
|
getInitialVideoCanvasNodeCreationOrdinal,
|
|
normalizeVideoCanvasNodeCreationConfig,
|
|
} from "../../lib/video-canvas/node-creation";
|
|
import type { VideoCanvasModelCatalogEntry } from "../../lib/video-canvas/video-model-catalog";
|
|
import { getContentType } from "../../lib/storage/content-type";
|
|
import {
|
|
VIDEO_CANVAS_RESOURCE_UPLOAD_PURPOSE,
|
|
VIDEO_CANVAS_RESOURCE_UPLOAD_SOURCE_TYPE,
|
|
getVideoCanvasUploadedResourceMediaType,
|
|
getVideoCanvasUploadedResourceUrl,
|
|
validateVideoCanvasUploadedResource,
|
|
} from "../../lib/video-canvas/uploaded-resource";
|
|
|
|
const catalog: VideoCanvasModelCatalogEntry[] = [
|
|
{
|
|
badge: "",
|
|
description: "",
|
|
discountRate: 1,
|
|
durationLabel: "",
|
|
enabled: true,
|
|
icon: "seedance",
|
|
id: "seedance-1-5-pro",
|
|
label: "Seedance1.5 Pro",
|
|
membershipOnly: false,
|
|
modelRef: "seedance-model-ref",
|
|
pointsPerSecondByResolution: {},
|
|
shortLabel: "Seedance1.5 Pro",
|
|
},
|
|
];
|
|
|
|
test.describe("video canvas node creation defaults", () => {
|
|
test("matches the observed image, video, and audio creation state", () => {
|
|
expect(defaultVideoCanvasNodeCreationConfig).toEqual({
|
|
audio: { advancedSettingsOpen: true },
|
|
image: {
|
|
count: 1,
|
|
height: 350,
|
|
modelLabel: "Lib Image",
|
|
quality: "标准画质",
|
|
ratio: "16:9",
|
|
size: "2K",
|
|
width: 622,
|
|
},
|
|
upload: {
|
|
accept: "image/*,video/*,audio/*",
|
|
maxFileSizeMb: 50,
|
|
maxFiles: 10,
|
|
placementGap: 450,
|
|
},
|
|
video: {
|
|
count: 1,
|
|
durationSeconds: 5,
|
|
generateAudio: true,
|
|
height: 350,
|
|
modelCatalogId: "seedance-1-5-pro",
|
|
ratio: "16:9",
|
|
resolution: "1080P",
|
|
width: 622,
|
|
},
|
|
});
|
|
});
|
|
|
|
test("normalizes administrator values and preserves explicit false", () => {
|
|
expect(
|
|
normalizeVideoCanvasNodeCreationConfig({
|
|
audio: { advancedSettingsOpen: false },
|
|
image: { count: 99, height: 100, ratio: "3:4", width: 9999 },
|
|
upload: {
|
|
maxFileSizeMb: 9999,
|
|
maxFiles: 0,
|
|
placementGap: 5,
|
|
},
|
|
video: {
|
|
count: 2,
|
|
durationSeconds: 0,
|
|
generateAudio: false,
|
|
resolution: "4k",
|
|
},
|
|
}),
|
|
).toMatchObject({
|
|
audio: { advancedSettingsOpen: false },
|
|
image: { count: 4, height: 240, ratio: "3:4", width: 1600 },
|
|
upload: {
|
|
maxFileSizeMb: 500,
|
|
maxFiles: 1,
|
|
placementGap: 40,
|
|
},
|
|
video: {
|
|
count: 2,
|
|
durationSeconds: 1,
|
|
generateAudio: false,
|
|
resolution: "4K",
|
|
},
|
|
});
|
|
});
|
|
|
|
test("writes image defaults into a structured node draft", () => {
|
|
expect(
|
|
buildVideoCanvasImageCreationParams(defaultVideoCanvasNodeCreationConfig),
|
|
).toMatchObject({
|
|
count: 1,
|
|
imageQuality: "标准画质",
|
|
imageSize: "2K",
|
|
modelLabel: "Lib Image",
|
|
ratio: "16:9",
|
|
settings: { ratio: "16:9" },
|
|
});
|
|
});
|
|
|
|
test("resolves the configured video catalog item and parameters", () => {
|
|
expect(
|
|
buildVideoCanvasVideoCreationParams(
|
|
defaultVideoCanvasNodeCreationConfig,
|
|
catalog,
|
|
),
|
|
).toMatchObject({
|
|
audio: true,
|
|
count: 1,
|
|
duration: 5,
|
|
mode: "text-to-video",
|
|
model: "seedance-model-ref",
|
|
ratio: "16:9",
|
|
resolution: "1080p",
|
|
settings: {
|
|
modelCatalogId: "seedance-1-5-pro",
|
|
modelLabel: "Seedance1.5 Pro",
|
|
resolution: "1080P",
|
|
},
|
|
});
|
|
});
|
|
|
|
test("initializes a session ordinal without reusing numeric titles", () => {
|
|
expect(getInitialVideoCanvasNodeCreationOrdinal([])).toBe(1);
|
|
expect(
|
|
getInitialVideoCanvasNodeCreationOrdinal([
|
|
{ title: "提示词" },
|
|
{ title: "成品" },
|
|
]),
|
|
).toBe(2);
|
|
expect(
|
|
getInitialVideoCanvasNodeCreationOrdinal([
|
|
{ title: "图片节点 9" },
|
|
{ title: "成品" },
|
|
]),
|
|
).toBe(10);
|
|
});
|
|
|
|
test("uses a dedicated persistent upload purpose and classifies all supported media", () => {
|
|
expect(VIDEO_CANVAS_RESOURCE_UPLOAD_PURPOSE).toBe(
|
|
"video-canvas-add-resource",
|
|
);
|
|
expect(VIDEO_CANVAS_RESOURCE_UPLOAD_SOURCE_TYPE).toBe(
|
|
"video_canvas_upload",
|
|
);
|
|
expect(getVideoCanvasUploadedResourceMediaType("image/png")).toBe(
|
|
"image",
|
|
);
|
|
expect(getVideoCanvasUploadedResourceMediaType("video/webm")).toBe(
|
|
"video",
|
|
);
|
|
expect(getVideoCanvasUploadedResourceMediaType("audio/wav")).toBe(
|
|
"audio",
|
|
);
|
|
expect(getContentType("clip.webm")).toBe("video/webm");
|
|
expect(getContentType("voice.wav")).toBe("audio/wav");
|
|
});
|
|
|
|
test("validates uploaded resource size and reads the persistent URL", () => {
|
|
expect(
|
|
validateVideoCanvasUploadedResource(
|
|
{ size: 1024, type: "image/png" },
|
|
defaultVideoCanvasNodeCreationConfig.upload,
|
|
),
|
|
).toEqual({ mediaType: "image", valid: true });
|
|
expect(
|
|
validateVideoCanvasUploadedResource(
|
|
{
|
|
size:
|
|
(defaultVideoCanvasNodeCreationConfig.upload.maxFileSizeMb + 1) *
|
|
1024 *
|
|
1024,
|
|
type: "video/mp4",
|
|
},
|
|
defaultVideoCanvasNodeCreationConfig.upload,
|
|
),
|
|
).toMatchObject({ valid: false });
|
|
expect(getVideoCanvasUploadedResourceUrl({ url: "/uploads/file.png" })).toBe(
|
|
"/uploads/file.png",
|
|
);
|
|
});
|
|
});
|