/** * 截图:详情抽屉里的富文本编辑器(Vditor,边写边看)。 * 只用于留存界面现状,不做断言。 */ import { chromium } from "playwright-core"; const API = "http://127.0.0.1:8100/api/v1"; const WEB = "http://127.0.0.1:5180"; const stamp = String(Date.now()).slice(-7); const phone = `137${stamp}0`; async function call(method, path, body, token) { const headers = { "content-type": "application/json" }; if (token) headers.authorization = `Bearer ${token}`; if (method !== "GET") headers["idempotency-key"] = `shot-${Math.random()}`; const res = await fetch(`${API}${path}`, { method, headers, body: body ? JSON.stringify(body) : undefined, }); const json = JSON.parse(await res.text()); if (json.code !== 0) throw new Error(`${path} ${json.code} ${json.message}`); return json.data; } const PNG = Buffer.from( "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAXklEQVR42u3BAQ0AAADCoPdPbQ8H" + "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4G8wAAAB" + "T2nSywAAAABJRU5ErkJggg==", "base64", ); await call("POST", "/auth/sms/send", { phone }); const login = await call("POST", "/auth/login", { phone, code: "123456" }); const token = login.tokens.access_token; const ws = await call("POST", "/workspaces", { name: "远航工作室" }, token); const body = [ "**快递只收顺丰**,其它快递到不了前台。", "", "寄之前先拍一张照片存档,并在下面写上单号。", "", "1. 抬头写「远航科技(上海)有限公司」", "2. 备注「报销 - 十月」", "3. 底单留在文件袋里", ].join("\n"); const task = await call( "POST", `/workspaces/${ws.id}/items`, { title: "把十月报销单寄给财务", body_md: body, priority: 2 }, token, ); const form = new FormData(); form.append("file", new Blob([PNG], { type: "image/png" }), "底单照片.png"); const uploaded = await fetch( `${API}/workspaces/${ws.id}/items/${task.id}/attachments`, { method: "POST", headers: { authorization: `Bearer ${token}` }, body: form }, ); const att = (await uploaded.json()).data; await call( "PATCH", `/workspaces/${ws.id}/items/${task.id}`, { version: task.version, body_md: `${body}\n\n![底单照片.png](/api/v1/workspaces/${ws.id}/attachments/${att.id}/raw?token=${token})`, }, token, ); const browser = await chromium.launch({ executablePath: `${process.env.LOCALAPPDATA}\\ms-playwright\\chromium-1223\\chrome-win64\\chrome.exe`, }); const context = await browser.newContext({ viewport: { width: 1440, height: 960 } }); const page = await context.newPage(); await page.goto(`${WEB}/login`); await page.evaluate( ([access, refresh]) => { localStorage.setItem("dadao.access", access); localStorage.setItem("dadao.refresh", refresh); }, [token, login.tokens.refresh_token], ); await page.goto(`${WEB}/w/${ws.id}`); await page.getByRole("heading", { name: "任务" }).waitFor(); await page.getByRole("button", { name: "全部", exact: true }).click(); await page.getByRole("button", { name: "把十月报销单寄给财务", exact: true }).click(); const drawer = page.getByRole("dialog"); await drawer.waitFor(); // Vditor 是"边写边看",没有单独的预览态:等它把 lute 与正文渲染出来再截图 await page.waitForSelector(".vditor-ir strong", { timeout: 20000 }); await page.waitForTimeout(1200); await page.screenshot({ path: "../2.Design/screens/web-editor-write.png" }); await context.close(); await browser.close(); console.log("shots saved");