fix: 补齐 WebProbe 浏览器启动门禁
This commit is contained in:
@@ -20,6 +20,11 @@ const viewport = parseViewport(process.env.UNIDESK_WEB_PROBE_VIEWPORT || "1440x9
|
||||
const browserProxyMode = parseBrowserProxyMode(process.env.UNIDESK_WEB_PROBE_BROWSER_PROXY_MODE || "auto");
|
||||
const playwrightProxy = proxyConfigFromEnv(baseUrl);
|
||||
const chromiumLaunchOptions = chromiumLaunchOptionsForProxy(playwrightProxy);
|
||||
const screenshotMode = requiredEnum(process.env.UNIDESK_WEB_PROBE_SCREENSHOT_MODE, ["viewport"]);
|
||||
const maxNetworkRequestEntries = requiredPositiveInteger(process.env.UNIDESK_WEB_PROBE_MAX_NETWORK_REQUEST_ENTRIES, "UNIDESK_WEB_PROBE_MAX_NETWORK_REQUEST_ENTRIES");
|
||||
const maxNetworkRequestBytes = requiredPositiveInteger(process.env.UNIDESK_WEB_PROBE_MAX_NETWORK_REQUEST_BYTES, "UNIDESK_WEB_PROBE_MAX_NETWORK_REQUEST_BYTES");
|
||||
const maxNetworkFailureEntries = requiredPositiveInteger(process.env.UNIDESK_WEB_PROBE_MAX_NETWORK_FAILURE_ENTRIES, "UNIDESK_WEB_PROBE_MAX_NETWORK_FAILURE_ENTRIES");
|
||||
const maxNetworkFailureBytes = requiredPositiveInteger(process.env.UNIDESK_WEB_PROBE_MAX_NETWORK_FAILURE_BYTES, "UNIDESK_WEB_PROBE_MAX_NETWORK_FAILURE_BYTES");
|
||||
const artifactRecords = [];
|
||||
const readinessRecords = [];
|
||||
const stepRecords = [];
|
||||
@@ -1314,36 +1319,54 @@ function createNetworkTracker(targetPage, apiPattern) {
|
||||
const started = Date.now();
|
||||
const requests = [];
|
||||
const failures = [];
|
||||
let requestBytes = 0;
|
||||
let requestDropped = 0;
|
||||
let failureBytes = 0;
|
||||
let failureDropped = 0;
|
||||
const matches = createApiMatcher(apiPattern);
|
||||
const appendBounded = (items, item, kind) => {
|
||||
const bytes = Buffer.byteLength(JSON.stringify(item), "utf8");
|
||||
const entryLimit = kind === "request" ? maxNetworkRequestEntries : maxNetworkFailureEntries;
|
||||
const byteLimit = kind === "request" ? maxNetworkRequestBytes : maxNetworkFailureBytes;
|
||||
const usedBytes = kind === "request" ? requestBytes : failureBytes;
|
||||
if (items.length >= entryLimit || usedBytes + bytes > byteLimit) {
|
||||
if (kind === "request") requestDropped += 1;
|
||||
else failureDropped += 1;
|
||||
return;
|
||||
}
|
||||
items.push(item);
|
||||
if (kind === "request") requestBytes += bytes;
|
||||
else failureBytes += bytes;
|
||||
};
|
||||
const onRequest = (request) => {
|
||||
if (!matches(request.url())) return;
|
||||
requests.push({
|
||||
appendBounded(requests, {
|
||||
method: request.method(),
|
||||
path: urlPath(request.url()),
|
||||
atMs: Date.now() - started,
|
||||
});
|
||||
}, "request");
|
||||
};
|
||||
const onResponse = (response) => {
|
||||
if (!matches(response.url())) return;
|
||||
if (response.status() >= 400) {
|
||||
failures.push({
|
||||
appendBounded(failures, {
|
||||
type: "response",
|
||||
status: response.status(),
|
||||
statusText: response.statusText(),
|
||||
path: urlPath(response.url()),
|
||||
atMs: Date.now() - started,
|
||||
});
|
||||
}, "failure");
|
||||
}
|
||||
};
|
||||
const onRequestFailed = (request) => {
|
||||
if (!matches(request.url())) return;
|
||||
failures.push({
|
||||
appendBounded(failures, {
|
||||
type: "requestfailed",
|
||||
method: request.method(),
|
||||
path: urlPath(request.url()),
|
||||
failureText: request.failure()?.errorText ?? null,
|
||||
atMs: Date.now() - started,
|
||||
});
|
||||
}, "failure");
|
||||
};
|
||||
targetPage.on("request", onRequest);
|
||||
targetPage.on("response", onResponse);
|
||||
@@ -1356,6 +1379,10 @@ function createNetworkTracker(targetPage, apiPattern) {
|
||||
apiFailureCount: failures.length,
|
||||
apiRequests: requests.slice(0, 5),
|
||||
apiFailures: failures.slice(0, 5),
|
||||
apiRequestEvidenceBytes: requestBytes,
|
||||
apiRequestEvidenceDropped: requestDropped,
|
||||
apiFailureEvidenceBytes: failureBytes,
|
||||
apiFailureEvidenceDropped: failureDropped,
|
||||
}),
|
||||
dispose: () => {
|
||||
targetPage.off("request", onRequest);
|
||||
@@ -1476,7 +1503,7 @@ async function captureFailureScreenshot(name = "failure.png") {
|
||||
|
||||
async function screenshotPage(targetPage, name = "screenshot.png", options = {}) {
|
||||
const file = artifactPath(name);
|
||||
await targetPage.screenshot({ path: file, fullPage: true, ...options });
|
||||
await targetPage.screenshot({ path: file, fullPage: screenshotMode !== "viewport", ...options });
|
||||
return recordArtifact(file, "screenshot");
|
||||
}
|
||||
|
||||
@@ -1910,6 +1937,17 @@ function positiveInteger(raw, fallback) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function requiredPositiveInteger(raw, name) {
|
||||
const value = Number(raw);
|
||||
if (!Number.isInteger(value) || value <= 0) throw new Error("missing or invalid " + name);
|
||||
return value;
|
||||
}
|
||||
|
||||
function requiredEnum(raw, allowed) {
|
||||
if (!allowed.includes(raw)) throw new Error("missing or invalid screenshot mode");
|
||||
return raw;
|
||||
}
|
||||
|
||||
function artifactPath(name) {
|
||||
const safe = String(name || "artifact")
|
||||
.replace(/[^A-Za-z0-9._-]/gu, "_")
|
||||
@@ -1920,7 +1958,7 @@ function artifactPath(name) {
|
||||
|
||||
async function screenshot(name = "screenshot.png", options = {}) {
|
||||
const file = artifactPath(name);
|
||||
await page.screenshot({ path: file, fullPage: true, ...options });
|
||||
await page.screenshot({ path: file, fullPage: screenshotMode !== "viewport", ...options });
|
||||
return recordArtifact(file, "screenshot");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user