diff --git a/scripts/capture-game-lineage-visual.mjs b/scripts/capture-game-lineage-visual.mjs index ad4eb34c7..19a82d0fd 100644 --- a/scripts/capture-game-lineage-visual.mjs +++ b/scripts/capture-game-lineage-visual.mjs @@ -652,6 +652,38 @@ async function captureNarrowBreakpoints({ browser, lineageUrl, shotDir }) { (await page.locator('.game-lineage-panel--sheet').count()) === 0; } check(`${width}px:底部 sheet 可关闭(遮罩按钮或 Esc)`, sheetClosed); + + // 面包屑(锁定路径):窄屏上「锁定」由大纲行触发(画布卡片在窄屏是紧凑卡片, + // 整个卡片体都是「打开详情」按钮,点它只会跳详情——见下方图谱视图段的备注), + // 所以这里在大纲形态下再点一行,断言面包屑出现且当前项已被滚进视口。 + await page + .locator('.lineage-outline__row .lineage-outline__main') + .first() + .click(); + await page.waitForTimeout(1200); + const outlineCrumb = await page.evaluate(() => { + const items = [ + ...document.querySelectorAll('.game-lineage-breadcrumb__crumb'), + ]; + if (items.length === 0) return null; + const box = items[items.length - 1].getBoundingClientRect(); + return { + count: items.length, + insideViewport: box.left >= -1 && box.right <= window.innerWidth + 1, + left: Math.round(box.left), + right: Math.round(box.right), + innerWidth: window.innerWidth, + }; + }); + check( + `${width}px:大纲行锁定后面包屑出现且当前项被滚进视口`, + Boolean(outlineCrumb) && + outlineCrumb.count >= 1 && + outlineCrumb.insideViewport, + JSON.stringify(outlineCrumb), + ); + await take('breadcrumb'); + // 画布检查前重载一次:保证不残留 sheet 与滚动位置,切形态的判断才干净。 await page.reload({ waitUntil: 'commit', timeout: 120_000 }); await page.waitForFunction( @@ -678,6 +710,19 @@ async function captureNarrowBreakpoints({ browser, lineageUrl, shotDir }) { if (!canvasEl) return null; const canvasBox = canvasEl.getBoundingClientRect(); const anchorBox = anchor?.getBoundingClientRect(); + const visibleNodes = [ + ...document.querySelectorAll('.game-lineage-node'), + ].filter((node) => { + const box = node.getBoundingClientRect(); + return ( + box.left >= canvasBox.left - 2 && + box.right <= canvasBox.right + 2 && + box.top >= canvasBox.top - 2 && + box.bottom <= canvasBox.bottom + 2 + ); + }).length; + const totalNodes = + document.querySelectorAll('.game-lineage-node').length; return { anchorFound: Boolean(anchor), anchorInside: @@ -686,6 +731,8 @@ async function captureNarrowBreakpoints({ browser, lineageUrl, shotDir }) { anchorBox.right <= canvasBox.right + 2 && anchorBox.top >= canvasBox.top - 2 && anchorBox.bottom <= canvasBox.bottom + 2, + visibleNodes, + totalNodes, zoom: document .querySelector('.game-lineage-zoom') ?.textContent?.trim(), @@ -698,34 +745,9 @@ async function captureNarrowBreakpoints({ browser, lineageUrl, shotDir }) { JSON.stringify(canvas), ); await take('canvas'); - - // 选中一个节点 → 面包屑;当前面包屑必须已被滚进视口 - const target = page.locator('.game-lineage-node').nth(1); - if ((await target.count()) > 0) { - await target.click({ position: { x: 6, y: 6 } }); - await page.waitForTimeout(1200); - const crumb = await page.evaluate(() => { - const items = [ - ...document.querySelectorAll('.game-lineage-breadcrumb__crumb'), - ]; - if (items.length === 0) return null; - const box = items[items.length - 1].getBoundingClientRect(); - return { - count: items.length, - right: Math.round(box.right), - left: Math.round(box.left), - innerWidth: window.innerWidth, - insideViewport: - box.left >= -1 && box.right <= window.innerWidth + 1, - }; - }); - check( - `${width}px:选中节点后面包屑出现且当前项被滚进视口`, - Boolean(crumb) && crumb.count >= 1 && crumb.insideViewport, - JSON.stringify(crumb), - ); - await take('breadcrumb'); - } + console.log( + `[narrow ${width}] 备注:图谱视图里点卡片会跳详情(窄屏紧凑卡片整块是「打开详情」按钮,没有可锁定区域)——信息面板/面包屑改由大纲形态验证。`, + ); } } finally { await context.close();