@riddledc/riddle-proof 0.7.148 → 0.7.150

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/dist/index.cjs CHANGED
@@ -8759,6 +8759,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
8759
8759
  "selector_text_visible",
8760
8760
  "selector_text_absent",
8761
8761
  "selector_text_order",
8762
+ "observe_within",
8762
8763
  "frame_text_visible",
8763
8764
  "frame_url_equals",
8764
8765
  "frame_url_matches",
@@ -9230,6 +9231,22 @@ function profileSetupWindowEvalReceipts(results) {
9230
9231
  return receipt;
9231
9232
  });
9232
9233
  }
9234
+ function profileSetupRangeValueReceipts(results) {
9235
+ return results.filter((result) => profileSetupResultAction(result) === "set_range_value").map((result) => ({
9236
+ ordinal: result.ordinal ?? null,
9237
+ ok: result.ok !== false,
9238
+ selector: result.selector ?? null,
9239
+ frame_selector: result.frame_selector ?? null,
9240
+ requested_value: result.requested_value ?? null,
9241
+ actual_value: result.actual_value ?? null,
9242
+ before_value: result.before_value ?? null,
9243
+ value_as_number: result.value_as_number ?? null,
9244
+ min: result.min ?? null,
9245
+ max: result.max ?? null,
9246
+ step: result.step ?? null,
9247
+ reason: result.reason ?? result.error ?? null
9248
+ }));
9249
+ }
9233
9250
  function sampleProfileSetupSummaryItems(items, limit) {
9234
9251
  if (items.length <= limit) return items;
9235
9252
  const firstCount = Math.floor(limit / 2);
@@ -9272,6 +9289,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
9272
9289
  const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
9273
9290
  const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
9274
9291
  const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
9292
+ const rangeValueReceipts = profileSetupRangeValueReceipts(results);
9293
+ const sampledRangeValueReceipts = sampleProfileSetupSummaryItems(rangeValueReceipts, 8);
9275
9294
  const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => {
9276
9295
  const clickCount = typeof result.click_count === "number" && Number.isFinite(result.click_count) && result.click_count > 1 ? result.click_count : void 0;
9277
9296
  return {
@@ -9320,6 +9339,9 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
9320
9339
  window_eval_captured_total: windowEvalCapturedTotal,
9321
9340
  window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
9322
9341
  window_eval: sampledWindowEvalReceipts,
9342
+ set_range_value_total: rangeValueReceipts.length,
9343
+ set_range_value_truncated: rangeValueReceipts.length > sampledRangeValueReceipts.length,
9344
+ set_range_value: sampledRangeValueReceipts,
9323
9345
  clicked,
9324
9346
  text_samples,
9325
9347
  failed: failed.map((result) => ({
@@ -10060,7 +10082,7 @@ function normalizeCheck(input, index) {
10060
10082
  throw new Error(`checks[${index}].type ${type} is not supported. Supported checks: ${RIDDLE_PROOF_PROFILE_CHECK_TYPES.join(", ")}`);
10061
10083
  }
10062
10084
  const isDialogCountCheck = isDialogCountCheckType(type);
10063
- if ((type === "selector_visible" || type === "selector_absent" || type === "selector_count_at_least" || type === "selector_count_equals" || type === "selector_count_equal" || type === "selector_count_eq" || type === "selector_text_visible" || type === "selector_text_absent") && !stringValue5(input.selector)) {
10085
+ if ((type === "selector_visible" || type === "selector_absent" || type === "selector_count_at_least" || type === "selector_count_equals" || type === "selector_count_equal" || type === "selector_count_eq" || type === "selector_text_visible" || type === "selector_text_absent" || type === "observe_within" && !stringValue5(input.text) && !stringValue5(input.pattern)) && !stringValue5(input.selector)) {
10064
10086
  throw new Error(`checks[${index}] ${type} requires selector.`);
10065
10087
  }
10066
10088
  if ((type === "frame_text_visible" || type === "frame_url_equals" || type === "frame_url_matches" || type === "frame_no_horizontal_overflow") && !stringValue5(input.selector)) {
@@ -10201,7 +10223,7 @@ function normalizeCheck(input, index) {
10201
10223
  allowed_content_types: allowedContentTypes,
10202
10224
  allow_get_fallback: isLinkStatusCheck ? input.allow_get_fallback === false || input.allowGetFallback === false ? false : true : void 0,
10203
10225
  max_overflow_px: numberValue3(input.max_overflow_px),
10204
- timeout_ms: numberValue3(input.timeout_ms) ?? numberValue3(input.timeoutMs),
10226
+ timeout_ms: numberValue3(input.timeout_ms) ?? numberValue3(input.timeoutMs) ?? numberValue3(input.within_ms) ?? numberValue3(input.withinMs),
10205
10227
  run_direct_routes: input.run_direct_routes === false || input.runDirectRoutes === false ? false : true,
10206
10228
  run_clickthroughs: input.run_clickthroughs === false || input.runClickthroughs === false ? false : true,
10207
10229
  run_all_viewports: input.run_all_viewports === true || input.runAllViewports === true,
@@ -10719,6 +10741,16 @@ function summarizeLinkStatusEvidence(viewport, check) {
10719
10741
  function textKey(check) {
10720
10742
  return check.pattern ? `pattern:${check.pattern}/${check.flags || ""}` : `text:${check.text || ""}`;
10721
10743
  }
10744
+ function observeWithinTimeoutMs(check) {
10745
+ const raw = check.timeout_ms;
10746
+ if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return Math.min(Math.round(raw), 6e4);
10747
+ return 2e3;
10748
+ }
10749
+ function observeWithinKey(check) {
10750
+ const target = check.selector ? `selector:${check.selector}` : "page";
10751
+ const expectation = check.pattern ? `pattern:${check.pattern}/${check.flags || ""}` : check.text ? `text:${check.text}` : "visible";
10752
+ return `${target}|${expectation}|within:${observeWithinTimeoutMs(check)}`;
10753
+ }
10722
10754
  function textSequenceForCheck(viewport, check) {
10723
10755
  const key = selectorKey(check);
10724
10756
  const sequence = viewport.text_sequences?.[key];
@@ -11225,6 +11257,40 @@ function assessCheckFromEvidence(check, evidence) {
11225
11257
  message: failed ? `Selector ${key} text order failed in ${failed} viewport(s).` : void 0
11226
11258
  };
11227
11259
  }
11260
+ if (check.type === "observe_within") {
11261
+ const key = observeWithinKey(check);
11262
+ const timeoutMs = observeWithinTimeoutMs(check);
11263
+ const results = viewports.map((viewport) => {
11264
+ const observation = viewport.observations?.[key];
11265
+ const matched = observation?.matched === true;
11266
+ return {
11267
+ viewport: viewport.name,
11268
+ matched,
11269
+ elapsed_ms: numberValue3(observation?.elapsed_ms) ?? null,
11270
+ timeout_ms: numberValue3(observation?.timeout_ms) ?? timeoutMs,
11271
+ attempts: numberValue3(observation?.attempts) ?? null,
11272
+ selector_count: numberValue3(observation?.selector_count) ?? null,
11273
+ visible_count: numberValue3(observation?.visible_count) ?? null,
11274
+ matched_count: numberValue3(observation?.matched_count) ?? null,
11275
+ sample: stringValue5(observation?.sample) ?? null,
11276
+ error: stringValue5(observation?.error) ?? null
11277
+ };
11278
+ });
11279
+ const failed = results.filter((result) => !result.matched).length;
11280
+ return {
11281
+ type: check.type,
11282
+ label: checkLabel(check),
11283
+ status: failed ? "failed" : "passed",
11284
+ evidence: {
11285
+ selector: check.selector || null,
11286
+ text: check.text || null,
11287
+ pattern: check.pattern || null,
11288
+ timeout_ms: timeoutMs,
11289
+ viewports: results.map((result) => toJsonValue(result))
11290
+ },
11291
+ message: failed ? `Observation did not match within ${timeoutMs}ms in ${failed} viewport(s).` : void 0
11292
+ };
11293
+ }
11228
11294
  if (check.type === "frame_text_visible") {
11229
11295
  const key = selectorKey(check);
11230
11296
  const results = viewports.map((viewport) => {
@@ -12629,6 +12695,24 @@ function profileSetupWindowEvalReceipts(results) {
12629
12695
  return receipt;
12630
12696
  });
12631
12697
  }
12698
+ function profileSetupRangeValueReceipts(results) {
12699
+ return (results || [])
12700
+ .filter((result) => result && profileSetupResultAction(result) === "set_range_value")
12701
+ .map((result) => ({
12702
+ ordinal: result.ordinal ?? null,
12703
+ ok: result.ok !== false,
12704
+ selector: result.selector ?? null,
12705
+ frame_selector: result.frame_selector ?? null,
12706
+ requested_value: result.requested_value ?? null,
12707
+ actual_value: result.actual_value ?? null,
12708
+ before_value: result.before_value ?? null,
12709
+ value_as_number: result.value_as_number ?? null,
12710
+ min: result.min ?? null,
12711
+ max: result.max ?? null,
12712
+ step: result.step ?? null,
12713
+ reason: result.reason || result.error || null,
12714
+ }));
12715
+ }
12632
12716
  function sampleProfileSetupSummaryItems(items, limit) {
12633
12717
  if ((items || []).length <= limit) return items || [];
12634
12718
  const firstCount = Math.floor(limit / 2);
@@ -12685,6 +12769,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
12685
12769
  const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
12686
12770
  const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
12687
12771
  const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
12772
+ const rangeValueReceipts = profileSetupRangeValueReceipts(results);
12773
+ const sampledRangeValueReceipts = sampleProfileSetupSummaryItems(rangeValueReceipts, 8);
12688
12774
  const clickedItems = results
12689
12775
  .filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
12690
12776
  .map((result) => {
@@ -12743,6 +12829,9 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
12743
12829
  window_eval_captured_total: windowEvalCapturedTotal,
12744
12830
  window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
12745
12831
  window_eval: sampledWindowEvalReceipts,
12832
+ set_range_value_total: rangeValueReceipts.length,
12833
+ set_range_value_truncated: rangeValueReceipts.length > sampledRangeValueReceipts.length,
12834
+ set_range_value: sampledRangeValueReceipts,
12746
12835
  clicked,
12747
12836
  text_samples: textSamples,
12748
12837
  failed: failed.map((result) => ({
@@ -13111,6 +13200,36 @@ function assessProfile(profile, evidence) {
13111
13200
  });
13112
13201
  continue;
13113
13202
  }
13203
+ if (check.type === "observe_within") {
13204
+ const key = observeWithinKey(check);
13205
+ const timeoutMs = observeWithinTimeoutMs(check);
13206
+ const results = checkViewports.map((viewport) => {
13207
+ const observation = viewport.observations && viewport.observations[key] && typeof viewport.observations[key] === "object"
13208
+ ? viewport.observations[key]
13209
+ : {};
13210
+ return {
13211
+ viewport: viewport.name,
13212
+ matched: observation.matched === true,
13213
+ elapsed_ms: typeof observation.elapsed_ms === "number" && Number.isFinite(observation.elapsed_ms) ? observation.elapsed_ms : null,
13214
+ timeout_ms: typeof observation.timeout_ms === "number" && Number.isFinite(observation.timeout_ms) ? observation.timeout_ms : timeoutMs,
13215
+ attempts: typeof observation.attempts === "number" && Number.isFinite(observation.attempts) ? observation.attempts : null,
13216
+ selector_count: typeof observation.selector_count === "number" && Number.isFinite(observation.selector_count) ? observation.selector_count : null,
13217
+ visible_count: typeof observation.visible_count === "number" && Number.isFinite(observation.visible_count) ? observation.visible_count : null,
13218
+ matched_count: typeof observation.matched_count === "number" && Number.isFinite(observation.matched_count) ? observation.matched_count : null,
13219
+ sample: typeof observation.sample === "string" && observation.sample.trim() ? observation.sample.trim() : null,
13220
+ error: typeof observation.error === "string" && observation.error.trim() ? observation.error.trim() : null,
13221
+ };
13222
+ });
13223
+ const failed = results.filter((result) => !result.matched).length;
13224
+ checks.push({
13225
+ type: check.type,
13226
+ label: check.label || check.type,
13227
+ status: failed ? "failed" : "passed",
13228
+ evidence: { selector: check.selector || null, text: check.text || null, pattern: check.pattern || null, timeout_ms: timeoutMs, viewports: results },
13229
+ message: failed ? "Observation did not match within " + timeoutMs + "ms in " + failed + " viewport(s)." : undefined,
13230
+ });
13231
+ continue;
13232
+ }
13114
13233
  if (check.type === "frame_text_visible") {
13115
13234
  const selector = check.selector || "";
13116
13235
  const results = checkViewports.map((viewport) => {
@@ -13543,6 +13662,19 @@ function ensureDialogHandler() {
13543
13662
  function textKey(check) {
13544
13663
  return check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
13545
13664
  }
13665
+ function observeWithinTimeoutMs(check) {
13666
+ const raw = Number(check && check.timeout_ms);
13667
+ return Number.isFinite(raw) && raw > 0 ? Math.min(Math.round(raw), 60000) : 2000;
13668
+ }
13669
+ function observeWithinKey(check) {
13670
+ const target = check && check.selector ? "selector:" + check.selector : "page";
13671
+ const expectation = check && check.pattern
13672
+ ? "pattern:" + check.pattern + "/" + (check.flags || "")
13673
+ : check && check.text
13674
+ ? "text:" + check.text
13675
+ : "visible";
13676
+ return target + "|" + expectation + "|within:" + observeWithinTimeoutMs(check);
13677
+ }
13546
13678
  function textMatches(sample, check) {
13547
13679
  if (check.pattern) {
13548
13680
  try { return new RegExp(check.pattern, check.flags || "").test(sample || ""); } catch { return false; }
@@ -14858,6 +14990,104 @@ async function selectorTextSequence(selector) {
14858
14990
  };
14859
14991
  }).catch((error) => ({ count: 0, visible_count: 0, texts: [], visible_texts: [], match_texts: [], visible_match_texts: [], error: String(error && error.message ? error.message : error).slice(0, 500) }));
14860
14992
  }
14993
+ async function observeWithinSnapshot(check) {
14994
+ const payload = {
14995
+ selector: check.selector || "",
14996
+ text: check.text || "",
14997
+ pattern: check.pattern || "",
14998
+ flags: check.flags || "",
14999
+ wants_text: Boolean(check.text || check.pattern),
15000
+ };
15001
+ if (payload.selector) {
15002
+ return page.locator(payload.selector).evaluateAll((elements, input) => {
15003
+ const compact = (value) => String(value || "").replace(/\s+/g, " ").trim();
15004
+ const matchText = (value) => {
15005
+ const source = compact(value);
15006
+ if (input.pattern) {
15007
+ try { return new RegExp(input.pattern, input.flags || "").test(source); } catch { return false; }
15008
+ }
15009
+ return source.includes(input.text || "");
15010
+ };
15011
+ const isVisible = (element) => {
15012
+ const style = window.getComputedStyle(element);
15013
+ const rect = element.getBoundingClientRect();
15014
+ return style && style.visibility !== "hidden" && style.display !== "none" && rect.width > 0 && rect.height > 0;
15015
+ };
15016
+ const rows = elements.map((element, index) => {
15017
+ const text = compact(element.innerText || element.textContent || "");
15018
+ const visible = isVisible(element);
15019
+ return { index, text, visible, matched: input.wants_text ? matchText(text) : visible };
15020
+ });
15021
+ const visibleRows = rows.filter((row) => row.visible);
15022
+ const matches = input.wants_text ? visibleRows.filter((row) => row.matched) : visibleRows;
15023
+ const sampleRow = matches[0] || visibleRows[0] || rows[0] || null;
15024
+ return {
15025
+ selector: input.selector,
15026
+ text: input.text || null,
15027
+ pattern: input.pattern || null,
15028
+ selector_count: rows.length,
15029
+ visible_count: visibleRows.length,
15030
+ matched_count: matches.length,
15031
+ matched: matches.length > 0,
15032
+ sample: sampleRow && sampleRow.text ? sampleRow.text.slice(0, 240) : null,
15033
+ };
15034
+ }, payload).catch((error) => ({
15035
+ selector: payload.selector,
15036
+ text: payload.text || null,
15037
+ pattern: payload.pattern || null,
15038
+ selector_count: 0,
15039
+ visible_count: 0,
15040
+ matched_count: 0,
15041
+ matched: false,
15042
+ sample: null,
15043
+ error: String(error && error.message ? error.message : error).slice(0, 500),
15044
+ }));
15045
+ }
15046
+ return page.evaluate((input) => {
15047
+ const compact = (value) => String(value || "").replace(/\s+/g, " ").trim();
15048
+ const sample = compact(document.body ? document.body.innerText || document.body.textContent || "" : "");
15049
+ let matched = false;
15050
+ if (input.pattern) {
15051
+ try { matched = new RegExp(input.pattern, input.flags || "").test(sample); } catch { matched = false; }
15052
+ } else {
15053
+ matched = sample.includes(input.text || "");
15054
+ }
15055
+ return {
15056
+ selector: null,
15057
+ text: input.text || null,
15058
+ pattern: input.pattern || null,
15059
+ matched,
15060
+ matched_count: matched ? 1 : 0,
15061
+ sample: sample.slice(0, 240),
15062
+ };
15063
+ }, payload).catch((error) => ({
15064
+ selector: null,
15065
+ text: payload.text || null,
15066
+ pattern: payload.pattern || null,
15067
+ matched: false,
15068
+ matched_count: 0,
15069
+ sample: null,
15070
+ error: String(error && error.message ? error.message : error).slice(0, 500),
15071
+ }));
15072
+ }
15073
+ async function observeWithin(check) {
15074
+ const timeoutMs = observeWithinTimeoutMs(check);
15075
+ const startedAt = Date.now();
15076
+ let attempts = 0;
15077
+ let last = null;
15078
+ while (true) {
15079
+ attempts += 1;
15080
+ last = await observeWithinSnapshot(check);
15081
+ const elapsedMs = Date.now() - startedAt;
15082
+ if (last && last.matched === true) {
15083
+ return { ...last, timeout_ms: timeoutMs, elapsed_ms: elapsedMs, attempts };
15084
+ }
15085
+ if (elapsedMs >= timeoutMs) {
15086
+ return { ...(last || {}), matched: false, timeout_ms: timeoutMs, elapsed_ms: elapsedMs, attempts };
15087
+ }
15088
+ await page.waitForTimeout(Math.min(100, Math.max(25, timeoutMs - elapsedMs)));
15089
+ }
15090
+ }
14861
15091
  function linkProbeMaxLinks(check) {
14862
15092
  const value = Number(check.max_links || check.maxLinks || check.limit || 100);
14863
15093
  return Number.isInteger(value) && value > 0 ? Math.min(value, 500) : 100;
@@ -15910,6 +16140,7 @@ async function captureViewport(viewport) {
15910
16140
  const text_matches = {};
15911
16141
  const text_match_samples = {};
15912
16142
  const text_case_insensitive_samples = {};
16143
+ const observations = {};
15913
16144
  const http_statuses = {};
15914
16145
  const link_statuses = {};
15915
16146
  for (const check of profile.checks || []) {
@@ -15930,6 +16161,10 @@ async function captureViewport(viewport) {
15930
16161
  selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
15931
16162
  text_sequences[check.selector] = await selectorTextSequence(check.selector);
15932
16163
  }
16164
+ if (check.type === "observe_within") {
16165
+ const key = observeWithinKey(check);
16166
+ observations[key] = observations[key] || await observeWithin(check);
16167
+ }
15933
16168
  if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
15934
16169
  const key = textKey(check);
15935
16170
  const sample = dom.body_text || dom.body_text_sample || "";
@@ -16023,6 +16258,7 @@ async function captureViewport(viewport) {
16023
16258
  text_matches,
16024
16259
  text_match_samples,
16025
16260
  text_case_insensitive_samples,
16261
+ observations,
16026
16262
  http_statuses,
16027
16263
  link_statuses,
16028
16264
  route_inventory: routeInventory,
package/dist/index.js CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  resolveRiddleProofProfileTimeoutSec,
63
63
  slugifyRiddleProofProfileName,
64
64
  summarizeRiddleProofProfileResult
65
- } from "./chunk-WAJA6TJV.js";
65
+ } from "./chunk-QJJ3ISMK.js";
66
66
  import {
67
67
  DEFAULT_RIDDLE_API_BASE_URL,
68
68
  DEFAULT_RIDDLE_API_KEY_FILE,