@riddledc/riddle-proof 0.7.34 → 0.7.36
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 +18 -1
- package/dist/{chunk-PWGJQLOS.js → chunk-VEK6QHPE.js} +182 -1
- package/dist/cli.cjs +182 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +182 -1
- package/dist/index.js +1 -1
- package/dist/profile.cjs +182 -1
- package/dist/profile.d.cts +4 -1
- package/dist/profile.d.ts +4 -1
- package/dist/profile.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8728,6 +8728,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
8728
8728
|
"route_loaded",
|
|
8729
8729
|
"selector_visible",
|
|
8730
8730
|
"selector_count_at_least",
|
|
8731
|
+
"selector_text_order",
|
|
8731
8732
|
"text_visible",
|
|
8732
8733
|
"text_absent",
|
|
8733
8734
|
"route_inventory",
|
|
@@ -9007,6 +9008,15 @@ function normalizeRouteInventoryRoutes(value, index) {
|
|
|
9007
9008
|
}
|
|
9008
9009
|
return routes;
|
|
9009
9010
|
}
|
|
9011
|
+
function normalizeExpectedTexts(value, index) {
|
|
9012
|
+
if (value === void 0) return void 0;
|
|
9013
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
9014
|
+
throw new Error(`checks[${index}] selector_text_order expected_texts must be a non-empty array.`);
|
|
9015
|
+
}
|
|
9016
|
+
const texts = value.map((item) => String(item).replace(/\s+/g, " ").trim()).filter(Boolean);
|
|
9017
|
+
if (!texts.length) throw new Error(`checks[${index}] selector_text_order expected_texts must contain non-empty strings.`);
|
|
9018
|
+
return texts;
|
|
9019
|
+
}
|
|
9010
9020
|
function normalizeCheck(input, index) {
|
|
9011
9021
|
if (!isRecord2(input)) throw new Error(`checks[${index}] must be an object.`);
|
|
9012
9022
|
const type = stringValue5(input.type);
|
|
@@ -9023,6 +9033,11 @@ function normalizeCheck(input, index) {
|
|
|
9023
9033
|
if (type === "selector_count_at_least" && numberValue3(input.min_count) === void 0) {
|
|
9024
9034
|
throw new Error(`checks[${index}] selector_count_at_least requires min_count.`);
|
|
9025
9035
|
}
|
|
9036
|
+
const expectedTexts = normalizeExpectedTexts(input.expected_texts ?? input.expectedTexts, index);
|
|
9037
|
+
if (type === "selector_text_order") {
|
|
9038
|
+
if (!stringValue5(input.selector)) throw new Error(`checks[${index}] selector_text_order requires selector.`);
|
|
9039
|
+
if (!expectedTexts?.length) throw new Error(`checks[${index}] selector_text_order requires expected_texts.`);
|
|
9040
|
+
}
|
|
9026
9041
|
const expectedRoutes = normalizeRouteInventoryRoutes(input.expected_routes ?? input.expectedRoutes, index);
|
|
9027
9042
|
if (type === "route_inventory" && !expectedRoutes?.length) {
|
|
9028
9043
|
throw new Error(`checks[${index}] route_inventory requires expected_routes.`);
|
|
@@ -9033,6 +9048,7 @@ function normalizeCheck(input, index) {
|
|
|
9033
9048
|
expected_path: stringValue5(input.expected_path),
|
|
9034
9049
|
expected_routes: expectedRoutes,
|
|
9035
9050
|
selector: stringValue5(input.selector),
|
|
9051
|
+
expected_texts: expectedTexts,
|
|
9036
9052
|
link_selector: stringValue5(input.link_selector) || stringValue5(input.linkSelector),
|
|
9037
9053
|
source_selector: stringValue5(input.source_selector) || stringValue5(input.sourceSelector),
|
|
9038
9054
|
route_path_prefix: stringValue5(input.route_path_prefix) || stringValue5(input.routePathPrefix),
|
|
@@ -9048,6 +9064,7 @@ function normalizeCheck(input, index) {
|
|
|
9048
9064
|
timeout_ms: numberValue3(input.timeout_ms) ?? numberValue3(input.timeoutMs),
|
|
9049
9065
|
run_direct_routes: input.run_direct_routes === false || input.runDirectRoutes === false ? false : true,
|
|
9050
9066
|
run_clickthroughs: input.run_clickthroughs === false || input.runClickthroughs === false ? false : true,
|
|
9067
|
+
run_all_viewports: input.run_all_viewports === true || input.runAllViewports === true,
|
|
9051
9068
|
require_unique_routes: input.require_unique_routes === false || input.requireUniqueRoutes === false ? false : true,
|
|
9052
9069
|
allow_unexpected_routes: input.allow_unexpected_routes === true || input.allowUnexpectedRoutes === true,
|
|
9053
9070
|
save_route_screenshots: input.save_route_screenshots === true || input.saveRouteScreenshots === true
|
|
@@ -9138,6 +9155,47 @@ function selectorKey(check) {
|
|
|
9138
9155
|
function textKey(check) {
|
|
9139
9156
|
return check.pattern ? `pattern:${check.pattern}/${check.flags || ""}` : `text:${check.text || ""}`;
|
|
9140
9157
|
}
|
|
9158
|
+
function textSequenceForCheck(viewport, check) {
|
|
9159
|
+
const key = selectorKey(check);
|
|
9160
|
+
const sequence = viewport.text_sequences?.[key];
|
|
9161
|
+
if (isRecord2(sequence)) {
|
|
9162
|
+
const visibleTexts = Array.isArray(sequence.visible_texts) ? sequence.visible_texts : [];
|
|
9163
|
+
const texts = Array.isArray(sequence.texts) ? sequence.texts : [];
|
|
9164
|
+
const candidates = visibleTexts.length ? visibleTexts : texts;
|
|
9165
|
+
return candidates.map((text) => String(text).replace(/\s+/g, " ").trim()).filter(Boolean);
|
|
9166
|
+
}
|
|
9167
|
+
return [];
|
|
9168
|
+
}
|
|
9169
|
+
function textOrderMatch(texts, expectedTexts) {
|
|
9170
|
+
const positions = [];
|
|
9171
|
+
let startAt = 0;
|
|
9172
|
+
for (const expected of expectedTexts) {
|
|
9173
|
+
const index = texts.findIndex((text, offset) => offset >= startAt && text.includes(expected));
|
|
9174
|
+
if (index < 0) return { matched: false, positions };
|
|
9175
|
+
positions.push(index);
|
|
9176
|
+
startAt = index + 1;
|
|
9177
|
+
}
|
|
9178
|
+
return { matched: true, positions };
|
|
9179
|
+
}
|
|
9180
|
+
function summarizeRouteInventory(viewport, inventory) {
|
|
9181
|
+
const directRoutes = Array.isArray(inventory.direct_routes) ? inventory.direct_routes : [];
|
|
9182
|
+
const clickthroughs = Array.isArray(inventory.clickthroughs) ? inventory.clickthroughs : [];
|
|
9183
|
+
const sourceLinkCount = numberValue3(inventory.source_link_count) ?? numberValue3(inventory.home_game_link_count) ?? null;
|
|
9184
|
+
const sourceUniqueLinkCount = numberValue3(inventory.source_unique_link_count) ?? numberValue3(inventory.home_unique_game_link_count) ?? null;
|
|
9185
|
+
const duplicateSourceLinks = Array.isArray(inventory.duplicate_source_link_paths) ? inventory.duplicate_source_link_paths.map((path6) => String(path6)) : [];
|
|
9186
|
+
const duplicateSourceLinkCount = numberValue3(inventory.duplicate_source_link_count) ?? (sourceLinkCount !== null && sourceUniqueLinkCount !== null ? Math.max(0, sourceLinkCount - sourceUniqueLinkCount) : null);
|
|
9187
|
+
const failures = Array.isArray(inventory.failures) ? inventory.failures : [];
|
|
9188
|
+
return {
|
|
9189
|
+
viewport,
|
|
9190
|
+
source_link_count: sourceLinkCount,
|
|
9191
|
+
source_unique_link_count: sourceUniqueLinkCount,
|
|
9192
|
+
duplicate_source_link_count: duplicateSourceLinkCount,
|
|
9193
|
+
duplicate_source_links: duplicateSourceLinks,
|
|
9194
|
+
direct_route_count: directRoutes.length,
|
|
9195
|
+
clickthrough_count: clickthroughs.length,
|
|
9196
|
+
failure_count: failures.length
|
|
9197
|
+
};
|
|
9198
|
+
}
|
|
9141
9199
|
function matchText(sample, check) {
|
|
9142
9200
|
if (check.pattern) {
|
|
9143
9201
|
try {
|
|
@@ -9257,6 +9315,32 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
9257
9315
|
message: failed.length ? `Selector ${key} count was below ${minCount} in ${failed.length} viewport(s).` : void 0
|
|
9258
9316
|
};
|
|
9259
9317
|
}
|
|
9318
|
+
if (check.type === "selector_text_order") {
|
|
9319
|
+
const key = selectorKey(check);
|
|
9320
|
+
const expectedTexts = check.expected_texts || [];
|
|
9321
|
+
const results = viewports.map((viewport) => {
|
|
9322
|
+
const texts = textSequenceForCheck(viewport, check);
|
|
9323
|
+
const match = textOrderMatch(texts, expectedTexts);
|
|
9324
|
+
return {
|
|
9325
|
+
viewport: viewport.name,
|
|
9326
|
+
matched: match.matched,
|
|
9327
|
+
matched_positions: match.positions,
|
|
9328
|
+
visible_texts: texts.slice(0, 20)
|
|
9329
|
+
};
|
|
9330
|
+
});
|
|
9331
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
9332
|
+
return {
|
|
9333
|
+
type: check.type,
|
|
9334
|
+
label: checkLabel(check),
|
|
9335
|
+
status: failed ? "failed" : "passed",
|
|
9336
|
+
evidence: {
|
|
9337
|
+
selector: key,
|
|
9338
|
+
expected_texts: expectedTexts,
|
|
9339
|
+
viewports: results.map((result) => toJsonValue(result))
|
|
9340
|
+
},
|
|
9341
|
+
message: failed ? `Selector ${key} text order failed in ${failed} viewport(s).` : void 0
|
|
9342
|
+
};
|
|
9343
|
+
}
|
|
9260
9344
|
if (check.type === "text_visible" || check.type === "text_absent") {
|
|
9261
9345
|
const key = textKey(check);
|
|
9262
9346
|
const expectedVisible = check.type === "text_visible";
|
|
@@ -9288,6 +9372,7 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
9288
9372
|
message: "No route inventory evidence was captured."
|
|
9289
9373
|
};
|
|
9290
9374
|
}
|
|
9375
|
+
const viewportSummaries = inventories.map((item) => summarizeRouteInventory(item.viewport, item.inventory));
|
|
9291
9376
|
const failures = inventories.flatMap((item) => Array.isArray(item.inventory?.failures) ? item.inventory.failures.map((failure) => toJsonValue({ viewport: item.viewport, failure })) : []);
|
|
9292
9377
|
const first = inventories[0]?.inventory;
|
|
9293
9378
|
const directRoutes = Array.isArray(first?.direct_routes) ? first.direct_routes : [];
|
|
@@ -9311,6 +9396,8 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
9311
9396
|
homepage_unique_link_count: numberValue3(first?.home_unique_game_link_count) ?? sourceUniqueLinkCount,
|
|
9312
9397
|
direct_route_count: directRoutes.length,
|
|
9313
9398
|
clickthrough_count: clickthroughs.length,
|
|
9399
|
+
viewport_count: inventories.length,
|
|
9400
|
+
viewports: viewportSummaries.map((summary) => toJsonValue(summary)),
|
|
9314
9401
|
failures
|
|
9315
9402
|
},
|
|
9316
9403
|
message: failures.length ? `Route inventory failed with ${failures.length} issue(s).` : void 0
|
|
@@ -9607,6 +9694,47 @@ function textMatches(sample, check) {
|
|
|
9607
9694
|
}
|
|
9608
9695
|
return String(sample || "").includes(check.text || "");
|
|
9609
9696
|
}
|
|
9697
|
+
function textSequenceForCheck(viewport, check) {
|
|
9698
|
+
const key = check.selector || "";
|
|
9699
|
+
const sequence = viewport.text_sequences && viewport.text_sequences[key];
|
|
9700
|
+
if (sequence && typeof sequence === "object") {
|
|
9701
|
+
const visibleTexts = Array.isArray(sequence.visible_texts) ? sequence.visible_texts : [];
|
|
9702
|
+
const texts = Array.isArray(sequence.texts) ? sequence.texts : [];
|
|
9703
|
+
const candidates = visibleTexts.length ? visibleTexts : texts;
|
|
9704
|
+
return candidates.map((text) => String(text || "").replace(/\s+/g, " ").trim()).filter(Boolean);
|
|
9705
|
+
}
|
|
9706
|
+
return [];
|
|
9707
|
+
}
|
|
9708
|
+
function textOrderMatch(texts, expectedTexts) {
|
|
9709
|
+
const positions = [];
|
|
9710
|
+
let startAt = 0;
|
|
9711
|
+
for (const expected of expectedTexts || []) {
|
|
9712
|
+
const index = texts.findIndex((text, offset) => offset >= startAt && text.includes(expected));
|
|
9713
|
+
if (index < 0) return { matched: false, positions };
|
|
9714
|
+
positions.push(index);
|
|
9715
|
+
startAt = index + 1;
|
|
9716
|
+
}
|
|
9717
|
+
return { matched: true, positions };
|
|
9718
|
+
}
|
|
9719
|
+
function summarizeRouteInventory(viewport, inventory) {
|
|
9720
|
+
const directRoutes = Array.isArray(inventory.direct_routes) ? inventory.direct_routes : [];
|
|
9721
|
+
const clickthroughs = Array.isArray(inventory.clickthroughs) ? inventory.clickthroughs : [];
|
|
9722
|
+
const sourceLinkCount = typeof inventory.source_link_count === "number" ? inventory.source_link_count : typeof inventory.home_game_link_count === "number" ? inventory.home_game_link_count : null;
|
|
9723
|
+
const sourceUniqueLinkCount = typeof inventory.source_unique_link_count === "number" ? inventory.source_unique_link_count : typeof inventory.home_unique_game_link_count === "number" ? inventory.home_unique_game_link_count : null;
|
|
9724
|
+
const duplicateSourceLinks = Array.isArray(inventory.duplicate_source_link_paths) ? inventory.duplicate_source_link_paths.map((path) => String(path)) : [];
|
|
9725
|
+
const duplicateSourceLinkCount = typeof inventory.duplicate_source_link_count === "number" ? inventory.duplicate_source_link_count : sourceLinkCount !== null && sourceUniqueLinkCount !== null ? Math.max(0, sourceLinkCount - sourceUniqueLinkCount) : null;
|
|
9726
|
+
const failures = Array.isArray(inventory.failures) ? inventory.failures : [];
|
|
9727
|
+
return {
|
|
9728
|
+
viewport,
|
|
9729
|
+
source_link_count: sourceLinkCount,
|
|
9730
|
+
source_unique_link_count: sourceUniqueLinkCount,
|
|
9731
|
+
duplicate_source_link_count: duplicateSourceLinkCount,
|
|
9732
|
+
duplicate_source_links: duplicateSourceLinks,
|
|
9733
|
+
direct_route_count: directRoutes.length,
|
|
9734
|
+
clickthrough_count: clickthroughs.length,
|
|
9735
|
+
failure_count: failures.length,
|
|
9736
|
+
};
|
|
9737
|
+
}
|
|
9610
9738
|
function numberValue(value) {
|
|
9611
9739
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
9612
9740
|
}
|
|
@@ -9811,6 +9939,29 @@ function assessProfile(profile, evidence) {
|
|
|
9811
9939
|
});
|
|
9812
9940
|
continue;
|
|
9813
9941
|
}
|
|
9942
|
+
if (check.type === "selector_text_order") {
|
|
9943
|
+
const selector = check.selector || "";
|
|
9944
|
+
const expectedTexts = check.expected_texts || [];
|
|
9945
|
+
const results = viewports.map((viewport) => {
|
|
9946
|
+
const texts = textSequenceForCheck(viewport, check);
|
|
9947
|
+
const match = textOrderMatch(texts, expectedTexts);
|
|
9948
|
+
return {
|
|
9949
|
+
viewport: viewport.name,
|
|
9950
|
+
matched: match.matched,
|
|
9951
|
+
matched_positions: match.positions,
|
|
9952
|
+
visible_texts: texts.slice(0, 20),
|
|
9953
|
+
};
|
|
9954
|
+
});
|
|
9955
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
9956
|
+
checks.push({
|
|
9957
|
+
type: check.type,
|
|
9958
|
+
label: check.label || check.type,
|
|
9959
|
+
status: failed ? "failed" : "passed",
|
|
9960
|
+
evidence: { selector, expected_texts: expectedTexts, viewports: results },
|
|
9961
|
+
message: failed ? "Selector " + selector + " text order failed in " + failed + " viewport(s)." : undefined,
|
|
9962
|
+
});
|
|
9963
|
+
continue;
|
|
9964
|
+
}
|
|
9814
9965
|
if (check.type === "text_visible" || check.type === "text_absent") {
|
|
9815
9966
|
const key = check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
|
|
9816
9967
|
const expectedVisible = check.type === "text_visible";
|
|
@@ -9839,6 +9990,7 @@ function assessProfile(profile, evidence) {
|
|
|
9839
9990
|
});
|
|
9840
9991
|
continue;
|
|
9841
9992
|
}
|
|
9993
|
+
const viewportSummaries = inventories.map((item) => summarizeRouteInventory(item.viewport, item.inventory || {}));
|
|
9842
9994
|
const failures = [];
|
|
9843
9995
|
for (const item of inventories) {
|
|
9844
9996
|
for (const failure of Array.isArray(item.inventory.failures) ? item.inventory.failures : []) {
|
|
@@ -9867,6 +10019,8 @@ function assessProfile(profile, evidence) {
|
|
|
9867
10019
|
homepage_unique_link_count: typeof first.home_unique_game_link_count === "number" ? first.home_unique_game_link_count : sourceUniqueLinkCount,
|
|
9868
10020
|
direct_route_count: directRoutes.length,
|
|
9869
10021
|
clickthrough_count: clickthroughs.length,
|
|
10022
|
+
viewport_count: inventories.length,
|
|
10023
|
+
viewports: viewportSummaries,
|
|
9870
10024
|
failures,
|
|
9871
10025
|
},
|
|
9872
10026
|
message: failures.length ? "Route inventory failed with " + failures.length + " issue(s)." : undefined,
|
|
@@ -10184,6 +10338,27 @@ async function selectorStats(selector) {
|
|
|
10184
10338
|
return { count: elements.length, visible_count: elements.filter(isVisible).length };
|
|
10185
10339
|
}).catch((error) => ({ count: 0, visible_count: 0, error: String(error && error.message ? error.message : error).slice(0, 500) }));
|
|
10186
10340
|
}
|
|
10341
|
+
async function selectorTextSequence(selector) {
|
|
10342
|
+
return page.locator(selector).evaluateAll((elements) => {
|
|
10343
|
+
const compact = (value) => String(value || "").replace(/\s+/g, " ").trim().slice(0, 240);
|
|
10344
|
+
const isVisible = (element) => {
|
|
10345
|
+
const style = window.getComputedStyle(element);
|
|
10346
|
+
const rect = element.getBoundingClientRect();
|
|
10347
|
+
return style && style.visibility !== "hidden" && style.display !== "none" && rect.width > 0 && rect.height > 0;
|
|
10348
|
+
};
|
|
10349
|
+
const rows = elements.map((element, index) => ({
|
|
10350
|
+
index,
|
|
10351
|
+
text: compact(element.innerText || element.textContent || ""),
|
|
10352
|
+
visible: isVisible(element),
|
|
10353
|
+
}));
|
|
10354
|
+
return {
|
|
10355
|
+
count: rows.length,
|
|
10356
|
+
visible_count: rows.filter((row) => row.visible).length,
|
|
10357
|
+
texts: rows.map((row) => row.text).filter(Boolean).slice(0, 40),
|
|
10358
|
+
visible_texts: rows.filter((row) => row.visible).map((row) => row.text).filter(Boolean).slice(0, 40),
|
|
10359
|
+
};
|
|
10360
|
+
}).catch((error) => ({ count: 0, visible_count: 0, texts: [], visible_texts: [], error: String(error && error.message ? error.message : error).slice(0, 500) }));
|
|
10361
|
+
}
|
|
10187
10362
|
function inventoryAppPathFromUrl(urlLike) {
|
|
10188
10363
|
const url = new URL(String(urlLike), targetUrl);
|
|
10189
10364
|
const mountPrefix = previewMountPrefix(new URL(targetUrl).pathname);
|
|
@@ -10581,11 +10756,16 @@ async function captureViewport(viewport) {
|
|
|
10581
10756
|
evaluation_error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
10582
10757
|
}));
|
|
10583
10758
|
const selectors = {};
|
|
10759
|
+
const text_sequences = {};
|
|
10584
10760
|
const text_matches = {};
|
|
10585
10761
|
for (const check of profile.checks || []) {
|
|
10586
10762
|
if ((check.type === "selector_visible" || check.type === "selector_count_at_least") && check.selector) {
|
|
10587
10763
|
selectors[check.selector] = await selectorStats(check.selector);
|
|
10588
10764
|
}
|
|
10765
|
+
if (check.type === "selector_text_order" && check.selector) {
|
|
10766
|
+
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
10767
|
+
text_sequences[check.selector] = await selectorTextSequence(check.selector);
|
|
10768
|
+
}
|
|
10589
10769
|
if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
|
|
10590
10770
|
text_matches[textKey(check)] = textMatches(dom.body_text || dom.body_text_sample || "", check);
|
|
10591
10771
|
}
|
|
@@ -10599,7 +10779,7 @@ async function captureViewport(viewport) {
|
|
|
10599
10779
|
let routeInventory;
|
|
10600
10780
|
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
|
|
10601
10781
|
const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
|
|
10602
|
-
if (routeInventoryCheck && (!firstViewportName || viewport.name === firstViewportName)) {
|
|
10782
|
+
if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
|
|
10603
10783
|
try {
|
|
10604
10784
|
routeInventory = await collectRouteInventory(routeInventoryCheck, viewport);
|
|
10605
10785
|
} catch (error) {
|
|
@@ -10649,6 +10829,7 @@ async function captureViewport(viewport) {
|
|
|
10649
10829
|
bounds_overflow_px: dom.bounds_overflow_px,
|
|
10650
10830
|
overflow_offenders: dom.overflow_offenders || [],
|
|
10651
10831
|
selectors,
|
|
10832
|
+
text_sequences,
|
|
10652
10833
|
text_matches,
|
|
10653
10834
|
route_inventory: routeInventory,
|
|
10654
10835
|
setup_action_results: setupActionResults,
|
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-VEK6QHPE.js";
|
|
62
62
|
import {
|
|
63
63
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
64
64
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
package/dist/profile.cjs
CHANGED
|
@@ -57,6 +57,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
57
57
|
"route_loaded",
|
|
58
58
|
"selector_visible",
|
|
59
59
|
"selector_count_at_least",
|
|
60
|
+
"selector_text_order",
|
|
60
61
|
"text_visible",
|
|
61
62
|
"text_absent",
|
|
62
63
|
"route_inventory",
|
|
@@ -336,6 +337,15 @@ function normalizeRouteInventoryRoutes(value, index) {
|
|
|
336
337
|
}
|
|
337
338
|
return routes;
|
|
338
339
|
}
|
|
340
|
+
function normalizeExpectedTexts(value, index) {
|
|
341
|
+
if (value === void 0) return void 0;
|
|
342
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
343
|
+
throw new Error(`checks[${index}] selector_text_order expected_texts must be a non-empty array.`);
|
|
344
|
+
}
|
|
345
|
+
const texts = value.map((item) => String(item).replace(/\s+/g, " ").trim()).filter(Boolean);
|
|
346
|
+
if (!texts.length) throw new Error(`checks[${index}] selector_text_order expected_texts must contain non-empty strings.`);
|
|
347
|
+
return texts;
|
|
348
|
+
}
|
|
339
349
|
function normalizeCheck(input, index) {
|
|
340
350
|
if (!isRecord(input)) throw new Error(`checks[${index}] must be an object.`);
|
|
341
351
|
const type = stringValue(input.type);
|
|
@@ -352,6 +362,11 @@ function normalizeCheck(input, index) {
|
|
|
352
362
|
if (type === "selector_count_at_least" && numberValue(input.min_count) === void 0) {
|
|
353
363
|
throw new Error(`checks[${index}] selector_count_at_least requires min_count.`);
|
|
354
364
|
}
|
|
365
|
+
const expectedTexts = normalizeExpectedTexts(input.expected_texts ?? input.expectedTexts, index);
|
|
366
|
+
if (type === "selector_text_order") {
|
|
367
|
+
if (!stringValue(input.selector)) throw new Error(`checks[${index}] selector_text_order requires selector.`);
|
|
368
|
+
if (!expectedTexts?.length) throw new Error(`checks[${index}] selector_text_order requires expected_texts.`);
|
|
369
|
+
}
|
|
355
370
|
const expectedRoutes = normalizeRouteInventoryRoutes(input.expected_routes ?? input.expectedRoutes, index);
|
|
356
371
|
if (type === "route_inventory" && !expectedRoutes?.length) {
|
|
357
372
|
throw new Error(`checks[${index}] route_inventory requires expected_routes.`);
|
|
@@ -362,6 +377,7 @@ function normalizeCheck(input, index) {
|
|
|
362
377
|
expected_path: stringValue(input.expected_path),
|
|
363
378
|
expected_routes: expectedRoutes,
|
|
364
379
|
selector: stringValue(input.selector),
|
|
380
|
+
expected_texts: expectedTexts,
|
|
365
381
|
link_selector: stringValue(input.link_selector) || stringValue(input.linkSelector),
|
|
366
382
|
source_selector: stringValue(input.source_selector) || stringValue(input.sourceSelector),
|
|
367
383
|
route_path_prefix: stringValue(input.route_path_prefix) || stringValue(input.routePathPrefix),
|
|
@@ -377,6 +393,7 @@ function normalizeCheck(input, index) {
|
|
|
377
393
|
timeout_ms: numberValue(input.timeout_ms) ?? numberValue(input.timeoutMs),
|
|
378
394
|
run_direct_routes: input.run_direct_routes === false || input.runDirectRoutes === false ? false : true,
|
|
379
395
|
run_clickthroughs: input.run_clickthroughs === false || input.runClickthroughs === false ? false : true,
|
|
396
|
+
run_all_viewports: input.run_all_viewports === true || input.runAllViewports === true,
|
|
380
397
|
require_unique_routes: input.require_unique_routes === false || input.requireUniqueRoutes === false ? false : true,
|
|
381
398
|
allow_unexpected_routes: input.allow_unexpected_routes === true || input.allowUnexpectedRoutes === true,
|
|
382
399
|
save_route_screenshots: input.save_route_screenshots === true || input.saveRouteScreenshots === true
|
|
@@ -467,6 +484,47 @@ function selectorKey(check) {
|
|
|
467
484
|
function textKey(check) {
|
|
468
485
|
return check.pattern ? `pattern:${check.pattern}/${check.flags || ""}` : `text:${check.text || ""}`;
|
|
469
486
|
}
|
|
487
|
+
function textSequenceForCheck(viewport, check) {
|
|
488
|
+
const key = selectorKey(check);
|
|
489
|
+
const sequence = viewport.text_sequences?.[key];
|
|
490
|
+
if (isRecord(sequence)) {
|
|
491
|
+
const visibleTexts = Array.isArray(sequence.visible_texts) ? sequence.visible_texts : [];
|
|
492
|
+
const texts = Array.isArray(sequence.texts) ? sequence.texts : [];
|
|
493
|
+
const candidates = visibleTexts.length ? visibleTexts : texts;
|
|
494
|
+
return candidates.map((text) => String(text).replace(/\s+/g, " ").trim()).filter(Boolean);
|
|
495
|
+
}
|
|
496
|
+
return [];
|
|
497
|
+
}
|
|
498
|
+
function textOrderMatch(texts, expectedTexts) {
|
|
499
|
+
const positions = [];
|
|
500
|
+
let startAt = 0;
|
|
501
|
+
for (const expected of expectedTexts) {
|
|
502
|
+
const index = texts.findIndex((text, offset) => offset >= startAt && text.includes(expected));
|
|
503
|
+
if (index < 0) return { matched: false, positions };
|
|
504
|
+
positions.push(index);
|
|
505
|
+
startAt = index + 1;
|
|
506
|
+
}
|
|
507
|
+
return { matched: true, positions };
|
|
508
|
+
}
|
|
509
|
+
function summarizeRouteInventory(viewport, inventory) {
|
|
510
|
+
const directRoutes = Array.isArray(inventory.direct_routes) ? inventory.direct_routes : [];
|
|
511
|
+
const clickthroughs = Array.isArray(inventory.clickthroughs) ? inventory.clickthroughs : [];
|
|
512
|
+
const sourceLinkCount = numberValue(inventory.source_link_count) ?? numberValue(inventory.home_game_link_count) ?? null;
|
|
513
|
+
const sourceUniqueLinkCount = numberValue(inventory.source_unique_link_count) ?? numberValue(inventory.home_unique_game_link_count) ?? null;
|
|
514
|
+
const duplicateSourceLinks = Array.isArray(inventory.duplicate_source_link_paths) ? inventory.duplicate_source_link_paths.map((path) => String(path)) : [];
|
|
515
|
+
const duplicateSourceLinkCount = numberValue(inventory.duplicate_source_link_count) ?? (sourceLinkCount !== null && sourceUniqueLinkCount !== null ? Math.max(0, sourceLinkCount - sourceUniqueLinkCount) : null);
|
|
516
|
+
const failures = Array.isArray(inventory.failures) ? inventory.failures : [];
|
|
517
|
+
return {
|
|
518
|
+
viewport,
|
|
519
|
+
source_link_count: sourceLinkCount,
|
|
520
|
+
source_unique_link_count: sourceUniqueLinkCount,
|
|
521
|
+
duplicate_source_link_count: duplicateSourceLinkCount,
|
|
522
|
+
duplicate_source_links: duplicateSourceLinks,
|
|
523
|
+
direct_route_count: directRoutes.length,
|
|
524
|
+
clickthrough_count: clickthroughs.length,
|
|
525
|
+
failure_count: failures.length
|
|
526
|
+
};
|
|
527
|
+
}
|
|
470
528
|
function matchText(sample, check) {
|
|
471
529
|
if (check.pattern) {
|
|
472
530
|
try {
|
|
@@ -586,6 +644,32 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
586
644
|
message: failed.length ? `Selector ${key} count was below ${minCount} in ${failed.length} viewport(s).` : void 0
|
|
587
645
|
};
|
|
588
646
|
}
|
|
647
|
+
if (check.type === "selector_text_order") {
|
|
648
|
+
const key = selectorKey(check);
|
|
649
|
+
const expectedTexts = check.expected_texts || [];
|
|
650
|
+
const results = viewports.map((viewport) => {
|
|
651
|
+
const texts = textSequenceForCheck(viewport, check);
|
|
652
|
+
const match = textOrderMatch(texts, expectedTexts);
|
|
653
|
+
return {
|
|
654
|
+
viewport: viewport.name,
|
|
655
|
+
matched: match.matched,
|
|
656
|
+
matched_positions: match.positions,
|
|
657
|
+
visible_texts: texts.slice(0, 20)
|
|
658
|
+
};
|
|
659
|
+
});
|
|
660
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
661
|
+
return {
|
|
662
|
+
type: check.type,
|
|
663
|
+
label: checkLabel(check),
|
|
664
|
+
status: failed ? "failed" : "passed",
|
|
665
|
+
evidence: {
|
|
666
|
+
selector: key,
|
|
667
|
+
expected_texts: expectedTexts,
|
|
668
|
+
viewports: results.map((result) => toJsonValue(result))
|
|
669
|
+
},
|
|
670
|
+
message: failed ? `Selector ${key} text order failed in ${failed} viewport(s).` : void 0
|
|
671
|
+
};
|
|
672
|
+
}
|
|
589
673
|
if (check.type === "text_visible" || check.type === "text_absent") {
|
|
590
674
|
const key = textKey(check);
|
|
591
675
|
const expectedVisible = check.type === "text_visible";
|
|
@@ -617,6 +701,7 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
617
701
|
message: "No route inventory evidence was captured."
|
|
618
702
|
};
|
|
619
703
|
}
|
|
704
|
+
const viewportSummaries = inventories.map((item) => summarizeRouteInventory(item.viewport, item.inventory));
|
|
620
705
|
const failures = inventories.flatMap((item) => Array.isArray(item.inventory?.failures) ? item.inventory.failures.map((failure) => toJsonValue({ viewport: item.viewport, failure })) : []);
|
|
621
706
|
const first = inventories[0]?.inventory;
|
|
622
707
|
const directRoutes = Array.isArray(first?.direct_routes) ? first.direct_routes : [];
|
|
@@ -640,6 +725,8 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
640
725
|
homepage_unique_link_count: numberValue(first?.home_unique_game_link_count) ?? sourceUniqueLinkCount,
|
|
641
726
|
direct_route_count: directRoutes.length,
|
|
642
727
|
clickthrough_count: clickthroughs.length,
|
|
728
|
+
viewport_count: inventories.length,
|
|
729
|
+
viewports: viewportSummaries.map((summary) => toJsonValue(summary)),
|
|
643
730
|
failures
|
|
644
731
|
},
|
|
645
732
|
message: failures.length ? `Route inventory failed with ${failures.length} issue(s).` : void 0
|
|
@@ -936,6 +1023,47 @@ function textMatches(sample, check) {
|
|
|
936
1023
|
}
|
|
937
1024
|
return String(sample || "").includes(check.text || "");
|
|
938
1025
|
}
|
|
1026
|
+
function textSequenceForCheck(viewport, check) {
|
|
1027
|
+
const key = check.selector || "";
|
|
1028
|
+
const sequence = viewport.text_sequences && viewport.text_sequences[key];
|
|
1029
|
+
if (sequence && typeof sequence === "object") {
|
|
1030
|
+
const visibleTexts = Array.isArray(sequence.visible_texts) ? sequence.visible_texts : [];
|
|
1031
|
+
const texts = Array.isArray(sequence.texts) ? sequence.texts : [];
|
|
1032
|
+
const candidates = visibleTexts.length ? visibleTexts : texts;
|
|
1033
|
+
return candidates.map((text) => String(text || "").replace(/\s+/g, " ").trim()).filter(Boolean);
|
|
1034
|
+
}
|
|
1035
|
+
return [];
|
|
1036
|
+
}
|
|
1037
|
+
function textOrderMatch(texts, expectedTexts) {
|
|
1038
|
+
const positions = [];
|
|
1039
|
+
let startAt = 0;
|
|
1040
|
+
for (const expected of expectedTexts || []) {
|
|
1041
|
+
const index = texts.findIndex((text, offset) => offset >= startAt && text.includes(expected));
|
|
1042
|
+
if (index < 0) return { matched: false, positions };
|
|
1043
|
+
positions.push(index);
|
|
1044
|
+
startAt = index + 1;
|
|
1045
|
+
}
|
|
1046
|
+
return { matched: true, positions };
|
|
1047
|
+
}
|
|
1048
|
+
function summarizeRouteInventory(viewport, inventory) {
|
|
1049
|
+
const directRoutes = Array.isArray(inventory.direct_routes) ? inventory.direct_routes : [];
|
|
1050
|
+
const clickthroughs = Array.isArray(inventory.clickthroughs) ? inventory.clickthroughs : [];
|
|
1051
|
+
const sourceLinkCount = typeof inventory.source_link_count === "number" ? inventory.source_link_count : typeof inventory.home_game_link_count === "number" ? inventory.home_game_link_count : null;
|
|
1052
|
+
const sourceUniqueLinkCount = typeof inventory.source_unique_link_count === "number" ? inventory.source_unique_link_count : typeof inventory.home_unique_game_link_count === "number" ? inventory.home_unique_game_link_count : null;
|
|
1053
|
+
const duplicateSourceLinks = Array.isArray(inventory.duplicate_source_link_paths) ? inventory.duplicate_source_link_paths.map((path) => String(path)) : [];
|
|
1054
|
+
const duplicateSourceLinkCount = typeof inventory.duplicate_source_link_count === "number" ? inventory.duplicate_source_link_count : sourceLinkCount !== null && sourceUniqueLinkCount !== null ? Math.max(0, sourceLinkCount - sourceUniqueLinkCount) : null;
|
|
1055
|
+
const failures = Array.isArray(inventory.failures) ? inventory.failures : [];
|
|
1056
|
+
return {
|
|
1057
|
+
viewport,
|
|
1058
|
+
source_link_count: sourceLinkCount,
|
|
1059
|
+
source_unique_link_count: sourceUniqueLinkCount,
|
|
1060
|
+
duplicate_source_link_count: duplicateSourceLinkCount,
|
|
1061
|
+
duplicate_source_links: duplicateSourceLinks,
|
|
1062
|
+
direct_route_count: directRoutes.length,
|
|
1063
|
+
clickthrough_count: clickthroughs.length,
|
|
1064
|
+
failure_count: failures.length,
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
939
1067
|
function numberValue(value) {
|
|
940
1068
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
941
1069
|
}
|
|
@@ -1140,6 +1268,29 @@ function assessProfile(profile, evidence) {
|
|
|
1140
1268
|
});
|
|
1141
1269
|
continue;
|
|
1142
1270
|
}
|
|
1271
|
+
if (check.type === "selector_text_order") {
|
|
1272
|
+
const selector = check.selector || "";
|
|
1273
|
+
const expectedTexts = check.expected_texts || [];
|
|
1274
|
+
const results = viewports.map((viewport) => {
|
|
1275
|
+
const texts = textSequenceForCheck(viewport, check);
|
|
1276
|
+
const match = textOrderMatch(texts, expectedTexts);
|
|
1277
|
+
return {
|
|
1278
|
+
viewport: viewport.name,
|
|
1279
|
+
matched: match.matched,
|
|
1280
|
+
matched_positions: match.positions,
|
|
1281
|
+
visible_texts: texts.slice(0, 20),
|
|
1282
|
+
};
|
|
1283
|
+
});
|
|
1284
|
+
const failed = results.filter((result) => !result.matched).length;
|
|
1285
|
+
checks.push({
|
|
1286
|
+
type: check.type,
|
|
1287
|
+
label: check.label || check.type,
|
|
1288
|
+
status: failed ? "failed" : "passed",
|
|
1289
|
+
evidence: { selector, expected_texts: expectedTexts, viewports: results },
|
|
1290
|
+
message: failed ? "Selector " + selector + " text order failed in " + failed + " viewport(s)." : undefined,
|
|
1291
|
+
});
|
|
1292
|
+
continue;
|
|
1293
|
+
}
|
|
1143
1294
|
if (check.type === "text_visible" || check.type === "text_absent") {
|
|
1144
1295
|
const key = check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
|
|
1145
1296
|
const expectedVisible = check.type === "text_visible";
|
|
@@ -1168,6 +1319,7 @@ function assessProfile(profile, evidence) {
|
|
|
1168
1319
|
});
|
|
1169
1320
|
continue;
|
|
1170
1321
|
}
|
|
1322
|
+
const viewportSummaries = inventories.map((item) => summarizeRouteInventory(item.viewport, item.inventory || {}));
|
|
1171
1323
|
const failures = [];
|
|
1172
1324
|
for (const item of inventories) {
|
|
1173
1325
|
for (const failure of Array.isArray(item.inventory.failures) ? item.inventory.failures : []) {
|
|
@@ -1196,6 +1348,8 @@ function assessProfile(profile, evidence) {
|
|
|
1196
1348
|
homepage_unique_link_count: typeof first.home_unique_game_link_count === "number" ? first.home_unique_game_link_count : sourceUniqueLinkCount,
|
|
1197
1349
|
direct_route_count: directRoutes.length,
|
|
1198
1350
|
clickthrough_count: clickthroughs.length,
|
|
1351
|
+
viewport_count: inventories.length,
|
|
1352
|
+
viewports: viewportSummaries,
|
|
1199
1353
|
failures,
|
|
1200
1354
|
},
|
|
1201
1355
|
message: failures.length ? "Route inventory failed with " + failures.length + " issue(s)." : undefined,
|
|
@@ -1513,6 +1667,27 @@ async function selectorStats(selector) {
|
|
|
1513
1667
|
return { count: elements.length, visible_count: elements.filter(isVisible).length };
|
|
1514
1668
|
}).catch((error) => ({ count: 0, visible_count: 0, error: String(error && error.message ? error.message : error).slice(0, 500) }));
|
|
1515
1669
|
}
|
|
1670
|
+
async function selectorTextSequence(selector) {
|
|
1671
|
+
return page.locator(selector).evaluateAll((elements) => {
|
|
1672
|
+
const compact = (value) => String(value || "").replace(/\s+/g, " ").trim().slice(0, 240);
|
|
1673
|
+
const isVisible = (element) => {
|
|
1674
|
+
const style = window.getComputedStyle(element);
|
|
1675
|
+
const rect = element.getBoundingClientRect();
|
|
1676
|
+
return style && style.visibility !== "hidden" && style.display !== "none" && rect.width > 0 && rect.height > 0;
|
|
1677
|
+
};
|
|
1678
|
+
const rows = elements.map((element, index) => ({
|
|
1679
|
+
index,
|
|
1680
|
+
text: compact(element.innerText || element.textContent || ""),
|
|
1681
|
+
visible: isVisible(element),
|
|
1682
|
+
}));
|
|
1683
|
+
return {
|
|
1684
|
+
count: rows.length,
|
|
1685
|
+
visible_count: rows.filter((row) => row.visible).length,
|
|
1686
|
+
texts: rows.map((row) => row.text).filter(Boolean).slice(0, 40),
|
|
1687
|
+
visible_texts: rows.filter((row) => row.visible).map((row) => row.text).filter(Boolean).slice(0, 40),
|
|
1688
|
+
};
|
|
1689
|
+
}).catch((error) => ({ count: 0, visible_count: 0, texts: [], visible_texts: [], error: String(error && error.message ? error.message : error).slice(0, 500) }));
|
|
1690
|
+
}
|
|
1516
1691
|
function inventoryAppPathFromUrl(urlLike) {
|
|
1517
1692
|
const url = new URL(String(urlLike), targetUrl);
|
|
1518
1693
|
const mountPrefix = previewMountPrefix(new URL(targetUrl).pathname);
|
|
@@ -1910,11 +2085,16 @@ async function captureViewport(viewport) {
|
|
|
1910
2085
|
evaluation_error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
1911
2086
|
}));
|
|
1912
2087
|
const selectors = {};
|
|
2088
|
+
const text_sequences = {};
|
|
1913
2089
|
const text_matches = {};
|
|
1914
2090
|
for (const check of profile.checks || []) {
|
|
1915
2091
|
if ((check.type === "selector_visible" || check.type === "selector_count_at_least") && check.selector) {
|
|
1916
2092
|
selectors[check.selector] = await selectorStats(check.selector);
|
|
1917
2093
|
}
|
|
2094
|
+
if (check.type === "selector_text_order" && check.selector) {
|
|
2095
|
+
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
2096
|
+
text_sequences[check.selector] = await selectorTextSequence(check.selector);
|
|
2097
|
+
}
|
|
1918
2098
|
if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
|
|
1919
2099
|
text_matches[textKey(check)] = textMatches(dom.body_text || dom.body_text_sample || "", check);
|
|
1920
2100
|
}
|
|
@@ -1928,7 +2108,7 @@ async function captureViewport(viewport) {
|
|
|
1928
2108
|
let routeInventory;
|
|
1929
2109
|
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
|
|
1930
2110
|
const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
|
|
1931
|
-
if (routeInventoryCheck && (!firstViewportName || viewport.name === firstViewportName)) {
|
|
2111
|
+
if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
|
|
1932
2112
|
try {
|
|
1933
2113
|
routeInventory = await collectRouteInventory(routeInventoryCheck, viewport);
|
|
1934
2114
|
} catch (error) {
|
|
@@ -1978,6 +2158,7 @@ async function captureViewport(viewport) {
|
|
|
1978
2158
|
bounds_overflow_px: dom.bounds_overflow_px,
|
|
1979
2159
|
overflow_offenders: dom.overflow_offenders || [],
|
|
1980
2160
|
selectors,
|
|
2161
|
+
text_sequences,
|
|
1981
2162
|
text_matches,
|
|
1982
2163
|
route_inventory: routeInventory,
|
|
1983
2164
|
setup_action_results: setupActionResults,
|
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", "selector_visible", "selector_count_at_least", "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", "selector_visible", "selector_count_at_least", "selector_text_order", "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", "fill", "set_input_value", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
@@ -66,6 +66,7 @@ interface RiddleProofProfileCheck {
|
|
|
66
66
|
expected_path?: string;
|
|
67
67
|
expected_routes?: RiddleProofProfileRouteInventoryRoute[];
|
|
68
68
|
selector?: string;
|
|
69
|
+
expected_texts?: string[];
|
|
69
70
|
link_selector?: string;
|
|
70
71
|
source_selector?: string;
|
|
71
72
|
route_path_prefix?: string;
|
|
@@ -81,6 +82,7 @@ interface RiddleProofProfileCheck {
|
|
|
81
82
|
timeout_ms?: number;
|
|
82
83
|
run_direct_routes?: boolean;
|
|
83
84
|
run_clickthroughs?: boolean;
|
|
85
|
+
run_all_viewports?: boolean;
|
|
84
86
|
require_unique_routes?: boolean;
|
|
85
87
|
allow_unexpected_routes?: boolean;
|
|
86
88
|
save_route_screenshots?: boolean;
|
|
@@ -137,6 +139,7 @@ interface RiddleProofProfileViewportEvidence {
|
|
|
137
139
|
count: number;
|
|
138
140
|
visible_count: number;
|
|
139
141
|
}>;
|
|
142
|
+
text_sequences?: Record<string, Record<string, JsonValue>>;
|
|
140
143
|
text_matches?: Record<string, boolean>;
|
|
141
144
|
route_inventory?: Record<string, JsonValue>;
|
|
142
145
|
setup_action_results?: Array<Record<string, JsonValue>>;
|