diff --git a/scripts/src/hwlab-node-web-sentinel-cicd.ts b/scripts/src/hwlab-node-web-sentinel-cicd.ts index 3ae10dce..69f4b7bc 100644 --- a/scripts/src/hwlab-node-web-sentinel-cicd.ts +++ b/scripts/src/hwlab-node-web-sentinel-cicd.ts @@ -2479,6 +2479,87 @@ const dom = await page.evaluate(async () => { } }); +const runFilterProbe = await page.evaluate(async () => { + const requestedRunId = "sentinel-run-mqxi16vo-39b603ae"; + const numberValue = (value) => Number.isFinite(Number(value)) ? Number(value) : 0; + const rowSeverity = (row) => { + const raw = String(row?.maxSeverity || row?.checkLevel || row?.severity || row?.level || "").toLowerCase(); + if (["red", "critical", "error", "blocked", "failed"].includes(raw)) return "red"; + if (["warning", "warn", "amber"].includes(raw)) return "warning"; + if (["info", "notice"].includes(raw)) return "info"; + return "healthy"; + }; + const sampleCount = (row) => Number.isFinite(Number(row?.count)) ? Number(row.count) : 1; + const summarizeRows = (rows) => { + const errorRows = rows.filter((row) => rowSeverity(row) === "red"); + const warningRows = rows.filter((row) => rowSeverity(row) === "warning"); + const sum = (items) => items.reduce((total, row) => total + sampleCount(row), 0); + return { + typeCount: rows.length, + alertTypeCount: errorRows.length + warningRows.length, + errorSamples: sum(errorRows), + warningSamples: sum(warningRows), + alertSamples: sum(errorRows) + sum(warningRows), + }; + }; + const panelCounts = () => { + const panel = document.querySelector("[data-monitor-checks='true']"); + return { + present: Boolean(panel), + runId: panel?.getAttribute("data-check-run-id") || null, + typeCount: numberValue(panel?.getAttribute("data-check-type-count")), + alertTypeCount: numberValue(panel?.getAttribute("data-check-alert-type-count")), + errorSamples: numberValue(panel?.getAttribute("data-check-error-samples")), + warningSamples: numberValue(panel?.getAttribute("data-check-warning-samples")), + alertSamples: numberValue(panel?.getAttribute("data-check-alert-samples")), + visibleCardCount: document.querySelectorAll(".finding-list .finding-card").length, + visibleAlertSamples: numberValue(panel?.getAttribute("data-visible-check-alert-samples")), + }; + }; + const waitForRun = async (runId) => { + for (let index = 0; index < 30; index += 1) { + const current = panelCounts(); + if (current.runId === runId && current.present === true) return true; + await new Promise((resolve) => window.setTimeout(resolve, 100)); + } + return false; + }; + const select = document.querySelector("select[aria-label='选择运行记录']"); + if (!(select instanceof HTMLSelectElement)) { + return { ok: false, requestedRunId, reason: "run-select-missing" }; + } + const requestedOption = Array.from(select.options).find((option) => option.value === requestedRunId); + const fallbackOption = requestedOption || select.options[Math.min(2, Math.max(0, select.options.length - 1))] || select.options[0] || null; + const targetRunId = fallbackOption?.value || requestedRunId; + if (!targetRunId) return { ok: false, requestedRunId, reason: "run-option-missing" }; + select.value = targetRunId; + select.dispatchEvent(new Event("change", { bubbles: true })); + const panelReady = await waitForRun(targetRunId); + const detailPayload = await fetch("/api/runs/" + encodeURIComponent(targetRunId), { cache: "no-store" }).then((item) => item.json()).catch(() => null); + const detailRows = Array.isArray(detailPayload?.findings) ? detailPayload.findings : []; + const expected = summarizeRows(detailRows); + const observed = panelCounts(); + const matchesRunDetail = observed.runId === targetRunId + && observed.typeCount === expected.typeCount + && observed.alertTypeCount === expected.alertTypeCount + && observed.errorSamples === expected.errorSamples + && observed.warningSamples === expected.warningSamples + && observed.alertSamples === expected.alertSamples + && observed.visibleCardCount === expected.alertTypeCount + && observed.visibleAlertSamples === expected.alertSamples; + return { + ok: panelReady === true && matchesRunDetail === true, + requestedRunId, + requestedOptionPresent: Boolean(requestedOption), + targetRunId, + panelReady, + observed, + expected, + matchesRunDetail, + }; +}); +dom.runFilterProbe = runFilterProbe; + const consoleErrors = consoleMessages.filter((item) => item.type === "error"); const ok = !navigationError && httpStatus !== null @@ -2492,6 +2573,8 @@ const ok = !navigationError && dom.chartCounts?.matchesLatestRun === true && dom.checkScope?.matchesLatestRun === true && dom.checkScope?.matchesRunDetail === true + && dom.runFilterProbe?.ok === true + && dom.runFilterProbe?.requestedOptionPresent === true && dom.checkScope?.belowWorkspace === true && dom.checkScope?.fullWidth === true && dom.scopeLabels?.latestPointLegend === true @@ -4797,6 +4880,9 @@ function renderDashboardResult(result: Record): string { const latestRunCounts = record(dom.latestRunCounts); const latestDetailSummary = record(dom.latestDetailSummary); const checkScope = record(dom.checkScope); + const runFilterProbe = record(dom.runFilterProbe); + const runFilterObserved = record(runFilterProbe.observed); + const runFilterExpected = record(runFilterProbe.expected); const overviewSamples = record(dom.overviewSamples); const screenshot = record(result.screenshot); const remote = record(result.remote); @@ -4860,6 +4946,17 @@ function renderDashboardResult(result: Record): string { checkScope.fullWidth ?? "-", ]]), "", + table(["FILTER_RUN", "FILTER_OPTION", "FILTER_TYPES", "FILTER_ALERT_TYPES", "FILTER_ERR", "FILTER_WARN", "FILTER_TOTAL", "FILTER_MATCH_DETAIL"], [[ + runFilterProbe.targetRunId ?? "-", + runFilterProbe.requestedOptionPresent ?? "-", + `${runFilterObserved.typeCount ?? "-"}/${runFilterExpected.typeCount ?? "-"}`, + `${runFilterObserved.alertTypeCount ?? "-"}/${runFilterExpected.alertTypeCount ?? "-"}`, + runFilterObserved.errorSamples ?? "-", + runFilterObserved.warningSamples ?? "-", + runFilterObserved.alertSamples ?? "-", + runFilterProbe.matchesRunDetail ?? "-", + ]]), + "", table(["VIEWPORT", "DOC", "H_OVERFLOW", "OVERFLOW_COUNT"], [[ result.viewport, `${record(layout.documentSize).width ?? "-"}x${record(layout.documentSize).height ?? "-"}`,