MME6 优化移动我的页自适应视觉
这个提交包含在:
@@ -406,6 +406,38 @@ async function collectRenderingMetrics(page: Page) {
|
||||
document.querySelector("[data-testid='mobile-reimbursement-sticky-invoice-add']"),
|
||||
document.querySelector("[data-testid='reimbursement-submit']"),
|
||||
].filter(Boolean).map((element) => element!.getBoundingClientRect());
|
||||
const mobileShell = document.querySelector(".hyb-mobile-shell");
|
||||
const avatarSlotRect = document.querySelector("[data-testid='mobile-me-avatar-slot']")?.getBoundingClientRect();
|
||||
const profileNameRect = document.querySelector("[data-testid='mobile-me-profile-name']")?.getBoundingClientRect();
|
||||
const actionGaps = Array.from(document.querySelectorAll("[data-testid='mobile-me-action-link']")).map((element) => {
|
||||
const iconRect = element.querySelector(".mobile-me-action-icon")?.getBoundingClientRect();
|
||||
const copyRect = element.querySelector(".mobile-me-action-copy")?.getBoundingClientRect();
|
||||
const linkRect = element.getBoundingClientRect();
|
||||
return {
|
||||
gap: iconRect && copyRect ? copyRect.left - iconRect.right : 0,
|
||||
iconWithin:
|
||||
Boolean(iconRect) &&
|
||||
iconRect!.left >= linkRect.left - 1 &&
|
||||
iconRect!.right <= linkRect.right + 1 &&
|
||||
iconRect!.top >= linkRect.top - 1 &&
|
||||
iconRect!.bottom <= linkRect.bottom + 1,
|
||||
copyWithin:
|
||||
Boolean(copyRect) &&
|
||||
copyRect!.left >= linkRect.left - 1 &&
|
||||
copyRect!.right <= linkRect.right + 1 &&
|
||||
copyRect!.top >= linkRect.top - 1 &&
|
||||
copyRect!.bottom <= linkRect.bottom + 1,
|
||||
};
|
||||
});
|
||||
const moreLinkRects = Array.from(document.querySelectorAll("[data-testid='mobile-more-links'] > *")).map((element) =>
|
||||
element.getBoundingClientRect(),
|
||||
);
|
||||
const mobileSectionHasDecorativeTopLine = Array.from(document.querySelectorAll(".hyb-mobile-shell .section-panel")).some((element) => {
|
||||
const before = window.getComputedStyle(element, "::before");
|
||||
const opacity = Number.parseFloat(before.opacity || "1");
|
||||
const height = Number.parseFloat(before.height || "0");
|
||||
return before.display !== "none" && before.visibility !== "hidden" && opacity > 0.01 && height > 0;
|
||||
});
|
||||
return {
|
||||
viewportWidth,
|
||||
scrollWidth: Math.max(document.documentElement.scrollWidth, document.body?.scrollWidth ?? 0),
|
||||
@@ -419,6 +451,18 @@ async function collectRenderingMetrics(page: Page) {
|
||||
stickyButtonsSameRow:
|
||||
stickyButtons.length === 2 ? Math.abs(stickyButtons[0].top - stickyButtons[1].top) <= 2 : stickyButtons.length <= 1,
|
||||
stickyButtonMinHeight: stickyButtons.length ? Math.min(...stickyButtons.map((rect) => rect.height)) : 0,
|
||||
mobileMe: {
|
||||
shellScoped: Boolean(mobileShell),
|
||||
profileGap: avatarSlotRect && profileNameRect ? profileNameRect.left - avatarSlotRect.right : null,
|
||||
actionGapMin: actionGaps.length ? Math.min(...actionGaps.map((item) => item.gap)) : null,
|
||||
actionGapMax: actionGaps.length ? Math.max(...actionGaps.map((item) => item.gap)) : null,
|
||||
actionSlotsWithin: actionGaps.every((item) => item.iconWithin && item.copyWithin),
|
||||
moreLinksTwoColumns:
|
||||
moreLinkRects.length >= 2
|
||||
? Math.abs(moreLinkRects[0].top - moreLinkRects[1].top) <= 4 && moreLinkRects[0].right <= moreLinkRects[1].left
|
||||
: true,
|
||||
hasDecorativeTopLine: mobileSectionHasDecorativeTopLine,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -474,7 +518,18 @@ async function exerciseMobileRendering(page: Page, key: string, label: string) {
|
||||
|
||||
await page.goto("/mobile/me");
|
||||
await expect(page.getByTestId("mobile-more-links")).toBeVisible();
|
||||
await expectRenderingStable(page, label, `${key}-mobile-me`);
|
||||
const meMetrics = await expectRenderingStable(page, label, `${key}-mobile-me`);
|
||||
const minSlotGap = meMetrics.viewportWidth >= 390 ? 14 : 12;
|
||||
expect(meMetrics.mobileMe.shellScoped, `${label} mobile shell scope`).toBe(true);
|
||||
expect(meMetrics.mobileMe.profileGap, `${label} profile avatar/text gap`).not.toBeNull();
|
||||
expect(meMetrics.mobileMe.profileGap ?? 0, `${label} profile avatar/text gap min`).toBeGreaterThanOrEqual(minSlotGap);
|
||||
expect(meMetrics.mobileMe.profileGap ?? 0, `${label} profile avatar/text gap max`).toBeLessThanOrEqual(20);
|
||||
expect(meMetrics.mobileMe.actionGapMin, `${label} action icon/text gap min`).not.toBeNull();
|
||||
expect(meMetrics.mobileMe.actionGapMin ?? 0, `${label} action icon/text gap min`).toBeGreaterThanOrEqual(minSlotGap);
|
||||
expect(meMetrics.mobileMe.actionGapMax ?? 0, `${label} action icon/text gap max`).toBeLessThanOrEqual(18);
|
||||
expect(meMetrics.mobileMe.actionSlotsWithin, `${label} action slots within link`).toBe(true);
|
||||
expect(meMetrics.mobileMe.moreLinksTwoColumns, `${label} more links keep two columns`).toBe(true);
|
||||
expect(meMetrics.mobileMe.hasDecorativeTopLine, `${label} mobile section top line hidden`).toBe(false);
|
||||
|
||||
await page.goto("/mobile/reimbursements/wcm6-reimbursement");
|
||||
await expect(page.getByTestId("mobile-reimbursement-detail")).toBeVisible();
|
||||
|
||||
在新工单中引用
屏蔽一个用户