UI6 修复 iPhone11 企业微信移动导航

这个提交包含在:
2026-05-11 11:36:01 +08:00
父节点 a9128e50d5
当前提交 16588b0dae
共修改 8 个文件,包含 75 行新增和 26 行删除
@@ -3,7 +3,7 @@ import path from "node:path";
import { expect, test, type Page, type Route } from "@playwright/test";
const ROOT_DIR = path.resolve(process.cwd(), "..");
const SCREENSHOT_DIR = path.join(ROOT_DIR, "output/playwright/r5-real-device-feedback-mobile-ux");
const SCREENSHOT_DIR = path.join(ROOT_DIR, "output/playwright/r6-iphone11-wecom-mobile-layout-hotfix");
const DEVICE_CASES = [
{
key: "iphone11-ios14",
@@ -164,6 +164,26 @@ async function mockApis(page: Page) {
return;
}
if (pathName === "/api/workflow/tasks" && request.method() === "GET") {
await fulfillJson(route, {
page: 1,
pageSize: 100,
total: 0,
items: [],
});
return;
}
if (pathName === "/api/workflow/approvers" && request.method() === "GET") {
await fulfillJson(route, {
page: 1,
pageSize: 20,
total: 0,
items: [],
});
return;
}
if (pathName === "/api/expense-types") {
await fulfillJson(route, {
page: 1,
@@ -219,11 +239,22 @@ async function collectMobileMetrics(page: Page) {
const navItems = ["home", "approvals", "reimbursements", "me"].map((key) => {
const element = document.querySelector(`[data-testid='mobile-nav-${key}']`);
const rect = element?.getBoundingClientRect();
const centerX = rect ? rect.left + rect.width / 2 : 0;
const centerY = rect ? rect.top + rect.height / 2 : 0;
const hit = rect ? document.elementFromPoint(centerX, centerY) : null;
const hitOwner = hit instanceof Element ? hit.closest(`[data-testid='mobile-nav-${key}']`) : null;
return {
key,
visible: Boolean(rect && rect.width > 0 && rect.height > 0),
width: rect?.width ?? 0,
height: rect?.height ?? 0,
centerX,
centerY,
hitWithin: Boolean(element && hitOwner === element),
hitTarget:
hit instanceof HTMLElement
? hit.dataset.testid ?? hit.getAttribute("aria-label") ?? hit.tagName.toLowerCase()
: null,
};
});
const stickyActions = document.querySelector("[data-testid='mobile-reimbursement-sticky-actions']");
@@ -287,6 +318,19 @@ test.describe("R5 真机反馈移动交互", () => {
expect(item.visible, `${device.label} ${item.key} nav item visible`).toBe(true);
expect(item.width, `${device.label} ${item.key} nav item touch width`).toBeGreaterThanOrEqual(44);
expect(item.height, `${device.label} ${item.key} nav item touch height`).toBeGreaterThanOrEqual(44);
expect(item.hitWithin, `${device.label} ${item.key} nav item hit target: ${item.hitTarget}`).toBe(true);
}
await page.getByTestId("mobile-nav-approvals").click();
await expect(page).toHaveURL(/\/mobile\/approvals$/);
await expect(page.getByTestId("mobile-approvals-list")).toBeVisible();
await page.screenshot({ path: screenshotPath(`${device.key}-mobile-approvals-tab-hit`) });
const approvalsMetrics = await collectMobileMetrics(page);
expect(approvalsMetrics.bottomNavVisible).toBe(true);
expect(approvalsMetrics.bottomNavFixed).toBe(true);
expect(approvalsMetrics.scrollWidth).toBeLessThanOrEqual(approvalsMetrics.width + 2);
for (const item of approvalsMetrics.navItems) {
expect(item.hitWithin, `${device.label} ${item.key} approvals page hit target: ${item.hitTarget}`).toBe(true);
}
await page.goto("/mobile/reimbursements");