@riddledc/riddle-proof 0.7.59 → 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 +10 -0
- package/dist/{chunk-Q5VW6MAP.js → chunk-FLQ4HHTT.js} +71 -2
- package/dist/cli.cjs +71 -2
- package/dist/cli.js +1 -1
- package/dist/index.cjs +71 -2
- package/dist/index.js +1 -1
- package/dist/profile.cjs +71 -2
- package/dist/profile.d.cts +2 -1
- package/dist/profile.d.ts +2 -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
|
@@ -355,6 +355,11 @@ game, or preview surfaces that render inside iframes:
|
|
|
355
355
|
|
|
356
356
|
```json
|
|
357
357
|
[
|
|
358
|
+
{
|
|
359
|
+
"type": "frame_url_matches",
|
|
360
|
+
"selector": ".game-player-root iframe",
|
|
361
|
+
"pattern": "/saved/hot-path-.+/index\\.html$"
|
|
362
|
+
},
|
|
358
363
|
{
|
|
359
364
|
"type": "frame_text_visible",
|
|
360
365
|
"selector": ".game-player-root iframe",
|
|
@@ -368,6 +373,11 @@ game, or preview surfaces that render inside iframes:
|
|
|
368
373
|
]
|
|
369
374
|
```
|
|
370
375
|
|
|
376
|
+
Use `frame_url_equals` when the iframe must resolve to one exact embedded
|
|
377
|
+
resource, or `frame_url_matches` when a preview/job/saved-game URL has a stable
|
|
378
|
+
shape but a generated ID. URL checks fail when the frame is missing, just like
|
|
379
|
+
frame text and overflow checks.
|
|
380
|
+
|
|
371
381
|
Frame checks capture each matching iframe's URL, title, compact text sample,
|
|
372
382
|
scroll width, client width, measured horizontal overflow, and top visible
|
|
373
383
|
overflow offenders. This keeps embedded-player audits in profile mode instead
|
|
@@ -22,6 +22,8 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
22
22
|
"selector_count_eq",
|
|
23
23
|
"selector_text_order",
|
|
24
24
|
"frame_text_visible",
|
|
25
|
+
"frame_url_equals",
|
|
26
|
+
"frame_url_matches",
|
|
25
27
|
"frame_no_horizontal_overflow",
|
|
26
28
|
"text_visible",
|
|
27
29
|
"text_absent",
|
|
@@ -506,12 +508,19 @@ function normalizeCheck(input, index) {
|
|
|
506
508
|
if ((type === "selector_visible" || type === "selector_absent" || type === "selector_count_at_least" || type === "selector_count_equals" || type === "selector_count_equal" || type === "selector_count_eq") && !stringValue(input.selector)) {
|
|
507
509
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
508
510
|
}
|
|
509
|
-
if ((type === "frame_text_visible" || type === "frame_no_horizontal_overflow") && !stringValue(input.selector)) {
|
|
511
|
+
if ((type === "frame_text_visible" || type === "frame_url_equals" || type === "frame_url_matches" || type === "frame_no_horizontal_overflow") && !stringValue(input.selector)) {
|
|
510
512
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
511
513
|
}
|
|
512
514
|
if (type === "frame_text_visible" && !stringValue(input.text) && !stringValue(input.pattern)) {
|
|
513
515
|
throw new Error(`checks[${index}] frame_text_visible requires text or pattern.`);
|
|
514
516
|
}
|
|
517
|
+
const expectedUrl = stringFromOwn(input, "expected_url", "expectedUrl", "url", "expected_value", "expectedValue", "value");
|
|
518
|
+
if (type === "frame_url_equals" && expectedUrl === void 0) {
|
|
519
|
+
throw new Error(`checks[${index}] frame_url_equals requires expected_url.`);
|
|
520
|
+
}
|
|
521
|
+
if (type === "frame_url_matches" && !stringValue(input.pattern)) {
|
|
522
|
+
throw new Error(`checks[${index}] frame_url_matches requires pattern.`);
|
|
523
|
+
}
|
|
515
524
|
if ((type === "text_visible" || type === "text_absent") && !stringValue(input.text) && !stringValue(input.pattern)) {
|
|
516
525
|
throw new Error(`checks[${index}] ${type} requires text or pattern.`);
|
|
517
526
|
}
|
|
@@ -544,6 +553,7 @@ function normalizeCheck(input, index) {
|
|
|
544
553
|
expected_path: stringValue(input.expected_path),
|
|
545
554
|
param: stringValue(input.param) || stringValue(input.search_param) || stringValue(input.searchParam) || stringValue(input.key),
|
|
546
555
|
expected_value: expectedValue,
|
|
556
|
+
expected_url: expectedUrl,
|
|
547
557
|
expected_routes: expectedRoutes,
|
|
548
558
|
selector: stringValue(input.selector),
|
|
549
559
|
expected_texts: expectedTexts,
|
|
@@ -1011,6 +1021,35 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
1011
1021
|
message: failed ? `Frame selector ${key} did not contain expected text in ${failed} viewport(s).` : void 0
|
|
1012
1022
|
};
|
|
1013
1023
|
}
|
|
1024
|
+
if (check.type === "frame_url_equals" || check.type === "frame_url_matches") {
|
|
1025
|
+
const key = selectorKey(check);
|
|
1026
|
+
const expectedUrl = check.expected_url || check.expected_value || "";
|
|
1027
|
+
const results = viewports.map((viewport) => {
|
|
1028
|
+
const frames = frameEvidenceForSelector(viewport, key);
|
|
1029
|
+
const urls = frames.map((frame) => String(frame.url || "")).filter(Boolean);
|
|
1030
|
+
const matches = urls.filter((url) => check.type === "frame_url_equals" ? url === expectedUrl : matchText(url, check));
|
|
1031
|
+
return {
|
|
1032
|
+
viewport: viewport.name,
|
|
1033
|
+
frame_count: frames.length,
|
|
1034
|
+
matched_count: matches.length,
|
|
1035
|
+
matched: matches.length > 0,
|
|
1036
|
+
urls: urls.slice(0, 10)
|
|
1037
|
+
};
|
|
1038
|
+
});
|
|
1039
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
1040
|
+
return {
|
|
1041
|
+
type: check.type,
|
|
1042
|
+
label: checkLabel(check),
|
|
1043
|
+
status: failed ? "failed" : "passed",
|
|
1044
|
+
evidence: {
|
|
1045
|
+
selector: key,
|
|
1046
|
+
expected_url: check.type === "frame_url_equals" ? expectedUrl : null,
|
|
1047
|
+
pattern: check.type === "frame_url_matches" ? check.pattern || null : null,
|
|
1048
|
+
viewports: results.map((result) => toJsonValue(result))
|
|
1049
|
+
},
|
|
1050
|
+
message: failed ? `Frame selector ${key} URL assertion failed in ${failed} viewport(s).` : void 0
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1014
1053
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
1015
1054
|
const key = selectorKey(check);
|
|
1016
1055
|
const maxOverflow = check.max_overflow_px ?? 4;
|
|
@@ -1902,6 +1941,36 @@ function assessProfile(profile, evidence) {
|
|
|
1902
1941
|
});
|
|
1903
1942
|
continue;
|
|
1904
1943
|
}
|
|
1944
|
+
if (check.type === "frame_url_equals" || check.type === "frame_url_matches") {
|
|
1945
|
+
const selector = check.selector || "";
|
|
1946
|
+
const expectedUrl = check.expected_url || check.expected_value || "";
|
|
1947
|
+
const results = checkViewports.map((viewport) => {
|
|
1948
|
+
const frames = frameEvidenceForSelector(viewport, selector);
|
|
1949
|
+
const urls = frames.map((frame) => String(frame.url || "")).filter(Boolean);
|
|
1950
|
+
const matches = urls.filter((url) => check.type === "frame_url_equals" ? url === expectedUrl : textMatches(url, check));
|
|
1951
|
+
return {
|
|
1952
|
+
viewport: viewport.name,
|
|
1953
|
+
frame_count: frames.length,
|
|
1954
|
+
matched_count: matches.length,
|
|
1955
|
+
matched: matches.length > 0,
|
|
1956
|
+
urls: urls.slice(0, 10),
|
|
1957
|
+
};
|
|
1958
|
+
});
|
|
1959
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
1960
|
+
checks.push({
|
|
1961
|
+
type: check.type,
|
|
1962
|
+
label: check.label || check.type,
|
|
1963
|
+
status: failed ? "failed" : "passed",
|
|
1964
|
+
evidence: {
|
|
1965
|
+
selector,
|
|
1966
|
+
expected_url: check.type === "frame_url_equals" ? expectedUrl : null,
|
|
1967
|
+
pattern: check.type === "frame_url_matches" ? check.pattern || null : null,
|
|
1968
|
+
viewports: results,
|
|
1969
|
+
},
|
|
1970
|
+
message: failed ? "Frame selector " + selector + " URL assertion failed in " + failed + " viewport(s)." : undefined,
|
|
1971
|
+
});
|
|
1972
|
+
continue;
|
|
1973
|
+
}
|
|
1905
1974
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
1906
1975
|
const selector = check.selector || "";
|
|
1907
1976
|
const maxOverflow = check.max_overflow_px == null ? 4 : check.max_overflow_px;
|
|
@@ -3373,7 +3442,7 @@ async function captureViewport(viewport) {
|
|
|
3373
3442
|
if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
|
|
3374
3443
|
text_matches[textKey(check)] = textMatches(dom.body_text || dom.body_text_sample || "", check);
|
|
3375
3444
|
}
|
|
3376
|
-
if ((check.type === "frame_text_visible" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
3445
|
+
if ((check.type === "frame_text_visible" || check.type === "frame_url_equals" || check.type === "frame_url_matches" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
3377
3446
|
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
3378
3447
|
frames[check.selector] = frames[check.selector] || await frameEvidence(check.selector);
|
|
3379
3448
|
}
|
package/dist/cli.cjs
CHANGED
|
@@ -6895,6 +6895,8 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
6895
6895
|
"selector_count_eq",
|
|
6896
6896
|
"selector_text_order",
|
|
6897
6897
|
"frame_text_visible",
|
|
6898
|
+
"frame_url_equals",
|
|
6899
|
+
"frame_url_matches",
|
|
6898
6900
|
"frame_no_horizontal_overflow",
|
|
6899
6901
|
"text_visible",
|
|
6900
6902
|
"text_absent",
|
|
@@ -7379,12 +7381,19 @@ function normalizeCheck(input, index) {
|
|
|
7379
7381
|
if ((type === "selector_visible" || type === "selector_absent" || type === "selector_count_at_least" || type === "selector_count_equals" || type === "selector_count_equal" || type === "selector_count_eq") && !stringValue2(input.selector)) {
|
|
7380
7382
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
7381
7383
|
}
|
|
7382
|
-
if ((type === "frame_text_visible" || type === "frame_no_horizontal_overflow") && !stringValue2(input.selector)) {
|
|
7384
|
+
if ((type === "frame_text_visible" || type === "frame_url_equals" || type === "frame_url_matches" || type === "frame_no_horizontal_overflow") && !stringValue2(input.selector)) {
|
|
7383
7385
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
7384
7386
|
}
|
|
7385
7387
|
if (type === "frame_text_visible" && !stringValue2(input.text) && !stringValue2(input.pattern)) {
|
|
7386
7388
|
throw new Error(`checks[${index}] frame_text_visible requires text or pattern.`);
|
|
7387
7389
|
}
|
|
7390
|
+
const expectedUrl = stringFromOwn(input, "expected_url", "expectedUrl", "url", "expected_value", "expectedValue", "value");
|
|
7391
|
+
if (type === "frame_url_equals" && expectedUrl === void 0) {
|
|
7392
|
+
throw new Error(`checks[${index}] frame_url_equals requires expected_url.`);
|
|
7393
|
+
}
|
|
7394
|
+
if (type === "frame_url_matches" && !stringValue2(input.pattern)) {
|
|
7395
|
+
throw new Error(`checks[${index}] frame_url_matches requires pattern.`);
|
|
7396
|
+
}
|
|
7388
7397
|
if ((type === "text_visible" || type === "text_absent") && !stringValue2(input.text) && !stringValue2(input.pattern)) {
|
|
7389
7398
|
throw new Error(`checks[${index}] ${type} requires text or pattern.`);
|
|
7390
7399
|
}
|
|
@@ -7417,6 +7426,7 @@ function normalizeCheck(input, index) {
|
|
|
7417
7426
|
expected_path: stringValue2(input.expected_path),
|
|
7418
7427
|
param: stringValue2(input.param) || stringValue2(input.search_param) || stringValue2(input.searchParam) || stringValue2(input.key),
|
|
7419
7428
|
expected_value: expectedValue,
|
|
7429
|
+
expected_url: expectedUrl,
|
|
7420
7430
|
expected_routes: expectedRoutes,
|
|
7421
7431
|
selector: stringValue2(input.selector),
|
|
7422
7432
|
expected_texts: expectedTexts,
|
|
@@ -7884,6 +7894,35 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
7884
7894
|
message: failed ? `Frame selector ${key} did not contain expected text in ${failed} viewport(s).` : void 0
|
|
7885
7895
|
};
|
|
7886
7896
|
}
|
|
7897
|
+
if (check.type === "frame_url_equals" || check.type === "frame_url_matches") {
|
|
7898
|
+
const key = selectorKey(check);
|
|
7899
|
+
const expectedUrl = check.expected_url || check.expected_value || "";
|
|
7900
|
+
const results = viewports.map((viewport) => {
|
|
7901
|
+
const frames = frameEvidenceForSelector(viewport, key);
|
|
7902
|
+
const urls = frames.map((frame) => String(frame.url || "")).filter(Boolean);
|
|
7903
|
+
const matches = urls.filter((url) => check.type === "frame_url_equals" ? url === expectedUrl : matchText(url, check));
|
|
7904
|
+
return {
|
|
7905
|
+
viewport: viewport.name,
|
|
7906
|
+
frame_count: frames.length,
|
|
7907
|
+
matched_count: matches.length,
|
|
7908
|
+
matched: matches.length > 0,
|
|
7909
|
+
urls: urls.slice(0, 10)
|
|
7910
|
+
};
|
|
7911
|
+
});
|
|
7912
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
7913
|
+
return {
|
|
7914
|
+
type: check.type,
|
|
7915
|
+
label: checkLabel(check),
|
|
7916
|
+
status: failed ? "failed" : "passed",
|
|
7917
|
+
evidence: {
|
|
7918
|
+
selector: key,
|
|
7919
|
+
expected_url: check.type === "frame_url_equals" ? expectedUrl : null,
|
|
7920
|
+
pattern: check.type === "frame_url_matches" ? check.pattern || null : null,
|
|
7921
|
+
viewports: results.map((result) => toJsonValue(result))
|
|
7922
|
+
},
|
|
7923
|
+
message: failed ? `Frame selector ${key} URL assertion failed in ${failed} viewport(s).` : void 0
|
|
7924
|
+
};
|
|
7925
|
+
}
|
|
7887
7926
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
7888
7927
|
const key = selectorKey(check);
|
|
7889
7928
|
const maxOverflow = check.max_overflow_px ?? 4;
|
|
@@ -8759,6 +8798,36 @@ function assessProfile(profile, evidence) {
|
|
|
8759
8798
|
});
|
|
8760
8799
|
continue;
|
|
8761
8800
|
}
|
|
8801
|
+
if (check.type === "frame_url_equals" || check.type === "frame_url_matches") {
|
|
8802
|
+
const selector = check.selector || "";
|
|
8803
|
+
const expectedUrl = check.expected_url || check.expected_value || "";
|
|
8804
|
+
const results = checkViewports.map((viewport) => {
|
|
8805
|
+
const frames = frameEvidenceForSelector(viewport, selector);
|
|
8806
|
+
const urls = frames.map((frame) => String(frame.url || "")).filter(Boolean);
|
|
8807
|
+
const matches = urls.filter((url) => check.type === "frame_url_equals" ? url === expectedUrl : textMatches(url, check));
|
|
8808
|
+
return {
|
|
8809
|
+
viewport: viewport.name,
|
|
8810
|
+
frame_count: frames.length,
|
|
8811
|
+
matched_count: matches.length,
|
|
8812
|
+
matched: matches.length > 0,
|
|
8813
|
+
urls: urls.slice(0, 10),
|
|
8814
|
+
};
|
|
8815
|
+
});
|
|
8816
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
8817
|
+
checks.push({
|
|
8818
|
+
type: check.type,
|
|
8819
|
+
label: check.label || check.type,
|
|
8820
|
+
status: failed ? "failed" : "passed",
|
|
8821
|
+
evidence: {
|
|
8822
|
+
selector,
|
|
8823
|
+
expected_url: check.type === "frame_url_equals" ? expectedUrl : null,
|
|
8824
|
+
pattern: check.type === "frame_url_matches" ? check.pattern || null : null,
|
|
8825
|
+
viewports: results,
|
|
8826
|
+
},
|
|
8827
|
+
message: failed ? "Frame selector " + selector + " URL assertion failed in " + failed + " viewport(s)." : undefined,
|
|
8828
|
+
});
|
|
8829
|
+
continue;
|
|
8830
|
+
}
|
|
8762
8831
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
8763
8832
|
const selector = check.selector || "";
|
|
8764
8833
|
const maxOverflow = check.max_overflow_px == null ? 4 : check.max_overflow_px;
|
|
@@ -10230,7 +10299,7 @@ async function captureViewport(viewport) {
|
|
|
10230
10299
|
if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
|
|
10231
10300
|
text_matches[textKey(check)] = textMatches(dom.body_text || dom.body_text_sample || "", check);
|
|
10232
10301
|
}
|
|
10233
|
-
if ((check.type === "frame_text_visible" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
10302
|
+
if ((check.type === "frame_text_visible" || check.type === "frame_url_equals" || check.type === "frame_url_matches" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
10234
10303
|
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
10235
10304
|
frames[check.selector] = frames[check.selector] || await frameEvidence(check.selector);
|
|
10236
10305
|
}
|
package/dist/cli.js
CHANGED
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",
|
|
@@ -9220,12 +9222,19 @@ function normalizeCheck(input, index) {
|
|
|
9220
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)) {
|
|
9221
9223
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
9222
9224
|
}
|
|
9223
|
-
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)) {
|
|
9224
9226
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
9225
9227
|
}
|
|
9226
9228
|
if (type === "frame_text_visible" && !stringValue5(input.text) && !stringValue5(input.pattern)) {
|
|
9227
9229
|
throw new Error(`checks[${index}] frame_text_visible requires text or pattern.`);
|
|
9228
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
|
+
}
|
|
9229
9238
|
if ((type === "text_visible" || type === "text_absent") && !stringValue5(input.text) && !stringValue5(input.pattern)) {
|
|
9230
9239
|
throw new Error(`checks[${index}] ${type} requires text or pattern.`);
|
|
9231
9240
|
}
|
|
@@ -9258,6 +9267,7 @@ function normalizeCheck(input, index) {
|
|
|
9258
9267
|
expected_path: stringValue5(input.expected_path),
|
|
9259
9268
|
param: stringValue5(input.param) || stringValue5(input.search_param) || stringValue5(input.searchParam) || stringValue5(input.key),
|
|
9260
9269
|
expected_value: expectedValue,
|
|
9270
|
+
expected_url: expectedUrl,
|
|
9261
9271
|
expected_routes: expectedRoutes,
|
|
9262
9272
|
selector: stringValue5(input.selector),
|
|
9263
9273
|
expected_texts: expectedTexts,
|
|
@@ -9725,6 +9735,35 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
9725
9735
|
message: failed ? `Frame selector ${key} did not contain expected text in ${failed} viewport(s).` : void 0
|
|
9726
9736
|
};
|
|
9727
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
|
+
}
|
|
9728
9767
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
9729
9768
|
const key = selectorKey(check);
|
|
9730
9769
|
const maxOverflow = check.max_overflow_px ?? 4;
|
|
@@ -10616,6 +10655,36 @@ function assessProfile(profile, evidence) {
|
|
|
10616
10655
|
});
|
|
10617
10656
|
continue;
|
|
10618
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
|
+
}
|
|
10619
10688
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
10620
10689
|
const selector = check.selector || "";
|
|
10621
10690
|
const maxOverflow = check.max_overflow_px == null ? 4 : check.max_overflow_px;
|
|
@@ -12087,7 +12156,7 @@ async function captureViewport(viewport) {
|
|
|
12087
12156
|
if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
|
|
12088
12157
|
text_matches[textKey(check)] = textMatches(dom.body_text || dom.body_text_sample || "", check);
|
|
12089
12158
|
}
|
|
12090
|
-
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) {
|
|
12091
12160
|
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
12092
12161
|
frames[check.selector] = frames[check.selector] || await frameEvidence(check.selector);
|
|
12093
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,
|
package/dist/profile.cjs
CHANGED
|
@@ -65,6 +65,8 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
65
65
|
"selector_count_eq",
|
|
66
66
|
"selector_text_order",
|
|
67
67
|
"frame_text_visible",
|
|
68
|
+
"frame_url_equals",
|
|
69
|
+
"frame_url_matches",
|
|
68
70
|
"frame_no_horizontal_overflow",
|
|
69
71
|
"text_visible",
|
|
70
72
|
"text_absent",
|
|
@@ -549,12 +551,19 @@ function normalizeCheck(input, index) {
|
|
|
549
551
|
if ((type === "selector_visible" || type === "selector_absent" || type === "selector_count_at_least" || type === "selector_count_equals" || type === "selector_count_equal" || type === "selector_count_eq") && !stringValue(input.selector)) {
|
|
550
552
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
551
553
|
}
|
|
552
|
-
if ((type === "frame_text_visible" || type === "frame_no_horizontal_overflow") && !stringValue(input.selector)) {
|
|
554
|
+
if ((type === "frame_text_visible" || type === "frame_url_equals" || type === "frame_url_matches" || type === "frame_no_horizontal_overflow") && !stringValue(input.selector)) {
|
|
553
555
|
throw new Error(`checks[${index}] ${type} requires selector.`);
|
|
554
556
|
}
|
|
555
557
|
if (type === "frame_text_visible" && !stringValue(input.text) && !stringValue(input.pattern)) {
|
|
556
558
|
throw new Error(`checks[${index}] frame_text_visible requires text or pattern.`);
|
|
557
559
|
}
|
|
560
|
+
const expectedUrl = stringFromOwn(input, "expected_url", "expectedUrl", "url", "expected_value", "expectedValue", "value");
|
|
561
|
+
if (type === "frame_url_equals" && expectedUrl === void 0) {
|
|
562
|
+
throw new Error(`checks[${index}] frame_url_equals requires expected_url.`);
|
|
563
|
+
}
|
|
564
|
+
if (type === "frame_url_matches" && !stringValue(input.pattern)) {
|
|
565
|
+
throw new Error(`checks[${index}] frame_url_matches requires pattern.`);
|
|
566
|
+
}
|
|
558
567
|
if ((type === "text_visible" || type === "text_absent") && !stringValue(input.text) && !stringValue(input.pattern)) {
|
|
559
568
|
throw new Error(`checks[${index}] ${type} requires text or pattern.`);
|
|
560
569
|
}
|
|
@@ -587,6 +596,7 @@ function normalizeCheck(input, index) {
|
|
|
587
596
|
expected_path: stringValue(input.expected_path),
|
|
588
597
|
param: stringValue(input.param) || stringValue(input.search_param) || stringValue(input.searchParam) || stringValue(input.key),
|
|
589
598
|
expected_value: expectedValue,
|
|
599
|
+
expected_url: expectedUrl,
|
|
590
600
|
expected_routes: expectedRoutes,
|
|
591
601
|
selector: stringValue(input.selector),
|
|
592
602
|
expected_texts: expectedTexts,
|
|
@@ -1054,6 +1064,35 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
1054
1064
|
message: failed ? `Frame selector ${key} did not contain expected text in ${failed} viewport(s).` : void 0
|
|
1055
1065
|
};
|
|
1056
1066
|
}
|
|
1067
|
+
if (check.type === "frame_url_equals" || check.type === "frame_url_matches") {
|
|
1068
|
+
const key = selectorKey(check);
|
|
1069
|
+
const expectedUrl = check.expected_url || check.expected_value || "";
|
|
1070
|
+
const results = viewports.map((viewport) => {
|
|
1071
|
+
const frames = frameEvidenceForSelector(viewport, key);
|
|
1072
|
+
const urls = frames.map((frame) => String(frame.url || "")).filter(Boolean);
|
|
1073
|
+
const matches = urls.filter((url) => check.type === "frame_url_equals" ? url === expectedUrl : matchText(url, check));
|
|
1074
|
+
return {
|
|
1075
|
+
viewport: viewport.name,
|
|
1076
|
+
frame_count: frames.length,
|
|
1077
|
+
matched_count: matches.length,
|
|
1078
|
+
matched: matches.length > 0,
|
|
1079
|
+
urls: urls.slice(0, 10)
|
|
1080
|
+
};
|
|
1081
|
+
});
|
|
1082
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
1083
|
+
return {
|
|
1084
|
+
type: check.type,
|
|
1085
|
+
label: checkLabel(check),
|
|
1086
|
+
status: failed ? "failed" : "passed",
|
|
1087
|
+
evidence: {
|
|
1088
|
+
selector: key,
|
|
1089
|
+
expected_url: check.type === "frame_url_equals" ? expectedUrl : null,
|
|
1090
|
+
pattern: check.type === "frame_url_matches" ? check.pattern || null : null,
|
|
1091
|
+
viewports: results.map((result) => toJsonValue(result))
|
|
1092
|
+
},
|
|
1093
|
+
message: failed ? `Frame selector ${key} URL assertion failed in ${failed} viewport(s).` : void 0
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1057
1096
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
1058
1097
|
const key = selectorKey(check);
|
|
1059
1098
|
const maxOverflow = check.max_overflow_px ?? 4;
|
|
@@ -1945,6 +1984,36 @@ function assessProfile(profile, evidence) {
|
|
|
1945
1984
|
});
|
|
1946
1985
|
continue;
|
|
1947
1986
|
}
|
|
1987
|
+
if (check.type === "frame_url_equals" || check.type === "frame_url_matches") {
|
|
1988
|
+
const selector = check.selector || "";
|
|
1989
|
+
const expectedUrl = check.expected_url || check.expected_value || "";
|
|
1990
|
+
const results = checkViewports.map((viewport) => {
|
|
1991
|
+
const frames = frameEvidenceForSelector(viewport, selector);
|
|
1992
|
+
const urls = frames.map((frame) => String(frame.url || "")).filter(Boolean);
|
|
1993
|
+
const matches = urls.filter((url) => check.type === "frame_url_equals" ? url === expectedUrl : textMatches(url, check));
|
|
1994
|
+
return {
|
|
1995
|
+
viewport: viewport.name,
|
|
1996
|
+
frame_count: frames.length,
|
|
1997
|
+
matched_count: matches.length,
|
|
1998
|
+
matched: matches.length > 0,
|
|
1999
|
+
urls: urls.slice(0, 10),
|
|
2000
|
+
};
|
|
2001
|
+
});
|
|
2002
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
2003
|
+
checks.push({
|
|
2004
|
+
type: check.type,
|
|
2005
|
+
label: check.label || check.type,
|
|
2006
|
+
status: failed ? "failed" : "passed",
|
|
2007
|
+
evidence: {
|
|
2008
|
+
selector,
|
|
2009
|
+
expected_url: check.type === "frame_url_equals" ? expectedUrl : null,
|
|
2010
|
+
pattern: check.type === "frame_url_matches" ? check.pattern || null : null,
|
|
2011
|
+
viewports: results,
|
|
2012
|
+
},
|
|
2013
|
+
message: failed ? "Frame selector " + selector + " URL assertion failed in " + failed + " viewport(s)." : undefined,
|
|
2014
|
+
});
|
|
2015
|
+
continue;
|
|
2016
|
+
}
|
|
1948
2017
|
if (check.type === "frame_no_horizontal_overflow") {
|
|
1949
2018
|
const selector = check.selector || "";
|
|
1950
2019
|
const maxOverflow = check.max_overflow_px == null ? 4 : check.max_overflow_px;
|
|
@@ -3416,7 +3485,7 @@ async function captureViewport(viewport) {
|
|
|
3416
3485
|
if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
|
|
3417
3486
|
text_matches[textKey(check)] = textMatches(dom.body_text || dom.body_text_sample || "", check);
|
|
3418
3487
|
}
|
|
3419
|
-
if ((check.type === "frame_text_visible" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
3488
|
+
if ((check.type === "frame_text_visible" || check.type === "frame_url_equals" || check.type === "frame_url_matches" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
3420
3489
|
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
3421
3490
|
frames[check.selector] = frames[check.selector] || await frameEvidence(check.selector);
|
|
3422
3491
|
}
|
package/dist/profile.d.cts
CHANGED
|
@@ -4,7 +4,7 @@ declare const RIDDLE_PROOF_PROFILE_VERSION: "riddle-proof.profile.v1";
|
|
|
4
4
|
declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evidence.v1";
|
|
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
|
-
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"];
|
|
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_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
8
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];
|
|
@@ -94,6 +94,7 @@ interface RiddleProofProfileCheck {
|
|
|
94
94
|
expected_path?: string;
|
|
95
95
|
param?: string;
|
|
96
96
|
expected_value?: string;
|
|
97
|
+
expected_url?: string;
|
|
97
98
|
expected_routes?: RiddleProofProfileRouteInventoryRoute[];
|
|
98
99
|
selector?: string;
|
|
99
100
|
expected_texts?: string[];
|
package/dist/profile.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ declare const RIDDLE_PROOF_PROFILE_VERSION: "riddle-proof.profile.v1";
|
|
|
4
4
|
declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evidence.v1";
|
|
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
|
-
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"];
|
|
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_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
8
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];
|
|
@@ -94,6 +94,7 @@ interface RiddleProofProfileCheck {
|
|
|
94
94
|
expected_path?: string;
|
|
95
95
|
param?: string;
|
|
96
96
|
expected_value?: string;
|
|
97
|
+
expected_url?: string;
|
|
97
98
|
expected_routes?: RiddleProofProfileRouteInventoryRoute[];
|
|
98
99
|
selector?: string;
|
|
99
100
|
expected_texts?: 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-FLQ4HHTT.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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|