優化活動頁手機商品列表
All checks were successful
CD Pipeline / deploy (push) Successful in 58s

This commit is contained in:
OoO
2026-05-13 23:35:37 +08:00
parent 42de2e4d3f
commit 15b5b79a51
4 changed files with 115 additions and 20 deletions

View File

@@ -105,6 +105,7 @@ function parseArgs(argv) {
routes: [],
viewports: DEFAULT_VIEWPORTS,
timeoutMs: 30000,
settleMs: 350,
maxOverflow: 1,
screenshotDir: '',
json: false,
@@ -126,6 +127,8 @@ function parseArgs(argv) {
options.viewports = [];
} else if (arg === '--timeout') {
options.timeoutMs = parseInt(argv[++i], 10) * 1000;
} else if (arg === '--settle-ms') {
options.settleMs = parseInt(argv[++i], 10);
} else if (arg === '--max-overflow') {
options.maxOverflow = parseInt(argv[++i], 10);
} else if (arg === '--screenshot-dir') {
@@ -159,6 +162,7 @@ Options:
--viewport name=WxH Add a viewport
--clear-default-viewports Use only custom --viewport entries
--timeout SEC Navigation timeout, default 30
--settle-ms MS Fixed post-DOM layout settle wait, default 350
--max-overflow PX Allowed body overflow, default 1
--screenshot-dir DIR Save failure screenshots
--json Print JSON summary
@@ -276,14 +280,20 @@ async function main() {
const browser = await chromium.launch(launchOptions);
const results = [];
const pages = new Map();
try {
for (const viewport of options.viewports) {
const page = await browser.newPage({
viewport: { width: viewport.width, height: viewport.height },
deviceScaleFactor: 1,
});
pages.set(viewport.name, page);
}
for (const route of options.routes) {
for (const viewport of options.viewports) {
const page = await browser.newPage({
viewport: { width: viewport.width, height: viewport.height },
deviceScaleFactor: 1,
});
const page = pages.get(viewport.name);
const url = routeToUrl(options.baseUrl, route);
let status = 0;
let error = '';
@@ -291,7 +301,10 @@ async function main() {
try {
const response = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: options.timeoutMs });
await page.waitForLoadState('networkidle', { timeout: Math.min(options.timeoutMs, 5000) }).catch(() => {});
await page.evaluate(() => document.fonts && document.fonts.ready).catch(() => {});
if (options.settleMs > 0) {
await page.waitForTimeout(options.settleMs);
}
status = response ? response.status() : 0;
metrics = await collectMetrics(page, options.maxOverflow);
if (new URL(metrics.finalUrl).pathname === '/login') {
@@ -315,11 +328,10 @@ async function main() {
const file = `${safeName(route)}_${safeName(viewport.name)}.png`;
await page.screenshot({ path: path.join(options.screenshotDir, file), fullPage: false });
}
await page.close();
}
}
} finally {
await Promise.all(Array.from(pages.values()).map((page) => page.close().catch(() => {})));
await browser.close();
}