fix: restore web sentinel cadence and monitor hover
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p9-multi-web-probe-sentinel.
|
||||
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p10-monitor-web-aggregation.
|
||||
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-27-p11-monitor-web-observability-dashboard.
|
||||
// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-27-p12-cadence-scheduler-monitor-web.
|
||||
// Responsibility: YAML-first CI/CD, image, GitOps and Argo command plan for the web-probe sentinel.
|
||||
import { createHash, randomUUID } from "node:crypto";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
@@ -1999,6 +2000,24 @@ for (let attempt = 1; attempt <= maxNavigationAttempts; attempt += 1) {
|
||||
await page.waitForTimeout(750 * attempt);
|
||||
}
|
||||
|
||||
await page.evaluate(() => {
|
||||
const detailPane = document.querySelector(".workspace-grid .pane-detail");
|
||||
if (detailPane instanceof HTMLElement) detailPane.scrollTop = Math.min(96, Math.max(0, detailPane.scrollHeight - detailPane.clientHeight));
|
||||
}).catch(() => {});
|
||||
await page.waitForTimeout(150);
|
||||
|
||||
const trendHoverPoint = await page.evaluate(() => {
|
||||
const target = document.querySelector(".trend-dot-hit .trend-dot-red") || document.querySelector(".trend-dot-hit .trend-dot-warning");
|
||||
if (!(target instanceof SVGElement)) return null;
|
||||
const rect = target.getBoundingClientRect();
|
||||
if (rect.width <= 0 || rect.height <= 0) return null;
|
||||
return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
|
||||
}).catch(() => null);
|
||||
if (trendHoverPoint) {
|
||||
await page.mouse.move(trendHoverPoint.x, trendHoverPoint.y);
|
||||
await page.waitForTimeout(250);
|
||||
}
|
||||
|
||||
if (captureScreenshot && screenshotPath) {
|
||||
await page.screenshot({ path: screenshotPath, fullPage, animations: "disabled" }).catch((error) => {
|
||||
pageErrors.push({ message: "screenshot failed: " + String(error?.message || error).slice(0, 400) });
|
||||
@@ -2012,9 +2031,12 @@ const dom = await page.evaluate(() => {
|
||||
const shell = document.querySelector("[data-monitor-shell='true']");
|
||||
const error = document.querySelector("#monitor-web-error");
|
||||
const trend = document.querySelector("[data-monitor-trend-curve]");
|
||||
const trendTooltip = document.querySelector("[data-monitor-trend-tooltip='true']");
|
||||
const timeline = document.querySelector("[data-monitor-timeline='true']");
|
||||
const workspace = document.querySelector("[data-monitor-independent-scroll='true']");
|
||||
const panes = Array.from(document.querySelectorAll(".workspace-grid .pane"));
|
||||
const detailPane = document.querySelector(".workspace-grid .pane-detail");
|
||||
const detailHeader = document.querySelector("#monitor-web-root > div > section.workspace-grid > main > div.pane-header");
|
||||
const doc = document.documentElement;
|
||||
const body = document.body;
|
||||
const viewport = { width: window.innerWidth, height: window.innerHeight };
|
||||
@@ -2063,6 +2085,8 @@ const dom = await page.evaluate(() => {
|
||||
runRows: document.querySelectorAll(".run-list .run-row").length,
|
||||
findingItems: document.querySelectorAll(".finding-list .finding-card").length,
|
||||
trendCurve: Boolean(trend),
|
||||
trendDotCount: document.querySelectorAll(".trend-dot-hit").length,
|
||||
trendTooltip: tooltipSummary(trendTooltip),
|
||||
trendPanelText: text("#trend-heading"),
|
||||
timelineItems: document.querySelectorAll(".timeline-list .timeline-item").length,
|
||||
timelineVisible: Boolean(timeline),
|
||||
@@ -2089,6 +2113,7 @@ const dom = await page.evaluate(() => {
|
||||
const style = window.getComputedStyle(pane);
|
||||
return style.overflowY === "auto" || style.overflowY === "scroll";
|
||||
}),
|
||||
stickyHeader: stickyHeaderSummary(detailPane, detailHeader),
|
||||
},
|
||||
layout: {
|
||||
viewport,
|
||||
@@ -2098,6 +2123,46 @@ const dom = await page.evaluate(() => {
|
||||
overflow,
|
||||
},
|
||||
};
|
||||
|
||||
function tooltipSummary(element) {
|
||||
const body = String(element?.textContent || "").replace(/\s+/g, " ").trim();
|
||||
return {
|
||||
visible: Boolean(element && body.length > 0),
|
||||
text: body.slice(0, 240),
|
||||
hasValues: /红色\s+\d+/u.test(body) && /警告\s+\d+/u.test(body) && /总量\s+\d+/u.test(body),
|
||||
hasTime: /UTC/u.test(body) || /\d{4}-\d{2}-\d{2}/u.test(body),
|
||||
};
|
||||
}
|
||||
|
||||
function stickyHeaderSummary(pane, header) {
|
||||
if (!(pane instanceof HTMLElement) || !(header instanceof HTMLElement)) {
|
||||
return { present: false, coversScroll: false, backgroundOpaque: false, detailScrollTop: null };
|
||||
}
|
||||
const rect = header.getBoundingClientRect();
|
||||
const style = window.getComputedStyle(header);
|
||||
const sampleX = Math.round(rect.left + Math.min(32, Math.max(2, rect.width / 2)));
|
||||
const sampleY = Math.round(rect.top + Math.min(12, Math.max(2, rect.height / 2)));
|
||||
const topElement = document.elementFromPoint(sampleX, sampleY);
|
||||
return {
|
||||
present: true,
|
||||
detailScrollTop: pane.scrollTop,
|
||||
headerTop: Math.round(rect.top),
|
||||
headerBottom: Math.round(rect.bottom),
|
||||
zIndex: style.zIndex,
|
||||
backgroundColor: style.backgroundColor,
|
||||
coversScroll: Boolean(topElement && header.contains(topElement)),
|
||||
backgroundOpaque: backgroundIsOpaque(style.backgroundColor),
|
||||
topElementClass: String(topElement?.className || "").slice(0, 80),
|
||||
};
|
||||
}
|
||||
|
||||
function backgroundIsOpaque(value) {
|
||||
const rgba = /rgba?\(([^)]+)\)/u.exec(value);
|
||||
if (rgba === null) return value.length > 0 && value !== "transparent";
|
||||
const parts = rgba[1].split(",").map((part) => part.trim());
|
||||
if (parts.length < 4) return true;
|
||||
return Number(parts[3]) >= 0.99;
|
||||
}
|
||||
});
|
||||
|
||||
const consoleErrors = consoleMessages.filter((item) => item.type === "error");
|
||||
@@ -2109,8 +2174,12 @@ const ok = !navigationError
|
||||
&& dom.ready === true
|
||||
&& dom.errorVisible !== true
|
||||
&& dom.trendCurve === true
|
||||
&& (dom.trendDotCount === 0 || (dom.trendTooltip?.visible === true && dom.trendTooltip?.hasValues === true && dom.trendTooltip?.hasTime === true))
|
||||
&& dom.timelineVisible === true
|
||||
&& dom.scrollModel?.independentScroll === true
|
||||
&& dom.scrollModel?.stickyHeader?.present === true
|
||||
&& dom.scrollModel?.stickyHeader?.coversScroll === true
|
||||
&& dom.scrollModel?.stickyHeader?.backgroundOpaque === true
|
||||
&& dom.layout?.horizontalOverflow !== true
|
||||
&& pageErrors.length === 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user