const fs = require("fs"); const path = require("path"); const { chromium } = require("playwright"); const runtimePath = path.join( __dirname, "..", "rust", "crates", "mnote-web", "browser", "sidebar-tree-live-apply-runtime.js", ); async function main() { const source = fs .readFileSync(runtimePath, "utf8") .replace( "export const createSidebarTreeLiveApplyRuntime =", "window.createSidebarTreeLiveApplyRuntime =", ); const browser = await chromium.launch({ headless: true }); const page = await browser.newPage(); await page.goto("http://127.0.0.1:3000/", { waitUntil: "domcontentloaded" }); await page.setContent( '', ); await page.addScriptTag({ content: source }); const result = await page.evaluate(async () => { const escapeHtml = (value) => String(value || "") .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); const rootProjection = { dataset: { kernel_file_tree_projection: { items: [ { rowId: "local:folder:design", rowKind: "folder", nodeId: "local:node:design", parentNodeId: null, title: "design", depth: 0, childCount: 1, expandable: true, expandedByDefault: false, resourceMeta: { extra: { source: { relativePath: "design", }, }, }, }, ], }, }, }; const childrenProjection = { result: { items: [ { rowId: "local:folder:design/03-rust-web", rowKind: "folder", nodeId: "local:node:design/03-rust-web", parentNodeId: "local:node:design", title: "03-rust-web", depth: 1, childCount: 0, expandable: false, expandedByDefault: false, resourceMeta: { extra: { source: { relativePath: "design/03-rust-web", }, }, }, }, ], }, }; window.fetch = async () => ({ ok: true, json: async () => childrenProjection, }); const runtime = window.createSidebarTreeLiveApplyRuntime({ activeSidebarTreeMode: () => "filetree", cssEscape: (value) => CSS.escape(String(value || "")), currentDocumentId: () => "local-md:AGENTS.md", currentFileTreeActiveRowId: () => "", currentRootUri: () => "file:///tmp/mnote-smoke", currentSourceKind: () => "local_folder", currentWorkspaceId: () => "local:test", escapeHtml, fileTreeRuntimeFunction: () => null, localFilePathFromAssetId: () => "", navigateToDocument: () => {}, refreshEditorLocalAttachmentExistence: () => {}, restoreSidebarTreeTab: () => {}, rowTitle: (row) => (row ? row.textContent || "" : ""), schedulePendingLocalFolderRestoreFocus: () => {}, shortMindmapFileName: () => "mindmap.json", syncSidebarFileTreeSelection: () => {}, }); const rendered = runtime.renderSidebarSnapshot(rootProjection); const designRow = document.querySelector('[data-row-id="local:folder:design"]'); if (!rendered || !designRow) { return { rendered, loadedBeforeRefresh: false, expandedBeforeRefresh: false, loadedAfterRefresh: false, expandedAfterRefresh: false, html: document.getElementById("sidebar-file-tree-root").innerHTML, }; } const toggle = designRow && designRow.querySelector('[data-rust-action="toggle"]'); runtime.toggleChildren(designRow, toggle); await new Promise((resolve) => setTimeout(resolve, 100)); const loadedBeforeRefresh = Boolean( document.querySelector('[data-row-id="local:folder:design/03-rust-web"]'), ); const expandedBeforeRefresh = designRow.getAttribute("aria-expanded") === "true"; runtime.renderSidebarSnapshot(rootProjection); const loadedAfterRefresh = Boolean( document.querySelector('[data-row-id="local:folder:design/03-rust-web"]'), ); const refreshedDesignRow = document.querySelector('[data-row-id="local:folder:design"]'); const expandedAfterRefresh = refreshedDesignRow && refreshedDesignRow.getAttribute("aria-expanded") === "true"; return { loadedBeforeRefresh, expandedBeforeRefresh, loadedAfterRefresh, expandedAfterRefresh, error: document.documentElement.getAttribute("data-mnote-tree-live-apply-error") || "", html: document.getElementById("sidebar-file-tree-root").innerHTML, }; }); await browser.close(); if (!result.loadedBeforeRefresh || !result.expandedBeforeRefresh) { throw new Error(`懒加载前置步骤失败: ${JSON.stringify(result, null, 2)}`); } if (!result.loadedAfterRefresh || !result.expandedAfterRefresh) { throw new Error(`FileTree root projection 刷新后丢失已展开子树: ${JSON.stringify(result, null, 2)}`); } } main().catch((error) => { console.error(error); process.exit(1); });