R30-1 R30-9: 建立零人工发布门禁并补齐高频回归

这个提交包含在:
2026-03-23 10:00:26 +08:00
父节点 c17a72830c
当前提交 994d98e74c
共修改 22 个文件,包含 1189 行新增和 41 行删除
+14 -5
查看文件
@@ -1,5 +1,7 @@
import { expect, request as playwrightRequest, type APIRequestContext, type Page } from "@playwright/test";
import { TEST_IDS } from "./testIds";
export const E2E_BASE_URL = process.env.E2E_BASE_URL ?? "http://127.0.0.1:3000";
export type E2EUser = {
@@ -74,15 +76,22 @@ async function readJson<T>(response: { ok(): boolean; status(): number; text():
export async function login(page: Page, user: E2EUser) {
await page.goto("/login");
await page.getByTestId("login-identifier").fill(user.identifier);
await page.getByTestId("login-password").fill(user.password);
await page.getByTestId("login-submit").click();
await page.getByTestId(TEST_IDS.login.identifier).fill(user.identifier);
await page.getByTestId(TEST_IDS.login.password).fill(user.password);
await page.getByTestId(TEST_IDS.login.submit).click();
await expect(page).toHaveURL(/\/portal/);
}
export async function logout(page: Page, userDisplayName: string) {
export async function logout(page: Page, userDisplayName?: string) {
try {
await page.getByRole("button", { name: userDisplayName, exact: true }).first().click({ force: true });
const profileTrigger = page.getByTestId(TEST_IDS.topbar.profileTrigger).first();
if (await profileTrigger.isVisible().catch(() => false)) {
await profileTrigger.click({ force: true });
} else if (userDisplayName) {
await page.getByRole("button", { name: userDisplayName, exact: true }).first().click({ force: true });
} else {
throw new Error("profile trigger not visible");
}
await expect(page.getByRole("menuitem", { name: "退出登录" })).toBeVisible({ timeout: 5_000 });
await page.getByRole("menuitem", { name: "退出登录" }).click();
} catch {
+17
查看文件
@@ -1,5 +1,7 @@
import { expect, type Locator, type Page } from "@playwright/test";
import { TEST_IDS } from "./testIds";
export async function openBackupModulesIfNeeded(page: Page) {
const summary = page.locator("summary").filter({ hasText: "备用模块" }).first();
if (await summary.count()) {
@@ -22,3 +24,18 @@ export async function openNavLink(page: Page, name: string | RegExp): Promise<Lo
await expect(link).toBeVisible();
return link;
}
export async function openProfileSettings(page: Page, userDisplayName?: string) {
const profileTrigger = page.getByTestId(TEST_IDS.topbar.profileTrigger).first();
if (await profileTrigger.isVisible().catch(() => false)) {
await profileTrigger.click();
} else if (userDisplayName) {
await page.getByRole("button", { name: userDisplayName, exact: true }).first().click();
} else {
throw new Error("无法定位个人设置入口:缺少 topbar profile trigger");
}
await expect(page.getByRole("menuitem", { name: "个人设置" })).toBeVisible();
await page.getByRole("menuitem", { name: "个人设置" }).click();
await expect(page).toHaveURL(/\/settings\/profile/);
}
+20
查看文件
@@ -0,0 +1,20 @@
export const TEST_IDS = {
login: {
identifier: "login-identifier",
password: "login-password",
submit: "login-submit",
},
topbar: {
profileTrigger: "topbar-profile-trigger",
},
workflow: {
tasksTable: "workflow-tasks-table",
taskRow: "workflow-task-row",
detailLink: "workflow-task-detail-link",
summary: "workflow-task-summary",
approve: "workflow-task-approve",
},
audit: {
export: "audit-export",
},
} as const;