@riddledc/riddle-proof 0.7.62 → 0.7.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -6
- package/dist/{chunk-MIHU2AWC.js → chunk-ZVKKBM2J.js} +66 -8
- package/dist/cli.cjs +66 -8
- package/dist/cli.js +1 -1
- package/dist/index.cjs +66 -8
- package/dist/index.js +1 -1
- package/dist/profile.cjs +66 -8
- package/dist/profile.d.cts +2 -1
- package/dist/profile.d.ts +2 -1
- package/dist/profile.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -242,10 +242,10 @@ appears only after a picker, tab, login stub, storage seed, form fill,
|
|
|
242
242
|
transport control, or other bounded interaction. Supported setup actions are
|
|
243
243
|
`click`, `drag`, `press`, `fill`, `set_input_value`, `assert_text_visible`,
|
|
244
244
|
`assert_text_absent`, `assert_selector_count`, `assert_window_value`,
|
|
245
|
-
`assert_window_number`, `local_storage`, `session_storage`, `clear_storage`,
|
|
246
|
-
`wait_for_selector`, `wait_for_text`, and `window_call`;
|
|
247
|
-
is recorded as a failed `setup_actions_succeeded` check so
|
|
248
|
-
pass without reaching the intended state. Text-matched `click` actions prefer
|
|
245
|
+
`assert_window_number`, `local_storage`, `session_storage`, `clear_storage`,
|
|
246
|
+
`screenshot`, `wait`, `wait_for_selector`, `wait_for_text`, and `window_call`;
|
|
247
|
+
a failed setup action is recorded as a failed `setup_actions_succeeded` check so
|
|
248
|
+
the profile cannot pass without reaching the intended state. Text-matched `click` actions prefer
|
|
249
249
|
visible matching elements, which keeps responsive layouts from selecting hidden
|
|
250
250
|
desktop or mobile-only links. Add `force: true` to a click action only when the
|
|
251
251
|
matched visible element is intentionally animated or otherwise never becomes
|
|
@@ -276,6 +276,10 @@ can include `repeat` / `repeat_count` / `times` from 1 to 100; each repetition
|
|
|
276
276
|
is recorded with `repeat_index` and `repeat_count`, and `after_ms` runs after
|
|
277
277
|
each repetition. Use it for bounded game proof helpers, retry controls, or other
|
|
278
278
|
workflows where one declarative action needs to advance the app several times.
|
|
279
|
+
Use `screenshot` with an optional `label` to capture durable Riddle screenshots
|
|
280
|
+
at important setup milestones, such as after a route switch, terminal state, or
|
|
281
|
+
reset. These labels are recorded in setup evidence and included in profile
|
|
282
|
+
artifact summaries alongside final viewport screenshots.
|
|
279
283
|
Add `frame_selector` / `frameSelector` to a setup action when the interaction
|
|
280
284
|
target lives inside an embedded iframe, such as a community game player or
|
|
281
285
|
hosted preview surface. Selector-based actions, storage actions, window calls,
|
|
@@ -287,8 +291,11 @@ it defaults to the first frame.
|
|
|
287
291
|
Profiles with setup actions also include a compact
|
|
288
292
|
`setup_actions_succeeded.evidence.setup_summary`. The summary groups each
|
|
289
293
|
viewport's final route, final URL, action counts, clicked targets, iframe URLs,
|
|
290
|
-
compact text samples, and failures so setup-heavy clickthrough or iframe proofs
|
|
291
|
-
can be reviewed without reading every raw setup-action result.
|
|
294
|
+
setup screenshots, compact text samples, and failures so setup-heavy clickthrough or iframe proofs
|
|
295
|
+
can be reviewed without reading every raw setup-action result. Long click
|
|
296
|
+
sequences include `clicked_total` and `clicked_truncated`; the compact `clicked`
|
|
297
|
+
list keeps the first and last clicked targets so later route switches and reset
|
|
298
|
+
actions stay visible.
|
|
292
299
|
|
|
293
300
|
`target.timeout_sec` is optional. Use it for known-heavy profile targets so the
|
|
294
301
|
profile carries its own hosted Riddle worker budget; an explicit CLI `--timeout`
|
|
@@ -46,6 +46,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
46
46
|
"local_storage",
|
|
47
47
|
"session_storage",
|
|
48
48
|
"clear_storage",
|
|
49
|
+
"screenshot",
|
|
49
50
|
"wait",
|
|
50
51
|
"wait_for_selector",
|
|
51
52
|
"wait_for_text",
|
|
@@ -206,6 +207,23 @@ function profileSetupActionCounts(results) {
|
|
|
206
207
|
}
|
|
207
208
|
return toJsonValue(counts);
|
|
208
209
|
}
|
|
210
|
+
function profileSetupScreenshotLabels(results) {
|
|
211
|
+
return results.filter((result) => profileSetupResultAction(result) === "screenshot" && result.ok !== false && typeof result.screenshot_label === "string").map((result) => result.screenshot_label).filter(Boolean);
|
|
212
|
+
}
|
|
213
|
+
function sampleProfileSetupSummaryItems(items, limit) {
|
|
214
|
+
if (items.length <= limit) return items;
|
|
215
|
+
const firstCount = Math.floor(limit / 2);
|
|
216
|
+
const lastCount = limit - firstCount;
|
|
217
|
+
return [...items.slice(0, firstCount), ...items.slice(-lastCount)];
|
|
218
|
+
}
|
|
219
|
+
function profileScreenshotLabels(viewports) {
|
|
220
|
+
const labels = [];
|
|
221
|
+
for (const viewport of viewports || []) {
|
|
222
|
+
if (viewport.screenshot_label) labels.push(viewport.screenshot_label);
|
|
223
|
+
labels.push(...profileSetupScreenshotLabels(viewport.setup_action_results || []));
|
|
224
|
+
}
|
|
225
|
+
return labels;
|
|
226
|
+
}
|
|
209
227
|
function profileSetupSummary(viewports, actionCount) {
|
|
210
228
|
return toJsonValue({
|
|
211
229
|
viewport_count: viewports.length,
|
|
@@ -213,12 +231,13 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
213
231
|
viewports: viewports.map((viewport) => {
|
|
214
232
|
const results = viewport.setup_action_results || [];
|
|
215
233
|
const failed = results.filter((result) => result.ok === false);
|
|
216
|
-
const
|
|
234
|
+
const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => ({
|
|
217
235
|
ordinal: result.ordinal ?? null,
|
|
218
236
|
selector: result.selector ?? null,
|
|
219
237
|
frame_selector: result.frame_selector ?? null,
|
|
220
238
|
text: compactProfileSetupSummaryText(result.text)
|
|
221
|
-
}))
|
|
239
|
+
}));
|
|
240
|
+
const clicked = sampleProfileSetupSummaryItems(clickedItems, 8);
|
|
222
241
|
const text_samples = results.filter((result) => result.ok !== false && typeof result.text === "string" && (profileSetupResultAction(result) === "assert_text_visible" || profileSetupResultAction(result) === "assert_text_absent" || profileSetupResultAction(result) === "wait_for_text")).map((result) => ({
|
|
223
242
|
ordinal: result.ordinal ?? null,
|
|
224
243
|
action: profileSetupResultAction(result),
|
|
@@ -234,6 +253,9 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
234
253
|
action_counts: profileSetupActionCounts(results),
|
|
235
254
|
frame_action_count: results.filter((result) => result.frame_selector).length,
|
|
236
255
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
256
|
+
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
257
|
+
clicked_total: clickedItems.length,
|
|
258
|
+
clicked_truncated: clickedItems.length > clicked.length,
|
|
237
259
|
clicked,
|
|
238
260
|
text_samples,
|
|
239
261
|
failed: failed.map((result) => ({
|
|
@@ -277,7 +299,7 @@ function isSupportedCheckType(value) {
|
|
|
277
299
|
}
|
|
278
300
|
function normalizeSetupActionType(value, index) {
|
|
279
301
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
280
|
-
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
|
|
302
|
+
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput;
|
|
281
303
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
282
304
|
return normalized;
|
|
283
305
|
}
|
|
@@ -408,6 +430,7 @@ function normalizeSetupAction(input, index) {
|
|
|
408
430
|
key,
|
|
409
431
|
value,
|
|
410
432
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
433
|
+
label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
|
|
411
434
|
path,
|
|
412
435
|
args,
|
|
413
436
|
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
@@ -1450,7 +1473,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
|
|
|
1450
1473
|
].filter((check) => Boolean(check)) : [];
|
|
1451
1474
|
const status = profileStatusFromEvidence(profile, evidence, checks);
|
|
1452
1475
|
const firstViewport = evidence?.viewports?.[0];
|
|
1453
|
-
const screenshots = (evidence?.viewports
|
|
1476
|
+
const screenshots = profileScreenshotLabels(evidence?.viewports);
|
|
1454
1477
|
return {
|
|
1455
1478
|
version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
1456
1479
|
profile_name: profile.name,
|
|
@@ -1799,6 +1822,26 @@ function profileSetupActionCounts(results) {
|
|
|
1799
1822
|
}
|
|
1800
1823
|
return counts;
|
|
1801
1824
|
}
|
|
1825
|
+
function profileSetupScreenshotLabels(results) {
|
|
1826
|
+
return (results || [])
|
|
1827
|
+
.filter((result) => result && profileSetupResultAction(result) === "screenshot" && result.ok !== false && typeof result.screenshot_label === "string")
|
|
1828
|
+
.map((result) => result.screenshot_label)
|
|
1829
|
+
.filter(Boolean);
|
|
1830
|
+
}
|
|
1831
|
+
function sampleProfileSetupSummaryItems(items, limit) {
|
|
1832
|
+
if ((items || []).length <= limit) return items || [];
|
|
1833
|
+
const firstCount = Math.floor(limit / 2);
|
|
1834
|
+
const lastCount = limit - firstCount;
|
|
1835
|
+
return [...items.slice(0, firstCount), ...items.slice(-lastCount)];
|
|
1836
|
+
}
|
|
1837
|
+
function profileScreenshotLabels(viewports) {
|
|
1838
|
+
const labels = [];
|
|
1839
|
+
for (const viewport of viewports || []) {
|
|
1840
|
+
if (viewport && viewport.screenshot_label) labels.push(viewport.screenshot_label);
|
|
1841
|
+
labels.push(...profileSetupScreenshotLabels(viewport && viewport.setup_action_results || []));
|
|
1842
|
+
}
|
|
1843
|
+
return labels;
|
|
1844
|
+
}
|
|
1802
1845
|
function profileSetupSummary(viewports, actionCount) {
|
|
1803
1846
|
return {
|
|
1804
1847
|
viewport_count: (viewports || []).length,
|
|
@@ -1806,15 +1849,15 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
1806
1849
|
viewports: (viewports || []).map((viewport) => {
|
|
1807
1850
|
const results = viewport.setup_action_results || [];
|
|
1808
1851
|
const failed = results.filter((result) => result && result.ok === false);
|
|
1809
|
-
const
|
|
1852
|
+
const clickedItems = results
|
|
1810
1853
|
.filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
|
|
1811
1854
|
.map((result) => ({
|
|
1812
1855
|
ordinal: result.ordinal ?? null,
|
|
1813
1856
|
selector: result.selector ?? null,
|
|
1814
1857
|
frame_selector: result.frame_selector ?? null,
|
|
1815
1858
|
text: compactProfileSetupSummaryText(result.text),
|
|
1816
|
-
}))
|
|
1817
|
-
|
|
1859
|
+
}));
|
|
1860
|
+
const clicked = sampleProfileSetupSummaryItems(clickedItems, 8);
|
|
1818
1861
|
const textSamples = results
|
|
1819
1862
|
.filter((result) => result && result.ok !== false && typeof result.text === "string" && (
|
|
1820
1863
|
profileSetupResultAction(result) === "assert_text_visible"
|
|
@@ -1838,6 +1881,9 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
1838
1881
|
action_counts: profileSetupActionCounts(results),
|
|
1839
1882
|
frame_action_count: results.filter((result) => result && result.frame_selector).length,
|
|
1840
1883
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
1884
|
+
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
1885
|
+
clicked_total: clickedItems.length,
|
|
1886
|
+
clicked_truncated: clickedItems.length > clicked.length,
|
|
1841
1887
|
clicked,
|
|
1842
1888
|
text_samples: textSamples,
|
|
1843
1889
|
failed: failed.map((result) => ({
|
|
@@ -2325,7 +2371,7 @@ function assessProfile(profile, evidence) {
|
|
|
2325
2371
|
else if (expectedViewportCount && viewports.length < expectedViewportCount) status = "proof_insufficient";
|
|
2326
2372
|
else if (checks.some((check) => check.status === "needs_human_review")) status = "needs_human_review";
|
|
2327
2373
|
else if (checks.some((check) => check.status === "failed")) status = "product_regression";
|
|
2328
|
-
const screenshotLabels = viewports
|
|
2374
|
+
const screenshotLabels = profileScreenshotLabels(viewports);
|
|
2329
2375
|
const route = viewports[0] && viewports[0].route ? viewports[0].route : { requested: evidence.target_url, observed: "", matched: false, error: "missing viewport evidence" };
|
|
2330
2376
|
const passedChecks = checks.filter((check) => check.status === "passed").length;
|
|
2331
2377
|
const failedChecks = checks.filter((check) => check.status === "failed").length;
|
|
@@ -2692,6 +2738,18 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2692
2738
|
await page.waitForTimeout(ms);
|
|
2693
2739
|
return { ...base, ok: true, ms };
|
|
2694
2740
|
}
|
|
2741
|
+
if (type === "screenshot") {
|
|
2742
|
+
const rawLabel = String(action.label || action.name || action.screenshot_label || action.screenshotLabel || ("setup-" + ordinal));
|
|
2743
|
+
const labelPart = rawLabel
|
|
2744
|
+
.toLowerCase()
|
|
2745
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
2746
|
+
.replace(/^-+|-+$/g, "")
|
|
2747
|
+
.slice(0, 80) || ("setup-" + ordinal);
|
|
2748
|
+
const label = profileSlug + "-" + viewport.name + "-" + labelPart;
|
|
2749
|
+
if (typeof saveScreenshot !== "function") return { ...base, reason: "save_screenshot_unavailable", label: rawLabel };
|
|
2750
|
+
await saveScreenshot(label);
|
|
2751
|
+
return { ...base, ok: true, label: rawLabel, screenshot_label: label };
|
|
2752
|
+
}
|
|
2695
2753
|
if (type === "wait_for_selector") {
|
|
2696
2754
|
const scope = await setupActionScope(action, timeout);
|
|
2697
2755
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
package/dist/cli.cjs
CHANGED
|
@@ -6919,6 +6919,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
6919
6919
|
"local_storage",
|
|
6920
6920
|
"session_storage",
|
|
6921
6921
|
"clear_storage",
|
|
6922
|
+
"screenshot",
|
|
6922
6923
|
"wait",
|
|
6923
6924
|
"wait_for_selector",
|
|
6924
6925
|
"wait_for_text",
|
|
@@ -7079,6 +7080,23 @@ function profileSetupActionCounts(results) {
|
|
|
7079
7080
|
}
|
|
7080
7081
|
return toJsonValue(counts);
|
|
7081
7082
|
}
|
|
7083
|
+
function profileSetupScreenshotLabels(results) {
|
|
7084
|
+
return results.filter((result) => profileSetupResultAction(result) === "screenshot" && result.ok !== false && typeof result.screenshot_label === "string").map((result) => result.screenshot_label).filter(Boolean);
|
|
7085
|
+
}
|
|
7086
|
+
function sampleProfileSetupSummaryItems(items, limit) {
|
|
7087
|
+
if (items.length <= limit) return items;
|
|
7088
|
+
const firstCount = Math.floor(limit / 2);
|
|
7089
|
+
const lastCount = limit - firstCount;
|
|
7090
|
+
return [...items.slice(0, firstCount), ...items.slice(-lastCount)];
|
|
7091
|
+
}
|
|
7092
|
+
function profileScreenshotLabels(viewports) {
|
|
7093
|
+
const labels = [];
|
|
7094
|
+
for (const viewport of viewports || []) {
|
|
7095
|
+
if (viewport.screenshot_label) labels.push(viewport.screenshot_label);
|
|
7096
|
+
labels.push(...profileSetupScreenshotLabels(viewport.setup_action_results || []));
|
|
7097
|
+
}
|
|
7098
|
+
return labels;
|
|
7099
|
+
}
|
|
7082
7100
|
function profileSetupSummary(viewports, actionCount) {
|
|
7083
7101
|
return toJsonValue({
|
|
7084
7102
|
viewport_count: viewports.length,
|
|
@@ -7086,12 +7104,13 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
7086
7104
|
viewports: viewports.map((viewport) => {
|
|
7087
7105
|
const results = viewport.setup_action_results || [];
|
|
7088
7106
|
const failed = results.filter((result) => result.ok === false);
|
|
7089
|
-
const
|
|
7107
|
+
const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => ({
|
|
7090
7108
|
ordinal: result.ordinal ?? null,
|
|
7091
7109
|
selector: result.selector ?? null,
|
|
7092
7110
|
frame_selector: result.frame_selector ?? null,
|
|
7093
7111
|
text: compactProfileSetupSummaryText(result.text)
|
|
7094
|
-
}))
|
|
7112
|
+
}));
|
|
7113
|
+
const clicked = sampleProfileSetupSummaryItems(clickedItems, 8);
|
|
7095
7114
|
const text_samples = results.filter((result) => result.ok !== false && typeof result.text === "string" && (profileSetupResultAction(result) === "assert_text_visible" || profileSetupResultAction(result) === "assert_text_absent" || profileSetupResultAction(result) === "wait_for_text")).map((result) => ({
|
|
7096
7115
|
ordinal: result.ordinal ?? null,
|
|
7097
7116
|
action: profileSetupResultAction(result),
|
|
@@ -7107,6 +7126,9 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
7107
7126
|
action_counts: profileSetupActionCounts(results),
|
|
7108
7127
|
frame_action_count: results.filter((result) => result.frame_selector).length,
|
|
7109
7128
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
7129
|
+
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
7130
|
+
clicked_total: clickedItems.length,
|
|
7131
|
+
clicked_truncated: clickedItems.length > clicked.length,
|
|
7110
7132
|
clicked,
|
|
7111
7133
|
text_samples,
|
|
7112
7134
|
failed: failed.map((result) => ({
|
|
@@ -7150,7 +7172,7 @@ function isSupportedCheckType(value) {
|
|
|
7150
7172
|
}
|
|
7151
7173
|
function normalizeSetupActionType(value, index) {
|
|
7152
7174
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
7153
|
-
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
|
|
7175
|
+
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput;
|
|
7154
7176
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
7155
7177
|
return normalized;
|
|
7156
7178
|
}
|
|
@@ -7281,6 +7303,7 @@ function normalizeSetupAction(input, index) {
|
|
|
7281
7303
|
key,
|
|
7282
7304
|
value,
|
|
7283
7305
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
7306
|
+
label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
|
|
7284
7307
|
path: path7,
|
|
7285
7308
|
args,
|
|
7286
7309
|
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
@@ -8323,7 +8346,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
|
|
|
8323
8346
|
].filter((check) => Boolean(check)) : [];
|
|
8324
8347
|
const status = profileStatusFromEvidence(profile, evidence, checks);
|
|
8325
8348
|
const firstViewport = evidence?.viewports?.[0];
|
|
8326
|
-
const screenshots = (evidence?.viewports
|
|
8349
|
+
const screenshots = profileScreenshotLabels(evidence?.viewports);
|
|
8327
8350
|
return {
|
|
8328
8351
|
version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
8329
8352
|
profile_name: profile.name,
|
|
@@ -8656,6 +8679,26 @@ function profileSetupActionCounts(results) {
|
|
|
8656
8679
|
}
|
|
8657
8680
|
return counts;
|
|
8658
8681
|
}
|
|
8682
|
+
function profileSetupScreenshotLabels(results) {
|
|
8683
|
+
return (results || [])
|
|
8684
|
+
.filter((result) => result && profileSetupResultAction(result) === "screenshot" && result.ok !== false && typeof result.screenshot_label === "string")
|
|
8685
|
+
.map((result) => result.screenshot_label)
|
|
8686
|
+
.filter(Boolean);
|
|
8687
|
+
}
|
|
8688
|
+
function sampleProfileSetupSummaryItems(items, limit) {
|
|
8689
|
+
if ((items || []).length <= limit) return items || [];
|
|
8690
|
+
const firstCount = Math.floor(limit / 2);
|
|
8691
|
+
const lastCount = limit - firstCount;
|
|
8692
|
+
return [...items.slice(0, firstCount), ...items.slice(-lastCount)];
|
|
8693
|
+
}
|
|
8694
|
+
function profileScreenshotLabels(viewports) {
|
|
8695
|
+
const labels = [];
|
|
8696
|
+
for (const viewport of viewports || []) {
|
|
8697
|
+
if (viewport && viewport.screenshot_label) labels.push(viewport.screenshot_label);
|
|
8698
|
+
labels.push(...profileSetupScreenshotLabels(viewport && viewport.setup_action_results || []));
|
|
8699
|
+
}
|
|
8700
|
+
return labels;
|
|
8701
|
+
}
|
|
8659
8702
|
function profileSetupSummary(viewports, actionCount) {
|
|
8660
8703
|
return {
|
|
8661
8704
|
viewport_count: (viewports || []).length,
|
|
@@ -8663,15 +8706,15 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
8663
8706
|
viewports: (viewports || []).map((viewport) => {
|
|
8664
8707
|
const results = viewport.setup_action_results || [];
|
|
8665
8708
|
const failed = results.filter((result) => result && result.ok === false);
|
|
8666
|
-
const
|
|
8709
|
+
const clickedItems = results
|
|
8667
8710
|
.filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
|
|
8668
8711
|
.map((result) => ({
|
|
8669
8712
|
ordinal: result.ordinal ?? null,
|
|
8670
8713
|
selector: result.selector ?? null,
|
|
8671
8714
|
frame_selector: result.frame_selector ?? null,
|
|
8672
8715
|
text: compactProfileSetupSummaryText(result.text),
|
|
8673
|
-
}))
|
|
8674
|
-
|
|
8716
|
+
}));
|
|
8717
|
+
const clicked = sampleProfileSetupSummaryItems(clickedItems, 8);
|
|
8675
8718
|
const textSamples = results
|
|
8676
8719
|
.filter((result) => result && result.ok !== false && typeof result.text === "string" && (
|
|
8677
8720
|
profileSetupResultAction(result) === "assert_text_visible"
|
|
@@ -8695,6 +8738,9 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
8695
8738
|
action_counts: profileSetupActionCounts(results),
|
|
8696
8739
|
frame_action_count: results.filter((result) => result && result.frame_selector).length,
|
|
8697
8740
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
8741
|
+
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
8742
|
+
clicked_total: clickedItems.length,
|
|
8743
|
+
clicked_truncated: clickedItems.length > clicked.length,
|
|
8698
8744
|
clicked,
|
|
8699
8745
|
text_samples: textSamples,
|
|
8700
8746
|
failed: failed.map((result) => ({
|
|
@@ -9182,7 +9228,7 @@ function assessProfile(profile, evidence) {
|
|
|
9182
9228
|
else if (expectedViewportCount && viewports.length < expectedViewportCount) status = "proof_insufficient";
|
|
9183
9229
|
else if (checks.some((check) => check.status === "needs_human_review")) status = "needs_human_review";
|
|
9184
9230
|
else if (checks.some((check) => check.status === "failed")) status = "product_regression";
|
|
9185
|
-
const screenshotLabels = viewports
|
|
9231
|
+
const screenshotLabels = profileScreenshotLabels(viewports);
|
|
9186
9232
|
const route = viewports[0] && viewports[0].route ? viewports[0].route : { requested: evidence.target_url, observed: "", matched: false, error: "missing viewport evidence" };
|
|
9187
9233
|
const passedChecks = checks.filter((check) => check.status === "passed").length;
|
|
9188
9234
|
const failedChecks = checks.filter((check) => check.status === "failed").length;
|
|
@@ -9549,6 +9595,18 @@ async function executeSetupAction(action, ordinal) {
|
|
|
9549
9595
|
await page.waitForTimeout(ms);
|
|
9550
9596
|
return { ...base, ok: true, ms };
|
|
9551
9597
|
}
|
|
9598
|
+
if (type === "screenshot") {
|
|
9599
|
+
const rawLabel = String(action.label || action.name || action.screenshot_label || action.screenshotLabel || ("setup-" + ordinal));
|
|
9600
|
+
const labelPart = rawLabel
|
|
9601
|
+
.toLowerCase()
|
|
9602
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
9603
|
+
.replace(/^-+|-+$/g, "")
|
|
9604
|
+
.slice(0, 80) || ("setup-" + ordinal);
|
|
9605
|
+
const label = profileSlug + "-" + viewport.name + "-" + labelPart;
|
|
9606
|
+
if (typeof saveScreenshot !== "function") return { ...base, reason: "save_screenshot_unavailable", label: rawLabel };
|
|
9607
|
+
await saveScreenshot(label);
|
|
9608
|
+
return { ...base, ok: true, label: rawLabel, screenshot_label: label };
|
|
9609
|
+
}
|
|
9552
9610
|
if (type === "wait_for_selector") {
|
|
9553
9611
|
const scope = await setupActionScope(action, timeout);
|
|
9554
9612
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
package/dist/cli.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -8760,6 +8760,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
8760
8760
|
"local_storage",
|
|
8761
8761
|
"session_storage",
|
|
8762
8762
|
"clear_storage",
|
|
8763
|
+
"screenshot",
|
|
8763
8764
|
"wait",
|
|
8764
8765
|
"wait_for_selector",
|
|
8765
8766
|
"wait_for_text",
|
|
@@ -8920,6 +8921,23 @@ function profileSetupActionCounts(results) {
|
|
|
8920
8921
|
}
|
|
8921
8922
|
return toJsonValue(counts);
|
|
8922
8923
|
}
|
|
8924
|
+
function profileSetupScreenshotLabels(results) {
|
|
8925
|
+
return results.filter((result) => profileSetupResultAction(result) === "screenshot" && result.ok !== false && typeof result.screenshot_label === "string").map((result) => result.screenshot_label).filter(Boolean);
|
|
8926
|
+
}
|
|
8927
|
+
function sampleProfileSetupSummaryItems(items, limit) {
|
|
8928
|
+
if (items.length <= limit) return items;
|
|
8929
|
+
const firstCount = Math.floor(limit / 2);
|
|
8930
|
+
const lastCount = limit - firstCount;
|
|
8931
|
+
return [...items.slice(0, firstCount), ...items.slice(-lastCount)];
|
|
8932
|
+
}
|
|
8933
|
+
function profileScreenshotLabels(viewports) {
|
|
8934
|
+
const labels = [];
|
|
8935
|
+
for (const viewport of viewports || []) {
|
|
8936
|
+
if (viewport.screenshot_label) labels.push(viewport.screenshot_label);
|
|
8937
|
+
labels.push(...profileSetupScreenshotLabels(viewport.setup_action_results || []));
|
|
8938
|
+
}
|
|
8939
|
+
return labels;
|
|
8940
|
+
}
|
|
8923
8941
|
function profileSetupSummary(viewports, actionCount) {
|
|
8924
8942
|
return toJsonValue({
|
|
8925
8943
|
viewport_count: viewports.length,
|
|
@@ -8927,12 +8945,13 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
8927
8945
|
viewports: viewports.map((viewport) => {
|
|
8928
8946
|
const results = viewport.setup_action_results || [];
|
|
8929
8947
|
const failed = results.filter((result) => result.ok === false);
|
|
8930
|
-
const
|
|
8948
|
+
const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => ({
|
|
8931
8949
|
ordinal: result.ordinal ?? null,
|
|
8932
8950
|
selector: result.selector ?? null,
|
|
8933
8951
|
frame_selector: result.frame_selector ?? null,
|
|
8934
8952
|
text: compactProfileSetupSummaryText(result.text)
|
|
8935
|
-
}))
|
|
8953
|
+
}));
|
|
8954
|
+
const clicked = sampleProfileSetupSummaryItems(clickedItems, 8);
|
|
8936
8955
|
const text_samples = results.filter((result) => result.ok !== false && typeof result.text === "string" && (profileSetupResultAction(result) === "assert_text_visible" || profileSetupResultAction(result) === "assert_text_absent" || profileSetupResultAction(result) === "wait_for_text")).map((result) => ({
|
|
8937
8956
|
ordinal: result.ordinal ?? null,
|
|
8938
8957
|
action: profileSetupResultAction(result),
|
|
@@ -8948,6 +8967,9 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
8948
8967
|
action_counts: profileSetupActionCounts(results),
|
|
8949
8968
|
frame_action_count: results.filter((result) => result.frame_selector).length,
|
|
8950
8969
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
8970
|
+
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
8971
|
+
clicked_total: clickedItems.length,
|
|
8972
|
+
clicked_truncated: clickedItems.length > clicked.length,
|
|
8951
8973
|
clicked,
|
|
8952
8974
|
text_samples,
|
|
8953
8975
|
failed: failed.map((result) => ({
|
|
@@ -8991,7 +9013,7 @@ function isSupportedCheckType(value) {
|
|
|
8991
9013
|
}
|
|
8992
9014
|
function normalizeSetupActionType(value, index) {
|
|
8993
9015
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
8994
|
-
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
|
|
9016
|
+
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput;
|
|
8995
9017
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
8996
9018
|
return normalized;
|
|
8997
9019
|
}
|
|
@@ -9122,6 +9144,7 @@ function normalizeSetupAction(input, index) {
|
|
|
9122
9144
|
key,
|
|
9123
9145
|
value,
|
|
9124
9146
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
9147
|
+
label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
|
|
9125
9148
|
path: path6,
|
|
9126
9149
|
args,
|
|
9127
9150
|
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
@@ -10164,7 +10187,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
|
|
|
10164
10187
|
].filter((check) => Boolean(check)) : [];
|
|
10165
10188
|
const status = profileStatusFromEvidence(profile, evidence, checks);
|
|
10166
10189
|
const firstViewport = evidence?.viewports?.[0];
|
|
10167
|
-
const screenshots = (evidence?.viewports
|
|
10190
|
+
const screenshots = profileScreenshotLabels(evidence?.viewports);
|
|
10168
10191
|
return {
|
|
10169
10192
|
version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
10170
10193
|
profile_name: profile.name,
|
|
@@ -10513,6 +10536,26 @@ function profileSetupActionCounts(results) {
|
|
|
10513
10536
|
}
|
|
10514
10537
|
return counts;
|
|
10515
10538
|
}
|
|
10539
|
+
function profileSetupScreenshotLabels(results) {
|
|
10540
|
+
return (results || [])
|
|
10541
|
+
.filter((result) => result && profileSetupResultAction(result) === "screenshot" && result.ok !== false && typeof result.screenshot_label === "string")
|
|
10542
|
+
.map((result) => result.screenshot_label)
|
|
10543
|
+
.filter(Boolean);
|
|
10544
|
+
}
|
|
10545
|
+
function sampleProfileSetupSummaryItems(items, limit) {
|
|
10546
|
+
if ((items || []).length <= limit) return items || [];
|
|
10547
|
+
const firstCount = Math.floor(limit / 2);
|
|
10548
|
+
const lastCount = limit - firstCount;
|
|
10549
|
+
return [...items.slice(0, firstCount), ...items.slice(-lastCount)];
|
|
10550
|
+
}
|
|
10551
|
+
function profileScreenshotLabels(viewports) {
|
|
10552
|
+
const labels = [];
|
|
10553
|
+
for (const viewport of viewports || []) {
|
|
10554
|
+
if (viewport && viewport.screenshot_label) labels.push(viewport.screenshot_label);
|
|
10555
|
+
labels.push(...profileSetupScreenshotLabels(viewport && viewport.setup_action_results || []));
|
|
10556
|
+
}
|
|
10557
|
+
return labels;
|
|
10558
|
+
}
|
|
10516
10559
|
function profileSetupSummary(viewports, actionCount) {
|
|
10517
10560
|
return {
|
|
10518
10561
|
viewport_count: (viewports || []).length,
|
|
@@ -10520,15 +10563,15 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
10520
10563
|
viewports: (viewports || []).map((viewport) => {
|
|
10521
10564
|
const results = viewport.setup_action_results || [];
|
|
10522
10565
|
const failed = results.filter((result) => result && result.ok === false);
|
|
10523
|
-
const
|
|
10566
|
+
const clickedItems = results
|
|
10524
10567
|
.filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
|
|
10525
10568
|
.map((result) => ({
|
|
10526
10569
|
ordinal: result.ordinal ?? null,
|
|
10527
10570
|
selector: result.selector ?? null,
|
|
10528
10571
|
frame_selector: result.frame_selector ?? null,
|
|
10529
10572
|
text: compactProfileSetupSummaryText(result.text),
|
|
10530
|
-
}))
|
|
10531
|
-
|
|
10573
|
+
}));
|
|
10574
|
+
const clicked = sampleProfileSetupSummaryItems(clickedItems, 8);
|
|
10532
10575
|
const textSamples = results
|
|
10533
10576
|
.filter((result) => result && result.ok !== false && typeof result.text === "string" && (
|
|
10534
10577
|
profileSetupResultAction(result) === "assert_text_visible"
|
|
@@ -10552,6 +10595,9 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
10552
10595
|
action_counts: profileSetupActionCounts(results),
|
|
10553
10596
|
frame_action_count: results.filter((result) => result && result.frame_selector).length,
|
|
10554
10597
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
10598
|
+
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
10599
|
+
clicked_total: clickedItems.length,
|
|
10600
|
+
clicked_truncated: clickedItems.length > clicked.length,
|
|
10555
10601
|
clicked,
|
|
10556
10602
|
text_samples: textSamples,
|
|
10557
10603
|
failed: failed.map((result) => ({
|
|
@@ -11039,7 +11085,7 @@ function assessProfile(profile, evidence) {
|
|
|
11039
11085
|
else if (expectedViewportCount && viewports.length < expectedViewportCount) status = "proof_insufficient";
|
|
11040
11086
|
else if (checks.some((check) => check.status === "needs_human_review")) status = "needs_human_review";
|
|
11041
11087
|
else if (checks.some((check) => check.status === "failed")) status = "product_regression";
|
|
11042
|
-
const screenshotLabels = viewports
|
|
11088
|
+
const screenshotLabels = profileScreenshotLabels(viewports);
|
|
11043
11089
|
const route = viewports[0] && viewports[0].route ? viewports[0].route : { requested: evidence.target_url, observed: "", matched: false, error: "missing viewport evidence" };
|
|
11044
11090
|
const passedChecks = checks.filter((check) => check.status === "passed").length;
|
|
11045
11091
|
const failedChecks = checks.filter((check) => check.status === "failed").length;
|
|
@@ -11406,6 +11452,18 @@ async function executeSetupAction(action, ordinal) {
|
|
|
11406
11452
|
await page.waitForTimeout(ms);
|
|
11407
11453
|
return { ...base, ok: true, ms };
|
|
11408
11454
|
}
|
|
11455
|
+
if (type === "screenshot") {
|
|
11456
|
+
const rawLabel = String(action.label || action.name || action.screenshot_label || action.screenshotLabel || ("setup-" + ordinal));
|
|
11457
|
+
const labelPart = rawLabel
|
|
11458
|
+
.toLowerCase()
|
|
11459
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
11460
|
+
.replace(/^-+|-+$/g, "")
|
|
11461
|
+
.slice(0, 80) || ("setup-" + ordinal);
|
|
11462
|
+
const label = profileSlug + "-" + viewport.name + "-" + labelPart;
|
|
11463
|
+
if (typeof saveScreenshot !== "function") return { ...base, reason: "save_screenshot_unavailable", label: rawLabel };
|
|
11464
|
+
await saveScreenshot(label);
|
|
11465
|
+
return { ...base, ok: true, label: rawLabel, screenshot_label: label };
|
|
11466
|
+
}
|
|
11409
11467
|
if (type === "wait_for_selector") {
|
|
11410
11468
|
const scope = await setupActionScope(action, timeout);
|
|
11411
11469
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
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-ZVKKBM2J.js";
|
|
62
62
|
import {
|
|
63
63
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
64
64
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
package/dist/profile.cjs
CHANGED
|
@@ -89,6 +89,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
89
89
|
"local_storage",
|
|
90
90
|
"session_storage",
|
|
91
91
|
"clear_storage",
|
|
92
|
+
"screenshot",
|
|
92
93
|
"wait",
|
|
93
94
|
"wait_for_selector",
|
|
94
95
|
"wait_for_text",
|
|
@@ -249,6 +250,23 @@ function profileSetupActionCounts(results) {
|
|
|
249
250
|
}
|
|
250
251
|
return toJsonValue(counts);
|
|
251
252
|
}
|
|
253
|
+
function profileSetupScreenshotLabels(results) {
|
|
254
|
+
return results.filter((result) => profileSetupResultAction(result) === "screenshot" && result.ok !== false && typeof result.screenshot_label === "string").map((result) => result.screenshot_label).filter(Boolean);
|
|
255
|
+
}
|
|
256
|
+
function sampleProfileSetupSummaryItems(items, limit) {
|
|
257
|
+
if (items.length <= limit) return items;
|
|
258
|
+
const firstCount = Math.floor(limit / 2);
|
|
259
|
+
const lastCount = limit - firstCount;
|
|
260
|
+
return [...items.slice(0, firstCount), ...items.slice(-lastCount)];
|
|
261
|
+
}
|
|
262
|
+
function profileScreenshotLabels(viewports) {
|
|
263
|
+
const labels = [];
|
|
264
|
+
for (const viewport of viewports || []) {
|
|
265
|
+
if (viewport.screenshot_label) labels.push(viewport.screenshot_label);
|
|
266
|
+
labels.push(...profileSetupScreenshotLabels(viewport.setup_action_results || []));
|
|
267
|
+
}
|
|
268
|
+
return labels;
|
|
269
|
+
}
|
|
252
270
|
function profileSetupSummary(viewports, actionCount) {
|
|
253
271
|
return toJsonValue({
|
|
254
272
|
viewport_count: viewports.length,
|
|
@@ -256,12 +274,13 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
256
274
|
viewports: viewports.map((viewport) => {
|
|
257
275
|
const results = viewport.setup_action_results || [];
|
|
258
276
|
const failed = results.filter((result) => result.ok === false);
|
|
259
|
-
const
|
|
277
|
+
const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => ({
|
|
260
278
|
ordinal: result.ordinal ?? null,
|
|
261
279
|
selector: result.selector ?? null,
|
|
262
280
|
frame_selector: result.frame_selector ?? null,
|
|
263
281
|
text: compactProfileSetupSummaryText(result.text)
|
|
264
|
-
}))
|
|
282
|
+
}));
|
|
283
|
+
const clicked = sampleProfileSetupSummaryItems(clickedItems, 8);
|
|
265
284
|
const text_samples = results.filter((result) => result.ok !== false && typeof result.text === "string" && (profileSetupResultAction(result) === "assert_text_visible" || profileSetupResultAction(result) === "assert_text_absent" || profileSetupResultAction(result) === "wait_for_text")).map((result) => ({
|
|
266
285
|
ordinal: result.ordinal ?? null,
|
|
267
286
|
action: profileSetupResultAction(result),
|
|
@@ -277,6 +296,9 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
277
296
|
action_counts: profileSetupActionCounts(results),
|
|
278
297
|
frame_action_count: results.filter((result) => result.frame_selector).length,
|
|
279
298
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
299
|
+
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
300
|
+
clicked_total: clickedItems.length,
|
|
301
|
+
clicked_truncated: clickedItems.length > clicked.length,
|
|
280
302
|
clicked,
|
|
281
303
|
text_samples,
|
|
282
304
|
failed: failed.map((result) => ({
|
|
@@ -320,7 +342,7 @@ function isSupportedCheckType(value) {
|
|
|
320
342
|
}
|
|
321
343
|
function normalizeSetupActionType(value, index) {
|
|
322
344
|
const normalizedInput = String(value || "").trim().replace(/-/g, "_");
|
|
323
|
-
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
|
|
345
|
+
const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput;
|
|
324
346
|
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
325
347
|
return normalized;
|
|
326
348
|
}
|
|
@@ -451,6 +473,7 @@ function normalizeSetupAction(input, index) {
|
|
|
451
473
|
key,
|
|
452
474
|
value,
|
|
453
475
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
476
|
+
label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
|
|
454
477
|
path,
|
|
455
478
|
args,
|
|
456
479
|
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
@@ -1493,7 +1516,7 @@ function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
|
|
|
1493
1516
|
].filter((check) => Boolean(check)) : [];
|
|
1494
1517
|
const status = profileStatusFromEvidence(profile, evidence, checks);
|
|
1495
1518
|
const firstViewport = evidence?.viewports?.[0];
|
|
1496
|
-
const screenshots = (evidence?.viewports
|
|
1519
|
+
const screenshots = profileScreenshotLabels(evidence?.viewports);
|
|
1497
1520
|
return {
|
|
1498
1521
|
version: RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
1499
1522
|
profile_name: profile.name,
|
|
@@ -1842,6 +1865,26 @@ function profileSetupActionCounts(results) {
|
|
|
1842
1865
|
}
|
|
1843
1866
|
return counts;
|
|
1844
1867
|
}
|
|
1868
|
+
function profileSetupScreenshotLabels(results) {
|
|
1869
|
+
return (results || [])
|
|
1870
|
+
.filter((result) => result && profileSetupResultAction(result) === "screenshot" && result.ok !== false && typeof result.screenshot_label === "string")
|
|
1871
|
+
.map((result) => result.screenshot_label)
|
|
1872
|
+
.filter(Boolean);
|
|
1873
|
+
}
|
|
1874
|
+
function sampleProfileSetupSummaryItems(items, limit) {
|
|
1875
|
+
if ((items || []).length <= limit) return items || [];
|
|
1876
|
+
const firstCount = Math.floor(limit / 2);
|
|
1877
|
+
const lastCount = limit - firstCount;
|
|
1878
|
+
return [...items.slice(0, firstCount), ...items.slice(-lastCount)];
|
|
1879
|
+
}
|
|
1880
|
+
function profileScreenshotLabels(viewports) {
|
|
1881
|
+
const labels = [];
|
|
1882
|
+
for (const viewport of viewports || []) {
|
|
1883
|
+
if (viewport && viewport.screenshot_label) labels.push(viewport.screenshot_label);
|
|
1884
|
+
labels.push(...profileSetupScreenshotLabels(viewport && viewport.setup_action_results || []));
|
|
1885
|
+
}
|
|
1886
|
+
return labels;
|
|
1887
|
+
}
|
|
1845
1888
|
function profileSetupSummary(viewports, actionCount) {
|
|
1846
1889
|
return {
|
|
1847
1890
|
viewport_count: (viewports || []).length,
|
|
@@ -1849,15 +1892,15 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
1849
1892
|
viewports: (viewports || []).map((viewport) => {
|
|
1850
1893
|
const results = viewport.setup_action_results || [];
|
|
1851
1894
|
const failed = results.filter((result) => result && result.ok === false);
|
|
1852
|
-
const
|
|
1895
|
+
const clickedItems = results
|
|
1853
1896
|
.filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
|
|
1854
1897
|
.map((result) => ({
|
|
1855
1898
|
ordinal: result.ordinal ?? null,
|
|
1856
1899
|
selector: result.selector ?? null,
|
|
1857
1900
|
frame_selector: result.frame_selector ?? null,
|
|
1858
1901
|
text: compactProfileSetupSummaryText(result.text),
|
|
1859
|
-
}))
|
|
1860
|
-
|
|
1902
|
+
}));
|
|
1903
|
+
const clicked = sampleProfileSetupSummaryItems(clickedItems, 8);
|
|
1861
1904
|
const textSamples = results
|
|
1862
1905
|
.filter((result) => result && result.ok !== false && typeof result.text === "string" && (
|
|
1863
1906
|
profileSetupResultAction(result) === "assert_text_visible"
|
|
@@ -1881,6 +1924,9 @@ function profileSetupSummary(viewports, actionCount) {
|
|
|
1881
1924
|
action_counts: profileSetupActionCounts(results),
|
|
1882
1925
|
frame_action_count: results.filter((result) => result && result.frame_selector).length,
|
|
1883
1926
|
frame_urls: profileSetupFrameUrls(viewport),
|
|
1927
|
+
setup_screenshots: profileSetupScreenshotLabels(results),
|
|
1928
|
+
clicked_total: clickedItems.length,
|
|
1929
|
+
clicked_truncated: clickedItems.length > clicked.length,
|
|
1884
1930
|
clicked,
|
|
1885
1931
|
text_samples: textSamples,
|
|
1886
1932
|
failed: failed.map((result) => ({
|
|
@@ -2368,7 +2414,7 @@ function assessProfile(profile, evidence) {
|
|
|
2368
2414
|
else if (expectedViewportCount && viewports.length < expectedViewportCount) status = "proof_insufficient";
|
|
2369
2415
|
else if (checks.some((check) => check.status === "needs_human_review")) status = "needs_human_review";
|
|
2370
2416
|
else if (checks.some((check) => check.status === "failed")) status = "product_regression";
|
|
2371
|
-
const screenshotLabels = viewports
|
|
2417
|
+
const screenshotLabels = profileScreenshotLabels(viewports);
|
|
2372
2418
|
const route = viewports[0] && viewports[0].route ? viewports[0].route : { requested: evidence.target_url, observed: "", matched: false, error: "missing viewport evidence" };
|
|
2373
2419
|
const passedChecks = checks.filter((check) => check.status === "passed").length;
|
|
2374
2420
|
const failedChecks = checks.filter((check) => check.status === "failed").length;
|
|
@@ -2735,6 +2781,18 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2735
2781
|
await page.waitForTimeout(ms);
|
|
2736
2782
|
return { ...base, ok: true, ms };
|
|
2737
2783
|
}
|
|
2784
|
+
if (type === "screenshot") {
|
|
2785
|
+
const rawLabel = String(action.label || action.name || action.screenshot_label || action.screenshotLabel || ("setup-" + ordinal));
|
|
2786
|
+
const labelPart = rawLabel
|
|
2787
|
+
.toLowerCase()
|
|
2788
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
2789
|
+
.replace(/^-+|-+$/g, "")
|
|
2790
|
+
.slice(0, 80) || ("setup-" + ordinal);
|
|
2791
|
+
const label = profileSlug + "-" + viewport.name + "-" + labelPart;
|
|
2792
|
+
if (typeof saveScreenshot !== "function") return { ...base, reason: "save_screenshot_unavailable", label: rawLabel };
|
|
2793
|
+
await saveScreenshot(label);
|
|
2794
|
+
return { ...base, ok: true, label: rawLabel, screenshot_label: label };
|
|
2795
|
+
}
|
|
2738
2796
|
if (type === "wait_for_selector") {
|
|
2739
2797
|
const scope = await setupActionScope(action, timeout);
|
|
2740
2798
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
package/dist/profile.d.cts
CHANGED
|
@@ -5,7 +5,7 @@ declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evide
|
|
|
5
5
|
declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
|
|
6
6
|
declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
|
|
7
7
|
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_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
|
-
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "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"];
|
|
8
|
+
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "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", "screenshot", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
11
11
|
type RiddleProofProfileSetupActionType = typeof RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES[number];
|
|
@@ -33,6 +33,7 @@ interface RiddleProofProfileSetupAction {
|
|
|
33
33
|
key?: string;
|
|
34
34
|
value?: string;
|
|
35
35
|
value_json?: JsonValue;
|
|
36
|
+
label?: string;
|
|
36
37
|
path?: string;
|
|
37
38
|
args?: JsonValue[];
|
|
38
39
|
expect_return?: JsonValue;
|
package/dist/profile.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evide
|
|
|
5
5
|
declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
|
|
6
6
|
declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
|
|
7
7
|
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_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
|
-
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "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"];
|
|
8
|
+
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "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", "screenshot", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
11
11
|
type RiddleProofProfileSetupActionType = typeof RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES[number];
|
|
@@ -33,6 +33,7 @@ interface RiddleProofProfileSetupAction {
|
|
|
33
33
|
key?: string;
|
|
34
34
|
value?: string;
|
|
35
35
|
value_json?: JsonValue;
|
|
36
|
+
label?: string;
|
|
36
37
|
path?: string;
|
|
37
38
|
args?: JsonValue[];
|
|
38
39
|
expect_return?: JsonValue;
|
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-ZVKKBM2J.js";
|
|
23
23
|
export {
|
|
24
24
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
25
25
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|