@riddledc/riddle-proof 0.7.60 → 0.7.62

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/cli.cjs CHANGED
@@ -6907,6 +6907,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
6907
6907
  ];
6908
6908
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
6909
6909
  "click",
6910
+ "drag",
6910
6911
  "press",
6911
6912
  "fill",
6912
6913
  "set_input_value",
@@ -7047,6 +7048,78 @@ function toJsonValue(value) {
7047
7048
  if (isRecord(value)) return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
7048
7049
  return String(value);
7049
7050
  }
7051
+ function compactProfileSetupSummaryText(value, limit = 160) {
7052
+ const text = typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
7053
+ if (!text) return void 0;
7054
+ if (text.length <= limit) return text;
7055
+ return `${text.slice(0, Math.max(0, limit - 15)).trimEnd()}... (${text.length} chars)`;
7056
+ }
7057
+ function profileSetupResultAction(value) {
7058
+ const action = value.action ?? value.type;
7059
+ return typeof action === "string" && action ? action : "unknown";
7060
+ }
7061
+ function profileSetupFrameUrls(viewport) {
7062
+ const urls = [];
7063
+ const frames = viewport.frames || {};
7064
+ for (const container of Object.values(frames)) {
7065
+ if (!isRecord(container) || !Array.isArray(container.frames)) continue;
7066
+ for (const frame of container.frames) {
7067
+ if (!isRecord(frame)) continue;
7068
+ const url = typeof frame.url === "string" ? frame.url : void 0;
7069
+ if (url && !urls.includes(url)) urls.push(url);
7070
+ }
7071
+ }
7072
+ return urls.slice(0, 10);
7073
+ }
7074
+ function profileSetupActionCounts(results) {
7075
+ const counts = {};
7076
+ for (const result of results) {
7077
+ const action = profileSetupResultAction(result);
7078
+ counts[action] = (counts[action] || 0) + 1;
7079
+ }
7080
+ return toJsonValue(counts);
7081
+ }
7082
+ function profileSetupSummary(viewports, actionCount) {
7083
+ return toJsonValue({
7084
+ viewport_count: viewports.length,
7085
+ action_count: actionCount ?? null,
7086
+ viewports: viewports.map((viewport) => {
7087
+ const results = viewport.setup_action_results || [];
7088
+ const failed = results.filter((result) => result.ok === false);
7089
+ const clicked = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => ({
7090
+ ordinal: result.ordinal ?? null,
7091
+ selector: result.selector ?? null,
7092
+ frame_selector: result.frame_selector ?? null,
7093
+ text: compactProfileSetupSummaryText(result.text)
7094
+ })).slice(0, 8);
7095
+ 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
+ ordinal: result.ordinal ?? null,
7097
+ action: profileSetupResultAction(result),
7098
+ frame_selector: result.frame_selector ?? null,
7099
+ text: compactProfileSetupSummaryText(result.text)
7100
+ })).filter((item) => item.text).slice(-6);
7101
+ return {
7102
+ name: viewport.name,
7103
+ ok: (actionCount === void 0 ? results.length > 0 : results.length >= actionCount) && failed.length === 0,
7104
+ result_count: results.length,
7105
+ observed_path: viewport.route?.observed ?? null,
7106
+ final_url: viewport.url ?? null,
7107
+ action_counts: profileSetupActionCounts(results),
7108
+ frame_action_count: results.filter((result) => result.frame_selector).length,
7109
+ frame_urls: profileSetupFrameUrls(viewport),
7110
+ clicked,
7111
+ text_samples,
7112
+ failed: failed.map((result) => ({
7113
+ ordinal: result.ordinal ?? null,
7114
+ action: profileSetupResultAction(result),
7115
+ selector: result.selector ?? null,
7116
+ frame_selector: result.frame_selector ?? null,
7117
+ reason: result.reason ?? result.error ?? null
7118
+ }))
7119
+ };
7120
+ })
7121
+ });
7122
+ }
7050
7123
  function normalizeName(value, fallback) {
7051
7124
  const name = stringValue2(value) || fallback;
7052
7125
  return name.replace(/\s+/g, " ").trim();
@@ -7077,7 +7150,7 @@ function isSupportedCheckType(value) {
7077
7150
  }
7078
7151
  function normalizeSetupActionType(value, index) {
7079
7152
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
7080
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
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;
7081
7154
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
7082
7155
  return normalized;
7083
7156
  }
@@ -7107,6 +7180,13 @@ function normalizeSetupActionRepeat(input, index) {
7107
7180
  }
7108
7181
  return repeat;
7109
7182
  }
