@riddledc/riddle-proof 0.7.9 → 0.7.10
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 +3 -1
- package/dist/{chunk-NUSUGO2P.js → chunk-A7RJZD4I.js} +45 -9
- package/dist/cli.cjs +45 -9
- package/dist/cli.js +1 -1
- package/dist/index.cjs +45 -9
- package/dist/index.js +1 -1
- package/dist/profile.cjs +45 -9
- 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
|
@@ -150,7 +150,9 @@ appears only after a picker, tab, login stub, transport control, or other
|
|
|
150
150
|
bounded interaction. Supported setup actions are `click`, `wait`,
|
|
151
151
|
`wait_for_selector`, and `wait_for_text`; a failed setup action is recorded as
|
|
152
152
|
a failed `setup_actions_succeeded` check so the profile cannot pass without
|
|
153
|
-
reaching the intended state.
|
|
153
|
+
reaching the intended state. Text-matched `click` actions prefer visible
|
|
154
|
+
matching elements, which keeps responsive layouts from selecting hidden desktop
|
|
155
|
+
or mobile-only links.
|
|
154
156
|
|
|
155
157
|
The result uses `riddle-proof.profile-result.v1` and separates product failures
|
|
156
158
|
from weak proof and environment blockers:
|
|
@@ -199,7 +199,13 @@ function resolveRiddleProofProfileTargetUrl(profile) {
|
|
|
199
199
|
throw new Error("profile target URL could not be resolved.");
|
|
200
200
|
}
|
|
201
201
|
function routeForViewport(viewport) {
|
|
202
|
-
|
|
202
|
+
if (viewport?.route) {
|
|
203
|
+
return {
|
|
204
|
+
...viewport.route,
|
|
205
|
+
matched: viewport.route.matched || routePathMatches(viewport.route.observed, viewport.route.expected_path)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
203
209
|
requested: "",
|
|
204
210
|
observed: "",
|
|
205
211
|
matched: false,
|
|
@@ -225,8 +231,17 @@ function matchText(sample, check) {
|
|
|
225
231
|
}
|
|
226
232
|
return sample.includes(check.text || "");
|
|
227
233
|
}
|
|
234
|
+
function normalizeRoutePath(path) {
|
|
235
|
+
const value = path || "/";
|
|
236
|
+
if (value === "/") return "/";
|
|
237
|
+
return value.replace(/\/+$/, "") || "/";
|
|
238
|
+
}
|
|
239
|
+
function routePathMatches(observed, expected) {
|
|
240
|
+
return normalizeRoutePath(observed) === normalizeRoutePath(expected);
|
|
241
|
+
}
|
|
228
242
|
function successfulRoute(route) {
|
|
229
|
-
|
|
243
|
+
const matched = route.matched || routePathMatches(route.observed, route.expected_path);
|
|
244
|
+
return matched && !route.error && (route.http_status === null || route.http_status === void 0 || route.http_status < 400);
|
|
230
245
|
}
|
|
231
246
|
function assessCheckFromEvidence(check, evidence) {
|
|
232
247
|
const viewports = evidence.viewports || [];
|
|
@@ -244,7 +259,7 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
244
259
|
const failed = viewports.filter((viewport) => !successfulRoute({
|
|
245
260
|
...viewport.route,
|
|
246
261
|
expected_path: expectedPath,
|
|
247
|
-
matched: viewport.route.observed
|
|
262
|
+
matched: routePathMatches(viewport.route.observed, expectedPath) || viewport.route.matched
|
|
248
263
|
}));
|
|
249
264
|
return {
|
|
250
265
|
type: check.type,
|
|
@@ -512,8 +527,16 @@ function createRiddleProofProfileInsufficientResult(input) {
|
|
|
512
527
|
}
|
|
513
528
|
function runtimeScriptAssessmentSource() {
|
|
514
529
|
return String.raw`
|
|
530
|
+
function normalizeRoutePath(path) {
|
|
531
|
+
const value = path || "/";
|
|
532
|
+
if (value === "/") return "/";
|
|
533
|
+
return value.replace(/\/+$/, "") || "/";
|
|
534
|
+
}
|
|
535
|
+
function routePathMatches(observed, expected) {
|
|
536
|
+
return normalizeRoutePath(observed) === normalizeRoutePath(expected);
|
|
537
|
+
}
|
|
515
538
|
function routeOk(route) {
|
|
516
|
-
return Boolean(route && route.matched && !route.error && (route.http_status == null || route.http_status < 400));
|
|
539
|
+
return Boolean(route && (route.matched || routePathMatches(route.observed, route.expected_path)) && !route.error && (route.http_status == null || route.http_status < 400));
|
|
517
540
|
}
|
|
518
541
|
function textMatches(sample, check) {
|
|
519
542
|
if (check.pattern) {
|
|
@@ -570,7 +593,7 @@ function assessProfile(profile, evidence) {
|
|
|
570
593
|
const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
|
|
571
594
|
const failed = viewports.filter((viewport) => {
|
|
572
595
|
const route = { ...(viewport.route || {}), expected_path: expectedPath };
|
|
573
|
-
route.matched = route.observed
|
|
596
|
+
route.matched = routePathMatches(route.observed, expectedPath) || route.matched;
|
|
574
597
|
return !routeOk(route);
|
|
575
598
|
});
|
|
576
599
|
checks.push({
|
|
@@ -743,6 +766,9 @@ function setupTextMatches(sample, action) {
|
|
|
743
766
|
async function setupLocatorText(locator, index) {
|
|
744
767
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
745
768
|
}
|
|
769
|
+
async function setupLocatorVisible(locator, index) {
|
|
770
|
+
return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
|
|
771
|
+
}
|
|
746
772
|
async function executeSetupAction(action, ordinal) {
|
|
747
773
|
const type = setupActionType(action);
|
|
748
774
|
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
|
|
@@ -763,16 +789,26 @@ async function executeSetupAction(action, ordinal) {
|
|
|
763
789
|
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
764
790
|
let targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
765
791
|
let matchedText = null;
|
|
792
|
+
let hiddenMatchIndex = -1;
|
|
793
|
+
let hiddenMatchedText = null;
|
|
766
794
|
if (action.text || action.pattern) {
|
|
767
795
|
targetIndex = -1;
|
|
768
796
|
for (let index = 0; index < count; index += 1) {
|
|
769
797
|
const text = await setupLocatorText(locator, index);
|
|
770
798
|
if (setupTextMatches(text, action)) {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
799
|
+
const visible = await setupLocatorVisible(locator, index);
|
|
800
|
+
if (visible) {
|
|
801
|
+
targetIndex = index;
|
|
802
|
+
matchedText = text;
|
|
803
|
+
break;
|
|
804
|
+
}
|
|
805
|
+
if (hiddenMatchIndex < 0) {
|
|
806
|
+
hiddenMatchIndex = index;
|
|
807
|
+
hiddenMatchedText = text;
|
|
808
|
+
}
|
|
774
809
|
}
|
|
775
810
|
}
|
|
811
|
+
if (targetIndex < 0 && hiddenMatchIndex >= 0) return { ...base, reason: "matching_element_not_visible", count, target_index: hiddenMatchIndex, text: hiddenMatchedText };
|
|
776
812
|
if (targetIndex < 0) return { ...base, reason: "text_not_found", count };
|
|
777
813
|
}
|
|
778
814
|
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
@@ -899,7 +935,7 @@ async function captureViewport(viewport) {
|
|
|
899
935
|
requested: targetUrl,
|
|
900
936
|
observed: dom.pathname,
|
|
901
937
|
expected_path: expectedPath,
|
|
902
|
-
matched: dom.pathname
|
|
938
|
+
matched: routePathMatches(dom.pathname, expectedPath),
|
|
903
939
|
http_status: httpStatus,
|
|
904
940
|
error: navigationError || waitError || undefined,
|
|
905
941
|
},
|
package/dist/cli.cjs
CHANGED
|
@@ -6978,7 +6978,13 @@ function resolveRiddleProofProfileTargetUrl(profile) {
|
|
|
6978
6978
|
throw new Error("profile target URL could not be resolved.");
|
|
6979
6979
|
}
|
|
6980
6980
|
function routeForViewport(viewport) {
|
|
6981
|
-
|
|
6981
|
+
if (viewport?.route) {
|
|
6982
|
+
return {
|
|
6983
|
+
...viewport.route,
|
|
6984
|
+
matched: viewport.route.matched || routePathMatches(viewport.route.observed, viewport.route.expected_path)
|
|
6985
|
+
};
|
|
6986
|
+
}
|
|
6987
|
+
return {
|
|
6982
6988
|
requested: "",
|
|
6983
6989
|
observed: "",
|
|
6984
6990
|
matched: false,
|
|
@@ -7004,8 +7010,17 @@ function matchText(sample, check) {
|
|
|
7004
7010
|
}
|
|
7005
7011
|
return sample.includes(check.text || "");
|
|
7006
7012
|
}
|
|
7013
|
+
function normalizeRoutePath(path7) {
|
|
7014
|
+
const value = path7 || "/";
|
|
7015
|
+
if (value === "/") return "/";
|
|
7016
|
+
return value.replace(/\/+$/, "") || "/";
|
|
7017
|
+
}
|
|
7018
|
+
function routePathMatches(observed, expected) {
|
|
7019
|
+
return normalizeRoutePath(observed) === normalizeRoutePath(expected);
|
|
7020
|
+
}
|
|
7007
7021
|
function successfulRoute(route) {
|
|
7008
|
-
|
|
7022
|
+
const matched = route.matched || routePathMatches(route.observed, route.expected_path);
|
|
7023
|
+
return matched && !route.error && (route.http_status === null || route.http_status === void 0 || route.http_status < 400);
|
|
7009
7024
|
}
|
|
7010
7025
|
function assessCheckFromEvidence(check, evidence) {
|
|
7011
7026
|
const viewports = evidence.viewports || [];
|
|
@@ -7023,7 +7038,7 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
7023
7038
|
const failed = viewports.filter((viewport) => !successfulRoute({
|
|
7024
7039
|
...viewport.route,
|
|
7025
7040
|
expected_path: expectedPath,
|
|
7026
|
-
matched: viewport.route.observed
|
|
7041
|
+
matched: routePathMatches(viewport.route.observed, expectedPath) || viewport.route.matched
|
|
7027
7042
|
}));
|
|
7028
7043
|
return {
|
|
7029
7044
|
type: check.type,
|
|
@@ -7275,8 +7290,16 @@ function createRiddleProofProfileInsufficientResult(input) {
|
|
|
7275
7290
|
}
|
|
7276
7291
|
function runtimeScriptAssessmentSource() {
|
|
7277
7292
|
return String.raw`
|
|
7293
|
+
function normalizeRoutePath(path) {
|
|
7294
|
+
const value = path || "/";
|
|
7295
|
+
if (value === "/") return "/";
|
|
7296
|
+
return value.replace(/\/+$/, "") || "/";
|
|
7297
|
+
}
|
|
7298
|
+
function routePathMatches(observed, expected) {
|
|
7299
|
+
return normalizeRoutePath(observed) === normalizeRoutePath(expected);
|
|
7300
|
+
}
|
|
7278
7301
|
function routeOk(route) {
|
|
7279
|
-
return Boolean(route && route.matched && !route.error && (route.http_status == null || route.http_status < 400));
|
|
7302
|
+
return Boolean(route && (route.matched || routePathMatches(route.observed, route.expected_path)) && !route.error && (route.http_status == null || route.http_status < 400));
|
|
7280
7303
|
}
|
|
7281
7304
|
function textMatches(sample, check) {
|
|
7282
7305
|
if (check.pattern) {
|
|
@@ -7333,7 +7356,7 @@ function assessProfile(profile, evidence) {
|
|
|
7333
7356
|
const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
|
|
7334
7357
|
const failed = viewports.filter((viewport) => {
|
|
7335
7358
|
const route = { ...(viewport.route || {}), expected_path: expectedPath };
|
|
7336
|
-
route.matched = route.observed
|
|
7359
|
+
route.matched = routePathMatches(route.observed, expectedPath) || route.matched;
|
|
7337
7360
|
return !routeOk(route);
|
|
7338
7361
|
});
|
|
7339
7362
|
checks.push({
|
|
@@ -7506,6 +7529,9 @@ function setupTextMatches(sample, action) {
|
|
|
7506
7529
|
async function setupLocatorText(locator, index) {
|
|
7507
7530
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
7508
7531
|
}
|
|
7532
|
+
async function setupLocatorVisible(locator, index) {
|
|
7533
|
+
return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
|
|
7534
|
+
}
|
|
7509
7535
|
async function executeSetupAction(action, ordinal) {
|
|
7510
7536
|
const type = setupActionType(action);
|
|
7511
7537
|
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
|
|
@@ -7526,16 +7552,26 @@ async function executeSetupAction(action, ordinal) {
|
|
|
7526
7552
|
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
7527
7553
|
let targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
7528
7554
|
let matchedText = null;
|
|
7555
|
+
let hiddenMatchIndex = -1;
|
|
7556
|
+
let hiddenMatchedText = null;
|
|
7529
7557
|
if (action.text || action.pattern) {
|
|
7530
7558
|
targetIndex = -1;
|
|
7531
7559
|
for (let index = 0; index < count; index += 1) {
|
|
7532
7560
|
const text = await setupLocatorText(locator, index);
|
|
7533
7561
|
if (setupTextMatches(text, action)) {
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7562
|
+
const visible = await setupLocatorVisible(locator, index);
|
|
7563
|
+
if (visible) {
|
|
7564
|
+
targetIndex = index;
|
|
7565
|
+
matchedText = text;
|
|
7566
|
+
break;
|
|
7567
|
+
}
|
|
7568
|
+
if (hiddenMatchIndex < 0) {
|
|
7569
|
+
hiddenMatchIndex = index;
|
|
7570
|
+
hiddenMatchedText = text;
|
|
7571
|
+
}
|
|
7537
7572
|
}
|
|
7538
7573
|
}
|
|
7574
|
+
if (targetIndex < 0 && hiddenMatchIndex >= 0) return { ...base, reason: "matching_element_not_visible", count, target_index: hiddenMatchIndex, text: hiddenMatchedText };
|
|
7539
7575
|
if (targetIndex < 0) return { ...base, reason: "text_not_found", count };
|
|
7540
7576
|
}
|
|
7541
7577
|
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
@@ -7662,7 +7698,7 @@ async function captureViewport(viewport) {
|
|
|
7662
7698
|
requested: targetUrl,
|
|
7663
7699
|
observed: dom.pathname,
|
|
7664
7700
|
expected_path: expectedPath,
|
|
7665
|
-
matched: dom.pathname
|
|
7701
|
+
matched: routePathMatches(dom.pathname, expectedPath),
|
|
7666
7702
|
http_status: httpStatus,
|
|
7667
7703
|
error: navigationError || waitError || undefined,
|
|
7668
7704
|
},
|
package/dist/cli.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -8705,7 +8705,13 @@ function resolveRiddleProofProfileTargetUrl(profile) {
|
|
|
8705
8705
|
throw new Error("profile target URL could not be resolved.");
|
|
8706
8706
|
}
|
|
8707
8707
|
function routeForViewport(viewport) {
|
|
8708
|
-
|
|
8708
|
+
if (viewport?.route) {
|
|
8709
|
+
return {
|
|
8710
|
+
...viewport.route,
|
|
8711
|
+
matched: viewport.route.matched || routePathMatches(viewport.route.observed, viewport.route.expected_path)
|
|
8712
|
+
};
|
|
8713
|
+
}
|
|
8714
|
+
return {
|
|
8709
8715
|
requested: "",
|
|
8710
8716
|
observed: "",
|
|
8711
8717
|
matched: false,
|
|
@@ -8731,8 +8737,17 @@ function matchText(sample, check) {
|
|
|
8731
8737
|
}
|
|
8732
8738
|
return sample.includes(check.text || "");
|
|
8733
8739
|
}
|
|
8740
|
+
function normalizeRoutePath(path6) {
|
|
8741
|
+
const value = path6 || "/";
|
|
8742
|
+
if (value === "/") return "/";
|
|
8743
|
+
return value.replace(/\/+$/, "") || "/";
|
|
8744
|
+
}
|
|
8745
|
+
function routePathMatches(observed, expected) {
|
|
8746
|
+
return normalizeRoutePath(observed) === normalizeRoutePath(expected);
|
|
8747
|
+
}
|
|
8734
8748
|
function successfulRoute(route) {
|
|
8735
|
-
|
|
8749
|
+
const matched = route.matched || routePathMatches(route.observed, route.expected_path);
|
|
8750
|
+
return matched && !route.error && (route.http_status === null || route.http_status === void 0 || route.http_status < 400);
|
|
8736
8751
|
}
|
|
8737
8752
|
function assessCheckFromEvidence(check, evidence) {
|
|
8738
8753
|
const viewports = evidence.viewports || [];
|
|
@@ -8750,7 +8765,7 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
8750
8765
|
const failed = viewports.filter((viewport) => !successfulRoute({
|
|
8751
8766
|
...viewport.route,
|
|
8752
8767
|
expected_path: expectedPath,
|
|
8753
|
-
matched: viewport.route.observed
|
|
8768
|
+
matched: routePathMatches(viewport.route.observed, expectedPath) || viewport.route.matched
|
|
8754
8769
|
}));
|
|
8755
8770
|
return {
|
|
8756
8771
|
type: check.type,
|
|
@@ -9018,8 +9033,16 @@ function createRiddleProofProfileInsufficientResult(input) {
|
|
|
9018
9033
|
}
|
|
9019
9034
|
function runtimeScriptAssessmentSource() {
|
|
9020
9035
|
return String.raw`
|
|
9036
|
+
function normalizeRoutePath(path) {
|
|
9037
|
+
const value = path || "/";
|
|
9038
|
+
if (value === "/") return "/";
|
|
9039
|
+
return value.replace(/\/+$/, "") || "/";
|
|
9040
|
+
}
|
|
9041
|
+
function routePathMatches(observed, expected) {
|
|
9042
|
+
return normalizeRoutePath(observed) === normalizeRoutePath(expected);
|
|
9043
|
+
}
|
|
9021
9044
|
function routeOk(route) {
|
|
9022
|
-
return Boolean(route && route.matched && !route.error && (route.http_status == null || route.http_status < 400));
|
|
9045
|
+
return Boolean(route && (route.matched || routePathMatches(route.observed, route.expected_path)) && !route.error && (route.http_status == null || route.http_status < 400));
|
|
9023
9046
|
}
|
|
9024
9047
|
function textMatches(sample, check) {
|
|
9025
9048
|
if (check.pattern) {
|
|
@@ -9076,7 +9099,7 @@ function assessProfile(profile, evidence) {
|
|
|
9076
9099
|
const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
|
|
9077
9100
|
const failed = viewports.filter((viewport) => {
|
|
9078
9101
|
const route = { ...(viewport.route || {}), expected_path: expectedPath };
|
|
9079
|
-
route.matched = route.observed
|
|
9102
|
+
route.matched = routePathMatches(route.observed, expectedPath) || route.matched;
|
|
9080
9103
|
return !routeOk(route);
|
|
9081
9104
|
});
|
|
9082
9105
|
checks.push({
|
|
@@ -9249,6 +9272,9 @@ function setupTextMatches(sample, action) {
|
|
|
9249
9272
|
async function setupLocatorText(locator, index) {
|
|
9250
9273
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
9251
9274
|
}
|
|
9275
|
+
async function setupLocatorVisible(locator, index) {
|
|
9276
|
+
return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
|
|
9277
|
+
}
|
|
9252
9278
|
async function executeSetupAction(action, ordinal) {
|
|
9253
9279
|
const type = setupActionType(action);
|
|
9254
9280
|
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
|
|
@@ -9269,16 +9295,26 @@ async function executeSetupAction(action, ordinal) {
|
|
|
9269
9295
|
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
9270
9296
|
let targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
9271
9297
|
let matchedText = null;
|
|
9298
|
+
let hiddenMatchIndex = -1;
|
|
9299
|
+
let hiddenMatchedText = null;
|
|
9272
9300
|
if (action.text || action.pattern) {
|
|
9273
9301
|
targetIndex = -1;
|
|
9274
9302
|
for (let index = 0; index < count; index += 1) {
|
|
9275
9303
|
const text = await setupLocatorText(locator, index);
|
|
9276
9304
|
if (setupTextMatches(text, action)) {
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
|
|
9305
|
+
const visible = await setupLocatorVisible(locator, index);
|
|
9306
|
+
if (visible) {
|
|
9307
|
+
targetIndex = index;
|
|
9308
|
+
matchedText = text;
|
|
9309
|
+
break;
|
|
9310
|
+
}
|
|
9311
|
+
if (hiddenMatchIndex < 0) {
|
|
9312
|
+
hiddenMatchIndex = index;
|
|
9313
|
+
hiddenMatchedText = text;
|
|
9314
|
+
}
|
|
9280
9315
|
}
|
|
9281
9316
|
}
|
|
9317
|
+
if (targetIndex < 0 && hiddenMatchIndex >= 0) return { ...base, reason: "matching_element_not_visible", count, target_index: hiddenMatchIndex, text: hiddenMatchedText };
|
|
9282
9318
|
if (targetIndex < 0) return { ...base, reason: "text_not_found", count };
|
|
9283
9319
|
}
|
|
9284
9320
|
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
@@ -9405,7 +9441,7 @@ async function captureViewport(viewport) {
|
|
|
9405
9441
|
requested: targetUrl,
|
|
9406
9442
|
observed: dom.pathname,
|
|
9407
9443
|
expected_path: expectedPath,
|
|
9408
|
-
matched: dom.pathname
|
|
9444
|
+
matched: routePathMatches(dom.pathname, expectedPath),
|
|
9409
9445
|
http_status: httpStatus,
|
|
9410
9446
|
error: navigationError || waitError || undefined,
|
|
9411
9447
|
},
|
package/dist/index.js
CHANGED
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
resolveRiddleProofProfileTargetUrl,
|
|
57
57
|
slugifyRiddleProofProfileName,
|
|
58
58
|
summarizeRiddleProofProfileResult
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-A7RJZD4I.js";
|
|
60
60
|
import {
|
|
61
61
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
62
62
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
package/dist/profile.cjs
CHANGED
|
@@ -240,7 +240,13 @@ function resolveRiddleProofProfileTargetUrl(profile) {
|
|
|
240
240
|
throw new Error("profile target URL could not be resolved.");
|
|
241
241
|
}
|
|
242
242
|
function routeForViewport(viewport) {
|
|
243
|
-
|
|
243
|
+
if (viewport?.route) {
|
|
244
|
+
return {
|
|
245
|
+
...viewport.route,
|
|
246
|
+
matched: viewport.route.matched || routePathMatches(viewport.route.observed, viewport.route.expected_path)
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
244
250
|
requested: "",
|
|
245
251
|
observed: "",
|
|
246
252
|
matched: false,
|
|
@@ -266,8 +272,17 @@ function matchText(sample, check) {
|
|
|
266
272
|
}
|
|
267
273
|
return sample.includes(check.text || "");
|
|
268
274
|
}
|
|
275
|
+
function normalizeRoutePath(path) {
|
|
276
|
+
const value = path || "/";
|
|
277
|
+
if (value === "/") return "/";
|
|
278
|
+
return value.replace(/\/+$/, "") || "/";
|
|
279
|
+
}
|
|
280
|
+
function routePathMatches(observed, expected) {
|
|
281
|
+
return normalizeRoutePath(observed) === normalizeRoutePath(expected);
|
|
282
|
+
}
|
|
269
283
|
function successfulRoute(route) {
|
|
270
|
-
|
|
284
|
+
const matched = route.matched || routePathMatches(route.observed, route.expected_path);
|
|
285
|
+
return matched && !route.error && (route.http_status === null || route.http_status === void 0 || route.http_status < 400);
|
|
271
286
|
}
|
|
272
287
|
function assessCheckFromEvidence(check, evidence) {
|
|
273
288
|
const viewports = evidence.viewports || [];
|
|
@@ -285,7 +300,7 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
285
300
|
const failed = viewports.filter((viewport) => !successfulRoute({
|
|
286
301
|
...viewport.route,
|
|
287
302
|
expected_path: expectedPath,
|
|
288
|
-
matched: viewport.route.observed
|
|
303
|
+
matched: routePathMatches(viewport.route.observed, expectedPath) || viewport.route.matched
|
|
289
304
|
}));
|
|
290
305
|
return {
|
|
291
306
|
type: check.type,
|
|
@@ -553,8 +568,16 @@ function createRiddleProofProfileInsufficientResult(input) {
|
|
|
553
568
|
}
|
|
554
569
|
function runtimeScriptAssessmentSource() {
|
|
555
570
|
return String.raw`
|
|
571
|
+
function normalizeRoutePath(path) {
|
|
572
|
+
const value = path || "/";
|
|
573
|
+
if (value === "/") return "/";
|
|
574
|
+
return value.replace(/\/+$/, "") || "/";
|
|
575
|
+
}
|
|
576
|
+
function routePathMatches(observed, expected) {
|
|
577
|
+
return normalizeRoutePath(observed) === normalizeRoutePath(expected);
|
|
578
|
+
}
|
|
556
579
|
function routeOk(route) {
|
|
557
|
-
return Boolean(route && route.matched && !route.error && (route.http_status == null || route.http_status < 400));
|
|
580
|
+
return Boolean(route && (route.matched || routePathMatches(route.observed, route.expected_path)) && !route.error && (route.http_status == null || route.http_status < 400));
|
|
558
581
|
}
|
|
559
582
|
function textMatches(sample, check) {
|
|
560
583
|
if (check.pattern) {
|
|
@@ -611,7 +634,7 @@ function assessProfile(profile, evidence) {
|
|
|
611
634
|
const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
|
|
612
635
|
const failed = viewports.filter((viewport) => {
|
|
613
636
|
const route = { ...(viewport.route || {}), expected_path: expectedPath };
|
|
614
|
-
route.matched = route.observed
|
|
637
|
+
route.matched = routePathMatches(route.observed, expectedPath) || route.matched;
|
|
615
638
|
return !routeOk(route);
|
|
616
639
|
});
|
|
617
640
|
checks.push({
|
|
@@ -784,6 +807,9 @@ function setupTextMatches(sample, action) {
|
|
|
784
807
|
async function setupLocatorText(locator, index) {
|
|
785
808
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
786
809
|
}
|
|
810
|
+
async function setupLocatorVisible(locator, index) {
|
|
811
|
+
return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
|
|
812
|
+
}
|
|
787
813
|
async function executeSetupAction(action, ordinal) {
|
|
788
814
|
const type = setupActionType(action);
|
|
789
815
|
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
|
|
@@ -804,16 +830,26 @@ async function executeSetupAction(action, ordinal) {
|
|
|
804
830
|
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
805
831
|
let targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
806
832
|
let matchedText = null;
|
|
833
|
+
let hiddenMatchIndex = -1;
|
|
834
|
+
let hiddenMatchedText = null;
|
|
807
835
|
if (action.text || action.pattern) {
|
|
808
836
|
targetIndex = -1;
|
|
809
837
|
for (let index = 0; index < count; index += 1) {
|
|
810
838
|
const text = await setupLocatorText(locator, index);
|
|
811
839
|
if (setupTextMatches(text, action)) {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
840
|
+
const visible = await setupLocatorVisible(locator, index);
|
|
841
|
+
if (visible) {
|
|
842
|
+
targetIndex = index;
|
|
843
|
+
matchedText = text;
|
|
844
|
+
break;
|
|
845
|
+
}
|
|
846
|
+
if (hiddenMatchIndex < 0) {
|
|
847
|
+
hiddenMatchIndex = index;
|
|
848
|
+
hiddenMatchedText = text;
|
|
849
|
+
}
|
|
815
850
|
}
|
|
816
851
|
}
|
|
852
|
+
if (targetIndex < 0 && hiddenMatchIndex >= 0) return { ...base, reason: "matching_element_not_visible", count, target_index: hiddenMatchIndex, text: hiddenMatchedText };
|
|
817
853
|
if (targetIndex < 0) return { ...base, reason: "text_not_found", count };
|
|
818
854
|
}
|
|
819
855
|
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
@@ -940,7 +976,7 @@ async function captureViewport(viewport) {
|
|
|
940
976
|
requested: targetUrl,
|
|
941
977
|
observed: dom.pathname,
|
|
942
978
|
expected_path: expectedPath,
|
|
943
|
-
matched: dom.pathname
|
|
979
|
+
matched: routePathMatches(dom.pathname, expectedPath),
|
|
944
980
|
http_status: httpStatus,
|
|
945
981
|
error: navigationError || waitError || undefined,
|
|
946
982
|
},
|
package/dist/profile.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
resolveRiddleProofProfileTargetUrl,
|
|
18
18
|
slugifyRiddleProofProfileName,
|
|
19
19
|
summarizeRiddleProofProfileResult
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-A7RJZD4I.js";
|
|
21
21
|
export {
|
|
22
22
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
23
23
|
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: "recon" | "author" | "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: "recon" | "author" | "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: "recon" | "author" | "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: "recon" | "author" | "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: "recon" | "author" | "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: "recon" | "author" | "ship" | "implement" | "verify" | "setup" | "run";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|