import { readFileSync } from "node:fs"; import { resolve } from "node:path"; import { expect, test } from "@playwright/test"; function readSource(path: string) { return readFileSync(resolve(process.cwd(), path), "utf8"); } test.describe("canvas AI layout replacement entry", () => { test("keeps the historical AI generation flow wired without routing to PSD", () => { const imageNode = readSource("components/canvas/nodes/ImageNode.tsx"); const workspace = readSource("components/canvas/CanvasWorkspace.tsx"); const toolbarConfig = readSource("lib/canvas-toolbar-config.ts"); const capabilityRegistry = readSource("lib/canvas/capabilities/registry.ts"); const route = readSource("app/api/canvas/layout-replace/route.ts"); expect(toolbarConfig).toContain('key: "imageLayoutReplace"'); expect(toolbarConfig).toContain('label: "排版替换"'); expect(toolbarConfig).not.toContain('key: "imagePsdTemplateReplace"'); expect(imageNode).toContain( 'getCanvasToolbarItem(\n canvasToolbarConfig,\n "imageLayoutReplace"' ); expect(imageNode).toContain('isSelectedImageActionInline("layoutReplace")'); expect(imageNode).toContain('isSelectedImageActionInMore("layoutReplace")'); expect(imageNode).toContain('handleAction("layout-replace")'); expect(imageNode).toContain("handleOpenLayoutReplace"); expect(imageNode).toContain("handleSubmitLayoutReplace"); expect(imageNode).toContain("imageGenerationService.layoutReplace({"); expect(imageNode).toContain("pollLayoutReplaceTask(taskId)"); expect(imageNode).toContain('editMode: "layout-replace"'); expect(imageNode).toContain("max-h-[calc(100dvh-1rem)]"); expect(imageNode).not.toContain("/psd-template?launch="); expect(workspace).toContain( 'requestImageNodeAction(selectedImageNodes[0].id, "layout-replace")' ); expect(capabilityRegistry).toContain('id: "image.layout_replace"'); expect(capabilityRegistry).toContain('clientAction: "layout-replace"'); expect(route).toContain("createCanvasImageTask({"); expect(route).toContain("await enqueueCanvasImageTask(task.id)"); }); });