import { expect, test } from "@playwright/test"; import JSZip from "jszip"; test("runtime errors and missing chunks preserve the open flow board without navigation", async ({ page }) => { await page.goto("/dev/flow-board-preview", { waitUntil: "commit" }); const zip = new JSZip(); zip.file("content.json", JSON.stringify([{ title: "刷新保护", rootTopic: { id: "recovery-root", title: "保留正在编辑的主题", children: { attached: [{ id: "recovery-child", title: "已编辑的分支" }] }, } }])); await page.locator("input[accept*=xmind]").setInputFiles({ name: "recovery.xmind", mimeType: "application/octet-stream", buffer: await zip.generateAsync({ type: "nodebuffer" }) }); const topic = page.locator(".drawnix").getByText("保留正在编辑的主题", { exact: true }); await expect(topic).toBeVisible(); await page.evaluate(() => document.fonts.ready); // Exercise the production pathname with the isolated, non-persistent fixture. await page.evaluate(() => window.history.replaceState(null, "", "/flow-board")); let navigations = 0; page.on("framenavigated", (frame) => { if (frame === page.mainFrame()) navigations += 1; }); await page.evaluate(() => { (window as any).__flowBoardRoot = document.querySelector(".drawnix"); window.dispatchEvent(new ErrorEvent("error", { message: "Cannot resolve a DOM node from Slate node", filename: `${window.location.origin}/_next/static/chunks/flow-board.js`, })); }); await page.waitForTimeout(1100); expect(navigations).toBe(0); await expect(topic).toBeVisible(); await expect(page.locator("[data-runtime-recovery-notice]")).toHaveCount(0); await page.evaluate(() => { const error = { message: "ChunkLoadError: Loading chunk 123 failed" }; window.dispatchEvent(new ErrorEvent("error", { message: error.message })); window.dispatchEvent(new ErrorEvent("error", { message: error.message })); }); await page.waitForTimeout(1100); expect(navigations).toBe(0); await expect(page.locator("[data-runtime-recovery-notice]")).toHaveCount(1); await expect(page.locator("[data-runtime-recovery-notice]")).toContainText("先保存白板后手动刷新"); expect(await page.evaluate(() => (window as any).__flowBoardRoot === document.querySelector(".drawnix"))).toBe(true); await topic.click(); await page.keyboard.press("Tab"); await expect(page.locator(".drawnix").getByText("已编辑的分支", { exact: true })).toBeVisible(); await expect(page.locator(".xmind-topic-count")).toContainText("3"); });