7183
+ function normalizeSetupActionCoordinateMode(value, index) {
7184
+ if (value === void 0 || value === null || value === "") return void 0;
7185
+ const normalized = String(value).trim().replace(/-/g, "_").toLowerCase();
7186
+ if (normalized === "pixels" || normalized === "pixel" || normalized === "px") return "pixels";
7187
+ if (normalized === "ratio" || normalized === "relative" || normalized === "fraction") return "ratio";
7188
+ throw new Error(`target.setup_actions[${index}].coordinate_mode ${String(value)} is not supported. Supported coordinate modes: pixels, ratio.`);
7189
+ }
7110
7190
  function normalizeSetupAction(input, index) {
7111
7191
  if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
7112
7192
  const type = normalizeSetupActionType(stringValue2(input.type), index);
@@ -7116,9 +7196,25 @@ function normalizeSetupAction(input, index) {
7116
7196
  if (frameIndex !== void 0 && (!Number.isInteger(frameIndex) || frameIndex < 0)) {
7117
7197
  throw new Error(`target.setup_actions[${index}].frame_index must be a non-negative integer.`);
7118
7198
  }
7119
- if ((type === "click" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
7199
+ if ((type === "click" || type === "drag" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
7120
7200
  throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
7121
7201
  }
7202
+ const fromX = numberValue(valueFromOwn(input, "from_x", "fromX", "start_x", "startX", "x1"));
7203
+ const fromY = numberValue(valueFromOwn(input, "from_y", "fromY", "start_y", "startY", "y1"));
7204
+ const toX = numberValue(valueFromOwn(input, "to_x", "toX", "end_x", "endX", "x2"));
7205
+ const toY = numberValue(valueFromOwn(input, "to_y", "toY", "end_y", "endY", "y2"));
7206
+ const coordinateMode = normalizeSetupActionCoordinateMode(valueFromOwn(input, "coordinate_mode", "coordinateMode", "coords", "units"), index);
7207
+ if (type === "drag") {
7208
+ if (fromX === void 0 || fromY === void 0 || toX === void 0 || toY === void 0) {
7209
+ throw new Error(`target.setup_actions[${index}] drag requires from_x, from_y, to_x, and to_y.`);
7210
+ }
7211
+ if (coordinateMode === "ratio" && [fromX, fromY, toX, toY].some((value2) => value2 < 0 || value2 > 1)) {
7212
+ throw new Error(`target.setup_actions[${index}] drag ratio coordinates must be between 0 and 1.`);
7213
+ }
7214
+ if ((coordinateMode === void 0 || coordinateMode === "pixels") && [fromX, fromY, toX, toY].some((value2) => value2 < 0)) {
7215
+ throw new Error(`target.setup_actions[${index}] drag pixel coordinates must be non-negative.`);
7216
+ }
7217
+ }
7122
7218
  if (type === "wait_for_text" && !stringValue2(input.text) && !stringValue2(input.pattern)) {
7123
7219
  throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
7124
7220
  }
@@ -7165,12 +7261,23 @@ function normalizeSetupAction(input, index) {
7165
7261
  }
7166
7262
  }
7167
7263
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
7264
+ const steps = numberValue(input.steps);
7265
+ if (type === "drag" && steps !== void 0 && (!Number.isInteger(steps) || steps < 1 || steps > 100)) {
7266
+ throw new Error(`target.setup_actions[${index}].steps must be an integer from 1 to 100.`);
7267
+ }
7168
7268
  return {
7169
7269
  type,
7170
7270
  selector,
7171
7271
  frame_selector: frameSelector,
7172
7272
  frame_index: frameIndex,
7173
7273
  force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
7274
+ coordinate_mode: coordinateMode,
7275
+ from_x: fromX,
7276
+ from_y: fromY,
7277
+ to_x: toX,
7278
+ to_y: toY,
7279
+ duration_ms: numberValue(input.duration_ms) ?? numberValue(input.durationMs),
7280
+ steps,
7174
7281
  key,
7175
7282
  value,
7176
7283
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
@@ -8119,6 +8226,7 @@ function assessSetupActionsFromEvidence(profile, evidence) {
8119
8226
  ok: (viewport.setup_action_results || []).length >= actionCount && (viewport.setup_action_results || []).every((result) => result.ok !== false),
8120
8227
  result_count: (viewport.setup_action_results || []).length
8121
8228
  })),
8229
+ setup_summary: profileSetupSummary(viewports, actionCount),
8122
8230
  failed
8123
8231
  },
8124
8232
  message: failed.length ? `Setup actions failed in ${failed.length} viewport action(s).` : void 0
@@ -8516,6 +8624,90 @@ function requiredNetworkMockHitCount(mock) {
8516
8624
  if (Array.isArray(mock.responses) && mock.responses.length) return mock.responses.length;
8517
8625
  return 1;
8518
8626
  }
8627
+ function compactProfileSetupSummaryText(value, limit) {
8628
+ limit = limit || 160;
8629
+ const text = typeof value === "string" ? value.replace(/\\s+/g, " ").trim() : "";
8630
+ if (!text) return undefined;
8631
+ if (text.length <= limit) return text;
8632
+ return text.slice(0, Math.max(0, limit - 15)).trimEnd() + "... (" + text.length + " chars)";
8633
+ }
8634
+ function profileSetupResultAction(result) {
8635
+ const action = result && (result.action || result.type);
8636
+ return typeof action === "string" && action ? action : "unknown";
8637
+ }
8638
+ function profileSetupFrameUrls(viewport) {
8639
+ const urls = [];
8640
+ const frames = viewport && viewport.frames || {};
8641
+ for (const container of Object.values(frames)) {
8642
+ if (!container || typeof container !== "object" || Array.isArray(container) || !Array.isArray(container.frames)) continue;
8643
+ for (const frame of container.frames) {
8644
+ if (!frame || typeof frame !== "object" || Array.isArray(frame)) continue;
8645
+ const url = typeof frame.url === "string" ? frame.url : null;
8646
+ if (url && !urls.includes(url)) urls.push(url);
8647
+ }
8648
+ }
8649
+ return urls.slice(0, 10);
8650
+ }
8651
+ function profileSetupActionCounts(results) {
8652
+ const counts = {};
8653
+ for (const result of results || []) {
8654
+ const action = profileSetupResultAction(result);
8655
+ counts[action] = (counts[action] || 0) + 1;
8656
+ }
8657
+ return counts;
8658
+ }
8659
+ function profileSetupSummary(viewports, actionCount) {
8660
+ return {
8661
+ viewport_count: (viewports || []).length,
8662
+ action_count: actionCount ?? null,
8663
+ viewports: (viewports || []).map((viewport) => {
8664
+ const results = viewport.setup_action_results || [];
8665
+ const failed = results.filter((result) => result && result.ok === false);
8666
+ const clicked = results
8667
+ .filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
8668
+ .map((result) => ({
8669
+ ordinal: result.ordinal ?? null,
8670
+ selector: result.selector ?? null,
8671
+ frame_selector: result.frame_selector ?? null,
8672
+ text: compactProfileSetupSummaryText(result.text),
8673
+ }))
8674
+ .slice(0, 8);
8675
+ const textSamples = results
8676
+ .filter((result) => result && result.ok !== false && typeof result.text === "string" && (
8677
+ profileSetupResultAction(result) === "assert_text_visible"
8678
+ || profileSetupResultAction(result) === "assert_text_absent"
8679
+ || profileSetupResultAction(result) === "wait_for_text"
8680
+ ))
8681
+ .map((result) => ({
8682
+ ordinal: result.ordinal ?? null,
8683
+ action: profileSetupResultAction(result),
8684
+ frame_selector: result.frame_selector ?? null,
8685
+ text: compactProfileSetupSummaryText(result.text),
8686
+ }))
8687
+ .filter((item) => item.text)
8688
+ .slice(-6);
8689
+ return {
8690
+ name: viewport.name,
8691
+ ok: (actionCount === undefined ? results.length > 0 : results.length >= actionCount) && failed.length === 0,
8692
+ result_count: results.length,
8693
+ observed_path: viewport.route && viewport.route.observed || null,
8694
+ final_url: viewport.url || null,
8695
+ action_counts: profileSetupActionCounts(results),
8696
+ frame_action_count: results.filter((result) => result && result.frame_selector).length,
8697
+ frame_urls: profileSetupFrameUrls(viewport),
8698
+ clicked,
8699
+ text_samples: textSamples,
8700
+ failed: failed.map((result) => ({
8701
+ ordinal: result.ordinal ?? null,
8702
+ action: profileSetupResultAction(result),
8703
+ selector: result.selector ?? null,
8704
+ frame_selector: result.frame_selector ?? null,
8705
+ reason: result.reason || result.error || null,
8706
+ })),
8707
+ };
8708
+ }),
8709
+ };
8710
+ }
8519
8711
  function assessProfile(profile, evidence) {
8520
8712
  const checks = [];
8521
8713
  const viewports = evidence.viewports || [];
@@ -8620,6 +8812,7 @@ function assessProfile(profile, evidence) {
8620
8812
  && (viewport.setup_action_results || []).every((result) => !result || result.ok !== false),
8621
8813
  result_count: (viewport.setup_action_results || []).length,
8622
8814
  })),
8815
+ setup_summary: profileSetupSummary(viewports, actionCount),
8623
8816
  failed,
8624
8817
  },
