@riddledc/riddle-proof 0.7.57 → 0.7.59
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 +13 -3
- package/dist/{chunk-H5LDZKGN.js → chunk-Q5VW6MAP.js} +171 -33
- package/dist/cli.cjs +171 -33
- package/dist/cli.js +1 -1
- package/dist/index.cjs +171 -33
- package/dist/index.js +1 -1
- package/dist/profile.cjs +171 -33
- package/dist/profile.d.cts +3 -1
- package/dist/profile.d.ts +3 -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/dist/profile.cjs
CHANGED
|
@@ -75,6 +75,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
75
75
|
];
|
|
76
76
|
var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
77
77
|
"click",
|
|
78
|
+
"press",
|
|
78
79
|
"fill",
|
|
79
80
|
"set_input_value",
|
|
80
81
|
"assert_text_visible",
|
|
@@ -244,7 +245,7 @@ function isSupportedCheckType(value) {
|
|
|
244
245
|
}
|
|
245
246
|
function normalizeSetupActionType(value, index) {
|
|
246
247
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
247
|
-
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput;
|
|
248
|
+
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
|
|
248
249
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
249
250
|
return normalized;
|
|
250
251
|
}
|
|
@@ -278,6 +279,11 @@ function normalizeSetupAction(input, index) {
|
|
|
278
279
|
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
279
280
|
const type = normalizeSetupActionType(stringValue(input.type), index);
|
|
280
281
|
const selector = stringValue(input.selector);
|
|
282
|
+
const frameSelector = stringFromOwn(input, "frame_selector", "frameSelector", "iframe_selector", "iframeSelector");
|
|
283
|
+
const frameIndex = numberValue(valueFromOwn(input, "frame_index", "frameIndex", "iframe_index", "iframeIndex"));
|
|
284
|
+
if (frameIndex !== void 0 && (!Number.isInteger(frameIndex) || frameIndex < 0)) {
|
|
285
|
+
throw new Error(`target.setup_actions[${index}].frame_index must be a non-negative integer.`);
|
|
286
|
+
}
|
|
281
287
|
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) {
|
|
282
288
|
throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
|
|
283
289
|
}
|
|
@@ -297,6 +303,9 @@ function normalizeSetupAction(input, index) {
|
|
|
297
303
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
298
304
|
}
|
|
299
305
|
const key = stringValue(input.key);
|
|
306
|
+
if (type === "press" && !key) {
|
|
307
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
|
|
308
|
+
}
|
|
300
309
|
if ((type === "local_storage" || type === "session_storage") && !key) {
|
|
301
310
|
throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
|
|
302
311
|
}
|
|
@@ -327,6 +336,8 @@ function normalizeSetupAction(input, index) {
|
|
|
327
336
|
return {
|
|
328
337
|
type,
|
|
329
338
|
selector,
|
|
339
|
+
frame_selector: frameSelector,
|
|
340
|
+
frame_index: frameIndex,
|
|
330
341
|
force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
|
|
331
342
|
key,
|
|
332
343
|
value,
|
|
@@ -1213,6 +1224,8 @@ function assessSetupActionsFromEvidence(profile, evidence) {
|
|
|
1213
1224
|
viewport: viewport.name,
|
|
1214
1225
|
action: result.action ?? result.type ?? null,
|
|
1215
1226
|
selector: result.selector ?? null,
|
|
1227
|
+
frame_selector: result.frame_selector ?? null,
|
|
1228
|
+
frame_index: result.frame_index ?? null,
|
|
1216
1229
|
reason: result.reason ?? result.error ?? null
|
|
1217
1230
|
});
|
|
1218
1231
|
}
|
|
@@ -1725,10 +1738,12 @@ function assessProfile(profile, evidence) {
|
|
|
1725
1738
|
if (result && result.ok === false) {
|
|
1726
1739
|
failed.push({
|
|
1727
1740
|
viewport: viewport.name,
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1741
|
+
action: result.action || result.type || null,
|
|
1742
|
+
selector: result.selector || null,
|
|
1743
|
+
frame_selector: result.frame_selector || null,
|
|
1744
|
+
frame_index: result.frame_index ?? null,
|
|
1745
|
+
reason: result.reason || result.error || null,
|
|
1746
|
+
});
|
|
1732
1747
|
}
|
|
1733
1748
|
}
|
|
1734
1749
|
if (results.length < actionCount && results.every((result) => !result || result.ok !== false)) {
|
|
@@ -2191,8 +2206,8 @@ function setupJsonValue(value) {
|
|
|
2191
2206
|
function setupValuesEqual(left, right) {
|
|
2192
2207
|
return JSON.stringify(setupJsonValue(left)) === JSON.stringify(setupJsonValue(right));
|
|
2193
2208
|
}
|
|
2194
|
-
async function setupReadWindowValue(path) {
|
|
2195
|
-
return await
|
|
2209
|
+
async function setupReadWindowValue(context, path) {
|
|
2210
|
+
return await context.evaluate(({ path }) => {
|
|
2196
2211
|
const toJsonValue = (value) => {
|
|
2197
2212
|
if (value === null || value === undefined) return null;
|
|
2198
2213
|
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
@@ -2214,6 +2229,80 @@ async function setupReadWindowValue(path) {
|
|
|
2214
2229
|
return { ok: true, value: toJsonValue(current) };
|
|
2215
2230
|
}, { path });
|
|
2216
2231
|
}
|
|
2232
|
+
function setupFrameSelector(action) {
|
|
2233
|
+
return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
|
|
2234
|
+
}
|
|
2235
|
+
function setupFrameIndex(action) {
|
|
2236
|
+
const raw = action?.frame_index ?? action?.frameIndex ?? action?.iframe_index ?? action?.iframeIndex ?? 0;
|
|
2237
|
+
const number = Number(raw);
|
|
2238
|
+
return Number.isInteger(number) && number >= 0 ? number : 0;
|
|
2239
|
+
}
|
|
2240
|
+
function setupScopeEvidence(scope) {
|
|
2241
|
+
if (!scope || !scope.frame_selector) return {};
|
|
2242
|
+
return {
|
|
2243
|
+
frame_selector: scope.frame_selector,
|
|
2244
|
+
frame_index: scope.frame_index,
|
|
2245
|
+
frame_count: scope.frame_count,
|
|
2246
|
+
};
|
|
2247
|
+
}
|
|
2248
|
+
function setupScopeFailure(base, scope) {
|
|
2249
|
+
return {
|
|
2250
|
+
...base,
|
|
2251
|
+
...setupScopeEvidence(scope),
|
|
2252
|
+
reason: scope?.reason || "frame_scope_unavailable",
|
|
2253
|
+
error: scope?.error || undefined,
|
|
2254
|
+
};
|
|
2255
|
+
}
|
|
2256
|
+
async function setupActionScope(action, timeout) {
|
|
2257
|
+
const frameSelector = setupFrameSelector(action);
|
|
2258
|
+
if (!frameSelector) return { ok: true, context: page };
|
|
2259
|
+
const frameIndex = setupFrameIndex(action);
|
|
2260
|
+
let frameCount = 0;
|
|
2261
|
+
let locator = null;
|
|
2262
|
+
try {
|
|
2263
|
+
await page.waitForSelector(frameSelector, { state: "attached", timeout });
|
|
2264
|
+
locator = page.locator(frameSelector);
|
|
2265
|
+
frameCount = await locator.count();
|
|
2266
|
+
} catch (error) {
|
|
2267
|
+
return {
|
|
2268
|
+
ok: false,
|
|
2269
|
+
reason: "frame_selector_not_found",
|
|
2270
|
+
frame_selector: frameSelector,
|
|
2271
|
+
frame_index: frameIndex,
|
|
2272
|
+
frame_count: frameCount,
|
|
2273
|
+
error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
2274
|
+
};
|
|
2275
|
+
}
|
|
2276
|
+
if (!frameCount) {
|
|
2277
|
+
return { ok: false, reason: "frame_selector_not_found", frame_selector: frameSelector, frame_index: frameIndex, frame_count: frameCount };
|
|
2278
|
+
}
|
|
2279
|
+
if (frameIndex >= frameCount) {
|
|
2280
|
+
return { ok: false, reason: "frame_index_out_of_range", frame_selector: frameSelector, frame_index: frameIndex, frame_count: frameCount };
|
|
2281
|
+
}
|
|
2282
|
+
const handle = await locator.nth(frameIndex).elementHandle({ timeout }).catch((error) => ({ __riddle_error: error }));
|
|
2283
|
+
if (!handle || handle.__riddle_error) {
|
|
2284
|
+
return {
|
|
2285
|
+
ok: false,
|
|
2286
|
+
reason: "frame_element_unavailable",
|
|
2287
|
+
frame_selector: frameSelector,
|
|
2288
|
+
frame_index: frameIndex,
|
|
2289
|
+
frame_count: frameCount,
|
|
2290
|
+
error: handle?.__riddle_error ? String(handle.__riddle_error && handle.__riddle_error.message ? handle.__riddle_error.message : handle.__riddle_error).slice(0, 1000) : undefined,
|
|
2291
|
+
};
|
|
2292
|
+
}
|
|
2293
|
+
const frame = typeof handle.contentFrame === "function" ? await handle.contentFrame().catch((error) => ({ __riddle_error: error })) : null;
|
|
2294
|
+
if (!frame || frame.__riddle_error) {
|
|
2295
|
+
return {
|
|
2296
|
+
ok: false,
|
|
2297
|
+
reason: "content_frame_unavailable",
|
|
2298
|
+
frame_selector: frameSelector,
|
|
2299
|
+
frame_index: frameIndex,
|
|
2300
|
+
frame_count: frameCount,
|
|
2301
|
+
error: frame?.__riddle_error ? String(frame.__riddle_error && frame.__riddle_error.message ? frame.__riddle_error.message : frame.__riddle_error).slice(0, 1000) : undefined,
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
return { ok: true, context: frame, frame_selector: frameSelector, frame_index: frameIndex, frame_count: frameCount };
|
|
2305
|
+
}
|
|
2217
2306
|
async function setupLocatorText(locator, index) {
|
|
2218
2307
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
2219
2308
|
}
|
|
@@ -2375,7 +2464,8 @@ async function registerNetworkMocks(mocks) {
|
|
|
2375
2464
|
}
|
|
2376
2465
|
async function executeSetupAction(action, ordinal) {
|
|
2377
2466
|
const type = setupActionType(action);
|
|
2378
|
-
const
|
|
2467
|
+
const frameSelector = setupFrameSelector(action);
|
|
2468
|
+
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null, frame_selector: frameSelector || null };
|
|
2379
2469
|
const timeout = setupNumber(action.timeout_ms, 5000);
|
|
2380
2470
|
try {
|
|
2381
2471
|
if (type === "wait") {
|
|
@@ -2384,36 +2474,65 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2384
2474
|
return { ...base, ok: true, ms };
|
|
2385
2475
|
}
|
|
2386
2476
|
if (type === "wait_for_selector") {
|
|
2387
|
-
await
|
|
2388
|
-
return
|
|
2477
|
+
const scope = await setupActionScope(action, timeout);
|
|
2478
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2479
|
+
await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
|
|
2480
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
|
|
2481
|
+
}
|
|
2482
|
+
if (type === "press") {
|
|
2483
|
+
const key = String(action.key || "").trim();
|
|
2484
|
+
if (!key) return { ...base, reason: "missing_key" };
|
|
2485
|
+
const scope = await setupActionScope(action, timeout);
|
|
2486
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2487
|
+
if (!action.selector) {
|
|
2488
|
+
if (scope.frame_selector) {
|
|
2489
|
+
await scope.context.locator("body").press(key, { timeout });
|
|
2490
|
+
} else {
|
|
2491
|
+
await page.keyboard.press(key);
|
|
2492
|
+
}
|
|
2493
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, key };
|
|
2494
|
+
}
|
|
2495
|
+
const locator = scope.context.locator(action.selector);
|
|
2496
|
+
const count = await locator.count();
|
|
2497
|
+
if (!count) return { ...base, reason: "selector_not_found", count, key };
|
|
2498
|
+
const targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
2499
|
+
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
|
|
2500
|
+
await locator.nth(targetIndex).press(key, { timeout });
|
|
2501
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, target_index: targetIndex, key };
|
|
2389
2502
|
}
|
|
2390
2503
|
if (type === "local_storage" || type === "session_storage") {
|
|
2391
2504
|
const value = setupActionValue(action);
|
|
2392
|
-
await
|
|
2505
|
+
const scope = await setupActionScope(action, timeout);
|
|
2506
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2507
|
+
await scope.context.evaluate(({ type, key, value }) => {
|
|
2393
2508
|
const storage = type === "session_storage" ? window.sessionStorage : window.localStorage;
|
|
2394
2509
|
storage.setItem(key, value);
|
|
2395
2510
|
}, { type, key: action.key, value });
|
|
2396
2511
|
if (action.reload === true) {
|
|
2397
2512
|
await page.reload({ waitUntil: "domcontentloaded", timeout: 45000 });
|
|
2398
2513
|
}
|
|
2399
|
-
return { ...base, ok: true, key: action.key, value_length: value.length, reload: action.reload === true };
|
|
2514
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, key: action.key, value_length: value.length, reload: action.reload === true };
|
|
2400
2515
|
}
|
|
2401
2516
|
if (type === "clear_storage") {
|
|
2402
2517
|
const storage = action.storage || "both";
|
|
2403
|
-
await
|
|
2518
|
+
const scope = await setupActionScope(action, timeout);
|
|
2519
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2520
|
+
await scope.context.evaluate(({ storage }) => {
|
|
2404
2521
|
if (storage === "local" || storage === "both") window.localStorage.clear();
|
|
2405
2522
|
if (storage === "session" || storage === "both") window.sessionStorage.clear();
|
|
2406
2523
|
}, { storage });
|
|
2407
2524
|
if (action.reload === true) {
|
|
2408
2525
|
await page.reload({ waitUntil: "domcontentloaded", timeout: 45000 });
|
|
2409
2526
|
}
|
|
2410
|
-
return { ...base, ok: true, storage, reload: action.reload === true };
|
|
2527
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
|
|
2411
2528
|
}
|
|
2412
2529
|
if (type === "window_call") {
|
|
2413
2530
|
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
2414
2531
|
const args = Array.isArray(action.args) ? action.args : [];
|
|
2415
2532
|
if (!path) return { ...base, path, reason: "missing_path" };
|
|
2416
|
-
const
|
|
2533
|
+
const scope = await setupActionScope(action, timeout);
|
|
2534
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2535
|
+
const result = await scope.context.evaluate(async ({ path, args }) => {
|
|
2417
2536
|
const toJsonValue = (value) => {
|
|
2418
2537
|
if (value === null || value === undefined) return null;
|
|
2419
2538
|
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
@@ -2453,6 +2572,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2453
2572
|
const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
|
|
2454
2573
|
return {
|
|
2455
2574
|
...base,
|
|
2575
|
+
...setupScopeEvidence(scope),
|
|
2456
2576
|
ok: Boolean(result.ok && expectationMet),
|
|
2457
2577
|
path,
|
|
2458
2578
|
arg_count: args.length,
|
|
@@ -2483,13 +2603,16 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2483
2603
|
: action.expect;
|
|
2484
2604
|
if (!path) return { ...base, path, reason: "missing_path" };
|
|
2485
2605
|
if (!hasExpected) return { ...base, path, reason: "missing_expected_value" };
|
|
2606
|
+
const scope = await setupActionScope(action, timeout);
|
|
2607
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2486
2608
|
const startedAt = Date.now();
|
|
2487
2609
|
let result = null;
|
|
2488
2610
|
while (Date.now() - startedAt <= timeout) {
|
|
2489
|
-
result = await setupReadWindowValue(path);
|
|
2611
|
+
result = await setupReadWindowValue(scope.context, path);
|
|
2490
2612
|
if (result.ok && setupValuesEqual(result.value, expected)) {
|
|
2491
2613
|
return {
|
|
2492
2614
|
...base,
|
|
2615
|
+
...setupScopeEvidence(scope),
|
|
2493
2616
|
ok: true,
|
|
2494
2617
|
path,
|
|
2495
2618
|
value: setupJsonValue(result.value),
|
|
@@ -2501,6 +2624,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2501
2624
|
}
|
|
2502
2625
|
return {
|
|
2503
2626
|
...base,
|
|
2627
|
+
...setupScopeEvidence(scope),
|
|
2504
2628
|
path,
|
|
2505
2629
|
reason: result?.ok ? "unexpected_value" : result?.reason || "path_not_found",
|
|
2506
2630
|
missing_part: result?.missing_part || undefined,
|
|
@@ -2517,11 +2641,13 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2517
2641
|
const hasExpected = expected !== undefined;
|
|
2518
2642
|
if (!path) return { ...base, path, reason: "missing_path" };
|
|
2519
2643
|
if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
|
|
2644
|
+
const scope = await setupActionScope(action, timeout);
|
|
2645
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2520
2646
|
const startedAt = Date.now();
|
|
2521
2647
|
let result = null;
|
|
2522
2648
|
let lastReason = "path_not_found";
|
|
2523
2649
|
while (Date.now() - startedAt <= timeout) {
|
|
2524
|
-
result = await setupReadWindowValue(path);
|
|
2650
|
+
result = await setupReadWindowValue(scope.context, path);
|
|
2525
2651
|
if (result.ok) {
|
|
2526
2652
|
const actual = setupFiniteNumber(result.value);
|
|
2527
2653
|
if (actual === undefined) {
|
|
@@ -2535,6 +2661,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2535
2661
|
} else {
|
|
2536
2662
|
return {
|
|
2537
2663
|
...base,
|
|
2664
|
+
...setupScopeEvidence(scope),
|
|
2538
2665
|
ok: true,
|
|
2539
2666
|
path,
|
|
2540
2667
|
value: actual,
|
|
@@ -2551,6 +2678,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2551
2678
|
}
|
|
2552
2679
|
return {
|
|
2553
2680
|
...base,
|
|
2681
|
+
...setupScopeEvidence(scope),
|
|
2554
2682
|
path,
|
|
2555
2683
|
reason: lastReason,
|
|
2556
2684
|
missing_part: result?.missing_part || undefined,
|
|
@@ -2562,7 +2690,9 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2562
2690
|
};
|
|
2563
2691
|
}
|
|
2564
2692
|
if (type === "click") {
|
|
2565
|
-
const
|
|
2693
|
+
const scope = await setupActionScope(action, timeout);
|
|
2694
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2695
|
+
const locator = scope.context.locator(action.selector);
|
|
2566
2696
|
const count = await locator.count();
|
|
2567
2697
|
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
2568
2698
|
let targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
@@ -2594,33 +2724,39 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2594
2724
|
? { timeout, noWaitAfter: true, force: true }
|
|
2595
2725
|
: { timeout, noWaitAfter: true };
|
|
2596
2726
|
await locator.nth(targetIndex).click(clickOptions);
|
|
2597
|
-
return { ...base, ok: true, count, target_index: targetIndex, text: matchedText, force: action.force === true || undefined };
|
|
2727
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, target_index: targetIndex, text: matchedText, force: action.force === true || undefined };
|
|
2598
2728
|
}
|
|
2599
2729
|
if (type === "fill" || type === "set_input_value") {
|
|
2600
|
-
const
|
|
2730
|
+
const scope = await setupActionScope(action, timeout);
|
|
2731
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2732
|
+
const locator = scope.context.locator(action.selector);
|
|
2601
2733
|
const count = await locator.count();
|
|
2602
2734
|
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
2603
2735
|
const targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
2604
2736
|
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
2605
2737
|
const value = setupActionValue(action);
|
|
2606
2738
|
await locator.nth(targetIndex).fill(value, { timeout });
|
|
2607
|
-
return { ...base, ok: true, count, target_index: targetIndex, value_length: value.length };
|
|
2739
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, target_index: targetIndex, value_length: value.length };
|
|
2608
2740
|
}
|
|
2609
2741
|
if (type === "assert_selector_count") {
|
|
2610
|
-
const
|
|
2742
|
+
const scope = await setupActionScope(action, timeout);
|
|
2743
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2744
|
+
const locator = scope.context.locator(action.selector);
|
|
2611
2745
|
const expectedCount = setupNumber(action.expected_count, -1);
|
|
2612
2746
|
if (!Number.isInteger(expectedCount) || expectedCount < 0) return { ...base, reason: "invalid_expected_count", expected_count: action.expected_count };
|
|
2613
2747
|
const startedAt = Date.now();
|
|
2614
2748
|
let count = 0;
|
|
2615
2749
|
while (Date.now() - startedAt <= timeout) {
|
|
2616
2750
|
count = await locator.count().catch(() => 0);
|
|
2617
|
-
if (count === expectedCount) return { ...base, ok: true, count, expected_count: expectedCount, timeout_ms: timeout };
|
|
2751
|
+
if (count === expectedCount) return { ...base, ...setupScopeEvidence(scope), ok: true, count, expected_count: expectedCount, timeout_ms: timeout };
|
|
2618
2752
|
await page.waitForTimeout(100);
|
|
2619
2753
|
}
|
|
2620
|
-
return { ...base, reason: "selector_count_mismatch", count, expected_count: expectedCount, timeout_ms: timeout };
|
|
2754
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "selector_count_mismatch", count, expected_count: expectedCount, timeout_ms: timeout };
|
|
2621
2755
|
}
|
|
2622
2756
|
if (type === "wait_for_text") {
|
|
2623
|
-
const
|
|
2757
|
+
const scope = await setupActionScope(action, timeout);
|
|
2758
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2759
|
+
const locator = scope.context.locator(action.selector);
|
|
2624
2760
|
const startedAt = Date.now();
|
|
2625
2761
|
let lastText = "";
|
|
2626
2762
|
while (Date.now() - startedAt <= timeout) {
|
|
@@ -2629,15 +2765,17 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2629
2765
|
const text = await setupLocatorText(locator, index);
|
|
2630
2766
|
lastText = text || lastText;
|
|
2631
2767
|
if (setupTextMatches(text, action)) {
|
|
2632
|
-
return { ...base, ok: true, text: compactSetupResultText(text), target_index: index, timeout_ms: timeout };
|
|
2768
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, text: compactSetupResultText(text), target_index: index, timeout_ms: timeout };
|
|
2633
2769
|
}
|
|
2634
2770
|
}
|
|
2635
2771
|
await page.waitForTimeout(100);
|
|
2636
2772
|
}
|
|
2637
|
-
return { ...base, reason: "text_not_found", text: compactSetupResultText(lastText), timeout_ms: timeout };
|
|
2773
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "text_not_found", text: compactSetupResultText(lastText), timeout_ms: timeout };
|
|
2638
2774
|
}
|
|
2639
2775
|
if (type === "assert_text_visible" || type === "assert_text_absent") {
|
|
2640
|
-
const
|
|
2776
|
+
const scope = await setupActionScope(action, timeout);
|
|
2777
|
+
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
2778
|
+
const locator = scope.context.locator(action.selector);
|
|
2641
2779
|
const startedAt = Date.now();
|
|
2642
2780
|
let lastText = "";
|
|
2643
2781
|
let matchedText = "";
|
|
@@ -2656,7 +2794,7 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2656
2794
|
if (type === "assert_text_visible") {
|
|
2657
2795
|
const visible = await setupLocatorVisible(locator, index);
|
|
2658
2796
|
if (visible) {
|
|
2659
|
-
return { ...base, ok: true, count, text: compactSetupResultText(text), target_index: index, timeout_ms: timeout };
|
|
2797
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, text: compactSetupResultText(text), target_index: index, timeout_ms: timeout };
|
|
2660
2798
|
}
|
|
2661
2799
|
hiddenMatch = true;
|
|
2662
2800
|
break;
|
|
@@ -2665,17 +2803,17 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2665
2803
|
}
|
|
2666
2804
|
}
|
|
2667
2805
|
if (type === "assert_text_absent" && !matched) {
|
|
2668
|
-
return { ...base, ok: true, count, timeout_ms: timeout };
|
|
2806
|
+
return { ...base, ...setupScopeEvidence(scope), ok: true, count, timeout_ms: timeout };
|
|
2669
2807
|
}
|
|
2670
2808
|
await page.waitForTimeout(100);
|
|
2671
2809
|
}
|
|
2672
2810
|
if (type === "assert_text_visible") {
|
|
2673
2811
|
if (hiddenMatch) {
|
|
2674
|
-
return { ...base, reason: "matching_element_not_visible", text: compactSetupResultText(matchedText), timeout_ms: timeout };
|
|
2812
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "matching_element_not_visible", text: compactSetupResultText(matchedText), timeout_ms: timeout };
|
|
2675
2813
|
}
|
|
2676
|
-
return { ...base, reason: "text_not_found", text: compactSetupResultText(lastText), timeout_ms: timeout };
|
|
2814
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "text_not_found", text: compactSetupResultText(lastText), timeout_ms: timeout };
|
|
2677
2815
|
}
|
|
2678
|
-
return { ...base, reason: "text_still_present", text: compactSetupResultText(matchedText || lastText), timeout_ms: timeout };
|
|
2816
|
+
return { ...base, ...setupScopeEvidence(scope), reason: "text_still_present", text: compactSetupResultText(matchedText || lastText), timeout_ms: timeout };
|
|
2679
2817
|
}
|
|
2680
2818
|
return { ...base, reason: "unsupported_action" };
|
|
2681
2819
|
} catch (error) {
|
package/dist/profile.d.cts
CHANGED
|
@@ -5,7 +5,7 @@ declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evide
|
|
|
5
5
|
declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
|
|
6
6
|
declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
|
|
7
7
|
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
8
|
-
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
8
|
+
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "press", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
11
11
|
type RiddleProofProfileSetupActionType = typeof RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES[number];
|
|
@@ -20,6 +20,8 @@ interface RiddleProofProfileViewport {
|
|
|
20
20
|
interface RiddleProofProfileSetupAction {
|
|
21
21
|
type: RiddleProofProfileSetupActionType;
|
|
22
22
|
selector?: string;
|
|
23
|
+
frame_selector?: string;
|
|
24
|
+
frame_index?: number;
|
|
23
25
|
force?: boolean;
|
|
24
26
|
key?: string;
|
|
25
27
|
value?: string;
|
package/dist/profile.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evide
|
|
|
5
5
|
declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
|
|
6
6
|
declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
|
|
7
7
|
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
8
|
-
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
8
|
+
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "press", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
11
11
|
type RiddleProofProfileSetupActionType = typeof RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES[number];
|
|
@@ -20,6 +20,8 @@ interface RiddleProofProfileViewport {
|
|
|
20
20
|
interface RiddleProofProfileSetupAction {
|
|
21
21
|
type: RiddleProofProfileSetupActionType;
|
|
22
22
|
selector?: string;
|
|
23
|
+
frame_selector?: string;
|
|
24
|
+
frame_index?: number;
|
|
23
25
|
force?: boolean;
|
|
24
26
|
key?: string;
|
|
25
27
|
value?: string;
|
package/dist/profile.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
resolveRiddleProofProfileTimeoutSec,
|
|
20
20
|
slugifyRiddleProofProfileName,
|
|
21
21
|
summarizeRiddleProofProfileResult
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-Q5VW6MAP.js";
|
|
23
23
|
export {
|
|
24
24
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
25
25
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
@@ -292,7 +292,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
292
292
|
blocking?: boolean;
|
|
293
293
|
details?: Record<string, unknown>;
|
|
294
294
|
ok: boolean;
|
|
295
|
-
action: "
|
|
295
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
296
296
|
state_path: string;
|
|
297
297
|
stage: any;
|
|
298
298
|
summary: string;
|
|
@@ -382,7 +382,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
382
382
|
continueWithStage?: WorkflowStage | null;
|
|
383
383
|
blocking?: boolean;
|
|
384
384
|
details?: Record<string, unknown>;
|
|
385
|
-
action: "
|
|
385
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
386
386
|
state_path: string;
|
|
387
387
|
stage: any;
|
|
388
388
|
checkpoint: string;
|
|
@@ -659,7 +659,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
659
659
|
error?: undefined;
|
|
660
660
|
} | {
|
|
661
661
|
ok: boolean;
|
|
662
|
-
action: "
|
|
662
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|
|
@@ -292,7 +292,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
292
292
|
blocking?: boolean;
|
|
293
293
|
details?: Record<string, unknown>;
|
|
294
294
|
ok: boolean;
|
|
295
|
-
action: "
|
|
295
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
296
296
|
state_path: string;
|
|
297
297
|
stage: any;
|
|
298
298
|
summary: string;
|
|
@@ -382,7 +382,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
382
382
|
continueWithStage?: WorkflowStage | null;
|
|
383
383
|
blocking?: boolean;
|
|
384
384
|
details?: Record<string, unknown>;
|
|
385
|
-
action: "
|
|
385
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
386
386
|
state_path: string;
|
|
387
387
|
stage: any;
|
|
388
388
|
checkpoint: string;
|
|
@@ -659,7 +659,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
659
659
|
error?: undefined;
|
|
660
660
|
} | {
|
|
661
661
|
ok: boolean;
|
|
662
|
-
action: "
|
|
662
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|