This commit is contained in:
@@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
* 知识列表翻页的界面验收:点「加载更多」能把 84 条翻到底,不出错。
|
||||||
|
*
|
||||||
|
* 这条脚本是有来历的:接口的游标字段名写错(`cur.item_id`),第二页直接 500,
|
||||||
|
* 但库小于一页时永远碰不到——导入 84 条旧备忘之后用户一点就撞上了。
|
||||||
|
*
|
||||||
|
* 用法:
|
||||||
|
* node web/e2e/knowledge-paging.mjs # 默认打生产
|
||||||
|
* WEB=http://127.0.0.1:5180 PHONE=13900000001 node web/e2e/knowledge-paging.mjs
|
||||||
|
*/
|
||||||
|
import { chromium } from "playwright-core";
|
||||||
|
|
||||||
|
const WEB = process.env.WEB ?? "http://192.168.8.188:8200";
|
||||||
|
const API = process.env.API ?? `${WEB}/api/v1`;
|
||||||
|
const PHONE = process.env.PHONE ?? "13605513683";
|
||||||
|
const CODE = process.env.CODE ?? "123456";
|
||||||
|
const CODE_PIN = process.env.CODE_PIN ?? "123456"; // 生产 pin 就是验证码本身
|
||||||
|
const CHROME =
|
||||||
|
process.env.CHROME ??
|
||||||
|
`${process.env.LOCALAPPDATA}\\ms-playwright\\chromium-1223\\chrome-win64\\chrome.exe`;
|
||||||
|
|
||||||
|
let pass = 0;
|
||||||
|
let fail = 0;
|
||||||
|
function check(name, ok, extra = "") {
|
||||||
|
if (ok) {
|
||||||
|
pass += 1;
|
||||||
|
console.log(`PASS ${name}`);
|
||||||
|
} else {
|
||||||
|
fail += 1;
|
||||||
|
console.log(`FAIL ${name} ${extra}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function login() {
|
||||||
|
const r = await fetch(`${API}/auth/sms/send`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ phone: PHONE }),
|
||||||
|
});
|
||||||
|
const sent = await r.json();
|
||||||
|
if (sent.code !== 0) throw new Error(`发码失败:${sent.message}`);
|
||||||
|
const login = await fetch(`${API}/auth/login`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ phone: PHONE, code: CODE_PIN }),
|
||||||
|
});
|
||||||
|
const body = await login.json();
|
||||||
|
if (body.code !== 0) throw new Error(`登录失败:${body.message}`);
|
||||||
|
return { tokens: body.data.tokens, workspaces: await workspaces(body.data.tokens) };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function workspaces(tokens) {
|
||||||
|
const r = await fetch(`${API}/workspaces`, {
|
||||||
|
headers: { Authorization: `Bearer ${tokens.access_token}` },
|
||||||
|
});
|
||||||
|
const body = await r.json();
|
||||||
|
return body.data?.items ?? body.data ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
void CODE;
|
||||||
|
const { tokens, workspaces: spaces } = await login();
|
||||||
|
if (!spaces.length) throw new Error("这个账号没有工作区");
|
||||||
|
const ws = spaces[0];
|
||||||
|
|
||||||
|
// 先问接口一共有多少条,作为界面上应该数出来的数字
|
||||||
|
const head = await fetch(`${API}/workspaces/${ws.id}/knowledge?limit=100`, {
|
||||||
|
headers: { Authorization: `Bearer ${tokens.access_token}` },
|
||||||
|
});
|
||||||
|
const headBody = await head.json();
|
||||||
|
const total = (headBody.data?.items ?? []).length;
|
||||||
|
|
||||||
|
const browser = await chromium.launch({ executablePath: CHROME });
|
||||||
|
const context = await browser.newContext({ viewport: { width: 1440, height: 960 } });
|
||||||
|
await context.addInitScript(
|
||||||
|
([access, refresh]) => {
|
||||||
|
localStorage.setItem("dadao.access", access);
|
||||||
|
localStorage.setItem("dadao.refresh", refresh);
|
||||||
|
},
|
||||||
|
[tokens.access_token, tokens.refresh_token],
|
||||||
|
);
|
||||||
|
const page = await context.newPage();
|
||||||
|
const errors = [];
|
||||||
|
const bad = [];
|
||||||
|
page.on("pageerror", (e) => errors.push(String(e)));
|
||||||
|
page.on("response", (r) => {
|
||||||
|
if (r.url().includes("/knowledge?") && r.status() >= 400) bad.push(`${r.status()} ${r.url()}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.goto(`${WEB}/w/${ws.id}/knowledge`, { waitUntil: "networkidle" });
|
||||||
|
const cards = () => page.locator("li");
|
||||||
|
const first = await cards().count();
|
||||||
|
check("首屏有列表", first > 0, `count=${first}`);
|
||||||
|
|
||||||
|
let rounds = 0;
|
||||||
|
while (rounds < 20) {
|
||||||
|
const more = page.getByRole("button", { name: "加载更多" });
|
||||||
|
if ((await more.count()) === 0) break;
|
||||||
|
const before = await cards().count();
|
||||||
|
await more.first().click();
|
||||||
|
const grew = async () => (await cards().count()) > before;
|
||||||
|
for (let i = 0; i < 40 && !(await grew()); i += 1) await page.waitForTimeout(100);
|
||||||
|
if (!(await grew())) break;
|
||||||
|
rounds += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shown = await cards().count();
|
||||||
|
check("点「加载更多」能把列表翻到底", shown >= total, `shown=${shown} total=${total}`);
|
||||||
|
check("翻页接口没有报错", bad.length === 0, bad.slice(0, 3).join(" | "));
|
||||||
|
const toast = await page.locator("text=服务器内部错误").count();
|
||||||
|
check("页面上没有「服务器内部错误」", toast === 0);
|
||||||
|
check("控制台零报错", errors.length === 0, errors.slice(0, 2).join(" | "));
|
||||||
|
|
||||||
|
await page.screenshot({ path: "e2e/artifacts/knowledge-paging.png" });
|
||||||
|
await browser.close();
|
||||||
|
|
||||||
|
console.log(`\n${fail === 0 ? "ALL PASS" : "SOME FAILED"} — pass ${pass}, fail ${fail}`);
|
||||||
|
process.exit(fail === 0 ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((err) => {
|
||||||
|
console.error("脚本异常 —", err?.message ?? err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user