@riddledc/riddle-proof 0.7.58 → 0.7.60
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 +17 -0
- package/dist/{chunk-7ZBK2GQX.js → chunk-FLQ4HHTT.js} +226 -38
- package/dist/cli.cjs +226 -38
- package/dist/cli.js +1 -1
- package/dist/index.cjs +226 -38
- package/dist/index.js +1 -1
- package/dist/profile.cjs +226 -38
- package/dist/profile.d.cts +4 -1
- package/dist/profile.d.ts +4 -1
- package/dist/profile.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8736,6 +8736,8 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
8736
8736
|
"selector_count_eq",
|
|
8737
8737
|
"selector_text_order",
|
|
8738
8738
|
"frame_text_visible",
|
|
8739
|
+
"frame_url_equals",
|
|
8740
|
+
"frame_url_matches",
|
|
8739
8741
|
"frame_no_horizontal_overflow",
|
|
8740
8742
|
"text_visible",
|
|
8741
8743
|
"text_absent",
|
|
@@ -8950,6 +8952,11 @@ function normalizeSetupAction(input, index) {
|
|
|
8950
8952
|
if (!isRecord2(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
8951
8953
|
const type = normalizeSetupActionType(stringValue5(input.type), index);
|
|
8952
8954
|
const selector = stringValue5(input.selector);
|
|
8955
|
+
const frameSelector = stringFromOwn(input, "frame_selector", "frameSelector", "iframe_selector", "iframeSelector");
|
|
8956
|
+
const frameIndex = numberValue3(valueFromOwn(input, "frame_index", "frameIndex", "iframe_index", "iframeIndex"));
|
|
8957
|
+
if (frameIndex !== void 0 && (!Number.isInteger(frameIndex) || frameIndex < 0)) {
|
|
8958
|
+
throw new Error(`target.setup_actions[${index}].frame_index must be a non-negative integer.`);
|
|
8959
|
+
}
|
|
8953
8960
|
if ((type === "click" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
|
|
8954
8961
|
throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
|
|
8955
8962
|
}
|
|
@@ -9002,6 +9009,8 @@ function normalizeSetupAction(input, index) {
|
|
|
9002
9009
|
return {
|
|
9003
9010
|
type,
|
|
9004
9011
|
selector,
|
|
9012
|
+
frame_selector: frameSelector,
|
|
9013
|
+
frame_index: frameIndex,
|
|
9005
9014
|
force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
|
|
9006
9015
|
key,
|
|
9007
9016
|
value,
|
|
@@ -9213,12 +9222,19 @@ function normalizeCheck(input, index) {
|
|
|
9213
9222
|
if ((type === "selector_visible" || type === "selector_absent" || type === "selector_count_at_least" || type === "selector_count_equals" || type === "selector_count_equal" || type === "selector_count_eq") && !stringValue5(input.selector)) {
|
|
9214
9223
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
9215
9224
|
}
|
|
9216
|
-
if ((type === "frame_text_visible" || type === "frame_no_horizontal_overflow") && !stringValue5(input.selector)) {
|
|
9225
|
+
if ((type === "frame_text_visible" || type === "frame_url_equals" || type === "frame_url_matches" || type === "frame_no_horizontal_overflow") && !stringValue5(input.selector)) {
|
|
9217
9226
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
9218
9227
|
}
|
|
9219
9228
|
if (type === "frame_text_visible" && !stringValue5(input.text) && !stringValue5(input.pattern)) {
|
|
9220
9229
|
throw new Error(`checks[${index}] frame_text_visible requires text or pattern.`);
|
|
9221
9230
|
}
|
|
9231
|
+
const expectedUrl = stringFromOwn(input, "expected_url", "expectedUrl", "url", "expected_value", "expectedValue", "value");
|
|
9232
|
+
if (type === "frame_url_equals" && expectedUrl === void 0) {
|
|
9233
|
+
throw new Error(`checks[${index}] frame_url_equals requires expected_url.`);
|
|
9234
|
+
}
|
|
9235
|
+
if (type === "frame_url_matches" && !stringValue5(input.pattern)) {
|
|
9236
|
+
throw new Error(`checks[${index}] frame_url_matches requires pattern.`);
|
|
9237
|
+
}
|
|
9222
9238
|
if ((type === "text_visible" || type === "text_absent") && !stringValue5(input.text) && !stringValue5(input.pattern)) {
|
|
9223
9239
|
throw new Error(`checks[${index}] ${type} requires text or pattern.`);
|
|
9224
9240
|
}
|
|
@@ -9251,6 +9267,7 @@ function normalizeCheck(input, index) {
|
|
|
9251
9267
|
expected_path: stringValue5(input.expected_path),
|
|
9252
9268
|
param: stringValue5(input.param) || stringValue5(input.search_param) || stringValue5(input.searchParam) || stringValue5(input.key),
|
|
9253
9269
|
expected_value: expectedValue,
|
|
9270
|
+
expected_url: expectedUrl,
|
|
9254
9271
|
expected_routes: expectedRoutes,
|
|
9255
9272
|
selector: stringValue5(input.selector),
|
|
9256
9273
|
expected_texts: expectedTexts,
|
|
@@ -9718,6 +9735,35 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
9718
9735
|
message: failed ? `Frame selector ${key} did not contain expected text in ${failed} viewport(s).` : void 0
|
|
9719
9736
|
};
|
|
9720
9737
|
}
|
|
9738
|
+
if (check.type === "frame_url_equals" || check.type === "frame_url_matches") {
|
|
9739
|
+
const key = selectorKey(check);
|
|
9740
|
+
const expectedUrl = check.expected_url || check.expected_value || "";
|
|
9741
|
+
const results = viewports.map((viewport) => {
|
|
9742
|
+
const frames = frameEvidenceForSelector(viewport, key);
|
|
9743
|
+
const urls = frames.map((frame) => String(frame.url || "")).filter(Boolean);
|
|
9744
|
+
const matches = urls.filter((url) => check.type === "frame_url_equals" ? url === expectedUrl : matchText(url, check));
|
|
9745
|
+
return {
|
|
9746
|
+
viewport: viewport.name,
|
|
9747
|
+
frame_count: frames.length,
|
|
9748
|
+
matched_count: matches.length,
|
|
9749
|
+
matched: matches.length > 0,
|
|
9750
|
+
urls: urls.slice(0, 10)
|
|
9751
|
+
};
|
|
9752
|
+
});
|
|
9753
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
9754
|
+
return {
|
|
9755
|
+
type: check.type,
|
|
9756
|
+
label: checkLabel(check),
|
|
9757
|
+
status: failed ? "failed" : "passed",
|
|
9758
|
+
evidence: {
|
|
9759
|
+
selector: key,
|
|
9760
|
+
expected_url: check.type === "frame_url_equals" ? expectedUrl : null,
|
|
9761
|
+
pattern: check.type === "frame_url_matches" ? check.pattern || null : null,
|
|
9762
|
+
viewports: results.map((result) => toJsonValue(result))
|
|
9763
|
+
},
|
|
9764
|
+
message: failed ? `Frame selector ${key} URL assertion failed in ${failed} viewport(s).` : void 0
|
|
9765
|
+
};
|
|
9766
|
+
}
|
|
9721
9767
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
9722
9768
|
const key = selectorKey(check);
|
|
9723
9769
|
const maxOverflow = check.max_overflow_px ?? 4;
|
|
@@ -9888,6 +9934,8 @@ function assessSetupActionsFromEvidence(profile, evidence) {
|
|
|
9888
9934
|
viewport: viewport.name,
|
|
9889
9935
|
action: result.action ?? result.type ?? null,
|
|
9890
9936
|
selector: result.selector ?? null,
|
|
9937
|
+
frame_selector: result.frame_selector ?? null,
|
|
9938
|
+
frame_index: result.frame_index ?? null,
|
|
9891
9939
|
reason: result.reason ?? result.error ?? null
|
|
9892
9940
|
});
|
|
9893
9941
|
}
|
|
@@ -10400,10 +10448,12 @@ function assessProfile(profile, evidence) {
|
|
|
10400
10448
|
if (result && result.ok === false) {
|
|
10401
10449
|
failed.push({
|
|
10402
10450
|
viewport: viewport.name,
|
|
10403
|
-
|
|
10404
|
-
|
|
10405
|
-
|
|
10406
|
-
|
|
10451
|
+
action: result.action || result.type || null,
|
|
10452
|
+
selector: result.selector || null,
|
|
10453
|
+
frame_selector: result.frame_selector || null,
|
|
10454
|
+
frame_index: result.frame_index ?? null,
|
|
10455
|
+
reason: result.reason || result.error || null,
|
|
10456
|
+
});
|
|
10407
10457
|
}
|
|
10408
10458
|
}
|
|
10409
10459
|
if (results.length < actionCount && results.every((result) => !result || result.ok !== false)) {
|
|
@@ -10605,6 +10655,36 @@ function assessProfile(profile, evidence) {
|
|
|
10605
10655
|
});
|
|
10606
10656
|
continue;
|
|
10607
10657
|
}
|
|
10658
|
+
if (check.type === "frame_url_equals" || check.type === "frame_url_matches") {
|
|
10659
|
+
const selector = check.selector || "";
|
|
10660
|
+
const expectedUrl = check.expected_url || check.expected_value || "";
|
|
10661
|
+
const results = checkViewports.map((viewport) => {
|
|
10662
|
+
const frames = frameEvidenceForSelector(viewport, selector);
|
|
10663
|
+
const urls = frames.map((frame) => String(frame.url || "")).filter(Boolean);
|
|
10664
|
+
const matches = urls.filter((url) => check.type === "frame_url_equals" ? url === expectedUrl : textMatches(url, check));
|
|
10665
|
+
return {
|
|
10666
|
+
viewport: viewport.name,
|
|
10667
|
+
frame_count: frames.length,
|
|
10668
|
+
matched_count: matches.length,
|
|
10669
|
+
matched: matches.length > 0,
|
|
10670
|
+
urls: urls.slice(0, 10),
|
|
10671
|
+
};
|
|
10672
|
+
});
|
|
10673
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
10674
|
+
checks.push({
|
|
10675
|
+
type: check.type,
|
|
10676
|
+
label: check.label || check.type,
|
|
10677
|
+
status: failed ? "failed" : "passed",
|
|
10678
|
+
evidence: {
|
|
10679
|
+
selector,
|
|
10680
|
+
expected_url: check.type === "frame_url_equals" ? expectedUrl : null,
|
|
10681
|
+
pattern: check.type === "frame_url_matches" ? check.pattern || null : null,
|
|
10682
|
+
viewports: results,
|
|
10683
|
+
},
|
|
10684
|
+
message: failed ? "Frame selector " + selector + " URL assertion failed in " + failed + " viewport(s)." : undefined,
|
|
10685
|
+
});
|
|
10686
|
+
continue;
|
|
10687
|
+
}
|
|
10608
10688
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
10609
10689
|
const selector = check.selector || "";
|
|
10610
10690
|
const maxOverflow = check.max_overflow_px == null ? 4 : check.max_overflow_px;
|
|
@@ -10866,8 +10946,8 @@ function setupJsonValue(value) {
|
|
|
10866
10946
|
function setupValuesEqual(left, right) {
|
|
10867
10947
|
return JSON.stringify(setupJsonValue(left)) === JSON.stringify(setupJsonValue(right));
|
|
10868
10948
|
}
|
|
10869
|
-
async function setupReadWindowValue(path) {
|
|
10870
|
-
return await
|
|
10949
|
+
async function setupReadWindowValue(context, path) {
|
|
10950
|
+
return await context.evaluate(({ path }) => {
|
|
10871
10951
|
const toJsonValue = (value) => {
|
|
10872
10952
|
if (value === null || value === undefined) return null;
|
|
10873
10953
|
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
@@ -10889,6 +10969,80 @@ async function setupReadWindowValue(path) {
|
|
|
10889
10969
|
return { ok: true, value: toJsonValue(current) };
|
|
10890
10970
|
}, { path });
|
|
10891
10971
|
}
|
|
10972
|
+
function setupFrameSelector(action) {
|
|
10973
|
+
return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
|
|
10974
|
+
}
|
|
10975
|
+
function setupFrameIndex(action) {
|
|
10976
|
+
const raw = action?.frame_index ?? action?.frameIndex ?? action?.iframe_index ?? action?.iframeIndex ?? 0;
|
|
10977
|
+
const number = Number(raw);
|
|
10978
|
+
return Number.isInteger(number) && number >= 0 ? number : 0;
|
|
10979
|
+
}
|
|
10980
|
+
function setupScopeEvidence(scope) {
|
|
10981
|
+
if (!scope || !scope.frame_selector) return {};
|
|
10982
|
+
return {
|
|
10983
|
+
frame_selector: scope.frame_selector,
|
|
10984
|
+
frame_index: scope.frame_index,
|
|
10985
|
+
frame_count: scope.frame_count,
|
|
10986
|
+
};
|
|
10987
|
+
}
|
|
10988
|
+
function setupScopeFailure(base, scope) {
|
|
10989
|
+
return {
|
|
10990
|
+
...base,
|
|
10991
|
+
...setupScopeEvidence(scope),
|
|
10992
|
+
reason: scope?.reason || "frame_scope_unavailable",
|
|
10993
|
+
error: scope?.error || undefined,
|
|
10994
|
+
};
|
|
10995
|
+
}
|
|
10996
|
+
async function setupActionScope(action, timeout) {
|
|
10997
|
+
const frameSelector = setupFrameSelector(action);
|
|
10998
|
+
if (!frameSelector) return { ok: true, context: page };
|
|
10999
|
+
const frameIndex = setupFrameIndex(action);
|
|
11000
|
+
let frameCount = 0;
|
|
11001
|
+
let locator = null;
|
|
11002
|
+
try {
|
|
11003
|
+
await page.waitForSelector(frameSelector, { state: "attached", timeout });
|
|
11004
|
+
locator = page.locator(frameSelector);
|
|
11005
|
+
frameCount = await locator.count();
|
|
11006
|
+
} catch (error) {
|
|
11007
|
+
return {
|
|
11008
|
+
ok: false,
|
|
11009
|
+
reason: "frame_selector_not_found",
|
|
11010
|
+
frame_selector: frameSelector,
|
|
11011
|
+
frame_index: frameIndex,
|
|
11012
|
+
frame_count: frameCount,
|
|
11013
|
+
error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
11014
|
+
};
|
|
11015
|
+
}
|
|
11016
|
+
if (!frameCount) {
|
|
11017
|
+
return { ok: false, reason: "frame_selector_not_found", frame_selector: frameSelector, frame_index: frameIndex, frame_count: frameCount };
|
|
11018
|
+
}
|
|
11019
|
+
if (frameIndex >= frameCount) {
|
|
11020
|
+
return { ok: false, reason: "frame_index_out_of_range", frame_selector: frameSelector, frame_index: frameIndex, frame_count: frameCount };
|
|
11021
|
+
}
|
|
11022
|
+
const handle = await locator.nth(frameIndex).elementHandle({ timeout }).catch((error) => ({ __riddle_error: error }));
|
|
11023
|
+
if (!handle || handle.__riddle_error) {
|
|
11024
|
+
return {
|
|
11025
|
+
ok: false,
|
|
11026
|
+
reason: "frame_element_unavailable",
|
|
11027
|
+
frame_selector: frameSelector,
|
|
11028
|
+
frame_index: frameIndex,
|
|
11029
|
+
frame_count: frameCount,
|
|
11030
|
+
error: handle?.__riddle_error ? String(handle.__riddle_error && handle.__riddle_error.message ? handle.__riddle_error.message : handle.__riddle_error).slice(0, 1000) : undefined,
|
|
11031
|
+
};
|
|
11032
|
+
}
|
|
11033
|
+
const frame = typeof handle.contentFrame === "function" ? await handle.contentFrame().catch((error) => ({ __riddle_error: error })) : null;
|
|
11034
|
+
if (!frame || frame.__riddle_error) {
|
|
11035
|
+
return {
|
|
11036
|
+
ok: false,
|
|
11037
|
+
reason: "content_frame_unavailable",
|
|
11038
|
+
frame_selector: frameSelector,
|
|
11039
|
+
frame_index: frameIndex,
|
|
11040
|
+
frame_count: frameCount,
|
|
11041
|
+
error: frame?.__riddle_error ? String(frame.__riddle_error && frame.__riddle_error.message ? frame.__riddle_error.message : frame.__riddle_error).slice(0, 1000) : undefined,
|
|
11042
|
+
};
|
|
11043
|
+
}
|
|
11044
|
+
return { ok: true, context: frame, frame_selector: frameSelector, frame_index: frameIndex, frame_count: frameCount };
|
|
11045
|
+
}
|
|
10892
11046
|
async function setupLocatorText(locator, index) {
|
|
10893
11047
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
10894
11048
|
}
|
|
@@ -11050,7 +11204,8 @@ async function registerNetworkMocks(mocks) {
|
|
|
11050
11204
|
}
|
|
11051
11205
|
async function executeSetupAction(action, ordinal) {
|
|
11052
11206
|
const type = setupActionType(action);
|
|
11053
|
-
const
|
|
11207
|
+
const frameSelector = setupFrameSelector(action);
|
|
11208
|
+
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null, frame_selector: frameSelector || null };
|
|
11054
11209
|
const timeout = setupNumber(action.timeout_ms, 5000);
|
|
11055
11210
|
try {
|
|
11056
11211
|
if (type === "wait") {
|
|
@@ -11059,51 +11214,65 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11059
11214
|
return { ...base, ok: true, ms };
|
|
11060
11215
|
}
|
|
11061
11216
|
if (type === "wait_for_selector") {
|
|
11062
|
-
await
|
|
11063
|
-
return
|
|
11217
|
+
const scope = await setupActionScope(action, timeout);
|
|
11218
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11219
|
+
await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
|
|
11220
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
|
|
11064
11221
|
}
|
|
11065
11222
|
if (type === "press") {
|
|
11066
11223
|
const key = String(action.key || "").trim();
|
|
11067
11224
|
if (!key) return { ...base, reason: "missing_key" };
|
|
11225
|
+
const scope = await setupActionScope(action, timeout);
|
|
11226
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11068
11227
|
if (!action.selector) {
|
|
11069
|
-
|
|
11070
|
-
|
|
11228
|
+
if (scope.frame_selector) {
|
|
11229
|
+
await scope.context.locator("body").press(key, { timeout });
|
|
11230
|
+
} else {
|
|
11231
|
+
await page.keyboard.press(key);
|
|
11232
|
+
}
|
|
11233
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, key };
|
|
11071
11234
|
}
|
|
11072
|
-
const locator =
|
|
11235
|
+
const locator = scope.context.locator(action.selector);
|
|
11073
11236
|
const count = await locator.count();
|
|
11074
11237
|
if (!count) return { ...base, reason: "selector_not_found", count, key };
|
|
11075
11238
|
const targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
11076
11239
|
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
|
|
11077
11240
|
await locator.nth(targetIndex).press(key, { timeout });
|
|
11078
|
-
return { ...base, ok: true, count, target_index: targetIndex, key };
|
|
11241
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, target_index: targetIndex, key };
|
|
11079
11242
|
}
|
|
11080
11243
|
if (type === "local_storage" || type === "session_storage") {
|
|
11081
11244
|
const value = setupActionValue(action);
|
|
11082
|
-
await
|
|
11245
|
+
const scope = await setupActionScope(action, timeout);
|
|
11246
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11247
|
+
await scope.context.evaluate(({ type, key, value }) => {
|
|
11083
11248
|
const storage = type === "session_storage" ? window.sessionStorage : window.localStorage;
|
|
11084
11249
|
storage.setItem(key, value);
|
|
11085
11250
|
}, { type, key: action.key, value });
|
|
11086
11251
|
if (action.reload === true) {
|
|
11087
11252
|
await page.reload({ waitUntil: "domcontentloaded", timeout: 45000 });
|
|
11088
11253
|
}
|
|
11089
|
-
return { ...base, ok: true, key: action.key, value_length: value.length, reload: action.reload === true };
|
|
11254
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, key: action.key, value_length: value.length, reload: action.reload === true };
|
|
11090
11255
|
}
|
|
11091
11256
|
if (type === "clear_storage") {
|
|
11092
11257
|
const storage = action.storage || "both";
|
|
11093
|
-
await
|
|
11258
|
+
const scope = await setupActionScope(action, timeout);
|
|
11259
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11260
|
+
await scope.context.evaluate(({ storage }) => {
|
|
11094
11261
|
if (storage === "local" || storage === "both") window.localStorage.clear();
|
|
11095
11262
|
if (storage === "session" || storage === "both") window.sessionStorage.clear();
|
|
11096
11263
|
}, { storage });
|
|
11097
11264
|
if (action.reload === true) {
|
|
11098
11265
|
await page.reload({ waitUntil: "domcontentloaded", timeout: 45000 });
|
|
11099
11266
|
}
|
|
11100
|
-
return { ...base, ok: true, storage, reload: action.reload === true };
|
|
11267
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
|
|
11101
11268
|
}
|
|
11102
11269
|
if (type === "window_call") {
|
|
11103
11270
|
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
11104
11271
|
const args = Array.isArray(action.args) ? action.args : [];
|
|
11105
11272
|
if (!path) return { ...base, path, reason: "missing_path" };
|
|
11106
|
-
const
|
|
11273
|
+
const scope = await setupActionScope(action, timeout);
|
|
11274
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11275
|
+
const result = await scope.context.evaluate(async ({ path, args }) => {
|
|
11107
11276
|
const toJsonValue = (value) => {
|
|
11108
11277
|
if (value === null || value === undefined) return null;
|
|
11109
11278
|
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
@@ -11143,6 +11312,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11143
11312
|
const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
|
|
11144
11313
|
return {
|
|
11145
11314
|
...base,
|
|
11315
|
+
...setupScopeEvidence(scope),
|
|
11146
11316
|
ok: Boolean(result.ok && expectationMet),
|
|
11147
11317
|
path,
|
|
11148
11318
|
arg_count: args.length,
|
|
@@ -11173,13 +11343,16 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11173
11343
|
: action.expect;
|
|
11174
11344
|
if (!path) return { ...base, path, reason: "missing_path" };
|
|
11175
11345
|
if (!hasExpected) return { ...base, path, reason: "missing_expected_value" };
|
|
11346
|
+
const scope = await setupActionScope(action, timeout);
|
|
11347
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11176
11348
|
const startedAt = Date.now();
|
|
11177
11349
|
let result = null;
|
|
11178
11350
|
while (Date.now() - startedAt <= timeout) {
|
|
11179
|
-
result = await setupReadWindowValue(path);
|
|
11351
|
+
result = await setupReadWindowValue(scope.context, path);
|
|
11180
11352
|
if (result.ok && setupValuesEqual(result.value, expected)) {
|
|
11181
11353
|
return {
|
|
11182
11354
|
...base,
|
|
11355
|
+
...setupScopeEvidence(scope),
|
|
11183
11356
|
ok: true,
|
|
11184
11357
|
path,
|
|
11185
11358
|
value: setupJsonValue(result.value),
|
|
@@ -11191,6 +11364,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11191
11364
|
}
|
|
11192
11365
|
return {
|
|
11193
11366
|
...base,
|
|
11367
|
+
...setupScopeEvidence(scope),
|
|
11194
11368
|
path,
|
|
11195
11369
|
reason: result?.ok ? "unexpected_value" : result?.reason || "path_not_found",
|
|
11196
11370
|
missing_part: result?.missing_part || undefined,
|
|
@@ -11207,11 +11381,13 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11207
11381
|
const hasExpected = expected !== undefined;
|
|
11208
11382
|
if (!path) return { ...base, path, reason: "missing_path" };
|
|
11209
11383
|
if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
|
|
11384
|
+
const scope = await setupActionScope(action, timeout);
|
|
11385
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11210
11386
|
const startedAt = Date.now();
|
|
11211
11387
|
let result = null;
|
|
11212
11388
|
let lastReason = "path_not_found";
|
|
11213
11389
|
while (Date.now() - startedAt <= timeout) {
|
|
11214
|
-
result = await setupReadWindowValue(path);
|
|
11390
|
+
result = await setupReadWindowValue(scope.context, path);
|
|
11215
11391
|
if (result.ok) {
|
|
11216
11392
|
const actual = setupFiniteNumber(result.value);
|
|
11217
11393
|
if (actual === undefined) {
|
|
@@ -11225,6 +11401,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11225
11401
|
} else {
|
|
11226
11402
|
return {
|
|
11227
11403
|
...base,
|
|
11404
|
+
...setupScopeEvidence(scope),
|
|
11228
11405
|
ok: true,
|
|
11229
11406
|
path,
|
|
11230
11407
|
value: actual,
|
|
@@ -11241,6 +11418,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11241
11418
|
}
|
|
11242
11419
|
return {
|
|
11243
11420
|
...base,
|
|
11421
|
+
...setupScopeEvidence(scope),
|
|
11244
11422
|
path,
|
|
11245
11423
|
reason: lastReason,
|
|
11246
11424
|
missing_part: result?.missing_part || undefined,
|
|
@@ -11252,7 +11430,9 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11252
11430
|
};
|
|
11253
11431
|
}
|
|
11254
11432
|
if (type === "click") {
|
|
11255
|
-
const
|
|
11433
|
+
const scope = await setupActionScope(action, timeout);
|
|
11434
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11435
|
+
const locator = scope.context.locator(action.selector);
|
|
11256
11436
|
const count = await locator.count();
|
|
11257
11437
|
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
11258
11438
|
let targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
@@ -11284,33 +11464,39 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11284
11464
|
? { timeout, noWaitAfter: true, force: true }
|
|
11285
11465
|
: { timeout, noWaitAfter: true };
|
|
11286
11466
|
await locator.nth(targetIndex).click(clickOptions);
|
|
11287
|
-
return { ...base, ok: true, count, target_index: targetIndex, text: matchedText, force: action.force === true || undefined };
|
|
11467
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, target_index: targetIndex, text: matchedText, force: action.force === true || undefined };
|
|
11288
11468
|
}
|
|
11289
11469
|
if (type === "fill" || type === "set_input_value") {
|
|
11290
|
-
const
|
|
11470
|
+
const scope = await setupActionScope(action, timeout);
|
|
11471
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11472
|
+
const locator = scope.context.locator(action.selector);
|
|
11291
11473
|
const count = await locator.count();
|
|
11292
11474
|
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
11293
11475
|
const targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
11294
11476
|
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
11295
11477
|
const value = setupActionValue(action);
|
|
11296
11478
|
await locator.nth(targetIndex).fill(value, { timeout });
|
|
11297
|
-
return { ...base, ok: true, count, target_index: targetIndex, value_length: value.length };
|
|
11479
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, target_index: targetIndex, value_length: value.length };
|
|
11298
11480
|
}
|
|
11299
11481
|
if (type === "assert_selector_count") {
|
|
11300
|
-
const
|
|
11482
|
+
const scope = await setupActionScope(action, timeout);
|
|
11483
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11484
|
+
const locator = scope.context.locator(action.selector);
|
|
11301
11485
|
const expectedCount = setupNumber(action.expected_count, -1);
|
|
11302
11486
|
if (!Number.isInteger(expectedCount) || expectedCount < 0) return { ...base, reason: "invalid_expected_count", expected_count: action.expected_count };
|
|
11303
11487
|
const startedAt = Date.now();
|
|
11304
11488
|
let count = 0;
|
|
11305
11489
|
while (Date.now() - startedAt <= timeout) {
|
|
11306
11490
|
count = await locator.count().catch(() => 0);
|
|
11307
|
-
if (count === expectedCount) return { ...base, ok: true, count, expected_count: expectedCount, timeout_ms: timeout };
|
|
11491
|
+
if (count === expectedCount) return { ...base, ...setupScopeEvidence(scope), ok: true, count, expected_count: expectedCount, timeout_ms: timeout };
|
|
11308
11492
|
await page.waitForTimeout(100);
|
|
11309
11493
|
}
|
|
11310
|
-
return { ...base, reason: "selector_count_mismatch", count, expected_count: expectedCount, timeout_ms: timeout };
|
|
11494
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "selector_count_mismatch", count, expected_count: expectedCount, timeout_ms: timeout };
|
|
11311
11495
|
}
|
|
11312
11496
|
if (type === "wait_for_text") {
|
|
11313
|
-
const
|
|
11497
|
+
const scope = await setupActionScope(action, timeout);
|
|
11498
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11499
|
+
const locator = scope.context.locator(action.selector);
|
|
11314
11500
|
const startedAt = Date.now();
|
|
11315
11501
|
let lastText = "";
|
|
11316
11502
|
while (Date.now() - startedAt <= timeout) {
|
|
@@ -11319,15 +11505,17 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11319
11505
|
const text = await setupLocatorText(locator, index);
|
|
11320
11506
|
lastText = text || lastText;
|
|
11321
11507
|
if (setupTextMatches(text, action)) {
|
|
11322
|
-
return { ...base, ok: true, text: compactSetupResultText(text), target_index: index, timeout_ms: timeout };
|
|
11508
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, text: compactSetupResultText(text), target_index: index, timeout_ms: timeout };
|
|
11323
11509
|
}
|
|
11324
11510
|
}
|
|
11325
11511
|
await page.waitForTimeout(100);
|
|
11326
11512
|
}
|
|
11327
|
-
return { ...base, reason: "text_not_found", text: compactSetupResultText(lastText), timeout_ms: timeout };
|
|
11513
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "text_not_found", text: compactSetupResultText(lastText), timeout_ms: timeout };
|
|
11328
11514
|
}
|
|
11329
11515
|
if (type === "assert_text_visible" || type === "assert_text_absent") {
|
|
11330
|
-
const
|
|
11516
|
+
const scope = await setupActionScope(action, timeout);
|
|
11517
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
11518
|
+
const locator = scope.context.locator(action.selector);
|
|
11331
11519
|
const startedAt = Date.now();
|
|
11332
11520
|
let lastText = "";
|
|
11333
11521
|
let matchedText = "";
|
|
@@ -11346,7 +11534,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11346
11534
|
if (type === "assert_text_visible") {
|
|
11347
11535
|
const visible = await setupLocatorVisible(locator, index);
|
|
11348
11536
|
if (visible) {
|
|
11349
|
-
return { ...base, ok: true, count, text: compactSetupResultText(text), target_index: index, timeout_ms: timeout };
|
|
11537
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, text: compactSetupResultText(text), target_index: index, timeout_ms: timeout };
|
|
11350
11538
|
}
|
|
11351
11539
|
hiddenMatch = true;
|
|
11352
11540
|
break;
|
|
@@ -11355,17 +11543,17 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11355
11543
|
}
|
|
11356
11544
|
}
|
|
11357
11545
|
if (type === "assert_text_absent" && !matched) {
|
|
11358
|
-
return { ...base, ok: true, count, timeout_ms: timeout };
|
|
11546
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, timeout_ms: timeout };
|
|
11359
11547
|
}
|
|
11360
11548
|
await page.waitForTimeout(100);
|
|
11361
11549
|
}
|
|
11362
11550
|
if (type === "assert_text_visible") {
|
|
11363
11551
|
if (hiddenMatch) {
|
|
11364
|
-
return { ...base, reason: "matching_element_not_visible", text: compactSetupResultText(matchedText), timeout_ms: timeout };
|
|
11552
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "matching_element_not_visible", text: compactSetupResultText(matchedText), timeout_ms: timeout };
|
|
11365
11553
|
}
|
|
11366
|
-
return { ...base, reason: "text_not_found", text: compactSetupResultText(lastText), timeout_ms: timeout };
|
|
11554
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "text_not_found", text: compactSetupResultText(lastText), timeout_ms: timeout };
|
|
11367
11555
|
}
|
|
11368
|
-
return { ...base, reason: "text_still_present", text: compactSetupResultText(matchedText || lastText), timeout_ms: timeout };
|
|
11556
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "text_still_present", text: compactSetupResultText(matchedText || lastText), timeout_ms: timeout };
|
|
11369
11557
|
}
|
|
11370
11558
|
return { ...base, reason: "unsupported_action" };
|
|
11371
11559
|
} catch (error) {
|
|
@@ -11968,7 +12156,7 @@ async function captureViewport(viewport) {
|
|
|
11968
12156
|
if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
|
|
11969
12157
|
text_matches[textKey(check)] = textMatches(dom.body_text || dom.body_text_sample || "", check);
|
|
11970
12158
|
}
|
|
11971
|
-
if ((check.type === "frame_text_visible" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
12159
|
+
if ((check.type === "frame_text_visible" || check.type === "frame_url_equals" || check.type === "frame_url_matches" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
11972
12160
|
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
11973
12161
|
frames[check.selector] = frames[check.selector] || await frameEvidence(check.selector);
|
|
11974
12162
|
}
|
package/dist/index.js
CHANGED
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
resolveRiddleProofProfileTimeoutSec,
|
|
59
59
|
slugifyRiddleProofProfileName,
|
|
60
60
|
summarizeRiddleProofProfileResult
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-FLQ4HHTT.js";
|
|
62
62
|
import {
|
|
63
63
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
64
64
|
DEFAULT_RIDDLE_API_KEY_FILE,
|