Files
mnote/scripts/task489-auth-profile-access-ui-smoke.js
T

126 lines
6.0 KiB
JavaScript

#!/usr/bin/env node
"use strict";
const assert = require("node:assert");
const fs = require("node:fs");
const { spawn } = require("node:child_process");
const { chromium } = require("playwright");
const {
findFreePort,
waitForGateway,
} = require("./task114-rust-web-gateway-entry-smoke.js");
const UI_TIMEOUT_MS = Number(process.env.UI_TIMEOUT_MS || 10_000);
function chromiumExecutablePath() {
return [
process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH || "",
"/usr/bin/google-chrome-stable",
"/usr/bin/google-chrome",
"/snap/bin/chromium",
"/usr/bin/chromium",
"/usr/bin/chromium-browser",
].find((candidate) => candidate && fs.existsSync(candidate)) || undefined;
}
function startGateway(port) {
return spawn("cargo", ["run", "-q", "-p", "mnote-web", "--bin", "mnote-web"], {
cwd: "/mnt/Data1T/mnote/rust",
env: {
...process.env,
MNOTE_WEB_ALLOW_DEV_FIXTURES: "1",
MNOTE_WEB_BIND: `127.0.0.1:${port}`,
MNOTE_WEB_PUBLIC_BIND: "127.0.0.1:3000",
MNOTE_WEB_ENABLE_LEGACY_NEXT_COMPAT: "1",
MNOTE_WEB_LEGACY_NEXT_BASE_URL: "http://127.0.0.1:3100",
},
stdio: ["ignore", "pipe", "pipe"],
});
}
async function main() {
let baseUrl = (process.env.MNOTE_UI_BASE_URL || "").replace(/\/+$/, "");
let gateway = null;
if (!baseUrl) {
const port = await findFreePort();
baseUrl = `http://127.0.0.1:${port}`;
gateway = startGateway(port);
await waitForGateway(baseUrl);
}
const executablePath = chromiumExecutablePath();
const browser = await chromium.launch({
headless: true,
...(executablePath ? { executablePath } : {}),
});
try {
const authPage = await browser.newPage();
await authPage.goto(`${baseUrl}/auth`, { waitUntil: "domcontentloaded", timeout: UI_TIMEOUT_MS });
await authPage.locator('[data-testid="mnote-auth-page"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
assert(await authPage.locator('#account').isVisible(), "登录态应显示邮箱或用户名输入框");
assert(!(await authPage.locator('#email').isVisible()), "登录态不应显示注册邮箱输入框");
await authPage.locator('[data-auth-switch]').click();
await authPage.locator('#email').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
assert(await authPage.locator('#username').isVisible(), "注册态应显示用户名输入框");
assert(!(await authPage.locator('#account').isVisible()), "注册态不应显示登录账号输入框");
await authPage.close();
const userContext = await browser.newContext({
extraHTTPHeaders: {
"x-mnote-actor-id": "user_profile_smoke",
"x-mnote-actor-type": "user",
},
});
const userPage = await userContext.newPage();
await userPage.goto(baseUrl, { waitUntil: "domcontentloaded", timeout: UI_TIMEOUT_MS });
await userPage.locator('[data-testid="mnote-account-menu-trigger"]').click();
await userPage.locator('[data-testid="mnote-account-menu"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
assert.equal(await userPage.locator('[data-testid="mnote-account-access-policy"]').count(), 0, "授权管理入口应已退役");
await userPage.locator('[data-testid="mnote-account-ai-management"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
await userPage.locator('[data-testid="mnote-account-profile"]').click();
await userPage.locator('[data-testid="mnote-profile-dialog"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
const profileText = await userPage.locator('[data-testid="mnote-profile-dialog"]').innerText();
assert(profileText.includes("user_profile_smoke"), "个人信息弹窗应显示完整用户 ID");
await userPage.goto(`${baseUrl}/user/access-policy`, { waitUntil: "commit", timeout: UI_TIMEOUT_MS });
await userPage.waitForURL((url) => url.pathname === "/user/ai" && url.hash === "#ai-admin-access", { timeout: UI_TIMEOUT_MS });
await userPage.locator("#ai-admin-access.is-active").waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
const userAccessText = await userPage.locator("#ai-admin-access").innerText();
assert(userAccessText.includes("目录权限"), "旧用户授权页应跳转到用户 AI 设置的目录权限面板");
await userContext.close();
const adminContext = await browser.newContext({
extraHTTPHeaders: {
"x-mnote-actor-id": "admin_profile_smoke",
"x-mnote-actor-type": "admin",
},
});
const adminPage = await adminContext.newPage();
await adminPage.goto(baseUrl, { waitUntil: "domcontentloaded", timeout: UI_TIMEOUT_MS });
await adminPage.locator('[data-testid="mnote-account-menu-trigger"]').click();
await adminPage.locator('[data-testid="mnote-account-menu"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
assert.equal(await adminPage.locator('[data-testid="mnote-account-access-policy"]').count(), 0, "管理员账号菜单不应再出现授权管理入口");
await adminPage.locator('[data-testid="mnote-account-ai-management"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
await adminPage.goto(`${baseUrl}/admin/access-policy`, { waitUntil: "commit", timeout: UI_TIMEOUT_MS });
await adminPage.waitForURL((url) => url.pathname === "/admin/ai" && url.hash === "#ai-admin-access", { timeout: UI_TIMEOUT_MS });
await adminPage.locator("#ai-admin-access.is-active").waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
const adminAccessText = await adminPage.locator("#ai-admin-access").innerText();
assert(adminAccessText.includes("目录权限"), "旧管理员授权页应跳转到管理员 AI 设置的目录权限面板");
await adminContext.close();
console.log(JSON.stringify({ ok: true, task: "task489-auth-profile-access-ui", baseUrl }, null, 2));
} finally {
await browser.close().catch(() => {});
if (gateway) {
gateway.kill("SIGTERM");
setTimeout(() => gateway.kill("SIGKILL"), 2_000).unref();
}
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});