@riddledc/riddle-proof 0.7.77 → 0.7.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-RBZ4A5M4.js → chunk-3RUIKF4C.js} +188 -6
- package/dist/cli.cjs +188 -6
- package/dist/cli.js +1 -1
- package/dist/index.cjs +188 -6
- package/dist/index.js +1 -1
- package/dist/profile.cjs +188 -6
- package/dist/profile.d.cts +5 -1
- package/dist/profile.d.ts +5 -1
- package/dist/profile.js +1 -1
- package/package.json +1 -1
|
@@ -47,6 +47,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
47
47
|
"session_storage",
|
|
48
48
|
"clear_storage",
|
|
49
49
|
"clear_console",
|
|
50
|
+
"dialog_response",
|
|
50
51
|
"screenshot",
|
|
51
52
|
"wait",
|
|
52
53
|
"wait_for_selector",
|
|
@@ -308,7 +309,7 @@ function isSupportedCheckType(value) {
|
|
|
308
309
|
}
|
|
309
310
|
function normalizeSetupActionType(value, index) {
|
|
310
311
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
311
|
-
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "reset_console" || normalizedInput === "clear_browser_console" || normalizedInput === "reset_browser_console" ? "clear_console" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput;
|
|
312
|
+
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "reset_console" || normalizedInput === "clear_browser_console" || normalizedInput === "reset_browser_console" ? "clear_console" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput === "accept_dialog" || normalizedInput === "accept_dialogs" || normalizedInput === "confirm_dialog" || normalizedInput === "set_dialog_response" ? "dialog_response" : normalizedInput === "dismiss_dialog" || normalizedInput === "dismiss_dialogs" || normalizedInput === "cancel_dialog" ? "dialog_response" : normalizedInput;
|
|
312
313
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
313
314
|
return normalized;
|
|
314
315
|
}
|
|
@@ -360,6 +361,7 @@ function normalizeSetupActionCoordinateMode(value, index) {
|
|
|
360
361
|
function normalizeSetupAction(input, index) {
|
|
361
362
|
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
362
363
|
const type = normalizeSetupActionType(stringValue(input.type), index);
|
|
364
|
+
const rawType = String(input.type || "").trim().replace(/-/g, "_").toLowerCase();
|
|
363
365
|
const selector = stringValue(input.selector);
|
|
364
366
|
const frameSelector = stringFromOwn(input, "frame_selector", "frameSelector", "iframe_selector", "iframeSelector");
|
|
365
367
|
const frameIndex = numberValue(valueFromOwn(input, "frame_index", "frameIndex", "iframe_index", "iframeIndex"));
|
|
@@ -401,6 +403,21 @@ function normalizeSetupAction(input, index) {
|
|
|
401
403
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
402
404
|
}
|
|
403
405
|
const key = stringValue(input.key);
|
|
406
|
+
let dialogAccept;
|
|
407
|
+
if (type === "dialog_response") {
|
|
408
|
+
const acceptInput = valueFromOwn(input, "accept", "accepted", "should_accept", "shouldAccept");
|
|
409
|
+
const responseInput = stringFromOwn(input, "response", "dialog_response", "dialogResponse", "mode");
|
|
410
|
+
const response = String(responseInput || "").trim().toLowerCase().replace(/-/g, "_");
|
|
411
|
+
if (acceptInput !== void 0) {
|
|
412
|
+
dialogAccept = acceptInput !== false && String(acceptInput).toLowerCase() !== "false";
|
|
413
|
+
} else if (rawType === "dismiss_dialog" || rawType === "dismiss_dialogs" || rawType === "cancel_dialog") {
|
|
414
|
+
dialogAccept = false;
|
|
415
|
+
} else if (response === "dismiss" || response === "cancel" || response === "reject" || response === "no" || response === "false") {
|
|
416
|
+
dialogAccept = false;
|
|
417
|
+
} else {
|
|
418
|
+
dialogAccept = true;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
404
421
|
if (type === "press" && !key) {
|
|
405
422
|
throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
|
|
406
423
|
}
|
|
@@ -462,6 +479,10 @@ function normalizeSetupAction(input, index) {
|
|
|
462
479
|
text: stringValue(input.text),
|
|
463
480
|
pattern: stringValue(input.pattern),
|
|
464
481
|
flags: stringValue(input.flags),
|
|
482
|
+
accept: dialogAccept,
|
|
483
|
+
prompt_text: stringFromOwn(input, "prompt_text", "promptText", "prompt_value", "promptValue"),
|
|
484
|
+
message_text: stringFromOwn(input, "message_text", "messageText", "dialog_text", "dialogText"),
|
|
485
|
+
message_pattern: stringFromOwn(input, "message_pattern", "messagePattern", "dialog_pattern", "dialogPattern"),
|
|
465
486
|
index: numberValue(input.index),
|
|
466
487
|
expected_count: expectedCount,
|
|
467
488
|
ms: numberValue(input.ms) ?? numberValue(input.wait_ms) ?? numberValue(input.waitMs),
|
|
@@ -927,6 +948,41 @@ function matchesAllowedMessage(input, texts, patterns) {
|
|
|
927
948
|
}
|
|
928
949
|
return false;
|
|
929
950
|
}
|
|
951
|
+
function consoleEventLocationUrl(input) {
|
|
952
|
+
if (!isRecord(input) || !isRecord(input.location)) return void 0;
|
|
953
|
+
return stringValue(input.location.url);
|
|
954
|
+
}
|
|
955
|
+
function expectedFailedNetworkMockEvents(evidence) {
|
|
956
|
+
return (evidence.network_mocks || []).filter((event) => {
|
|
957
|
+
if (!isRecord(event) || event.ok === false) return false;
|
|
958
|
+
const status = numberValue(event.status);
|
|
959
|
+
return status !== void 0 && status >= 400 && Boolean(stringValue(event.url));
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
function matchingExpectedFailedNetworkMockConsoleEvent(event, evidence) {
|
|
963
|
+
const sample = allowedMessageSample(event);
|
|
964
|
+
if (!/Failed to load resource/i.test(sample)) return void 0;
|
|
965
|
+
const eventUrl = consoleEventLocationUrl(event);
|
|
966
|
+
if (!eventUrl) return void 0;
|
|
967
|
+
return expectedFailedNetworkMockEvents(evidence).find((mockEvent) => {
|
|
968
|
+
const status = numberValue(mockEvent.status);
|
|
969
|
+
return stringValue(mockEvent.url) === eventUrl && status !== void 0 && sample.includes(String(status));
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
function isExpectedFailedNetworkMockConsoleEvent(event, evidence) {
|
|
973
|
+
return Boolean(matchingExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
974
|
+
}
|
|
975
|
+
function expectedFailedNetworkMockConsoleEventSummary(event, evidence) {
|
|
976
|
+
const match = matchingExpectedFailedNetworkMockConsoleEvent(event, evidence);
|
|
977
|
+
const sample = allowedMessageSample(event);
|
|
978
|
+
return {
|
|
979
|
+
url: consoleEventLocationUrl(event) ?? null,
|
|
980
|
+
status: match ? numberValue(match.status) ?? null : null,
|
|
981
|
+
label: match ? stringValue(match.label) ?? null : null,
|
|
982
|
+
response_label: match ? stringValue(match.response_label) ?? null : null,
|
|
983
|
+
text: isRecord(event) && typeof event.text === "string" ? event.text.slice(0, 300) : sample.slice(0, 300)
|
|
984
|
+
};
|
|
985
|
+
}
|
|
930
986
|
function normalizeRoutePath(path) {
|
|
931
987
|
const value = path || "/";
|
|
932
988
|
if (value === "/") return "/";
|
|
@@ -1344,8 +1400,10 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
1344
1400
|
}
|
|
1345
1401
|
if (check.type === "no_fatal_console_errors") {
|
|
1346
1402
|
const fatalConsoleEvents = (evidence.console?.events || []).filter((event) => event.type === "error" || event.type === "assert");
|
|
1347
|
-
const
|
|
1348
|
-
const
|
|
1403
|
+
const explicitlyAllowedConsoleEvents = fatalConsoleEvents.filter((event) => matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns));
|
|
1404
|
+
const expectedNetworkMockConsoleEvents = fatalConsoleEvents.filter((event) => !matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns) && isExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
1405
|
+
const allowedConsoleEvents = fatalConsoleEvents.filter((event) => matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns) || isExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
1406
|
+
const unallowedConsoleEvents = fatalConsoleEvents.filter((event) => !matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns) && !isExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
1349
1407
|
const pageErrors = evidence.page_errors || [];
|
|
1350
1408
|
const allowedPageErrors = pageErrors.filter((error) => matchesAllowedMessage(error, check.allowed_page_error_texts, check.allowed_page_error_patterns));
|
|
1351
1409
|
const unallowedPageErrors = pageErrors.filter((error) => !matchesAllowedMessage(error, check.allowed_page_error_texts, check.allowed_page_error_patterns));
|
|
@@ -1360,6 +1418,9 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
1360
1418
|
total_console_fatal_count: fatalConsoleEvents.length,
|
|
1361
1419
|
total_page_error_count: pageErrors.length,
|
|
1362
1420
|
allowed_console_fatal_count: allowedConsoleEvents.length,
|
|
1421
|
+
explicitly_allowed_console_fatal_count: explicitlyAllowedConsoleEvents.length,
|
|
1422
|
+
allowed_expected_network_mock_console_count: expectedNetworkMockConsoleEvents.length,
|
|
1423
|
+
allowed_expected_network_mock_console_events: expectedNetworkMockConsoleEvents.slice(0, 5).map((event) => expectedFailedNetworkMockConsoleEventSummary(event, evidence)),
|
|
1363
1424
|
allowed_page_error_count: allowedPageErrors.length,
|
|
1364
1425
|
allowed_console_texts: check.allowed_console_texts || [],
|
|
1365
1426
|
allowed_console_patterns: check.allowed_console_patterns || [],
|
|
@@ -1722,6 +1783,44 @@ function matchesAllowedMessage(input, texts, patterns) {
|
|
|
1722
1783
|
}
|
|
1723
1784
|
return false;
|
|
1724
1785
|
}
|
|
1786
|
+
function consoleEventLocationUrl(input) {
|
|
1787
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return undefined;
|
|
1788
|
+
if (!input.location || typeof input.location !== "object" || Array.isArray(input.location)) return undefined;
|
|
1789
|
+
return typeof input.location.url === "string" && input.location.url.trim() ? input.location.url.trim() : undefined;
|
|
1790
|
+
}
|
|
1791
|
+
function expectedFailedNetworkMockEvents(evidence) {
|
|
1792
|
+
return ((evidence && evidence.network_mocks) || []).filter((event) => {
|
|
1793
|
+
if (!event || typeof event !== "object" || Array.isArray(event) || event.ok === false) return false;
|
|
1794
|
+
const status = typeof event.status === "number" && Number.isFinite(event.status) ? event.status : undefined;
|
|
1795
|
+
const url = typeof event.url === "string" && event.url.trim() ? event.url.trim() : undefined;
|
|
1796
|
+
return status !== undefined && status >= 400 && Boolean(url);
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
1799
|
+
function matchingExpectedFailedNetworkMockConsoleEvent(event, evidence) {
|
|
1800
|
+
const sample = allowedMessageSample(event);
|
|
1801
|
+
if (!/Failed to load resource/i.test(sample)) return undefined;
|
|
1802
|
+
const eventUrl = consoleEventLocationUrl(event);
|
|
1803
|
+
if (!eventUrl) return undefined;
|
|
1804
|
+
return expectedFailedNetworkMockEvents(evidence).find((mockEvent) => {
|
|
1805
|
+
const status = typeof mockEvent.status === "number" && Number.isFinite(mockEvent.status) ? mockEvent.status : undefined;
|
|
1806
|
+
const mockUrl = typeof mockEvent.url === "string" && mockEvent.url.trim() ? mockEvent.url.trim() : undefined;
|
|
1807
|
+
return mockUrl === eventUrl && status !== undefined && sample.includes(String(status));
|
|
1808
|
+
});
|
|
1809
|
+
}
|
|
1810
|
+
function isExpectedFailedNetworkMockConsoleEvent(event, evidence) {
|
|
1811
|
+
return Boolean(matchingExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
1812
|
+
}
|
|
1813
|
+
function expectedFailedNetworkMockConsoleEventSummary(event, evidence) {
|
|
1814
|
+
const match = matchingExpectedFailedNetworkMockConsoleEvent(event, evidence);
|
|
1815
|
+
const sample = allowedMessageSample(event);
|
|
1816
|
+
return {
|
|
1817
|
+
url: consoleEventLocationUrl(event) || null,
|
|
1818
|
+
status: match && typeof match.status === "number" && Number.isFinite(match.status) ? match.status : null,
|
|
1819
|
+
label: match && typeof match.label === "string" && match.label.trim() ? match.label.trim() : null,
|
|
1820
|
+
response_label: match && typeof match.response_label === "string" && match.response_label.trim() ? match.response_label.trim() : null,
|
|
1821
|
+
text: event && typeof event === "object" && !Array.isArray(event) && typeof event.text === "string" ? event.text.slice(0, 300) : sample.slice(0, 300),
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1725
1824
|
function textSequenceForCheck(viewport, check) {
|
|
1726
1825
|
const key = check.selector || "";
|
|
1727
1826
|
const sequence = viewport.text_sequences && viewport.text_sequences[key];
|
|
@@ -2445,8 +2544,19 @@ function assessProfile(profile, evidence) {
|
|
|
2445
2544
|
}
|
|
2446
2545
|
if (check.type === "no_fatal_console_errors") {
|
|
2447
2546
|
const fatalConsoleEvents = ((evidence.console && evidence.console.events) || []).filter((event) => event && (event.type === "error" || event.type === "assert"));
|
|
2448
|
-
const
|
|
2449
|
-
const
|
|
2547
|
+
const explicitlyAllowedConsoleEvents = fatalConsoleEvents.filter((event) => matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns));
|
|
2548
|
+
const expectedNetworkMockConsoleEvents = fatalConsoleEvents.filter((event) => (
|
|
2549
|
+
!matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns)
|
|
2550
|
+
&& isExpectedFailedNetworkMockConsoleEvent(event, evidence)
|
|
2551
|
+
));
|
|
2552
|
+
const allowedConsoleEvents = fatalConsoleEvents.filter((event) => (
|
|
2553
|
+
matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns)
|
|
2554
|
+
|| isExpectedFailedNetworkMockConsoleEvent(event, evidence)
|
|
2555
|
+
));
|
|
2556
|
+
const unallowedConsoleEvents = fatalConsoleEvents.filter((event) => (
|
|
2557
|
+
!matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns)
|
|
2558
|
+
&& !isExpectedFailedNetworkMockConsoleEvent(event, evidence)
|
|
2559
|
+
));
|
|
2450
2560
|
const pageErrors = evidence.page_errors || [];
|
|
2451
2561
|
const allowedPageErrors = pageErrors.filter((error) => matchesAllowedMessage(error, check.allowed_page_error_texts, check.allowed_page_error_patterns));
|
|
2452
2562
|
const unallowedPageErrors = pageErrors.filter((error) => !matchesAllowedMessage(error, check.allowed_page_error_texts, check.allowed_page_error_patterns));
|
|
@@ -2461,6 +2571,9 @@ function assessProfile(profile, evidence) {
|
|
|
2461
2571
|
total_console_fatal_count: fatalConsoleEvents.length,
|
|
2462
2572
|
total_page_error_count: pageErrors.length,
|
|
2463
2573
|
allowed_console_fatal_count: allowedConsoleEvents.length,
|
|
2574
|
+
explicitly_allowed_console_fatal_count: explicitlyAllowedConsoleEvents.length,
|
|
2575
|
+
allowed_expected_network_mock_console_count: expectedNetworkMockConsoleEvents.length,
|
|
2576
|
+
allowed_expected_network_mock_console_events: expectedNetworkMockConsoleEvents.slice(0, 5).map((event) => expectedFailedNetworkMockConsoleEventSummary(event, evidence)),
|
|
2464
2577
|
allowed_page_error_count: allowedPageErrors.length,
|
|
2465
2578
|
allowed_console_texts: check.allowed_console_texts || [],
|
|
2466
2579
|
allowed_console_patterns: check.allowed_console_patterns || [],
|
|
@@ -2520,6 +2633,9 @@ const capturedAt = new Date().toISOString();
|
|
|
2520
2633
|
const consoleEvents = [];
|
|
2521
2634
|
const pageErrors = [];
|
|
2522
2635
|
const networkMockEvents = [];
|
|
2636
|
+
const dialogEvents = [];
|
|
2637
|
+
let dialogResponseConfig = null;
|
|
2638
|
+
let dialogHandlerInstalled = false;
|
|
2523
2639
|
page.on("console", (message) => {
|
|
2524
2640
|
const type = message.type();
|
|
2525
2641
|
if (type === "error" || type === "warning" || type === "assert") {
|
|
@@ -2533,6 +2649,50 @@ page.on("console", (message) => {
|
|
|
2533
2649
|
page.on("pageerror", (error) => {
|
|
2534
2650
|
pageErrors.push({ message: String(error && error.message ? error.message : error).slice(0, 1000) });
|
|
2535
2651
|
});
|
|
2652
|
+
function setupDialogMessageMatches(message, config) {
|
|
2653
|
+
if (!config) return true;
|
|
2654
|
+
if (config.message_pattern) {
|
|
2655
|
+
try { return new RegExp(config.message_pattern, config.flags || "").test(message || ""); } catch { return false; }
|
|
2656
|
+
}
|
|
2657
|
+
if (config.message_text) return String(message || "").includes(config.message_text);
|
|
2658
|
+
return true;
|
|
2659
|
+
}
|
|
2660
|
+
function ensureDialogHandler() {
|
|
2661
|
+
if (dialogHandlerInstalled) return;
|
|
2662
|
+
dialogHandlerInstalled = true;
|
|
2663
|
+
page.on("dialog", async (dialog) => {
|
|
2664
|
+
const config = dialogResponseConfig || { accept: false };
|
|
2665
|
+
const message = typeof dialog.message === "function" ? dialog.message() : "";
|
|
2666
|
+
const type = typeof dialog.type === "function" ? dialog.type() : "dialog";
|
|
2667
|
+
const defaultValue = typeof dialog.defaultValue === "function" ? dialog.defaultValue() : "";
|
|
2668
|
+
const accept = config.accept !== false;
|
|
2669
|
+
const event = {
|
|
2670
|
+
type,
|
|
2671
|
+
message: String(message || "").slice(0, 1000),
|
|
2672
|
+
default_value: String(defaultValue || "").slice(0, 500),
|
|
2673
|
+
configured: Boolean(dialogResponseConfig),
|
|
2674
|
+
response: accept ? "accept" : "dismiss",
|
|
2675
|
+
message_matches: setupDialogMessageMatches(message, config),
|
|
2676
|
+
expected_message_text: config.message_text || undefined,
|
|
2677
|
+
expected_message_pattern: config.message_pattern || undefined,
|
|
2678
|
+
};
|
|
2679
|
+
try {
|
|
2680
|
+
if (accept) {
|
|
2681
|
+
const promptText = config.prompt_text === undefined ? undefined : String(config.prompt_text);
|
|
2682
|
+
await dialog.accept(promptText);
|
|
2683
|
+
} else {
|
|
2684
|
+
await dialog.dismiss();
|
|
2685
|
+
}
|
|
2686
|
+
dialogEvents.push({ ...event, ok: true });
|
|
2687
|
+
} catch (error) {
|
|
2688
|
+
dialogEvents.push({
|
|
2689
|
+
...event,
|
|
2690
|
+
ok: false,
|
|
2691
|
+
error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
2692
|
+
});
|
|
2693
|
+
}
|
|
2694
|
+
});
|
|
2695
|
+
}
|
|
2536
2696
|
function textKey(check) {
|
|
2537
2697
|
return check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
|
|
2538
2698
|
}
|
|
@@ -2871,6 +3031,24 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
2871
3031
|
pageErrors.length = 0;
|
|
2872
3032
|
return { ...base, ok: true, cleared_console_event_count, cleared_page_error_count };
|
|
2873
3033
|
}
|
|
3034
|
+
if (type === "dialog_response") {
|
|
3035
|
+
ensureDialogHandler();
|
|
3036
|
+
dialogResponseConfig = {
|
|
3037
|
+
accept: action.accept !== false,
|
|
3038
|
+
prompt_text: action.prompt_text,
|
|
3039
|
+
message_text: action.message_text,
|
|
3040
|
+
message_pattern: action.message_pattern,
|
|
3041
|
+
flags: action.flags || "",
|
|
3042
|
+
};
|
|
3043
|
+
return {
|
|
3044
|
+
...base,
|
|
3045
|
+
ok: true,
|
|
3046
|
+
response: dialogResponseConfig.accept ? "accept" : "dismiss",
|
|
3047
|
+
message_text: dialogResponseConfig.message_text || undefined,
|
|
3048
|
+
message_pattern: dialogResponseConfig.message_pattern || undefined,
|
|
3049
|
+
prompt_text_length: dialogResponseConfig.prompt_text === undefined ? undefined : String(dialogResponseConfig.prompt_text).length,
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
2874
3052
|
if (type === "wait_for_selector") {
|
|
2875
3053
|
const scope = await setupActionScope(action, timeout);
|
|
2876
3054
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
@@ -3971,6 +4149,7 @@ function buildProfileEvidence(currentViewports) {
|
|
|
3971
4149
|
fatal_count: consoleEvents.filter((event) => event.type === "error" || event.type === "assert").length,
|
|
3972
4150
|
},
|
|
3973
4151
|
page_errors: pageErrors,
|
|
4152
|
+
dialogs: dialogEvents.slice(),
|
|
3974
4153
|
network_mocks: networkMockEvents.slice(),
|
|
3975
4154
|
dom_summary: {
|
|
3976
4155
|
expected_viewport_count: expectedViewportCount,
|
|
@@ -4010,6 +4189,9 @@ function buildProfileEvidence(currentViewports) {
|
|
|
4010
4189
|
})),
|
|
4011
4190
|
network_mock_count: (profile.target.network_mocks || []).length,
|
|
4012
4191
|
network_mock_hit_count: networkMockEvents.filter((event) => event.ok !== false).length,
|
|
4192
|
+
dialog_count: dialogEvents.length,
|
|
4193
|
+
dialog_accept_count: dialogEvents.filter((event) => event.response === "accept" && event.ok !== false).length,
|
|
4194
|
+
dialog_dismiss_count: dialogEvents.filter((event) => event.response === "dismiss" && event.ok !== false).length,
|
|
4013
4195
|
},
|
|
4014
4196
|
};
|
|
4015
4197
|
}
|
|
@@ -4018,7 +4200,7 @@ async function saveProfileArtifacts(currentViewports) {
|
|
|
4018
4200
|
const result = assessProfile(profile, evidence);
|
|
4019
4201
|
if (typeof saveJson === "function") {
|
|
4020
4202
|
await saveJson("proof.json", result);
|
|
4021
|
-
await saveJson("console.json", { events: consoleEvents, page_errors: pageErrors });
|
|
4203
|
+
await saveJson("console.json", { events: consoleEvents, page_errors: pageErrors, dialogs: dialogEvents });
|
|
4022
4204
|
await saveJson("dom-summary.json", evidence.dom_summary);
|
|
4023
4205
|
}
|
|
4024
4206
|
return result;
|
package/dist/cli.cjs
CHANGED
|
@@ -6920,6 +6920,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
6920
6920
|
"session_storage",
|
|
6921
6921
|
"clear_storage",
|
|
6922
6922
|
"clear_console",
|
|
6923
|
+
"dialog_response",
|
|
6923
6924
|
"screenshot",
|
|
6924
6925
|
"wait",
|
|
6925
6926
|
"wait_for_selector",
|
|
@@ -7181,7 +7182,7 @@ function isSupportedCheckType(value) {
|
|
|
7181
7182
|
}
|
|
7182
7183
|
function normalizeSetupActionType(value, index) {
|
|
7183
7184
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
7184
|
-
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "reset_console" || normalizedInput === "clear_browser_console" || normalizedInput === "reset_browser_console" ? "clear_console" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput;
|
|
7185
|
+
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "reset_console" || normalizedInput === "clear_browser_console" || normalizedInput === "reset_browser_console" ? "clear_console" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput === "accept_dialog" || normalizedInput === "accept_dialogs" || normalizedInput === "confirm_dialog" || normalizedInput === "set_dialog_response" ? "dialog_response" : normalizedInput === "dismiss_dialog" || normalizedInput === "dismiss_dialogs" || normalizedInput === "cancel_dialog" ? "dialog_response" : normalizedInput;
|
|
7185
7186
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
7186
7187
|
return normalized;
|
|
7187
7188
|
}
|
|
@@ -7233,6 +7234,7 @@ function normalizeSetupActionCoordinateMode(value, index) {
|
|
|
7233
7234
|
function normalizeSetupAction(input, index) {
|
|
7234
7235
|
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
7235
7236
|
const type = normalizeSetupActionType(stringValue2(input.type), index);
|
|
7237
|
+
const rawType = String(input.type || "").trim().replace(/-/g, "_").toLowerCase();
|
|
7236
7238
|
const selector = stringValue2(input.selector);
|
|
7237
7239
|
const frameSelector = stringFromOwn(input, "frame_selector", "frameSelector", "iframe_selector", "iframeSelector");
|
|
7238
7240
|
const frameIndex = numberValue(valueFromOwn(input, "frame_index", "frameIndex", "iframe_index", "iframeIndex"));
|
|
@@ -7274,6 +7276,21 @@ function normalizeSetupAction(input, index) {
|
|
|
7274
7276
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
7275
7277
|
}
|
|
7276
7278
|
const key = stringValue2(input.key);
|
|
7279
|
+
let dialogAccept;
|
|
7280
|
+
if (type === "dialog_response") {
|
|
7281
|
+
const acceptInput = valueFromOwn(input, "accept", "accepted", "should_accept", "shouldAccept");
|
|
7282
|
+
const responseInput = stringFromOwn(input, "response", "dialog_response", "dialogResponse", "mode");
|
|
7283
|
+
const response = String(responseInput || "").trim().toLowerCase().replace(/-/g, "_");
|
|
7284
|
+
if (acceptInput !== void 0) {
|
|
7285
|
+
dialogAccept = acceptInput !== false && String(acceptInput).toLowerCase() !== "false";
|
|
7286
|
+
} else if (rawType === "dismiss_dialog" || rawType === "dismiss_dialogs" || rawType === "cancel_dialog") {
|
|
7287
|
+
dialogAccept = false;
|
|
7288
|
+
} else if (response === "dismiss" || response === "cancel" || response === "reject" || response === "no" || response === "false") {
|
|
7289
|
+
dialogAccept = false;
|
|
7290
|
+
} else {
|
|
7291
|
+
dialogAccept = true;
|
|
7292
|
+
}
|
|
7293
|
+
}
|
|
7277
7294
|
if (type === "press" && !key) {
|
|
7278
7295
|
throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
|
|
7279
7296
|
}
|
|
@@ -7335,6 +7352,10 @@ function normalizeSetupAction(input, index) {
|
|
|
7335
7352
|
text: stringValue2(input.text),
|
|
7336
7353
|
pattern: stringValue2(input.pattern),
|
|
7337
7354
|
flags: stringValue2(input.flags),
|
|
7355
|
+
accept: dialogAccept,
|
|
7356
|
+
prompt_text: stringFromOwn(input, "prompt_text", "promptText", "prompt_value", "promptValue"),
|
|
7357
|
+
message_text: stringFromOwn(input, "message_text", "messageText", "dialog_text", "dialogText"),
|
|
7358
|
+
message_pattern: stringFromOwn(input, "message_pattern", "messagePattern", "dialog_pattern", "dialogPattern"),
|
|
7338
7359
|
index: numberValue(input.index),
|
|
7339
7360
|
expected_count: expectedCount,
|
|
7340
7361
|
ms: numberValue(input.ms) ?? numberValue(input.wait_ms) ?? numberValue(input.waitMs),
|
|
@@ -7800,6 +7821,41 @@ function matchesAllowedMessage(input, texts, patterns) {
|
|
|
7800
7821
|
}
|
|
7801
7822
|
return false;
|
|
7802
7823
|
}
|
|
7824
|
+
function consoleEventLocationUrl(input) {
|
|
7825
|
+
if (!isRecord(input) || !isRecord(input.location)) return void 0;
|
|
7826
|
+
return stringValue2(input.location.url);
|
|
7827
|
+
}
|
|
7828
|
+
function expectedFailedNetworkMockEvents(evidence) {
|
|
7829
|
+
return (evidence.network_mocks || []).filter((event) => {
|
|
7830
|
+
if (!isRecord(event) || event.ok === false) return false;
|
|
7831
|
+
const status = numberValue(event.status);
|
|
7832
|
+
return status !== void 0 && status >= 400 && Boolean(stringValue2(event.url));
|
|
7833
|
+
});
|
|
7834
|
+
}
|
|
7835
|
+
function matchingExpectedFailedNetworkMockConsoleEvent(event, evidence) {
|
|
7836
|
+
const sample = allowedMessageSample(event);
|
|
7837
|
+
if (!/Failed to load resource/i.test(sample)) return void 0;
|
|
7838
|
+
const eventUrl = consoleEventLocationUrl(event);
|
|
7839
|
+
if (!eventUrl) return void 0;
|
|
7840
|
+
return expectedFailedNetworkMockEvents(evidence).find((mockEvent) => {
|
|
7841
|
+
const status = numberValue(mockEvent.status);
|
|
7842
|
+
return stringValue2(mockEvent.url) === eventUrl && status !== void 0 && sample.includes(String(status));
|
|
7843
|
+
});
|
|
7844
|
+
}
|
|
7845
|
+
function isExpectedFailedNetworkMockConsoleEvent(event, evidence) {
|
|
7846
|
+
return Boolean(matchingExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
7847
|
+
}
|
|
7848
|
+
function expectedFailedNetworkMockConsoleEventSummary(event, evidence) {
|
|
7849
|
+
const match = matchingExpectedFailedNetworkMockConsoleEvent(event, evidence);
|
|
7850
|
+
const sample = allowedMessageSample(event);
|
|
7851
|
+
return {
|
|
7852
|
+
url: consoleEventLocationUrl(event) ?? null,
|
|
7853
|
+
status: match ? numberValue(match.status) ?? null : null,
|
|
7854
|
+
label: match ? stringValue2(match.label) ?? null : null,
|
|
7855
|
+
response_label: match ? stringValue2(match.response_label) ?? null : null,
|
|
7856
|
+
text: isRecord(event) && typeof event.text === "string" ? event.text.slice(0, 300) : sample.slice(0, 300)
|
|
7857
|
+
};
|
|
7858
|
+
}
|
|
7803
7859
|
function normalizeRoutePath(path7) {
|
|
7804
7860
|
const value = path7 || "/";
|
|
7805
7861
|
if (value === "/") return "/";
|
|
@@ -8217,8 +8273,10 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
8217
8273
|
}
|
|
8218
8274
|
if (check.type === "no_fatal_console_errors") {
|
|
8219
8275
|
const fatalConsoleEvents = (evidence.console?.events || []).filter((event) => event.type === "error" || event.type === "assert");
|
|
8220
|
-
const
|
|
8221
|
-
const
|
|
8276
|
+
const explicitlyAllowedConsoleEvents = fatalConsoleEvents.filter((event) => matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns));
|
|
8277
|
+
const expectedNetworkMockConsoleEvents = fatalConsoleEvents.filter((event) => !matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns) && isExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
8278
|
+
const allowedConsoleEvents = fatalConsoleEvents.filter((event) => matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns) || isExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
8279
|
+
const unallowedConsoleEvents = fatalConsoleEvents.filter((event) => !matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns) && !isExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
8222
8280
|
const pageErrors = evidence.page_errors || [];
|
|
8223
8281
|
const allowedPageErrors = pageErrors.filter((error) => matchesAllowedMessage(error, check.allowed_page_error_texts, check.allowed_page_error_patterns));
|
|
8224
8282
|
const unallowedPageErrors = pageErrors.filter((error) => !matchesAllowedMessage(error, check.allowed_page_error_texts, check.allowed_page_error_patterns));
|
|
@@ -8233,6 +8291,9 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
8233
8291
|
total_console_fatal_count: fatalConsoleEvents.length,
|
|
8234
8292
|
total_page_error_count: pageErrors.length,
|
|
8235
8293
|
allowed_console_fatal_count: allowedConsoleEvents.length,
|
|
8294
|
+
explicitly_allowed_console_fatal_count: explicitlyAllowedConsoleEvents.length,
|
|
8295
|
+
allowed_expected_network_mock_console_count: expectedNetworkMockConsoleEvents.length,
|
|
8296
|
+
allowed_expected_network_mock_console_events: expectedNetworkMockConsoleEvents.slice(0, 5).map((event) => expectedFailedNetworkMockConsoleEventSummary(event, evidence)),
|
|
8236
8297
|
allowed_page_error_count: allowedPageErrors.length,
|
|
8237
8298
|
allowed_console_texts: check.allowed_console_texts || [],
|
|
8238
8299
|
allowed_console_patterns: check.allowed_console_patterns || [],
|
|
@@ -8579,6 +8640,44 @@ function matchesAllowedMessage(input, texts, patterns) {
|
|
|
8579
8640
|
}
|
|
8580
8641
|
return false;
|
|
8581
8642
|
}
|
|
8643
|
+
function consoleEventLocationUrl(input) {
|
|
8644
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return undefined;
|
|
8645
|
+
if (!input.location || typeof input.location !== "object" || Array.isArray(input.location)) return undefined;
|
|
8646
|
+
return typeof input.location.url === "string" && input.location.url.trim() ? input.location.url.trim() : undefined;
|
|
8647
|
+
}
|
|
8648
|
+
function expectedFailedNetworkMockEvents(evidence) {
|
|
8649
|
+
return ((evidence && evidence.network_mocks) || []).filter((event) => {
|
|
8650
|
+
if (!event || typeof event !== "object" || Array.isArray(event) || event.ok === false) return false;
|
|
8651
|
+
const status = typeof event.status === "number" && Number.isFinite(event.status) ? event.status : undefined;
|
|
8652
|
+
const url = typeof event.url === "string" && event.url.trim() ? event.url.trim() : undefined;
|
|
8653
|
+
return status !== undefined && status >= 400 && Boolean(url);
|
|
8654
|
+
});
|
|
8655
|
+
}
|
|
8656
|
+
function matchingExpectedFailedNetworkMockConsoleEvent(event, evidence) {
|
|
8657
|
+
const sample = allowedMessageSample(event);
|
|
8658
|
+
if (!/Failed to load resource/i.test(sample)) return undefined;
|
|
8659
|
+
const eventUrl = consoleEventLocationUrl(event);
|
|
8660
|
+
if (!eventUrl) return undefined;
|
|
8661
|
+
return expectedFailedNetworkMockEvents(evidence).find((mockEvent) => {
|
|
8662
|
+
const status = typeof mockEvent.status === "number" && Number.isFinite(mockEvent.status) ? mockEvent.status : undefined;
|
|
8663
|
+
const mockUrl = typeof mockEvent.url === "string" && mockEvent.url.trim() ? mockEvent.url.trim() : undefined;
|
|
8664
|
+
return mockUrl === eventUrl && status !== undefined && sample.includes(String(status));
|
|
8665
|
+
});
|
|
8666
|
+
}
|
|
8667
|
+
function isExpectedFailedNetworkMockConsoleEvent(event, evidence) {
|
|
8668
|
+
return Boolean(matchingExpectedFailedNetworkMockConsoleEvent(event, evidence));
|
|
8669
|
+
}
|
|
8670
|
+
function expectedFailedNetworkMockConsoleEventSummary(event, evidence) {
|
|
8671
|
+
const match = matchingExpectedFailedNetworkMockConsoleEvent(event, evidence);
|
|
8672
|
+
const sample = allowedMessageSample(event);
|
|
8673
|
+
return {
|
|
8674
|
+
url: consoleEventLocationUrl(event) || null,
|
|
8675
|
+
status: match && typeof match.status === "number" && Number.isFinite(match.status) ? match.status : null,
|
|
8676
|
+
label: match && typeof match.label === "string" && match.label.trim() ? match.label.trim() : null,
|
|
8677
|
+
response_label: match && typeof match.response_label === "string" && match.response_label.trim() ? match.response_label.trim() : null,
|
|
8678
|
+
text: event && typeof event === "object" && !Array.isArray(event) && typeof event.text === "string" ? event.text.slice(0, 300) : sample.slice(0, 300),
|
|
8679
|
+
};
|
|
8680
|
+
}
|
|
8582
8681
|
function textSequenceForCheck(viewport, check) {
|
|
8583
8682
|
const key = check.selector || "";
|
|
8584
8683
|
const sequence = viewport.text_sequences && viewport.text_sequences[key];
|
|
@@ -9302,8 +9401,19 @@ function assessProfile(profile, evidence) {
|
|
|
9302
9401
|
}
|
|
9303
9402
|
if (check.type === "no_fatal_console_errors") {
|
|
9304
9403
|
const fatalConsoleEvents = ((evidence.console && evidence.console.events) || []).filter((event) => event && (event.type === "error" || event.type === "assert"));
|
|
9305
|
-
const
|
|
9306
|
-
const
|
|
9404
|
+
const explicitlyAllowedConsoleEvents = fatalConsoleEvents.filter((event) => matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns));
|
|
9405
|
+
const expectedNetworkMockConsoleEvents = fatalConsoleEvents.filter((event) => (
|
|
9406
|
+
!matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns)
|
|
9407
|
+
&& isExpectedFailedNetworkMockConsoleEvent(event, evidence)
|
|
9408
|
+
));
|
|
9409
|
+
const allowedConsoleEvents = fatalConsoleEvents.filter((event) => (
|
|
9410
|
+
matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns)
|
|
9411
|
+
|| isExpectedFailedNetworkMockConsoleEvent(event, evidence)
|
|
9412
|
+
));
|
|
9413
|
+
const unallowedConsoleEvents = fatalConsoleEvents.filter((event) => (
|
|
9414
|
+
!matchesAllowedMessage(event, check.allowed_console_texts, check.allowed_console_patterns)
|
|
9415
|
+
&& !isExpectedFailedNetworkMockConsoleEvent(event, evidence)
|
|
9416
|
+
));
|
|
9307
9417
|
const pageErrors = evidence.page_errors || [];
|
|
9308
9418
|
const allowedPageErrors = pageErrors.filter((error) => matchesAllowedMessage(error, check.allowed_page_error_texts, check.allowed_page_error_patterns));
|
|
9309
9419
|
const unallowedPageErrors = pageErrors.filter((error) => !matchesAllowedMessage(error, check.allowed_page_error_texts, check.allowed_page_error_patterns));
|
|
@@ -9318,6 +9428,9 @@ function assessProfile(profile, evidence) {
|
|
|
9318
9428
|
total_console_fatal_count: fatalConsoleEvents.length,
|
|
9319
9429
|
total_page_error_count: pageErrors.length,
|
|
9320
9430
|
allowed_console_fatal_count: allowedConsoleEvents.length,
|
|
9431
|
+
explicitly_allowed_console_fatal_count: explicitlyAllowedConsoleEvents.length,
|
|
9432
|
+
allowed_expected_network_mock_console_count: expectedNetworkMockConsoleEvents.length,
|
|
9433
|
+
allowed_expected_network_mock_console_events: expectedNetworkMockConsoleEvents.slice(0, 5).map((event) => expectedFailedNetworkMockConsoleEventSummary(event, evidence)),
|
|
9321
9434
|
allowed_page_error_count: allowedPageErrors.length,
|
|
9322
9435
|
allowed_console_texts: check.allowed_console_texts || [],
|
|
9323
9436
|
allowed_console_patterns: check.allowed_console_patterns || [],
|
|
@@ -9377,6 +9490,9 @@ const capturedAt = new Date().toISOString();
|
|
|
9377
9490
|
const consoleEvents = [];
|
|
9378
9491
|
const pageErrors = [];
|
|
9379
9492
|
const networkMockEvents = [];
|
|
9493
|
+
const dialogEvents = [];
|
|
9494
|
+
let dialogResponseConfig = null;
|
|
9495
|
+
let dialogHandlerInstalled = false;
|
|
9380
9496
|
page.on("console", (message) => {
|
|
9381
9497
|
const type = message.type();
|
|
9382
9498
|
if (type === "error" || type === "warning" || type === "assert") {
|
|
@@ -9390,6 +9506,50 @@ page.on("console", (message) => {
|
|
|
9390
9506
|
page.on("pageerror", (error) => {
|
|
9391
9507
|
pageErrors.push({ message: String(error && error.message ? error.message : error).slice(0, 1000) });
|
|
9392
9508
|
});
|
|
9509
|
+
function setupDialogMessageMatches(message, config) {
|
|
9510
|
+
if (!config) return true;
|
|
9511
|
+
if (config.message_pattern) {
|
|
9512
|
+
try { return new RegExp(config.message_pattern, config.flags || "").test(message || ""); } catch { return false; }
|
|
9513
|
+
}
|
|
9514
|
+
if (config.message_text) return String(message || "").includes(config.message_text);
|
|
9515
|
+
return true;
|
|
9516
|
+
}
|
|
9517
|
+
function ensureDialogHandler() {
|
|
9518
|
+
if (dialogHandlerInstalled) return;
|
|
9519
|
+
dialogHandlerInstalled = true;
|
|
9520
|
+
page.on("dialog", async (dialog) => {
|
|
9521
|
+
const config = dialogResponseConfig || { accept: false };
|
|
9522
|
+
const message = typeof dialog.message === "function" ? dialog.message() : "";
|
|
9523
|
+
const type = typeof dialog.type === "function" ? dialog.type() : "dialog";
|
|
9524
|
+
const defaultValue = typeof dialog.defaultValue === "function" ? dialog.defaultValue() : "";
|
|
9525
|
+
const accept = config.accept !== false;
|
|
9526
|
+
const event = {
|
|
9527
|
+
type,
|
|
9528
|
+
message: String(message || "").slice(0, 1000),
|
|
9529
|
+
default_value: String(defaultValue || "").slice(0, 500),
|
|
9530
|
+
configured: Boolean(dialogResponseConfig),
|
|
9531
|
+
response: accept ? "accept" : "dismiss",
|
|
9532
|
+
message_matches: setupDialogMessageMatches(message, config),
|
|
9533
|
+
expected_message_text: config.message_text || undefined,
|
|
9534
|
+
expected_message_pattern: config.message_pattern || undefined,
|
|
9535
|
+
};
|
|
9536
|
+
try {
|
|
9537
|
+
if (accept) {
|
|
9538
|
+
const promptText = config.prompt_text === undefined ? undefined : String(config.prompt_text);
|
|
9539
|
+
await dialog.accept(promptText);
|
|
9540
|
+
} else {
|
|
9541
|
+
await dialog.dismiss();
|
|
9542
|
+
}
|
|
9543
|
+
dialogEvents.push({ ...event, ok: true });
|
|
9544
|
+
} catch (error) {
|
|
9545
|
+
dialogEvents.push({
|
|
9546
|
+
...event,
|
|
9547
|
+
ok: false,
|
|
9548
|
+
error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
9549
|
+
});
|
|
9550
|
+
}
|
|
9551
|
+
});
|
|
9552
|
+
}
|
|
9393
9553
|
function textKey(check) {
|
|
9394
9554
|
return check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
|
|
9395
9555
|
}
|
|
@@ -9728,6 +9888,24 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
9728
9888
|
pageErrors.length = 0;
|
|
9729
9889
|
return { ...base, ok: true, cleared_console_event_count, cleared_page_error_count };
|
|
9730
9890
|
}
|
|
9891
|
+
if (type === "dialog_response") {
|
|
9892
|
+
ensureDialogHandler();
|
|
9893
|
+
dialogResponseConfig = {
|
|
9894
|
+
accept: action.accept !== false,
|
|
9895
|
+
prompt_text: action.prompt_text,
|
|
9896
|
+
message_text: action.message_text,
|
|
9897
|
+
message_pattern: action.message_pattern,
|
|
9898
|
+
flags: action.flags || "",
|
|
9899
|
+
};
|
|
9900
|
+
return {
|
|
9901
|
+
...base,
|
|
9902
|
+
ok: true,
|
|
9903
|
+
response: dialogResponseConfig.accept ? "accept" : "dismiss",
|
|
9904
|
+
message_text: dialogResponseConfig.message_text || undefined,
|
|
9905
|
+
message_pattern: dialogResponseConfig.message_pattern || undefined,
|
|
9906
|
+
prompt_text_length: dialogResponseConfig.prompt_text === undefined ? undefined : String(dialogResponseConfig.prompt_text).length,
|
|
9907
|
+
};
|
|
9908
|
+
}
|
|
9731
9909
|
if (type === "wait_for_selector") {
|
|
9732
9910
|
const scope = await setupActionScope(action, timeout);
|
|
9733
9911
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
@@ -10828,6 +11006,7 @@ function buildProfileEvidence(currentViewports) {
|
|
|
10828
11006
|
fatal_count: consoleEvents.filter((event) => event.type === "error" || event.type === "assert").length,
|
|
10829
11007
|
},
|
|
10830
11008
|
page_errors: pageErrors,
|
|
11009
|
+
dialogs: dialogEvents.slice(),
|
|
10831
11010
|
network_mocks: networkMockEvents.slice(),
|
|
10832
11011
|
dom_summary: {
|
|
10833
11012
|
expected_viewport_count: expectedViewportCount,
|
|
@@ -10867,6 +11046,9 @@ function buildProfileEvidence(currentViewports) {
|
|
|
10867
11046
|
})),
|
|
10868
11047
|
network_mock_count: (profile.target.network_mocks || []).length,
|
|
10869
11048
|
network_mock_hit_count: networkMockEvents.filter((event) => event.ok !== false).length,
|
|
11049
|
+
dialog_count: dialogEvents.length,
|
|
11050
|
+
dialog_accept_count: dialogEvents.filter((event) => event.response === "accept" && event.ok !== false).length,
|
|
11051
|
+
dialog_dismiss_count: dialogEvents.filter((event) => event.response === "dismiss" && event.ok !== false).length,
|
|
10870
11052
|
},
|
|
10871
11053
|
};
|
|
10872
11054
|
}
|
|
@@ -10875,7 +11057,7 @@ async function saveProfileArtifacts(currentViewports) {
|
|
|
10875
11057
|
const result = assessProfile(profile, evidence);
|
|
10876
11058
|
if (typeof saveJson === "function") {
|
|
10877
11059
|
await saveJson("proof.json", result);
|
|
10878
|
-
await saveJson("console.json", { events: consoleEvents, page_errors: pageErrors });
|
|
11060
|
+
await saveJson("console.json", { events: consoleEvents, page_errors: pageErrors, dialogs: dialogEvents });
|
|
10879
11061
|
await saveJson("dom-summary.json", evidence.dom_summary);
|
|
10880
11062
|
}
|
|
10881
11063
|
return result;
|
package/dist/cli.js
CHANGED