@riddledc/riddle-proof 0.7.139 → 0.7.141
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/README.md +10 -2
- package/dist/{chunk-DB6J53V5.js → chunk-F46O7DP2.js} +174 -8
- package/dist/cli.cjs +203 -9
- package/dist/cli.js +30 -2
- package/dist/index.cjs +174 -8
- package/dist/index.js +1 -1
- package/dist/profile.cjs +174 -8
- package/dist/profile.d.cts +3 -1
- package/dist/profile.d.ts +3 -1
- package/dist/profile.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -401,7 +401,7 @@ transport control, or other bounded interaction. Supported setup actions are
|
|
|
401
401
|
`assert_text_absent`, `assert_selector_count`, `assert_window_value`,
|
|
402
402
|
`assert_window_number`, `local_storage`, `session_storage`, `clear_storage`,
|
|
403
403
|
`clear_console`, `screenshot`, `wait`, `wait_for_selector`, `wait_for_text`,
|
|
404
|
-
`window_call`, and `window_call_until`;
|
|
404
|
+
`window_eval`, `window_call`, and `window_call_until`;
|
|
405
405
|
a failed setup action is recorded as a failed `setup_actions_succeeded` check so
|
|
406
406
|
the profile cannot pass without reaching the intended state. Text-matched `click` actions prefer
|
|
407
407
|
visible matching elements, which keeps responsive layouts from selecting hidden
|
|
@@ -447,6 +447,12 @@ errors, but keeps network mock hit evidence intact. Any setup action can include
|
|
|
447
447
|
with `repeat_index` and `repeat_count`, and `after_ms` runs after each
|
|
448
448
|
repetition. Use it for bounded game proof helpers, retry controls, or other
|
|
449
449
|
workflows where one declarative action needs to advance the app several times.
|
|
450
|
+
Use `window_eval` for async browser-side helper code that is easier to express
|
|
451
|
+
as a short script body than as a preexisting `window` function. It accepts
|
|
452
|
+
`script` plus optional JSON `args`, can compare `expect_return`, can store the
|
|
453
|
+
JSON-safe return value with `store_return_to`, and honors `capture_return:
|
|
454
|
+
false` for compact receipts. The script runs as an async function body with
|
|
455
|
+
`args` available in scope, so `return { ok: true }` records a structured return.
|
|
450
456
|
Use `window_call_until` when a proof helper needs to advance randomized or
|
|
451
457
|
progressive state until a window-state receipt is true. It accepts `path` plus
|
|
452
458
|
optional `args`, `until_path`, `until_expected_value`, `max_calls` from 1 to
|
|
@@ -486,7 +492,9 @@ Profile final viewport screenshots are full-page by default. Set
|
|
|
486
492
|
`target.screenshot_full_page: false`, `target.screenshotFullPage: false`, or
|
|
487
493
|
`target.screenshot_mode: "viewport"` when the automatic final screenshots
|
|
488
494
|
should capture only the current viewport, for example when fixed or sticky
|
|
489
|
-
headers make full-page captures misleading.
|
|
495
|
+
headers make full-page captures misleading. Compact profile summaries include
|
|
496
|
+
the final screenshot count and mode when a profile sets an explicit target
|
|
497
|
+
screenshot mode.
|
|
490
498
|
|
|
491
499
|
Use `allowed_console_patterns` / `allowed_console_texts` on
|
|
492
500
|
`no_fatal_console_errors` when a negative-path profile intentionally triggers a
|
|
@@ -61,6 +61,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
61
61
|
"wait",
|
|
62
62
|
"wait_for_selector",
|
|
63
63
|
"wait_for_text",
|
|
64
|
+
"window_eval",
|
|
64
65
|
"window_call",
|
|
65
66
|
"window_call_until"
|
|
66
67
|
];
|
|
@@ -480,6 +481,21 @@ function profileSetupWindowCallReceipts(results) {
|
|
|
480
481
|
return receipt;
|
|
481
482
|
});
|
|
482
483
|
}
|
|
484
|
+
function profileSetupWindowEvalReceipts(results) {
|
|
485
|
+
return results.filter((result) => profileSetupResultAction(result) === "window_eval").map((result) => {
|
|
486
|
+
const receipt = {
|
|
487
|
+
ordinal: result.ordinal ?? null,
|
|
488
|
+
ok: result.ok !== false,
|
|
489
|
+
script_length: result.script_length ?? null,
|
|
490
|
+
return_captured: result.return_captured ?? null,
|
|
491
|
+
return_stored_to: result.return_stored_to ?? null,
|
|
492
|
+
reason: result.reason ?? result.error ?? result.store_reason ?? null
|
|
493
|
+
};
|
|
494
|
+
if (result.returned !== void 0) receipt.returned = result.returned;
|
|
495
|
+
if (result.expected_return !== void 0) receipt.expected_return = result.expected_return;
|
|
496
|
+
return receipt;
|
|
497
|
+
});
|
|
498
|
+
}
|
|
483
499
|
function sampleProfileSetupSummaryItems(items, limit) {
|
|
484
500
|
if (items.length <= limit) return items;
|
|
485
501
|
const firstCount = Math.floor(limit / 2);
|
|
@@ -494,12 +510,18 @@ function profileScreenshotLabels(viewports) {
|
|
|
494
510
|
}
|
|
495
511
|
return labels;
|
|
496
512
|
}
|
|
497
|
-
function profileSetupSummary(viewports, actionCount, expectedActionCountByViewport) {
|
|
513
|
+
function profileSetupSummary(viewports, actionCount, expectedActionCountByViewport, finalScreenshotFullPage) {
|
|
514
|
+
const normalizedFinalScreenshotFullPage = finalScreenshotFullPage === void 0 ? void 0 : finalScreenshotFullPage !== false;
|
|
515
|
+
const finalScreenshotCount = viewports.filter((viewport) => typeof viewport.screenshot_label === "string" && viewport.screenshot_label.trim()).length;
|
|
498
516
|
return toJsonValue({
|
|
499
517
|
viewport_count: viewports.length,
|
|
500
518
|
action_count: actionCount ?? null,
|
|
519
|
+
final_screenshot_count: finalScreenshotCount,
|
|
520
|
+
final_screenshot_full_page: normalizedFinalScreenshotFullPage ?? null,
|
|
521
|
+
final_screenshot_mode: normalizedFinalScreenshotFullPage === void 0 ? null : normalizedFinalScreenshotFullPage ? "full_page" : "viewport",
|
|
501
522
|
viewports: viewports.map((viewport) => {
|
|
502
523
|
const expectedActionCount = expectedActionCountByViewport?.get(viewport.name) ?? actionCount;
|
|
524
|
+
const viewportFinalScreenshotFullPage = typeof viewport.screenshot_full_page === "boolean" ? viewport.screenshot_full_page : normalizedFinalScreenshotFullPage;
|
|
503
525
|
const results = viewport.setup_action_results || [];
|
|
504
526
|
const failed = results.filter((result) => result.ok === false && result.optional !== true);
|
|
505
527
|
const optionalFailed = results.filter((result) => result.ok === false && result.optional === true);
|
|
@@ -512,6 +534,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
|
|
|
512
534
|
const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
|
|
513
535
|
const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
|
|
514
536
|
const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
|
|
537
|
+
const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
|
|
538
|
+
const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
|
|
539
|
+
const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
|
|
540
|
+
const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
|
|
515
541
|
const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => {
|
|
516
542
|
const clickCount = typeof result.click_count === "number" && Number.isFinite(result.click_count) && result.click_count > 1 ? result.click_count : void 0;
|
|
517
543
|
return {
|
|
@@ -539,6 +565,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
|
|
|
539
565
|
action_counts: profileSetupActionCounts(results),
|
|
540
566
|
frame_action_count: results.filter((result) => result.frame_selector).length,
|
|
541
567
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
568
|
+
final_screenshot: viewport.screenshot_label ?? null,
|
|
569
|
+
final_screenshot_full_page: viewportFinalScreenshotFullPage ?? null,
|
|
542
570
|
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
543
571
|
clicked_total: clickedItems.length,
|
|
544
572
|
clicked_truncated: clickedItems.length > clicked.length,
|
|
@@ -553,6 +581,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
|
|
|
553
581
|
window_call_captured_total: windowCallCapturedTotal,
|
|
554
582
|
window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
|
|
555
583
|
window_call: sampledWindowCallReceipts,
|
|
584
|
+
window_eval_total: windowEvalReceipts.length,
|
|
585
|
+
window_eval_stored_total: windowEvalStoredTotal,
|
|
586
|
+
window_eval_captured_total: windowEvalCapturedTotal,
|
|
587
|
+
window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
|
|
588
|
+
window_eval: sampledWindowEvalReceipts,
|
|
556
589
|
clicked,
|
|
557
590
|
text_samples,
|
|
558
591
|
failed: failed.map((result) => ({
|
|
@@ -605,7 +638,7 @@ function isSupportedCheckType(value) {
|
|
|
605
638
|
}
|
|
606
639
|
function normalizeSetupActionType(value, index) {
|
|
607
640
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
608
|
-
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 === "window_call_until" || normalizedInput === "call_until" || normalizedInput === "window_call_repeat_until" || normalizedInput === "repeat_window_call_until" ? "window_call_until" : normalizedInput;
|
|
641
|
+
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 === "window_call_until" || normalizedInput === "call_until" || normalizedInput === "window_call_repeat_until" || normalizedInput === "repeat_window_call_until" ? "window_call_until" : normalizedInput === "window_evaluate" || normalizedInput === "browser_eval" || normalizedInput === "browser_evaluate" || normalizedInput === "evaluate_script" || normalizedInput === "profile_script" ? "window_eval" : normalizedInput;
|
|
609
642
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
610
643
|
return normalized;
|
|
611
644
|
}
|
|
@@ -623,7 +656,7 @@ function normalizeSetupActionArgs(input, index) {
|
|
|
623
656
|
const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
|
|
624
657
|
if (argsInput === void 0) return void 0;
|
|
625
658
|
if (!Array.isArray(argsInput)) {
|
|
626
|
-
throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
|
|
659
|
+
throw new Error(`target.setup_actions[${index}] window_call/window_eval args must be an array.`);
|
|
627
660
|
}
|
|
628
661
|
return argsInput.map(toJsonValue);
|
|
629
662
|
}
|
|
@@ -767,7 +800,11 @@ function normalizeSetupAction(input, index) {
|
|
|
767
800
|
if ((type === "window_call" || type === "window_call_until" || type === "assert_window_value" || type === "assert_window_number") && !path) {
|
|
768
801
|
throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
|
|
769
802
|
}
|
|
770
|
-
const
|
|
803
|
+
const script = stringFromOwn(input, "script", "code", "source", "body");
|
|
804
|
+
if (type === "window_eval" && !script) {
|
|
805
|
+
throw new Error(`target.setup_actions[${index}] window_eval requires script.`);
|
|
806
|
+
}
|
|
807
|
+
const args = type === "window_call" || type === "window_call_until" || type === "window_eval" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
771
808
|
const hasExpectedValue = hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected") || hasOwn(input, "expect_value") || hasOwn(input, "expectValue") || hasOwn(input, "expect");
|
|
772
809
|
if (type === "assert_window_value" && !hasExpectedValue) {
|
|
773
810
|
throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
|
|
@@ -838,6 +875,7 @@ function normalizeSetupAction(input, index) {
|
|
|
838
875
|
value,
|
|
839
876
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
840
877
|
label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
|
|
878
|
+
script,
|
|
841
879
|
path,
|
|
842
880
|
args,
|
|
843
881
|
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
@@ -2783,7 +2821,7 @@ function assessSetupActionsFromEvidence(profile, evidence) {
|
|
|
2783
2821
|
ok: (viewport.setup_action_results || []).length >= (expectedActionCountByViewport.get(viewport.name) ?? actionCount) && (viewport.setup_action_results || []).every((result) => result.ok !== false || result.optional === true),
|
|
2784
2822
|
result_count: (viewport.setup_action_results || []).length
|
|
2785
2823
|
})),
|
|
2786
|
-
setup_summary: profileSetupSummary(viewports, actionCount, expectedActionCountByViewport),
|
|
2824
|
+
setup_summary: profileSetupSummary(viewports, actionCount, expectedActionCountByViewport, profile.target.screenshot_full_page),
|
|
2787
2825
|
failed
|
|
2788
2826
|
},
|
|
2789
2827
|
message: failed.length ? `Setup actions failed in ${failed.length} viewport action(s).` : void 0
|
|
@@ -3789,6 +3827,23 @@ function profileSetupWindowCallReceipts(results) {
|
|
|
3789
3827
|
return receipt;
|
|
3790
3828
|
});
|
|
3791
3829
|
}
|
|
3830
|
+
function profileSetupWindowEvalReceipts(results) {
|
|
3831
|
+
return (results || [])
|
|
3832
|
+
.filter((result) => result && profileSetupResultAction(result) === "window_eval")
|
|
3833
|
+
.map((result) => {
|
|
3834
|
+
const receipt = {
|
|
3835
|
+
ordinal: result.ordinal ?? null,
|
|
3836
|
+
ok: result.ok !== false,
|
|
3837
|
+
script_length: result.script_length ?? null,
|
|
3838
|
+
return_captured: result.return_captured ?? null,
|
|
3839
|
+
return_stored_to: result.return_stored_to ?? null,
|
|
3840
|
+
reason: result.reason || result.error || result.store_reason || null,
|
|
3841
|
+
};
|
|
3842
|
+
if (result.returned !== undefined) receipt.returned = result.returned;
|
|
3843
|
+
if (result.expected_return !== undefined) receipt.expected_return = result.expected_return;
|
|
3844
|
+
return receipt;
|
|
3845
|
+
});
|
|
3846
|
+
}
|
|
3792
3847
|
function sampleProfileSetupSummaryItems(items, limit) {
|
|
3793
3848
|
if ((items || []).length <= limit) return items || [];
|
|
3794
3849
|
const firstCount = Math.floor(limit / 2);
|
|
@@ -3803,14 +3858,28 @@ function profileScreenshotLabels(viewports) {
|
|
|
3803
3858
|
}
|
|
3804
3859
|
return labels;
|
|
3805
3860
|
}
|
|
3806
|
-
function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewport) {
|
|
3861
|
+
function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewport, finalScreenshotFullPage) {
|
|
3862
|
+
const normalizedFinalScreenshotFullPage = finalScreenshotFullPage === undefined
|
|
3863
|
+
? undefined
|
|
3864
|
+
: finalScreenshotFullPage !== false;
|
|
3865
|
+
const finalScreenshotCount = (viewports || []).filter((viewport) => viewport && typeof viewport.screenshot_label === "string" && viewport.screenshot_label.trim()).length;
|
|
3807
3866
|
return {
|
|
3808
3867
|
viewport_count: (viewports || []).length,
|
|
3809
3868
|
action_count: actionCount ?? null,
|
|
3869
|
+
final_screenshot_count: finalScreenshotCount,
|
|
3870
|
+
final_screenshot_full_page: normalizedFinalScreenshotFullPage ?? null,
|
|
3871
|
+
final_screenshot_mode: normalizedFinalScreenshotFullPage === undefined
|
|
3872
|
+
? null
|
|
3873
|
+
: normalizedFinalScreenshotFullPage
|
|
3874
|
+
? "full_page"
|
|
3875
|
+
: "viewport",
|
|
3810
3876
|
viewports: (viewports || []).map((viewport) => {
|
|
3811
3877
|
const expectedActionCount = expectedActionCountsByViewport && expectedActionCountsByViewport[viewport.name] !== undefined
|
|
3812
3878
|
? expectedActionCountsByViewport[viewport.name]
|
|
3813
3879
|
: actionCount;
|
|
3880
|
+
const viewportFinalScreenshotFullPage = typeof viewport.screenshot_full_page === "boolean"
|
|
3881
|
+
? viewport.screenshot_full_page
|
|
3882
|
+
: normalizedFinalScreenshotFullPage;
|
|
3814
3883
|
const results = viewport.setup_action_results || [];
|
|
3815
3884
|
const failed = results.filter((result) => result && result.ok === false && result.optional !== true);
|
|
3816
3885
|
const optionalFailed = results.filter((result) => result && result.ok === false && result.optional === true);
|
|
@@ -3827,6 +3896,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
|
|
|
3827
3896
|
const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
|
|
3828
3897
|
const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
|
|
3829
3898
|
const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
|
|
3899
|
+
const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
|
|
3900
|
+
const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
|
|
3901
|
+
const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
|
|
3902
|
+
const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
|
|
3830
3903
|
const clickedItems = results
|
|
3831
3904
|
.filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
|
|
3832
3905
|
.map((result) => {
|
|
@@ -3864,6 +3937,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
|
|
|
3864
3937
|
action_counts: profileSetupActionCounts(results),
|
|
3865
3938
|
frame_action_count: results.filter((result) => result && result.frame_selector).length,
|
|
3866
3939
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
3940
|
+
final_screenshot: viewport.screenshot_label || null,
|
|
3941
|
+
final_screenshot_full_page: viewportFinalScreenshotFullPage ?? null,
|
|
3867
3942
|
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
3868
3943
|
clicked_total: clickedItems.length,
|
|
3869
3944
|
clicked_truncated: clickedItems.length > clicked.length,
|
|
@@ -3878,6 +3953,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
|
|
|
3878
3953
|
window_call_captured_total: windowCallCapturedTotal,
|
|
3879
3954
|
window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
|
|
3880
3955
|
window_call: sampledWindowCallReceipts,
|
|
3956
|
+
window_eval_total: windowEvalReceipts.length,
|
|
3957
|
+
window_eval_stored_total: windowEvalStoredTotal,
|
|
3958
|
+
window_eval_captured_total: windowEvalCapturedTotal,
|
|
3959
|
+
window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
|
|
3960
|
+
window_eval: sampledWindowEvalReceipts,
|
|
3881
3961
|
clicked,
|
|
3882
3962
|
text_samples: textSamples,
|
|
3883
3963
|
failed: failed.map((result) => ({
|
|
@@ -4048,7 +4128,7 @@ function assessProfile(profile, evidence) {
|
|
|
4048
4128
|
&& (viewport.setup_action_results || []).every((result) => !result || result.ok !== false || result.optional === true),
|
|
4049
4129
|
result_count: (viewport.setup_action_results || []).length,
|
|
4050
4130
|
})),
|
|
4051
|
-
setup_summary: profileSetupSummary(viewports, actionCount, expectedActionCountsByViewport),
|
|
4131
|
+
setup_summary: profileSetupSummary(viewports, actionCount, expectedActionCountsByViewport, profile.target && profile.target.screenshot_full_page),
|
|
4052
4132
|
failed,
|
|
4053
4133
|
},
|
|
4054
4134
|
message: failed.length ? "Setup actions failed in " + failed.length + " viewport action(s)." : undefined,
|
|
@@ -4858,6 +4938,49 @@ async function setupCallWindowFunction(context, path, args, storeReturnTo, captu
|
|
|
4858
4938
|
}
|
|
4859
4939
|
}, { path, args, storeReturnTo, captureReturn });
|
|
4860
4940
|
}
|
|
4941
|
+
async function setupEvaluateWindowScript(context, script, args, storeReturnTo, captureReturn) {
|
|
4942
|
+
return await context.evaluate(async ({ script, args, storeReturnTo, captureReturn }) => {
|
|
4943
|
+
const toJsonValue = (value) => {
|
|
4944
|
+
if (value === null || value === undefined) return null;
|
|
4945
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
4946
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
4947
|
+
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
4948
|
+
if (typeof value === "object") {
|
|
4949
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
4950
|
+
}
|
|
4951
|
+
return String(value);
|
|
4952
|
+
};
|
|
4953
|
+
const storeWindowReturn = (storePath, value) => {
|
|
4954
|
+
const pathParts = String(storePath || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
4955
|
+
if (pathParts[0] === "window") pathParts.shift();
|
|
4956
|
+
if (!pathParts.length) return { ok: false, reason: "missing_store_path" };
|
|
4957
|
+
let target = window;
|
|
4958
|
+
for (let index = 0; index < pathParts.length - 1; index += 1) {
|
|
4959
|
+
const part = pathParts[index];
|
|
4960
|
+
if (target[part] === null || typeof target[part] !== "object") target[part] = {};
|
|
4961
|
+
target = target[part];
|
|
4962
|
+
}
|
|
4963
|
+
target[pathParts[pathParts.length - 1]] = value;
|
|
4964
|
+
return { ok: true, path: pathParts.join(".") };
|
|
4965
|
+
};
|
|
4966
|
+
const body = String(script || "");
|
|
4967
|
+
if (!body.trim()) return { ok: false, reason: "missing_script" };
|
|
4968
|
+
try {
|
|
4969
|
+
const run = new Function("args", "\"use strict\"; return (async () => {\\n" + body + "\\n})();");
|
|
4970
|
+
const returned = await run(Array.isArray(args) ? args : []);
|
|
4971
|
+
const jsonReturned = toJsonValue(returned);
|
|
4972
|
+
const returnedForResult = captureReturn === false ? undefined : jsonReturned;
|
|
4973
|
+
if (storeReturnTo) {
|
|
4974
|
+
const stored = storeWindowReturn(storeReturnTo, jsonReturned);
|
|
4975
|
+
if (!stored.ok) return { ok: false, reason: "return_store_failed", store_reason: stored.reason, returned: returnedForResult };
|
|
4976
|
+
return { ok: true, returned: returnedForResult, return_stored_to: stored.path };
|
|
4977
|
+
}
|
|
4978
|
+
return { ok: true, returned: returnedForResult };
|
|
4979
|
+
} catch (error) {
|
|
4980
|
+
return { ok: false, reason: "script_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
4981
|
+
}
|
|
4982
|
+
}, { script, args, storeReturnTo, captureReturn });
|
|
4983
|
+
}
|
|
4861
4984
|
function setupFrameSelector(action) {
|
|
4862
4985
|
return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
|
|
4863
4986
|
}
|
|
@@ -5371,6 +5494,44 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
5371
5494
|
}
|
|
5372
5495
|
return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
|
|
5373
5496
|
}
|
|
5497
|
+
if (type === "window_eval") {
|
|
5498
|
+
const script = String(action.script || action.code || action.source || action.body || "");
|
|
5499
|
+
const args = Array.isArray(action.args) ? action.args : [];
|
|
5500
|
+
const storeReturnTo = String(action.store_return_to || action.storeReturnTo || action.save_return_to || action.saveReturnTo || action.assign_return_to || action.assignReturnTo || action.return_state_path || action.returnStatePath || "").trim();
|
|
5501
|
+
if (!script.trim()) return { ...base, reason: "missing_script" };
|
|
5502
|
+
const scope = await setupActionScope(action, timeout);
|
|
5503
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
5504
|
+
const hasExpectation = setupHasOwn(action, "expect_return")
|
|
5505
|
+
|| setupHasOwn(action, "expectReturn")
|
|
5506
|
+
|| setupHasOwn(action, "expected_return")
|
|
5507
|
+
|| setupHasOwn(action, "expectedReturn");
|
|
5508
|
+
const expected = setupHasOwn(action, "expect_return")
|
|
5509
|
+
? action.expect_return
|
|
5510
|
+
: setupHasOwn(action, "expectReturn")
|
|
5511
|
+
? action.expectReturn
|
|
5512
|
+
: setupHasOwn(action, "expected_return")
|
|
5513
|
+
? action.expected_return
|
|
5514
|
+
: action.expectedReturn;
|
|
5515
|
+
const captureReturn = action.capture_return === false || action.captureReturn === false || action.include_return === false || action.includeReturn === false || action.omit_return === true || action.omitReturn === true
|
|
5516
|
+
? hasExpectation
|
|
5517
|
+
: true;
|
|
5518
|
+
const result = await setupEvaluateWindowScript(scope.context, script, args, storeReturnTo, captureReturn);
|
|
5519
|
+
const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
|
|
5520
|
+
return {
|
|
5521
|
+
...base,
|
|
5522
|
+
...setupScopeEvidence(scope),
|
|
5523
|
+
ok: Boolean(result.ok && expectationMet),
|
|
5524
|
+
script_length: script.length,
|
|
5525
|
+
arg_count: args.length,
|
|
5526
|
+
returned: captureReturn ? setupJsonValue(result.returned) : undefined,
|
|
5527
|
+
return_captured: captureReturn,
|
|
5528
|
+
expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
|
|
5529
|
+
return_stored_to: result.return_stored_to || storeReturnTo || undefined,
|
|
5530
|
+
reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
|
|
5531
|
+
store_reason: result.store_reason || undefined,
|
|
5532
|
+
error: result.error || undefined,
|
|
5533
|
+
};
|
|
5534
|
+
}
|
|
5374
5535
|
if (type === "window_call") {
|
|
5375
5536
|
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
5376
5537
|
const args = Array.isArray(action.args) ? action.args : [];
|
|
@@ -6926,9 +7087,13 @@ async function captureViewport(viewport) {
|
|
|
6926
7087
|
}
|
|
6927
7088
|
}
|
|
6928
7089
|
const screenshotLabel = profileSlug + "-" + viewport.name;
|
|
7090
|
+
let screenshotFullPage = null;
|
|
6929
7091
|
try {
|
|
6930
7092
|
const screenshotOptions = {};
|
|
6931
|
-
if (profile.target && profile.target.screenshot_full_page !== undefined)
|
|
7093
|
+
if (profile.target && profile.target.screenshot_full_page !== undefined) {
|
|
7094
|
+
screenshotFullPage = profile.target.screenshot_full_page !== false;
|
|
7095
|
+
screenshotOptions.fullPage = screenshotFullPage;
|
|
7096
|
+
}
|
|
6932
7097
|
if (typeof saveScreenshot === "function") await saveScreenshot(screenshotLabel, screenshotOptions);
|
|
6933
7098
|
} catch (error) {
|
|
6934
7099
|
pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
|
|
@@ -6996,6 +7161,7 @@ async function captureViewport(viewport) {
|
|
|
6996
7161
|
route_inventory: routeInventory,
|
|
6997
7162
|
setup_action_results: setupActionResults,
|
|
6998
7163
|
screenshot_label: screenshotLabel,
|
|
7164
|
+
screenshot_full_page: screenshotFullPage,
|
|
6999
7165
|
navigation_error: navigationError,
|
|
7000
7166
|
wait_error: waitError,
|
|
7001
7167
|
};
|