8625
8818
  message: failed.length ? "Setup actions failed in " + failed.length + " viewport action(s)." : undefined,
@@ -9362,6 +9555,71 @@ async function executeSetupAction(action, ordinal) {
9362
9555
  await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
9363
9556
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
9364
9557
  }
9558
+ if (type === "drag") {
9559
+ const scope = await setupActionScope(action, timeout);
9560
+ if (!scope.ok) return setupScopeFailure(base, scope);
9561
+ const locator = scope.context.locator(action.selector);
9562
+ const count = await locator.count();
9563
+ if (!count) return { ...base, ...setupScopeEvidence(scope), reason: "selector_not_found", count };
9564
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
9565
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, ...setupScopeEvidence(scope), reason: "index_out_of_range", count, target_index: targetIndex };
9566
+ const target = locator.nth(targetIndex);
9567
+ await target.waitFor({ state: "visible", timeout });
9568
+ const box = await target.boundingBox();
9569
+ if (!box) return { ...base, ...setupScopeEvidence(scope), reason: "bounding_box_unavailable", count, target_index: targetIndex };
9570
+ const mode = String(action.coordinate_mode || action.coordinateMode || "pixels").trim();
9571
+ const coordinate = (value, size) => mode === "ratio" ? value * size : value;
9572
+ const fromX = setupFiniteNumber(action.from_x ?? action.fromX ?? action.start_x ?? action.startX ?? action.x1);
9573
+ const fromY = setupFiniteNumber(action.from_y ?? action.fromY ?? action.start_y ?? action.startY ?? action.y1);
9574
+ const toX = setupFiniteNumber(action.to_x ?? action.toX ?? action.end_x ?? action.endX ?? action.x2);
9575
+ const toY = setupFiniteNumber(action.to_y ?? action.toY ?? action.end_y ?? action.endY ?? action.y2);
9576
+ if (fromX === undefined || fromY === undefined || toX === undefined || toY === undefined) return { ...base, ...setupScopeEvidence(scope), reason: "missing_drag_coordinates", count, target_index: targetIndex };
9577
+ if (mode === "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0 || value > 1)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_ratio_coordinates", count, target_index: targetIndex };
9578
+ if (mode !== "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_pixel_coordinates", count, target_index: targetIndex };
9579
+ const start = {
9580
+ x: box.x + coordinate(fromX, box.width),
9581
+ y: box.y + coordinate(fromY, box.height),
9582
+ };
9583
+ const end = {
9584
+ x: box.x + coordinate(toX, box.width),
9585
+ y: box.y + coordinate(toY, box.height),
9586
+ };
9587
+ const requestedSteps = setupNumber(action.steps, 8);
9588
+ const steps = Math.min(100, Math.max(1, Math.floor(requestedSteps || 8)));
9589
+ const durationMs = setupNumber(action.duration_ms ?? action.durationMs, 0);
9590
+ await page.mouse.move(start.x, start.y);
9591
+ await page.mouse.down();
9592
+ try {
9593
+ if (durationMs && steps > 1) {
9594
+ for (let step = 1; step <= steps; step += 1) {
9595
+ const progress = step / steps;
9596
+ await page.mouse.move(
9597
+ start.x + (end.x - start.x) * progress,
9598
+ start.y + (end.y - start.y) * progress,
9599
+ );
9600
+ await page.waitForTimeout(durationMs / steps);
9601
+ }
9602
+ } else {
9603
+ await page.mouse.move(end.x, end.y, { steps });
9604
+ }
9605
+ } finally {
9606
+ await page.mouse.up().catch(() => {});
9607
+ }
9608
+ return {
9609
+ ...base,
9610
+ ...setupScopeEvidence(scope),
9611
+ ok: true,
9612
+ count,
9613
+ target_index: targetIndex,
9614
+ coordinate_mode: mode,
9615
+ from_x: fromX,
9616
+ from_y: fromY,
9617
+ to_x: toX,
9618
+ to_y: toY,
9619
+ steps,
9620
+ duration_ms: durationMs || undefined,
9621
+ };
9622
+ }
9365
9623
  if (type === "press") {
9366
9624
  const key = String(action.key || "").trim();
9367
9625
  if (!key) return { ...base, reason: "missing_key" };
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  profileStatusExitCode,
11
11
  resolveRiddleProofProfileTargetUrl,
12
12
  resolveRiddleProofProfileTimeoutSec
13
- } from "./chunk-FLQ4HHTT.js";
13
+ } from "./chunk-MIHU2AWC.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport