61 lines
4.3 KiB
JavaScript
61 lines
4.3 KiB
JavaScript
const path = require("path");
|
||
const fs = require("fs");
|
||
const root = process.env.PLAYWRIGHT_REQUIRE_FROM;
|
||
if (!root) throw new Error("PLAYWRIGHT_REQUIRE_FROM is required");
|
||
const { chromium } = require(path.join(root, "playwright"));
|
||
const chromePath = process.env.CHROME_PATH || "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
|
||
const outputDir = path.resolve(process.env.UI_SCREENSHOT_DIR || "test/e2e/screenshots/operations");
|
||
fs.mkdirSync(outputDir, { recursive: true });
|
||
|
||
(async () => {
|
||
const browser = await chromium.launch({ executablePath: chromePath, headless: true });
|
||
const page = await browser.newPage({ viewport: { width: 1440, height: 1100 } });
|
||
const failures = [];
|
||
page.on("pageerror", (error) => failures.push(`pageerror: ${error.message}`));
|
||
page.on("console", (message) => { if (message.type() === "error") failures.push(`console: ${message.text()}`); });
|
||
page.on("response", (response) => { if (response.status() >= 400) failures.push(`http ${response.status()}: ${response.url()}`); });
|
||
await page.goto("http://localhost:3100", { waitUntil: "networkidle" });
|
||
const login = page.getByRole("button", { name: "登录研发环境" });
|
||
if (await login.isVisible()) {
|
||
await login.click();
|
||
await page.locator("#username").fill("owner");
|
||
await page.locator("#password").fill("LocalOnly123!");
|
||
await page.locator("#kc-login").click();
|
||
}
|
||
await page.waitForURL("http://localhost:3100/**", { timeout: 15000 });
|
||
await page.getByRole("button", { name: /^运行配置/ }).click();
|
||
await page.getByRole("heading", { name: "配置发布与版本控制" }).waitFor({ state: "visible", timeout: 10000 });
|
||
await page.getByLabel("配置类型").selectOption("AGENT_BUNDLE");
|
||
await page.locator(".ops-bundle-composer").waitFor({ state: "visible" });
|
||
const componentLabels = ["人设版本", "音色版本", "模型版本", "路由版本"];
|
||
for (const label of componentLabels) {
|
||
const selector = page.getByLabel(label);
|
||
if (await selector.count() !== 1) failures.push(`missing Agent bundle selector: ${label}`);
|
||
if (process.env.EXPECT_AGENT_BUNDLE_COMPONENTS === "1") {
|
||
const optionCount = await selector.locator("option").count();
|
||
if (optionCount < 2) failures.push(`Agent bundle selector has no published component: ${label}`);
|
||
if (await selector.inputValue() === "") failures.push(`Agent bundle selector was not automatically selected: ${label}`);
|
||
}
|
||
}
|
||
if (await page.getByLabel("配置正文(JSON)").count()) failures.push("Agent bundle still exposes raw JSON editor");
|
||
if (!await page.getByText("组合不直接保存密钥引用").isVisible()) failures.push("Agent bundle credential ownership note is missing");
|
||
if (!await page.getByText("配置投放控制", { exact: true }).isVisible()) failures.push("rollout control ledger is missing");
|
||
if (process.env.EXPECT_ROLLOUT_CONTROLS === "1" && await page.getByRole("button", { name: /^(暂停|恢复)$/ }).count() < 1) {
|
||
failures.push("active or paused rollout has no control action");
|
||
}
|
||
if (process.env.EXERCISE_ROLLOUT_CONTROLS === "1") {
|
||
const pauseButton = page.getByRole("button", { name: "暂停", exact: true }).first();
|
||
await Promise.all([page.waitForEvent("dialog").then((dialog) => dialog.accept("浏览器纵向冒烟暂停")), pauseButton.click()]);
|
||
await page.getByText("配置投放已暂停,后续新建通话不再命中该范围。").waitFor({ state: "visible", timeout: 10000 });
|
||
const resumeButton = page.getByRole("button", { name: "恢复", exact: true }).first();
|
||
await Promise.all([page.waitForEvent("dialog").then((dialog) => dialog.accept("浏览器纵向冒烟恢复")), resumeButton.click()]);
|
||
await page.getByText("配置投放已恢复,后续新建通话可再次命中该范围。").waitFor({ state: "visible", timeout: 10000 });
|
||
}
|
||
const overflow = await page.evaluate(() => document.documentElement.scrollWidth > document.documentElement.clientWidth + 1);
|
||
if (overflow) failures.push("operations workspace has horizontal overflow");
|
||
await page.screenshot({ path: path.join(outputDir, "ops-config-workspace.png"), fullPage: true });
|
||
await browser.close();
|
||
if (failures.length) throw new Error(failures.join("\n"));
|
||
process.stdout.write(`Operations config UI browser smoke passed. Screenshot: ${outputDir}\n`);
|
||
})().catch((error) => { process.stderr.write(`${error.stack || error}\n`); process.exitCode = 1; });
|