CI / backend (push) Canceled after 0s
- 知识列表 tab 顺序改成 全部 / 待核对 / 已发布 / 已归档,默认停在「全部」: 进知识库先看"我这儿都有些什么",待核对是待办,不该当门面。 - 正文编辑器不再是写死的 240px:新增 useEditorHeight(reserve), 按 window.innerHeight 减掉标题/分类/标签/附件/底部按钮算高度 (新建留 420、编辑留 340,最低 360、最高 960,窗口 resize 时重算), 新建面板与详情编辑两处共用,长文一屏能写完一段。 - 截图脚本 shots-knowledge-view.mjs 支持 EDIT=1 出编辑态图、ALL=1 留在默认 tab; 新增 2.Design/screens/knowledge-tab-all.png、knowledge-edit-tall.png。 - 验证:tsc --noEmit 通过、vite build ✓、e2e knowledge.mjs 9 项与 knowledge-notebook.mjs 17 项全绿(含"侧栏分类按树排""已发布也有编辑")。
105 lines
4.2 KiB
JavaScript
105 lines
4.2 KiB
JavaScript
/**
|
|
* 截图脚本:把导入的备忘录点开,看「浏览」样式是否真的渲染成 Markdown。
|
|
*
|
|
* 只用于出图,不做断言;账号用 dev 的 13900000001(导入数据的归属)。
|
|
*/
|
|
import { chromium } from "playwright-core";
|
|
import { mkdirSync } from "node:fs";
|
|
|
|
const WEB = process.env.WEB ?? "http://127.0.0.1:5180";
|
|
const API = process.env.API ?? "http://127.0.0.1:8100/api/v1";
|
|
const PHONE = process.env.PHONE ?? "13900000001";
|
|
const WS_NAME = process.env.WS_NAME ?? "我的备忘";
|
|
|
|
async function call(method, path, body, token) {
|
|
const res = await fetch(`${API}${path}`, {
|
|
method,
|
|
headers: {
|
|
"content-type": "application/json",
|
|
...(token ? { authorization: `Bearer ${token}` } : {}),
|
|
...(method === "GET" ? {} : { "idempotency-key": `shot-${Math.random()}` }),
|
|
},
|
|
body: body ? JSON.stringify(body) : undefined,
|
|
});
|
|
const text = await res.text();
|
|
const json = text ? JSON.parse(text) : {};
|
|
if (json.code !== 0) throw new Error(`${method} ${path} -> ${json.code} ${json.message}`);
|
|
return json.data;
|
|
}
|
|
|
|
async function loginAs(phone) {
|
|
// dev 下验证码固定,发码接口有 60 秒节流:能直接登录就直接登,被节流就等够了再发
|
|
try {
|
|
return await call("POST", "/auth/login", { phone, code: "123456" });
|
|
} catch {
|
|
/* 验证码过期或没发过,往下走发码 */
|
|
}
|
|
for (let i = 0; i < 2; i += 1) {
|
|
try {
|
|
await call("POST", "/auth/sms/send", { phone });
|
|
break;
|
|
} catch (err) {
|
|
if (!String(err.message).includes("2011") || i === 1) throw err;
|
|
await new Promise((r) => setTimeout(r, 61_000));
|
|
}
|
|
}
|
|
return await call("POST", "/auth/login", { phone, code: "123456" });
|
|
}
|
|
|
|
mkdirSync("e2e/artifacts", { recursive: true });
|
|
|
|
const login = await loginAs(PHONE);
|
|
const token = login.tokens.access_token;
|
|
const me = await call("GET", "/auth/me", undefined, token);
|
|
const ws = me.workspaces.find((w) => w.name === WS_NAME) ?? me.workspaces[0];
|
|
if (!ws) throw new Error(`${PHONE} 名下没有工作区`);
|
|
console.log(`工作区:${ws.name} ${ws.id}`);
|
|
|
|
const browser = await chromium.launch({
|
|
executablePath:
|
|
process.env.CHROME ??
|
|
`${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.addInitScript(
|
|
([access, refresh]) => {
|
|
localStorage.setItem("dadao.access", access);
|
|
localStorage.setItem("dadao.refresh", refresh);
|
|
},
|
|
[token, login.tokens.refresh_token],
|
|
);
|
|
await page.goto(`${WEB}/w/${ws.id}/knowledge`, { waitUntil: "networkidle" });
|
|
await page.getByRole("heading", { name: "知识" }).waitFor({ timeout: 20_000 });
|
|
// 导入的备忘都是发布过的,切到「已发布」才看得到;ALL=1 时留在默认的「全部」
|
|
if (!process.env.ALL) {
|
|
await page.getByRole("button", { name: "已发布", exact: true }).first().click();
|
|
}
|
|
if (process.env.TITLE) {
|
|
// 挑一条带标题/列表的,截图里才看得出 Markdown 真的渲染了
|
|
const target = page.locator("li").filter({ hasText: process.env.TITLE }).first();
|
|
await target.waitFor({ timeout: 20_000 });
|
|
await page.screenshot({ path: "e2e/artifacts/memo-list.png" });
|
|
await target.getByRole("button", { name: "打开", exact: true }).click();
|
|
} else {
|
|
await page.getByRole("button", { name: "打开", exact: true }).first().waitFor({ timeout: 20_000 });
|
|
await page.waitForTimeout(600);
|
|
await page.screenshot({ path: "e2e/artifacts/memo-list.png" });
|
|
await page.getByRole("button", { name: "打开", exact: true }).first().click();
|
|
}
|
|
await page.locator(".prose-dadao").first().waitFor({ timeout: 20_000 });
|
|
await page.waitForTimeout(600);
|
|
await page.screenshot({ path: "e2e/artifacts/memo-read.png" });
|
|
|
|
if (process.env.EDIT) {
|
|
// 编辑态:正文编辑器要占满剩下的高度,不能只露几行
|
|
await page.getByRole("button", { name: "编辑", exact: true }).last().click();
|
|
await page.locator(".vditor-ir [contenteditable]").first().waitFor({ timeout: 20_000 });
|
|
await page.waitForTimeout(800);
|
|
await page.screenshot({ path: "e2e/artifacts/memo-edit.png" });
|
|
}
|
|
|
|
await browser.close();
|
|
console.log("OK");
|