import { clickXmindAction } from "./editor-actions"; import { expect, test } from "@playwright/test"; import JSZip from "jszip"; const pixel = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAO0lEQVR4AezXwQkAMAgDwND9d27rBD4FOdB3wv1yktzJrwI/f+4UIECAAAECBAgQIECAAAEC+wW63f0AAAD//+3aM8YAAAAGSURBVAMABkQgIT13JVIAAAAASUVORK5CYII="; test("export downloads all sheets and preserves editable topic content after reimport", async ({ page, }) => { const errors: string[] = []; page.on("pageerror", (error) => errors.push(error.message)); await page.goto("/dev/flow-board-preview", { waitUntil: "commit" }); const source = new JSZip(); source.file( "content.json", JSON.stringify([ { title: "策划", rootTopic: { id: "r", title: "产品发布", image: { src: "xap:resources/image.png", width: 48 }, structureClass: "org.xmind.ui.logic.right", children: { attached: [ { id: "a", title: "设计方案", notes: { plain: { content: "备注第一行\n备注第二行" } }, labels: ["重点"], style: { properties: { "fo:font-size": "22", "fo:font-weight": "bold", "svg:fill": "#fff4cc", }, }, }, { id: "b", title: "交付文件", href: "xap:attachments/需求.txt" }, { id: "c", title: "定位设计", href: "xmind:#a" }, ], summary: [{ id: "summary", title: "准备阶段" }], detached: [ { id: "free", title: "待讨论", position: { x: 400, y: 300 } }, ], }, summaries: [{ range: "(0,1)", topicId: "summary" }], boundaries: [{ range: "(0,1)" }], }, relationships: [{ end1Id: "a", end2Id: "b", title: "交付" }], }, { title: "上线", rootTopic: { id: "root2", title: "验收清单", structureClass: "org.xmind.ui.org-chart.down", children: { attached: [{ id: "item", title: "功能验收" }] }, }, }, ]) ); source.file("attachments/需求.txt", "附件原文"); source.file("resources/image.png", pixel, { base64: true }); const input = page.locator("input[accept*=xmind]"); await input.setInputFiles({ name: "发布计划.xmind", mimeType: "application/octet-stream", buffer: await source.generateAsync({ type: "nodebuffer" }), }); const canvas = page.locator(".drawnix"); await canvas.getByText("设计方案", { exact: true }).click(); await clickXmindAction(page, "备注"); await page.getByRole("button",{name:"主题详情",exact:true}).click(); await page.getByLabel("主题备注").fill("编辑后的备注"); const downloading = page.waitForEvent("download"); await page.getByRole("button", { name: "导出 XMind", exact: true }).click(); const downloaded = await downloading; expect(downloaded.suggestedFilename()).toBe("发布计划.xmind"); const stream = await downloaded.createReadStream(); const chunks = []; for await (const chunk of stream!) chunks.push(chunk); const bytes = Buffer.concat(chunks); const exported = await JSZip.loadAsync(bytes); const content = JSON.parse( await exported.file("content.json")!.async("string") ); expect(content).toHaveLength(2); expect(content[0].rootTopic.children.attached[0].notes.plain.content).toBe( "编辑后的备注" ); expect(content[0].relationships[0].title).toBe("交付"); expect( await exported .file(content[0].rootTopic.image.src.replace(/^xap:/, ""))! .async("base64") ).toBe(pixel); const attachmentPath = content[0].rootTopic.children.attached[1].href.replace( /^xap:/, "" ); expect(await exported.file(attachmentPath)!.async("string")).toBe("附件原文"); await downloaded.saveAs(test.info().outputPath("发布计划.xmind")); await page.getByRole("button", { name: "上线", exact: true }).click(); await expect(canvas.getByText("功能验收", { exact: true })).toBeVisible(); await input.setInputFiles({ name: "往返验证.xmind", mimeType: "application/octet-stream", buffer: bytes, }); await expect(canvas.getByText("设计方案", { exact: true })).toHaveCSS( "font-size", "22px" ); for (const label of ["准备阶段", "待讨论", "交付"]) await expect(canvas.getByText(label, { exact: true })).toBeVisible(); await expect(page.locator("[plait-geometry=true]")).toHaveCount(1); await expect(page.locator("[plait-arrow-line=true]")).toHaveCount(1); await expect( canvas.locator('img[src^="data:image/png"], image[href^="data:image/png"]') ).toHaveCount(1); await canvas.getByText("设计方案", { exact: true }).click(); await clickXmindAction(page, "备注"); await page.getByRole("button",{name:"主题详情",exact:true}).click(); await expect.poll(() => page.getByLabel("主题备注").locator("p").allTextContents().then(lines => lines.join("\n"))).toBe("编辑后的备注"); await expect( page.getByRole("button", { name: "移除标签 重点", exact: true }) ).toBeVisible(); await canvas.getByText("定位设计", { exact: true }).click(); await page.getByRole("button", { name: "定位目标主题", exact: true }).click(); await expect.poll(() => page.getByLabel("主题备注").locator("p").allTextContents().then(lines => lines.join("\n"))).toBe("编辑后的备注"); await page.getByRole("button", { name: "上线", exact: true }).click(); await expect(canvas.getByText("功能验收", { exact: true })).toBeVisible(); expect(errors).toEqual([]); });