import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { resolve } from "node:path"; import { removeCreationAttachment } from "../src/pages/create/creation-assets"; function compactSource(source: string) { return source.replace(/\s+/g, " ").trim(); } describe("creation library button", () => { test("places a library control beside the generation mode picker", () => { const source = readFileSync(resolve(import.meta.dir, "../src/pages/create/index.tsx"), "utf8"); const dockStart = source.indexOf('", dockStart); expect(dockStart).toBeGreaterThanOrEqual(0); expect(dockEnd).toBeGreaterThan(dockStart); const dockSource = compactSource(source.slice(dockStart, dockEnd)); const modePickerIndex = dockSource.indexOf(" { const source = readFileSync(resolve(import.meta.dir, "../src/pages/create/index.tsx"), "utf8"); const pickerSource = readFileSync(resolve(import.meta.dir, "../src/components/assets/asset-library-picker-modal.tsx"), "utf8"); const uploadStart = source.indexOf("const uploadLibraryAssets = async"); const uploadEnd = source.indexOf("const handleFileChange", uploadStart); expect(uploadStart).toBeGreaterThanOrEqual(0); expect(uploadEnd).toBeGreaterThan(uploadStart); expect(source.slice(uploadStart, uploadEnd)).not.toContain("setAttachments"); expect(source).toContain("onUpload: uploadLibraryAssets"); expect(source).not.toContain("onUpload={() => fileInputRef.current?.click()}"); expect(source).toContain("上传后保存到素材库"); expect(pickerSource).toContain("保存完成后会自动选中"); expect(source).toContain("个素材已上传到素材库并自动选中"); }); test("previews prompt reference images without removing them", () => { const createSource = readFileSync(resolve(import.meta.dir, "../src/pages/create/index.tsx"), "utf8"); const canvasSource = readFileSync(resolve(import.meta.dir, "../src/components/canvas/canvas-node-prompt-panel.tsx"), "utf8"); expect(createSource).toContain('className="creation-user-message-attachments"'); expect(createSource).toContain('setPreviewType(kind === "video" ? "video" : "image")'); expect(createSource).toContain(" onInsert(reference)}"); }); test("参考内容层叠轨道支持折叠、展开和 Reorder 排序", () => { const source = readFileSync(resolve(import.meta.dir, "../src/pages/create/index.tsx"), "utf8"); const styles = readFileSync(resolve(import.meta.dir, "../src/styles/globals.css"), "utf8"); expect(source).toContain('import { Reorder } from "motion/react"'); expect(source).toContain(" event.stopPropagation()}'); expect(source).toContain(" { const attachments = [ { id: "first", name: "首个" }, { id: "middle", name: "中间" }, { id: "last", name: "末尾" }, ]; expect(removeCreationAttachment(attachments, "first").map((item) => item.id)).toEqual(["middle", "last"]); expect(removeCreationAttachment(attachments, "middle").map((item) => item.id)).toEqual(["first", "last"]); expect(removeCreationAttachment(attachments, "last").map((item) => item.id)).toEqual(["first", "middle"]); }); test("删除按钮在指针按下阶段隔离拖拽,附件与素材库入口职责独立", () => { const source = compactSource(readFileSync(resolve(import.meta.dir, "../src/pages/create/index.tsx"), "utf8")); expect(source).toContain("onPointerDownCapture={(event) => event.stopPropagation()}"); expect(source).toContain("onRemove(item.id)"); expect(source).toContain("onClick={() => props.fileInputRef.current?.click()}"); expect(source).toContain("onClick={props.onOpenLibrary}"); }); });