@riddledc/riddle-proof 0.7.131 → 0.7.133
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 +6 -1
- package/dist/{chunk-ZYD2SGEM.js → chunk-TA2KLHMX.js} +182 -32
- package/dist/cli.cjs +195 -32
- package/dist/cli.js +14 -1
- package/dist/index.cjs +182 -32
- package/dist/index.js +1 -1
- package/dist/profile.cjs +182 -32
- package/dist/profile.d.cts +5 -1
- package/dist/profile.d.ts +5 -1
- package/dist/profile.js +1 -1
- package/dist/proof-run-engine.d.cts +3 -3
- package/dist/proof-run-engine.d.ts +3 -3
- 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
|
-
and `
|
|
404
|
+
`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,11 @@ 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_call_until` when a proof helper needs to advance randomized or
|
|
451
|
+
progressive state until a window-state receipt is true. It accepts `path` plus
|
|
452
|
+
optional `args`, `until_path`, `until_expected_value`, `max_calls` from 1 to
|
|
453
|
+
100, and optional `interval_ms`; the action stops early when the predicate is
|
|
454
|
+
met and records `call_count`, final `returned`, and final `until_value`.
|
|
450
455
|
Use `screenshot` with an optional `label` to capture durable Riddle screenshots
|
|
451
456
|
at important setup milestones, such as after a route switch, terminal state, or
|
|
452
457
|
reset. These labels are recorded in setup evidence and included in profile
|
|
@@ -61,7 +61,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
61
61
|
"wait",
|
|
62
62
|
"wait_for_selector",
|
|
63
63
|
"wait_for_text",
|
|
64
|
-
"window_call"
|
|
64
|
+
"window_call",
|
|
65
|
+
"window_call_until"
|
|
65
66
|
];
|
|
66
67
|
var RIDDLE_PROOF_PROFILE_NETWORK_ABORT_ERROR_CODES = [
|
|
67
68
|
"aborted",
|
|
@@ -515,14 +516,16 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
|
|
|
515
516
|
action: profileSetupResultAction(result),
|
|
516
517
|
selector: result.selector ?? null,
|
|
517
518
|
frame_selector: result.frame_selector ?? null,
|
|
518
|
-
reason: result.reason ?? result.error ?? null
|
|
519
|
+
reason: result.reason ?? result.error ?? null,
|
|
520
|
+
case_insensitive_text: compactProfileSetupSummaryText(result.case_insensitive_text)
|
|
519
521
|
})),
|
|
520
522
|
optional_failed: optionalFailed.map((result) => ({
|
|
521
523
|
ordinal: result.ordinal ?? null,
|
|
522
524
|
action: profileSetupResultAction(result),
|
|
523
525
|
selector: result.selector ?? null,
|
|
524
526
|
frame_selector: result.frame_selector ?? null,
|
|
525
|
-
reason: result.reason ?? result.error ?? null
|
|
527
|
+
reason: result.reason ?? result.error ?? null,
|
|
528
|
+
case_insensitive_text: compactProfileSetupSummaryText(result.case_insensitive_text)
|
|
526
529
|
}))
|
|
527
530
|
};
|
|
528
531
|
})
|
|
@@ -558,7 +561,7 @@ function isSupportedCheckType(value) {
|
|
|
558
561
|
}
|
|
559
562
|
function normalizeSetupActionType(value, index) {
|
|
560
563
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
561
|
-
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;
|
|
564
|
+
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;
|
|
562
565
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
563
566
|
return normalized;
|
|
564
567
|
}
|
|
@@ -689,10 +692,10 @@ function normalizeSetupAction(input, index) {
|
|
|
689
692
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
690
693
|
}
|
|
691
694
|
const path = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
|
|
692
|
-
if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path) {
|
|
695
|
+
if ((type === "window_call" || type === "window_call_until" || type === "assert_window_value" || type === "assert_window_number") && !path) {
|
|
693
696
|
throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
|
|
694
697
|
}
|
|
695
|
-
const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
698
|
+
const args = type === "window_call" || type === "window_call_until" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
696
699
|
const hasExpectedValue = hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected") || hasOwn(input, "expect_value") || hasOwn(input, "expectValue") || hasOwn(input, "expect");
|
|
697
700
|
if (type === "assert_window_value" && !hasExpectedValue) {
|
|
698
701
|
throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
|
|
@@ -709,6 +712,24 @@ function normalizeSetupAction(input, index) {
|
|
|
709
712
|
}
|
|
710
713
|
}
|
|
711
714
|
const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
|
|
715
|
+
const untilPath = stringFromOwn(input, "until_path", "untilPath", "until_state_path", "untilStatePath", "until_window_path", "untilWindowPath", "until");
|
|
716
|
+
const hasUntilExpectedValue = hasOwn(input, "until_expected_value") || hasOwn(input, "untilExpectedValue") || hasOwn(input, "until_expected") || hasOwn(input, "untilExpected") || hasOwn(input, "until_value") || hasOwn(input, "untilValue") || hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected");
|
|
717
|
+
if (type === "window_call_until") {
|
|
718
|
+
if (!untilPath) {
|
|
719
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires until_path.`);
|
|
720
|
+
}
|
|
721
|
+
if (!hasUntilExpectedValue) {
|
|
722
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires until_expected_value.`);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
const maxCalls = numberValue(valueFromOwn(input, "max_calls", "maxCalls", "max_attempts", "maxAttempts", "attempts"));
|
|
726
|
+
if (type === "window_call_until" && (maxCalls === void 0 || !Number.isInteger(maxCalls) || maxCalls < 1 || maxCalls > 100)) {
|
|
727
|
+
throw new Error(`target.setup_actions[${index}].max_calls must be an integer from 1 to 100.`);
|
|
728
|
+
}
|
|
729
|
+
const intervalMs = numberValue(valueFromOwn(input, "interval_ms", "intervalMs", "poll_ms", "pollMs", "call_interval_ms", "callIntervalMs"));
|
|
730
|
+
if (type === "window_call_until" && intervalMs !== void 0 && (!Number.isInteger(intervalMs) || intervalMs < 0 || intervalMs > 5e3)) {
|
|
731
|
+
throw new Error(`target.setup_actions[${index}].interval_ms must be an integer from 0 to 5000.`);
|
|
732
|
+
}
|
|
712
733
|
const steps = numberValue(input.steps);
|
|
713
734
|
if (type === "drag" && steps !== void 0 && (!Number.isInteger(steps) || steps < 1 || steps > 100)) {
|
|
714
735
|
throw new Error(`target.setup_actions[${index}].steps must be an integer from 1 to 100.`);
|
|
@@ -735,6 +756,10 @@ function normalizeSetupAction(input, index) {
|
|
|
735
756
|
path,
|
|
736
757
|
args,
|
|
737
758
|
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
759
|
+
until_path: untilPath,
|
|
760
|
+
until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
|
|
761
|
+
max_calls: maxCalls,
|
|
762
|
+
interval_ms: intervalMs,
|
|
738
763
|
expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
|
|
739
764
|
min_value: minValue,
|
|
740
765
|
max_value: maxValue,
|
|
@@ -3687,6 +3712,7 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
|
|
|
3687
3712
|
selector: result.selector ?? null,
|
|
3688
3713
|
frame_selector: result.frame_selector ?? null,
|
|
3689
3714
|
reason: result.reason || result.error || null,
|
|
3715
|
+
case_insensitive_text: compactProfileSetupSummaryText(result.case_insensitive_text),
|
|
3690
3716
|
})),
|
|
3691
3717
|
optional_failed: optionalFailed.map((result) => ({
|
|
3692
3718
|
ordinal: result.ordinal ?? null,
|
|
@@ -3694,6 +3720,7 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
|
|
|
3694
3720
|
selector: result.selector ?? null,
|
|
3695
3721
|
frame_selector: result.frame_selector ?? null,
|
|
3696
3722
|
reason: result.reason || result.error || null,
|
|
3723
|
+
case_insensitive_text: compactProfileSetupSummaryText(result.case_insensitive_text),
|
|
3697
3724
|
})),
|
|
3698
3725
|
};
|
|
3699
3726
|
}),
|
|
@@ -4609,6 +4636,34 @@ async function setupReadWindowValue(context, path) {
|
|
|
4609
4636
|
return { ok: true, value: toJsonValue(current) };
|
|
4610
4637
|
}, { path });
|
|
4611
4638
|
}
|
|
4639
|
+
async function setupCallWindowFunction(context, path, args) {
|
|
4640
|
+
return await context.evaluate(async ({ path, args }) => {
|
|
4641
|
+
const toJsonValue = (value) => {
|
|
4642
|
+
if (value === null || value === undefined) return null;
|
|
4643
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
4644
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
4645
|
+
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
4646
|
+
if (typeof value === "object") {
|
|
4647
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
4648
|
+
}
|
|
4649
|
+
return String(value);
|
|
4650
|
+
};
|
|
4651
|
+
const pathParts = String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
4652
|
+
let parent = window;
|
|
4653
|
+
let current = window;
|
|
4654
|
+
for (const part of pathParts) {
|
|
4655
|
+
parent = current;
|
|
4656
|
+
current = current?.[part];
|
|
4657
|
+
}
|
|
4658
|
+
if (typeof current !== "function") return { ok: false, reason: "missing_function" };
|
|
4659
|
+
try {
|
|
4660
|
+
const returned = await current.apply(parent, Array.isArray(args) ? args : []);
|
|
4661
|
+
return { ok: true, returned: toJsonValue(returned) };
|
|
4662
|
+
} catch (error) {
|
|
4663
|
+
return { ok: false, reason: "function_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
4664
|
+
}
|
|
4665
|
+
}, { path, args });
|
|
4666
|
+
}
|
|
4612
4667
|
function setupFrameSelector(action) {
|
|
4613
4668
|
return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
|
|
4614
4669
|
}
|
|
@@ -5126,32 +5181,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
5126
5181
|
if (!path) return { ...base, path, reason: "missing_path" };
|
|
5127
5182
|
const scope = await setupActionScope(action, timeout);
|
|
5128
5183
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
5129
|
-
const result = await scope.context
|
|
5130
|
-
const toJsonValue = (value) => {
|
|
5131
|
-
if (value === null || value === undefined) return null;
|
|
5132
|
-
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
5133
|
-
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
5134
|
-
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
5135
|
-
if (typeof value === "object") {
|
|
5136
|
-
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
5137
|
-
}
|
|
5138
|
-
return String(value);
|
|
5139
|
-
};
|
|
5140
|
-
const pathParts = String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
5141
|
-
let parent = window;
|
|
5142
|
-
let current = window;
|
|
5143
|
-
for (const part of pathParts) {
|
|
5144
|
-
parent = current;
|
|
5145
|
-
current = current?.[part];
|
|
5146
|
-
}
|
|
5147
|
-
if (typeof current !== "function") return { ok: false, reason: "missing_function" };
|
|
5148
|
-
try {
|
|
5149
|
-
const returned = await current.apply(parent, Array.isArray(args) ? args : []);
|
|
5150
|
-
return { ok: true, returned: toJsonValue(returned) };
|
|
5151
|
-
} catch (error) {
|
|
5152
|
-
return { ok: false, reason: "function_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
5153
|
-
}
|
|
5154
|
-
}, { path, args });
|
|
5184
|
+
const result = await setupCallWindowFunction(scope.context, path, args);
|
|
5155
5185
|
const hasExpectation = setupHasOwn(action, "expect_return")
|
|
5156
5186
|
|| setupHasOwn(action, "expectReturn")
|
|
5157
5187
|
|| setupHasOwn(action, "expected_return")
|
|
@@ -5176,6 +5206,126 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
5176
5206
|
error: result.error || undefined,
|
|
5177
5207
|
};
|
|
5178
5208
|
}
|
|
5209
|
+
if (type === "window_call_until") {
|
|
5210
|
+
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
5211
|
+
const untilPath = String(action.until_path || action.untilPath || action.until_state_path || action.untilStatePath || action.until_window_path || action.untilWindowPath || action.until || "");
|
|
5212
|
+
const args = Array.isArray(action.args) ? action.args : [];
|
|
5213
|
+
if (!path) return { ...base, path, reason: "missing_path" };
|
|
5214
|
+
if (!untilPath) return { ...base, path, reason: "missing_until_path" };
|
|
5215
|
+
const hasUntilExpected = setupHasOwn(action, "until_expected_value")
|
|
5216
|
+
|| setupHasOwn(action, "untilExpectedValue")
|
|
5217
|
+
|| setupHasOwn(action, "until_expected")
|
|
5218
|
+
|| setupHasOwn(action, "untilExpected")
|
|
5219
|
+
|| setupHasOwn(action, "until_value")
|
|
5220
|
+
|| setupHasOwn(action, "untilValue")
|
|
5221
|
+
|| setupHasOwn(action, "expected_value")
|
|
5222
|
+
|| setupHasOwn(action, "expectedValue")
|
|
5223
|
+
|| setupHasOwn(action, "expected");
|
|
5224
|
+
const untilExpected = setupHasOwn(action, "until_expected_value")
|
|
5225
|
+
? action.until_expected_value
|
|
5226
|
+
: setupHasOwn(action, "untilExpectedValue")
|
|
5227
|
+
? action.untilExpectedValue
|
|
5228
|
+
: setupHasOwn(action, "until_expected")
|
|
5229
|
+
? action.until_expected
|
|
5230
|
+
: setupHasOwn(action, "untilExpected")
|
|
5231
|
+
? action.untilExpected
|
|
5232
|
+
: setupHasOwn(action, "until_value")
|
|
5233
|
+
? action.until_value
|
|
5234
|
+
: setupHasOwn(action, "untilValue")
|
|
5235
|
+
? action.untilValue
|
|
5236
|
+
: setupHasOwn(action, "expected_value")
|
|
5237
|
+
? action.expected_value
|
|
5238
|
+
: setupHasOwn(action, "expectedValue")
|
|
5239
|
+
? action.expectedValue
|
|
5240
|
+
: action.expected;
|
|
5241
|
+
if (!hasUntilExpected) return { ...base, path, until_path: untilPath, reason: "missing_until_expected_value" };
|
|
5242
|
+
const maxCalls = Math.min(100, Math.max(1, Math.floor(setupNumber(action.max_calls ?? action.maxCalls ?? action.max_attempts ?? action.maxAttempts ?? action.attempts, 1) || 1)));
|
|
5243
|
+
const intervalMs = Math.min(5000, Math.max(0, Math.floor(setupNumber(action.interval_ms ?? action.intervalMs ?? action.poll_ms ?? action.pollMs ?? action.call_interval_ms ?? action.callIntervalMs, 100) || 0)));
|
|
5244
|
+
const hasReturnExpectation = setupHasOwn(action, "expect_return")
|
|
5245
|
+
|| setupHasOwn(action, "expectReturn")
|
|
5246
|
+
|| setupHasOwn(action, "expected_return")
|
|
5247
|
+
|| setupHasOwn(action, "expectedReturn");
|
|
5248
|
+
const expectedReturn = setupHasOwn(action, "expect_return")
|
|
5249
|
+
? action.expect_return
|
|
5250
|
+
: setupHasOwn(action, "expectReturn")
|
|
5251
|
+
? action.expectReturn
|
|
5252
|
+
: setupHasOwn(action, "expected_return")
|
|
5253
|
+
? action.expected_return
|
|
5254
|
+
: action.expectedReturn;
|
|
5255
|
+
const scope = await setupActionScope(action, timeout);
|
|
5256
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
5257
|
+
const startedAt = Date.now();
|
|
5258
|
+
let callCount = 0;
|
|
5259
|
+
let lastCallResult = null;
|
|
5260
|
+
let lastPredicateResult = await setupReadWindowValue(scope.context, untilPath);
|
|
5261
|
+
if (lastPredicateResult.ok && setupValuesEqual(lastPredicateResult.value, untilExpected)) {
|
|
5262
|
+
return {
|
|
5263
|
+
...base,
|
|
5264
|
+
...setupScopeEvidence(scope),
|
|
5265
|
+
ok: true,
|
|
5266
|
+
path,
|
|
5267
|
+
arg_count: args.length,
|
|
5268
|
+
until_path: untilPath,
|
|
5269
|
+
until_value: setupJsonValue(lastPredicateResult.value),
|
|
5270
|
+
until_expected_value: setupJsonValue(untilExpected),
|
|
5271
|
+
call_count: callCount,
|
|
5272
|
+
max_calls: maxCalls,
|
|
5273
|
+
interval_ms: intervalMs,
|
|
5274
|
+
timeout_ms: timeout,
|
|
5275
|
+
};
|
|
5276
|
+
}
|
|
5277
|
+
while (callCount < maxCalls && Date.now() - startedAt <= timeout) {
|
|
5278
|
+
lastCallResult = await setupCallWindowFunction(scope.context, path, args);
|
|
5279
|
+
callCount += 1;
|
|
5280
|
+
if (!lastCallResult.ok) break;
|
|
5281
|
+
if (hasReturnExpectation && !setupValuesEqual(lastCallResult.returned, expectedReturn)) break;
|
|
5282
|
+
lastPredicateResult = await setupReadWindowValue(scope.context, untilPath);
|
|
5283
|
+
if (lastPredicateResult.ok && setupValuesEqual(lastPredicateResult.value, untilExpected)) {
|
|
5284
|
+
return {
|
|
5285
|
+
...base,
|
|
5286
|
+
...setupScopeEvidence(scope),
|
|
5287
|
+
ok: true,
|
|
5288
|
+
path,
|
|
5289
|
+
arg_count: args.length,
|
|
5290
|
+
returned: setupJsonValue(lastCallResult.returned),
|
|
5291
|
+
expected_return: hasReturnExpectation ? setupJsonValue(expectedReturn) : undefined,
|
|
5292
|
+
until_path: untilPath,
|
|
5293
|
+
until_value: setupJsonValue(lastPredicateResult.value),
|
|
5294
|
+
until_expected_value: setupJsonValue(untilExpected),
|
|
5295
|
+
call_count: callCount,
|
|
5296
|
+
max_calls: maxCalls,
|
|
5297
|
+
interval_ms: intervalMs,
|
|
5298
|
+
timeout_ms: timeout,
|
|
5299
|
+
};
|
|
5300
|
+
}
|
|
5301
|
+
if (callCount < maxCalls && intervalMs) await page.waitForTimeout(intervalMs);
|
|
5302
|
+
}
|
|
5303
|
+
const returnExpectationMet = !hasReturnExpectation || setupValuesEqual(lastCallResult?.returned, expectedReturn);
|
|
5304
|
+
return {
|
|
5305
|
+
...base,
|
|
5306
|
+
...setupScopeEvidence(scope),
|
|
5307
|
+
path,
|
|
5308
|
+
arg_count: args.length,
|
|
5309
|
+
returned: setupJsonValue(lastCallResult?.returned),
|
|
5310
|
+
expected_return: hasReturnExpectation ? setupJsonValue(expectedReturn) : undefined,
|
|
5311
|
+
until_path: untilPath,
|
|
5312
|
+
until_value: setupJsonValue(lastPredicateResult?.value),
|
|
5313
|
+
until_expected_value: setupJsonValue(untilExpected),
|
|
5314
|
+
call_count: callCount,
|
|
5315
|
+
max_calls: maxCalls,
|
|
5316
|
+
interval_ms: intervalMs,
|
|
5317
|
+
timeout_ms: timeout,
|
|
5318
|
+
reason: lastCallResult && !lastCallResult.ok
|
|
5319
|
+
? lastCallResult.reason
|
|
5320
|
+
: hasReturnExpectation && !returnExpectationMet
|
|
5321
|
+
? "unexpected_return_value"
|
|
5322
|
+
: Date.now() - startedAt > timeout
|
|
5323
|
+
? "timeout"
|
|
5324
|
+
: "until_condition_not_met",
|
|
5325
|
+
error: lastCallResult?.error || undefined,
|
|
5326
|
+
missing_part: lastPredicateResult?.missing_part || undefined,
|
|
5327
|
+
};
|
|
5328
|
+
}
|
|
5179
5329
|
if (type === "assert_window_value") {
|
|
5180
5330
|
const path = String(action.path || action.window_path || action.windowPath || "");
|
|
5181
5331
|
const hasExpected = setupHasOwn(action, "expected_value")
|
package/dist/cli.cjs
CHANGED
|
@@ -6998,7 +6998,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
6998
6998
|
"wait",
|
|
6999
6999
|
"wait_for_selector",
|
|
7000
7000
|
"wait_for_text",
|
|
7001
|
-
"window_call"
|
|
7001
|
+
"window_call",
|
|
7002
|
+
"window_call_until"
|
|
7002
7003
|
];
|
|
7003
7004
|
var RIDDLE_PROOF_PROFILE_NETWORK_ABORT_ERROR_CODES = [
|
|
7004
7005
|
"aborted",
|
|
@@ -7452,14 +7453,16 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
|
|
|
7452
7453
|
action: profileSetupResultAction(result),
|
|
7453
7454
|
selector: result.selector ?? null,
|
|
7454
7455
|
frame_selector: result.frame_selector ?? null,
|
|
7455
|
-
reason: result.reason ?? result.error ?? null
|
|
7456
|
+
reason: result.reason ?? result.error ?? null,
|
|
7457
|
+
case_insensitive_text: compactProfileSetupSummaryText(result.case_insensitive_text)
|
|
7456
7458
|
})),
|
|
7457
7459
|
optional_failed: optionalFailed.map((result) => ({
|
|
7458
7460
|
ordinal: result.ordinal ?? null,
|
|
7459
7461
|
action: profileSetupResultAction(result),
|
|
7460
7462
|
selector: result.selector ?? null,
|
|
7461
7463
|
frame_selector: result.frame_selector ?? null,
|
|
7462
|
-
reason: result.reason ?? result.error ?? null
|
|
7464
|
+
reason: result.reason ?? result.error ?? null,
|
|
7465
|
+
case_insensitive_text: compactProfileSetupSummaryText(result.case_insensitive_text)
|
|
7463
7466
|
}))
|
|
7464
7467
|
};
|
|
7465
7468
|
})
|
|
@@ -7495,7 +7498,7 @@ function isSupportedCheckType(value) {
|
|
|
7495
7498
|
}
|
|
7496
7499
|
function normalizeSetupActionType(value, index) {
|
|
7497
7500
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
7498
|
-
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;
|
|
7501
|
+
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;
|
|
7499
7502
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
7500
7503
|
return normalized;
|
|
7501
7504
|
}
|
|
@@ -7626,10 +7629,10 @@ function normalizeSetupAction(input, index) {
|
|
|
7626
7629
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
7627
7630
|
}
|
|
7628
7631
|
const path7 = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
|
|
7629
|
-
if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path7) {
|
|
7632
|
+
if ((type === "window_call" || type === "window_call_until" || type === "assert_window_value" || type === "assert_window_number") && !path7) {
|
|
7630
7633
|
throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
|
|
7631
7634
|
}
|
|
7632
|
-
const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
7635
|
+
const args = type === "window_call" || type === "window_call_until" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
7633
7636
|
const hasExpectedValue = hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected") || hasOwn(input, "expect_value") || hasOwn(input, "expectValue") || hasOwn(input, "expect");
|
|
7634
7637
|
if (type === "assert_window_value" && !hasExpectedValue) {
|
|
7635
7638
|
throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
|
|
@@ -7646,6 +7649,24 @@ function normalizeSetupAction(input, index) {
|
|
|
7646
7649
|
}
|
|
7647
7650
|
}
|
|
7648
7651
|
const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
|
|
7652
|
+
const untilPath = stringFromOwn(input, "until_path", "untilPath", "until_state_path", "untilStatePath", "until_window_path", "untilWindowPath", "until");
|
|
7653
|
+
const hasUntilExpectedValue = hasOwn(input, "until_expected_value") || hasOwn(input, "untilExpectedValue") || hasOwn(input, "until_expected") || hasOwn(input, "untilExpected") || hasOwn(input, "until_value") || hasOwn(input, "untilValue") || hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected");
|
|
7654
|
+
if (type === "window_call_until") {
|
|
7655
|
+
if (!untilPath) {
|
|
7656
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires until_path.`);
|
|
7657
|
+
}
|
|
7658
|
+
if (!hasUntilExpectedValue) {
|
|
7659
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires until_expected_value.`);
|
|
7660
|
+
}
|
|
7661
|
+
}
|
|
7662
|
+
const maxCalls = numberValue(valueFromOwn(input, "max_calls", "maxCalls", "max_attempts", "maxAttempts", "attempts"));
|
|
7663
|
+
if (type === "window_call_until" && (maxCalls === void 0 || !Number.isInteger(maxCalls) || maxCalls < 1 || maxCalls > 100)) {
|
|
7664
|
+
throw new Error(`target.setup_actions[${index}].max_calls must be an integer from 1 to 100.`);
|
|
7665
|
+
}
|
|
7666
|
+
const intervalMs = numberValue(valueFromOwn(input, "interval_ms", "intervalMs", "poll_ms", "pollMs", "call_interval_ms", "callIntervalMs"));
|
|
7667
|
+
if (type === "window_call_until" && intervalMs !== void 0 && (!Number.isInteger(intervalMs) || intervalMs < 0 || intervalMs > 5e3)) {
|
|
7668
|
+
throw new Error(`target.setup_actions[${index}].interval_ms must be an integer from 0 to 5000.`);
|
|
7669
|
+
}
|
|
7649
7670
|
const steps = numberValue(input.steps);
|
|
7650
7671
|
if (type === "drag" && steps !== void 0 && (!Number.isInteger(steps) || steps < 1 || steps > 100)) {
|
|
7651
7672
|
throw new Error(`target.setup_actions[${index}].steps must be an integer from 1 to 100.`);
|
|
@@ -7672,6 +7693,10 @@ function normalizeSetupAction(input, index) {
|
|
|
7672
7693
|
path: path7,
|
|
7673
7694
|
args,
|
|
7674
7695
|
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
7696
|
+
until_path: untilPath,
|
|
7697
|
+
until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
|
|
7698
|
+
max_calls: maxCalls,
|
|
7699
|
+
interval_ms: intervalMs,
|
|
7675
7700
|
expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
|
|
7676
7701
|
min_value: minValue,
|
|
7677
7702
|
max_value: maxValue,
|
|
@@ -10608,6 +10633,7 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
|
|
|
10608
10633
|
selector: result.selector ?? null,
|
|
10609
10634
|
frame_selector: result.frame_selector ?? null,
|
|
10610
10635
|
reason: result.reason || result.error || null,
|
|
10636
|
+
case_insensitive_text: compactProfileSetupSummaryText(result.case_insensitive_text),
|
|
10611
10637
|
})),
|
|
10612
10638
|
optional_failed: optionalFailed.map((result) => ({
|
|
10613
10639
|
ordinal: result.ordinal ?? null,
|
|
@@ -10615,6 +10641,7 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
|
|
|
10615
10641
|
selector: result.selector ?? null,
|
|
10616
10642
|
frame_selector: result.frame_selector ?? null,
|
|
10617
10643
|
reason: result.reason || result.error || null,
|
|
10644
|
+
case_insensitive_text: compactProfileSetupSummaryText(result.case_insensitive_text),
|
|
10618
10645
|
})),
|
|
10619
10646
|
};
|
|
10620
10647
|
}),
|
|
@@ -11530,6 +11557,34 @@ async function setupReadWindowValue(context, path) {
|
|
|
11530
11557
|
return { ok: true, value: toJsonValue(current) };
|
|
11531
11558
|
}, { path });
|
|
11532
11559
|
}
|
|
11560
|
+
async function setupCallWindowFunction(context, path, args) {
|
|
11561
|
+
return await context.evaluate(async ({ path, args }) => {
|
|
11562
|
+
const toJsonValue = (value) => {
|
|
11563
|
+
if (value === null || value === undefined) return null;
|
|
11564
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
11565
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
11566
|
+
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
11567
|
+
if (typeof value === "object") {
|
|
11568
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
11569
|
+
}
|
|
11570
|
+
return String(value);
|
|
11571
|
+
};
|
|
11572
|
+
const pathParts = String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
11573
|
+
let parent = window;
|
|
11574
|
+
let current = window;
|
|
11575
|
+
for (const part of pathParts) {
|
|
11576
|
+
parent = current;
|
|
11577
|
+
current = current?.[part];
|
|
11578
|
+
}
|
|
11579
|
+
if (typeof current !== "function") return { ok: false, reason: "missing_function" };
|
|
11580
|
+
try {
|
|
11581
|
+
const returned = await current.apply(parent, Array.isArray(args) ? args : []);
|
|
11582
|
+
return { ok: true, returned: toJsonValue(returned) };
|
|
11583
|
+
} catch (error) {
|
|
11584
|
+
return { ok: false, reason: "function_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
11585
|
+
}
|
|
11586
|
+
}, { path, args });
|
|
11587
|
+
}
|
|
11533
11588
|
function setupFrameSelector(action) {
|
|
11534
11589
|
return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
|
|
11535
11590
|
}
|
|
@@ -12047,32 +12102,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
12047
12102
|
if (!path) return { ...base, path, reason: "missing_path" };
|
|
12048
12103
|
const scope = await setupActionScope(action, timeout);
|
|
12049
12104
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
12050
|
-
const result = await scope.context
|
|
12051
|
-
const toJsonValue = (value) => {
|
|
12052
|
-
if (value === null || value === undefined) return null;
|
|
12053
|
-
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
12054
|
-
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
12055
|
-
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
12056
|
-
if (typeof value === "object") {
|
|
12057
|
-
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
12058
|
-
}
|
|
12059
|
-
return String(value);
|
|
12060
|
-
};
|
|
12061
|
-
const pathParts = String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
12062
|
-
let parent = window;
|
|
12063
|
-
let current = window;
|
|
12064
|
-
for (const part of pathParts) {
|
|
12065
|
-
parent = current;
|
|
12066
|
-
current = current?.[part];
|
|
12067
|
-
}
|
|
12068
|
-
if (typeof current !== "function") return { ok: false, reason: "missing_function" };
|
|
12069
|
-
try {
|
|
12070
|
-
const returned = await current.apply(parent, Array.isArray(args) ? args : []);
|
|
12071
|
-
return { ok: true, returned: toJsonValue(returned) };
|
|
12072
|
-
} catch (error) {
|
|
12073
|
-
return { ok: false, reason: "function_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
12074
|
-
}
|
|
12075
|
-
}, { path, args });
|
|
12105
|
+
const result = await setupCallWindowFunction(scope.context, path, args);
|
|
12076
12106
|
const hasExpectation = setupHasOwn(action, "expect_return")
|
|
12077
12107
|
|| setupHasOwn(action, "expectReturn")
|
|
12078
12108
|
|| setupHasOwn(action, "expected_return")
|
|
@@ -12097,6 +12127,126 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
12097
12127
|
error: result.error || undefined,
|
|
12098
12128
|
};
|
|
12099
12129
|
}
|
|
12130
|
+
if (type === "window_call_until") {
|
|
12131
|
+
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
12132
|
+
const untilPath = String(action.until_path || action.untilPath || action.until_state_path || action.untilStatePath || action.until_window_path || action.untilWindowPath || action.until || "");
|
|
12133
|
+
const args = Array.isArray(action.args) ? action.args : [];
|
|
12134
|
+
if (!path) return { ...base, path, reason: "missing_path" };
|
|
12135
|
+
if (!untilPath) return { ...base, path, reason: "missing_until_path" };
|
|
12136
|
+
const hasUntilExpected = setupHasOwn(action, "until_expected_value")
|
|
12137
|
+
|| setupHasOwn(action, "untilExpectedValue")
|
|
12138
|
+
|| setupHasOwn(action, "until_expected")
|
|
12139
|
+
|| setupHasOwn(action, "untilExpected")
|
|
12140
|
+
|| setupHasOwn(action, "until_value")
|
|
12141
|
+
|| setupHasOwn(action, "untilValue")
|
|
12142
|
+
|| setupHasOwn(action, "expected_value")
|
|
12143
|
+
|| setupHasOwn(action, "expectedValue")
|
|
12144
|
+
|| setupHasOwn(action, "expected");
|
|
12145
|
+
const untilExpected = setupHasOwn(action, "until_expected_value")
|
|
12146
|
+
? action.until_expected_value
|
|
12147
|
+
: setupHasOwn(action, "untilExpectedValue")
|
|
12148
|
+
? action.untilExpectedValue
|
|
12149
|
+
: setupHasOwn(action, "until_expected")
|
|
12150
|
+
? action.until_expected
|
|
12151
|
+
: setupHasOwn(action, "untilExpected")
|
|
12152
|
+
? action.untilExpected
|
|
12153
|
+
: setupHasOwn(action, "until_value")
|
|
12154
|
+
? action.until_value
|
|
12155
|
+
: setupHasOwn(action, "untilValue")
|
|
12156
|
+
? action.untilValue
|
|
12157
|
+
: setupHasOwn(action, "expected_value")
|
|
12158
|
+
? action.expected_value
|
|
12159
|
+
: setupHasOwn(action, "expectedValue")
|
|
12160
|
+
? action.expectedValue
|
|
12161
|
+
: action.expected;
|
|
12162
|
+
if (!hasUntilExpected) return { ...base, path, until_path: untilPath, reason: "missing_until_expected_value" };
|
|
12163
|
+
const maxCalls = Math.min(100, Math.max(1, Math.floor(setupNumber(action.max_calls ?? action.maxCalls ?? action.max_attempts ?? action.maxAttempts ?? action.attempts, 1) || 1)));
|
|
12164
|
+
const intervalMs = Math.min(5000, Math.max(0, Math.floor(setupNumber(action.interval_ms ?? action.intervalMs ?? action.poll_ms ?? action.pollMs ?? action.call_interval_ms ?? action.callIntervalMs, 100) || 0)));
|
|
12165
|
+
const hasReturnExpectation = setupHasOwn(action, "expect_return")
|
|
12166
|
+
|| setupHasOwn(action, "expectReturn")
|
|
12167
|
+
|| setupHasOwn(action, "expected_return")
|
|
12168
|
+
|| setupHasOwn(action, "expectedReturn");
|
|
12169
|
+
const expectedReturn = setupHasOwn(action, "expect_return")
|
|
12170
|
+
? action.expect_return
|
|
12171
|
+
: setupHasOwn(action, "expectReturn")
|
|
12172
|
+
? action.expectReturn
|
|
12173
|
+
: setupHasOwn(action, "expected_return")
|
|
12174
|
+
? action.expected_return
|
|
12175
|
+
: action.expectedReturn;
|
|
12176
|
+
const scope = await setupActionScope(action, timeout);
|
|
12177
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
12178
|
+
const startedAt = Date.now();
|
|
12179
|
+
let callCount = 0;
|
|
12180
|
+
let lastCallResult = null;
|
|
12181
|
+
let lastPredicateResult = await setupReadWindowValue(scope.context, untilPath);
|
|
12182
|
+
if (lastPredicateResult.ok && setupValuesEqual(lastPredicateResult.value, untilExpected)) {
|
|
12183
|
+
return {
|
|
12184
|
+
...base,
|
|
12185
|
+
...setupScopeEvidence(scope),
|
|
12186
|
+
ok: true,
|
|
12187
|
+
path,
|
|
12188
|
+
arg_count: args.length,
|
|
12189
|
+
until_path: untilPath,
|
|
12190
|
+
until_value: setupJsonValue(lastPredicateResult.value),
|
|
12191
|
+
until_expected_value: setupJsonValue(untilExpected),
|
|
12192
|
+
call_count: callCount,
|
|
12193
|
+
max_calls: maxCalls,
|
|
12194
|
+
interval_ms: intervalMs,
|
|
12195
|
+
timeout_ms: timeout,
|
|
12196
|
+
};
|
|
12197
|
+
}
|
|
12198
|
+
while (callCount < maxCalls && Date.now() - startedAt <= timeout) {
|
|
12199
|
+
lastCallResult = await setupCallWindowFunction(scope.context, path, args);
|
|
12200
|
+
callCount += 1;
|
|
12201
|
+
if (!lastCallResult.ok) break;
|
|
12202
|
+
if (hasReturnExpectation && !setupValuesEqual(lastCallResult.returned, expectedReturn)) break;
|
|
12203
|
+
lastPredicateResult = await setupReadWindowValue(scope.context, untilPath);
|
|
12204
|
+
if (lastPredicateResult.ok && setupValuesEqual(lastPredicateResult.value, untilExpected)) {
|
|
12205
|
+
return {
|
|
12206
|
+
...base,
|
|
12207
|
+
...setupScopeEvidence(scope),
|
|
12208
|
+
ok: true,
|
|
12209
|
+
path,
|
|
12210
|
+
arg_count: args.length,
|
|
12211
|
+
returned: setupJsonValue(lastCallResult.returned),
|
|
12212
|
+
expected_return: hasReturnExpectation ? setupJsonValue(expectedReturn) : undefined,
|
|
12213
|
+
until_path: untilPath,
|
|
12214
|
+
until_value: setupJsonValue(lastPredicateResult.value),
|
|
12215
|
+
until_expected_value: setupJsonValue(untilExpected),
|
|
12216
|
+
call_count: callCount,
|
|
12217
|
+
max_calls: maxCalls,
|
|
12218
|
+
interval_ms: intervalMs,
|
|
12219
|
+
timeout_ms: timeout,
|
|
12220
|
+
};
|
|
12221
|
+
}
|
|
12222
|
+
if (callCount < maxCalls && intervalMs) await page.waitForTimeout(intervalMs);
|
|
12223
|
+
}
|
|
12224
|
+
const returnExpectationMet = !hasReturnExpectation || setupValuesEqual(lastCallResult?.returned, expectedReturn);
|
|
12225
|
+
return {
|
|
12226
|
+
...base,
|
|
12227
|
+
...setupScopeEvidence(scope),
|
|
12228
|
+
path,
|
|
12229
|
+
arg_count: args.length,
|
|
12230
|
+
returned: setupJsonValue(lastCallResult?.returned),
|
|
12231
|
+
expected_return: hasReturnExpectation ? setupJsonValue(expectedReturn) : undefined,
|
|
12232
|
+
until_path: untilPath,
|
|
12233
|
+
until_value: setupJsonValue(lastPredicateResult?.value),
|
|
12234
|
+
until_expected_value: setupJsonValue(untilExpected),
|
|
12235
|
+
call_count: callCount,
|
|
12236
|
+
max_calls: maxCalls,
|
|
12237
|
+
interval_ms: intervalMs,
|
|
12238
|
+
timeout_ms: timeout,
|
|
12239
|
+
reason: lastCallResult && !lastCallResult.ok
|
|
12240
|
+
? lastCallResult.reason
|
|
12241
|
+
: hasReturnExpectation && !returnExpectationMet
|
|
12242
|
+
? "unexpected_return_value"
|
|
12243
|
+
: Date.now() - startedAt > timeout
|
|
12244
|
+
? "timeout"
|
|
12245
|
+
: "until_condition_not_met",
|
|
12246
|
+
error: lastCallResult?.error || undefined,
|
|
12247
|
+
missing_part: lastPredicateResult?.missing_part || undefined,
|
|
12248
|
+
};
|
|
12249
|
+
}
|
|
12100
12250
|
if (type === "assert_window_value") {
|
|
12101
12251
|
const path = String(action.path || action.window_path || action.windowPath || "");
|
|
12102
12252
|
const hasExpected = setupHasOwn(action, "expected_value")
|
|
@@ -14325,6 +14475,19 @@ function profileSetupSummaryMarkdown(result) {
|
|
|
14325
14475
|
const observedPath = cliString(viewport.observed_path);
|
|
14326
14476
|
lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count action(s)` : ""}${observedPath ? `, path ${observedPath}` : ""}`);
|
|
14327
14477
|
}
|
|
14478
|
+
const failedDetails = viewports.flatMap((viewport) => {
|
|
14479
|
+
const name = cliString(viewport.name) || "viewport";
|
|
14480
|
+
const failed = Array.isArray(viewport.failed) ? viewport.failed.map(cliRecord).filter((item) => Boolean(item)) : [];
|
|
14481
|
+
return failed.map((failure) => ({ name, failure }));
|
|
14482
|
+
});
|
|
14483
|
+
for (const { name, failure } of failedDetails.slice(0, 8)) {
|
|
14484
|
+
const action = cliString(failure.action) || "setup_action";
|
|
14485
|
+
const selector = cliString(failure.selector);
|
|
14486
|
+
const reason = cliString(failure.reason);
|
|
14487
|
+
const caseInsensitiveText = cliString(failure.case_insensitive_text);
|
|
14488
|
+
lines.push(`- failed ${name}: ${action}${selector ? ` ${markdownInlineCode(selector)}` : ""}${reason ? ` reason ${markdownInlineCode(reason)}` : ""}${caseInsensitiveText ? `; case-insensitive sample ${markdownInlineCode(caseInsensitiveText, 140)}` : ""}`);
|
|
14489
|
+
}
|
|
14490
|
+
if (failedDetails.length > 8) lines.push(`- ${failedDetails.length - 8} additional failed setup action(s) omitted.`);
|
|
14328
14491
|
if (viewports.length > 8) lines.push(`- ${viewports.length - 8} additional viewport(s) omitted from setup summary.`);
|
|
14329
14492
|
return lines;
|
|
14330
14493
|
}
|