UI6 修复 iPhone11 企业微信移动导航
这个提交包含在:
@@ -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");
|
||||
|
||||
在新工单中引用
屏蔽一个用户