R97 B6 补充高频页面视觉回归证据

这个提交包含在:
2026-05-06 17:57:11 +08:00
父节点 705cf1e361
当前提交 adb41db725
共修改 4 个文件,包含 82 行新增和 9 行删除
@@ -373,7 +373,7 @@ test.describe("R89 企业微信移动入口", () => {
await expect(page.getByTestId("login-wecom-primary-panel")).toBeVisible();
await expect(page.getByTestId("wecom-entry-primary")).toBeVisible();
await expect(page.getByTestId("login-password-primary-panel")).toHaveCount(0);
await attachScreenshot(page, testInfo, "r96-wecom-login.png");
await attachScreenshot(page, testInfo, "r97-wecom-login.png");
await page.getByTestId("wecom-entry-primary").click();
await expect(page).toHaveURL(/\/api\/auth\/wecom\/login\?returnTo=%2Fmobile/);
@@ -390,7 +390,7 @@ test.describe("R89 移动底部导航与核心页面", () => {
await expect(page).toHaveURL(/\/mobile$/);
await expect(page.getByTestId("mobile-today-focus")).toBeVisible();
await expect(page.getByTestId("topbar-profile-trigger")).toBeHidden();
await attachScreenshot(page, testInfo, "r96-mobile-today.png");
await attachScreenshot(page, testInfo, "r97-mobile-today.png");
await expect(page.getByTestId("mobile-nav-home")).toBeVisible();
await expect(page.getByTestId("mobile-nav-approvals")).toBeVisible();
@@ -404,7 +404,7 @@ test.describe("R89 移动底部导航与核心页面", () => {
await expect(page.getByTestId("mobile-approvals-detail")).toBeVisible();
await expect(page.getByTestId("mobile-approvals-approve")).toBeVisible();
await expect(page.getByTestId("mobile-approvals-reject")).toBeVisible();
await attachScreenshot(page, testInfo, "r96-mobile-approvals.png");
await attachScreenshot(page, testInfo, "r97-mobile-approvals.png");
await page.getByTestId("mobile-nav-capture").click();
await expect(page).toHaveURL(/\/mobile\/capture/);
@@ -415,7 +415,7 @@ test.describe("R89 移动底部导航与核心页面", () => {
buffer: Buffer.from("%PDF-1.4\n% R89"),
});
await expect(page.getByTestId("mobile-capture-upload")).toBeEnabled();
await attachScreenshot(page, testInfo, "r96-mobile-capture.png");
await attachScreenshot(page, testInfo, "r97-mobile-capture.png");
await page.getByTestId("mobile-nav-me").click();
await expect(page).toHaveURL(/\/mobile\/me/);
@@ -1,4 +1,4 @@
import { expect, test, type Page, type Route } from "@playwright/test";
import { expect, test, type Page, type Route, type TestInfo } from "@playwright/test";
import { ADMIN } from "./helpers/auth";
import { TEST_IDS } from "./helpers/testIds";
@@ -15,6 +15,13 @@ async function fulfillJson(route: Route, data: unknown) {
});
}
async function attachScreenshot(page: Page, testInfo: TestInfo, name: string) {
await testInfo.attach(name, {
body: await page.screenshot({ fullPage: true }),
contentType: "image/png",
});
}
async function mockAuthenticatedShell(page: Page) {
await page.route((url) => url.pathname === "/api/auth/sso/providers", (route) => fulfillJson(route, []));
await page.route((url) => url.pathname === "/api/auth/wecom/config", (route) =>
@@ -289,7 +296,7 @@ test.describe("R92 手机端票据与报销可用性", () => {
await mockReimbursements(page);
});
test("报销草稿在手机视口使用卡片并暴露继续编辑入口", async ({ page }) => {
test("报销草稿在手机视口使用卡片并暴露继续编辑入口", async ({ page }, testInfo) => {
await loginThenUseMobileViewport(page);
await page.goto("/reimbursements?status=draft&scope=own");
@@ -302,9 +309,11 @@ test.describe("R92 手机端票据与报销可用性", () => {
const box = await editLink.boundingBox();
expect(box).not.toBeNull();
expect((box?.x ?? 0) + (box?.width ?? 0)).toBeLessThanOrEqual(390);
await attachScreenshot(page, testInfo, "r97-reimbursements-mobile-draft.png");
});
test("票据中心手机视口可批量选择并顺序上传", async ({ page }) => {
test("票据中心手机视口可批量选择并顺序上传", async ({ page }, testInfo) => {
const uploadCounter = { value: 0 };
await mockInvoicePool(page, uploadCounter);
await loginThenUseMobileViewport(page);
@@ -312,6 +321,10 @@ test.describe("R92 手机端票据与报销可用性", () => {
await expect(page.getByTestId("invoice-mobile-row")).toBeVisible();
await expect(page.getByTestId("invoice-pool-table")).toBeHidden();
await page.getByTestId("invoice-mobile-detail-button").click();
await expect(page.getByTestId("invoice-detail-panel")).toBeVisible();
await expect(page.getByText("票据详情")).toBeVisible();
await attachScreenshot(page, testInfo, "r97-invoice-pool-mobile.png");
await page.getByTestId("invoice-upload-file").setInputFiles([
{ name: "invoice-a.pdf", mimeType: "application/pdf", buffer: Buffer.from("%PDF-a") },
@@ -323,7 +336,7 @@ test.describe("R92 手机端票据与报销可用性", () => {
await expect.poll(() => uploadCounter.value).toBe(2);
});
test("手机票据上传页支持一次选择多张并逐张上传", async ({ page }) => {
test("手机票据上传页支持一次选择多张并逐张上传", async ({ page }, testInfo) => {
const uploadCounter = { value: 0 };
await mockInvoicePool(page, uploadCounter);
await loginThenUseMobileViewport(page);
@@ -334,6 +347,7 @@ test.describe("R92 手机端票据与报销可用性", () => {
{ name: "mobile-b.jpg", mimeType: "image/jpeg", buffer: Buffer.from("mobile-b") },
]);
await expect(page.getByText("已选择 2 个")).toBeVisible();
await attachScreenshot(page, testInfo, "r97-mobile-capture-multi-upload.png");
await page.getByTestId("mobile-capture-upload").click();
await expect.poll(() => uploadCounter.value).toBe(2);
+18 -1
查看文件
@@ -22,7 +22,7 @@ const visualMe = {
directManagerId: null,
status: "active",
notificationPushEnabled: true,
roleCodes: ["employee"],
roleCodes: ["manager"],
profileCompleteness: {
hasEmergencyContact: true,
hasBankAccount: true,
@@ -156,6 +156,7 @@ async function mockVisualApis(page: Page) {
createdAt: "2026-05-06T09:00:00.000Z",
completedAt: null,
workflowInstance: { entityType: "reimbursement", entityId: "rb-r96" },
allowedActions: ["approve"],
},
],
total: 1,
@@ -242,4 +243,20 @@ test.describe("visual shell", () => {
await attachScreenshot(page, testInfo, "mobile-today.png");
});
test("审批待办手机卡片布局基线", async ({ page }, testInfo) => {
await mockVisualApis(page);
await page.setViewportSize({ width: 390, height: 844 });
await page.goto("/login");
await page.getByTestId("login-identifier").fill("[email protected]");
await page.getByTestId("login-password").fill("EmployeePassword1234");
await page.getByTestId("login-submit").click();
await page.goto("/workflow/tasks");
await expect(page.getByTestId("workflow-tasks-mobile-list")).toBeVisible();
await expect(page.getByTestId("workflow-tasks-table")).toBeHidden();
await expect(page.getByRole("link", { name: "详情" })).toBeVisible();
await attachScreenshot(page, testInfo, "r97-workflow-tasks-mobile.png");
});
});