import { expect, test } from "@playwright/test"; import { defaultVideoCanvasRolePresets } from "../../lib/video-canvas/config"; import { composeVideoCanvasRolePrompt, getVideoCanvasAttachedRole, setVideoCanvasAttachedRole, toVideoCanvasAttachedRole, } from "../../lib/video-canvas/video-roles"; test.describe("video role attachments", () => { test("stores one selected role material in both node and generation params", () => { const preset = defaultVideoCanvasRolePresets[0]; const next = setVideoCanvasAttachedRole( { params: { prompt: "原提示词" } }, preset, "face", ); expect((next as Record).videoRole).toEqual( toVideoCanvasAttachedRole(preset, "face"), ); expect(next.params).toMatchObject({ prompt: "原提示词", roles: [ { id: "role-003", imageUrl: expect.stringContaining("003_face_closeup_1.png"), materialKind: "face", materialLabel: "近景", }, ], }); expect(getVideoCanvasAttachedRole(next)).toMatchObject({ id: "role-003", materialKind: "face", name: "甜妹/清新少女", }); }); test("removes only the role attachment and preserves unrelated params", () => { const attached = setVideoCanvasAttachedRole( { params: { model: "seedance", prompt: "镜头提示" }, untouched: true }, defaultVideoCanvasRolePresets[0], "full", ); const removed = setVideoCanvasAttachedRole(attached, null); expect(getVideoCanvasAttachedRole(removed)).toBeNull(); expect(removed).toMatchObject({ params: { model: "seedance", prompt: "镜头提示" }, untouched: true, }); expect(removed.params).not.toHaveProperty("roles"); expect(removed).not.toHaveProperty("videoRole"); }); test("merges the role identity, compliant asset and consistency prompt", () => { const role = toVideoCanvasAttachedRole(defaultVideoCanvasRolePresets[0], "full"); const prompt = composeVideoCanvasRolePrompt("女孩转身看向镜头。", [role]); expect(prompt).toContain("女孩转身看向镜头。"); expect(prompt).toContain("角色引用「甜妹/清新少女」(合规资产 public-role:003)。"); expect(prompt).toContain("避免换脸、换装、年龄漂移、性别漂移和肢体畸变"); }); });