Files
DadaoTask/web/e2e/prod-account-check.mjs
T
Steven e3f1310cff
CI / backend (push) Canceled after 0s
fix(web): 内网 http 下写请求与复制邀请链接都会失败
crypto.randomUUID() 与 navigator.clipboard 只在安全上下文(https / localhost)里存在,
生产入口是纯 http,于是:

- 所有 POST/PATCH/DELETE 在拼 Idempotency-Key 时直接抛 TypeError,
  登录页只显示"登录失败",GET 一切正常,所以这个坑一直没暴露
- 「复制邀请链接」永远回"浏览器不允许自动复制"

改成幂等键自己拼一个 v4(getRandomValues 不受安全上下文限制,退回 Math.random),
复制走 navigator.clipboard → document.execCommand("copy") 两级降级。

顺带说明:这是生产上"能看不能写"的真正原因,不是权限或接口问题。
2026-10-31 04:13:13 +08:00

56 lines
2.7 KiB
JavaScript

/**
* 生产只读核对:首页外壳、账号页、工作区页的宽度是否一致。
*
* 这个脚本**不写数据**:不设密码、不改昵称,只用验证码登录看界面。
* 生产是内测模式(任意手机号 + 123456),所以用真实账号也能进。
*/
import { chromium } from "playwright-core";
const WEB = process.env.WEB ?? "http://192.168.8.188:8200";
const PHONE = process.env.PHONE ?? "13605513683";
const CODE = process.env.CODE ?? "123456";
const browser = await chromium.launch({
executablePath:
process.env.CHROME ??
`${process.env.LOCALAPPDATA}\\ms-playwright\\chromium-1223\\chrome-win64\\chrome.exe`,
});
const page = await browser.newPage({ viewport: { width: 1440, height: 960 } });
const errors = [];
page.on("console", (m) => m.type() === "error" && errors.push(m.text()));
page.on("request", (r) => r.url().includes("/api") && console.log("req:", r.method(), r.url()));
page.on("response", (r) => r.url().includes("/auth/") && console.log("resp:", r.status(), r.url()));
page.on("requestfailed", (r) => r.url().includes("/auth/") && console.log("reqfailed:", r.failure()?.errorText, r.url()));
await page.goto(`${WEB}/login`);
await page.getByLabel("手机号").fill(PHONE);
await page.getByRole("button", { name: "获取验证码" }).click();
await page.getByLabel("验证码").fill(CODE);
await page.getByRole("button", { name: "登录" }).click();
await page.waitForTimeout(4000);
console.log("url after login:", page.url());
console.log("body:", (await page.locator("body").innerText()).replace(/\s+/g, " | ").slice(0, 400));
await page.waitForURL(`${WEB}/`, { timeout: 20_000 });
await page.waitForSelector("text=我的工作区");
const homeRail = await page.locator("aside").first().boundingBox();
console.log("首页侧栏宽度:", homeRail?.width);
await page.screenshot({ path: "e2e/artifacts/prod-home.png" });
await page.getByRole("button", { name: /我的备忘/ }).first().click();
await page.waitForURL(/\/w\//);
await page.waitForSelector("aside");
const wsRail = await page.locator("aside").first().boundingBox();
console.log("工作区侧栏宽度:", wsRail?.width, "差值:", Math.abs((wsRail?.width ?? 0) - (homeRail?.width ?? 0)));
await page.goto(`${WEB}/account`);
await page.waitForSelector("text=登录密码");
const accountRail = await page.locator("aside").first().boundingBox();
console.log("账号页侧栏宽度:", accountRail?.width);
const bodyText = await page.locator("main").innerText();
console.log("账号页文案片段:", bodyText.replace(/\n+/g, " | ").slice(0, 220));
await page.screenshot({ path: "e2e/artifacts/prod-account.png" });
console.log("控制台报错:", errors.length === 0 ? "无" : errors.slice(0, 3));
await browser.close();