@riddledc/riddle-proof 0.7.128 → 0.7.130
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/{chunk-TO3FVF5S.js → chunk-ZJNM3YAB.js} +224 -21
- package/dist/cli.cjs +224 -21
- package/dist/cli.js +1 -1
- package/dist/index.cjs +224 -21
- package/dist/index.js +1 -1
- package/dist/profile.cjs +224 -21
- package/dist/profile.d.cts +2 -0
- package/dist/profile.d.ts +2 -0
- package/dist/profile.js +1 -1
- package/dist/proof-run-engine.d.cts +3 -3
- package/dist/proof-run-engine.d.ts +3 -3
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -7544,6 +7544,17 @@ function normalizeSetupActionCoordinateMode(value, index) {
|
|
|
7544
7544
|
if (normalized === "ratio" || normalized === "relative" || normalized === "fraction") return "ratio";
|
|
7545
7545
|
throw new Error(`target.setup_actions[${index}].coordinate_mode ${String(value)} is not supported. Supported coordinate modes: pixels, ratio.`);
|
|
7546
7546
|
}
|
|
7547
|
+
function normalizeSetupActionPointerType(value, type, index) {
|
|
7548
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
7549
|
+
if (type !== "drag") {
|
|
7550
|
+
throw new Error(`target.setup_actions[${index}].pointer_type is only supported for drag actions.`);
|
|
7551
|
+
}
|
|
7552
|
+
const normalized = String(value).trim().replace(/-/g, "_").toLowerCase();
|
|
7553
|
+
if (normalized === "mouse") return "mouse";
|
|
7554
|
+
if (normalized === "touch" || normalized === "finger") return "touch";
|
|
7555
|
+
if (normalized === "pen" || normalized === "stylus") return "pen";
|
|
7556
|
+
throw new Error(`target.setup_actions[${index}].pointer_type ${String(value)} is not supported. Supported pointer types: mouse, touch, pen.`);
|
|
7557
|
+
}
|
|
7547
7558
|
function normalizeSetupAction(input, index) {
|
|
7548
7559
|
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
7549
7560
|
const type = normalizeSetupActionType(stringValue2(input.type), index);
|
|
@@ -7562,6 +7573,7 @@ function normalizeSetupAction(input, index) {
|
|
|
7562
7573
|
const toX = numberValue(valueFromOwn(input, "to_x", "toX", "end_x", "endX", "x2"));
|
|
7563
7574
|
const toY = numberValue(valueFromOwn(input, "to_y", "toY", "end_y", "endY", "y2"));
|
|
7564
7575
|
const coordinateMode = normalizeSetupActionCoordinateMode(valueFromOwn(input, "coordinate_mode", "coordinateMode", "coords", "units"), index);
|
|
7576
|
+
const pointerType = normalizeSetupActionPointerType(valueFromOwn(input, "pointer_type", "pointerType", "input_type", "inputType"), type, index);
|
|
7565
7577
|
if (type === "drag") {
|
|
7566
7578
|
if (fromX === void 0 || fromY === void 0 || toX === void 0 || toY === void 0) {
|
|
7567
7579
|
throw new Error(`target.setup_actions[${index}] drag requires from_x, from_y, to_x, and to_y.`);
|
|
@@ -7646,6 +7658,7 @@ function normalizeSetupAction(input, index) {
|
|
|
7646
7658
|
force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
|
|
7647
7659
|
click_count: normalizeSetupActionClickCount(input, type, index),
|
|
7648
7660
|
coordinate_mode: coordinateMode,
|
|
7661
|
+
pointer_type: pointerType,
|
|
7649
7662
|
from_x: fromX,
|
|
7650
7663
|
from_y: fromY,
|
|
7651
7664
|
to_x: toX,
|
|
@@ -8791,6 +8804,49 @@ function matchText(sample, check) {
|
|
|
8791
8804
|
}
|
|
8792
8805
|
return sample.includes(check.text || "");
|
|
8793
8806
|
}
|
|
8807
|
+
function compactTextEvidenceSample(value) {
|
|
8808
|
+
return String(value || "").replace(/\s+/g, " ").trim();
|
|
8809
|
+
}
|
|
8810
|
+
function textSampleAroundMatch(sample, index, length) {
|
|
8811
|
+
if (index < 0) return void 0;
|
|
8812
|
+
const source = String(sample || "");
|
|
8813
|
+
const context = 120;
|
|
8814
|
+
const start = Math.max(0, index - context);
|
|
8815
|
+
const end = Math.min(source.length, index + Math.max(length, 1) + context);
|
|
8816
|
+
const prefix = start > 0 ? "..." : "";
|
|
8817
|
+
const suffix = end < source.length ? "..." : "";
|
|
8818
|
+
const compacted = compactTextEvidenceSample(`${prefix}${source.slice(start, end)}${suffix}`);
|
|
8819
|
+
return compacted ? compacted.slice(0, 240) : void 0;
|
|
8820
|
+
}
|
|
8821
|
+
function textMatchSamples(sample, check) {
|
|
8822
|
+
const source = String(sample || "");
|
|
8823
|
+
if (!source) return [];
|
|
8824
|
+
if (check.pattern) {
|
|
8825
|
+
try {
|
|
8826
|
+
const flags = Array.from(new Set(String(check.flags || "").replace(/[gy]/g, "").split(""))).join("");
|
|
8827
|
+
const match = new RegExp(check.pattern, flags).exec(source);
|
|
8828
|
+
const sampleText2 = match ? textSampleAroundMatch(source, match.index, match[0]?.length || 1) : void 0;
|
|
8829
|
+
return sampleText2 ? [sampleText2] : [];
|
|
8830
|
+
} catch {
|
|
8831
|
+
return [];
|
|
8832
|
+
}
|
|
8833
|
+
}
|
|
8834
|
+
const text = check.text || "";
|
|
8835
|
+
if (!text) return [];
|
|
8836
|
+
const index = source.indexOf(text);
|
|
8837
|
+
const sampleText = textSampleAroundMatch(source, index, text.length);
|
|
8838
|
+
return sampleText ? [sampleText] : [];
|
|
8839
|
+
}
|
|
8840
|
+
function textCheckFailureSamples(viewport, check) {
|
|
8841
|
+
const key = textKey(check);
|
|
8842
|
+
const captured = viewport.text_match_samples?.[key] || [];
|
|
8843
|
+
const capturedSamples = captured.map((sample) => compactTextEvidenceSample(sample).slice(0, 240)).filter(Boolean);
|
|
8844
|
+
if (capturedSamples.length) return capturedSamples.slice(0, 3);
|
|
8845
|
+
const matchedSamples = textMatchSamples(viewport.body_text_sample || "", check);
|
|
8846
|
+
if (matchedSamples.length) return matchedSamples.slice(0, 3);
|
|
8847
|
+
const fallback = compactTextEvidenceSample(viewport.body_text_sample || "").slice(0, 240);
|
|
8848
|
+
return fallback ? [fallback] : [];
|
|
8849
|
+
}
|
|
8794
8850
|
function allowedMessageSample(input) {
|
|
8795
8851
|
if (!isRecord(input)) return String(input || "");
|
|
8796
8852
|
const parts = [
|
|
@@ -9235,10 +9291,17 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
9235
9291
|
if (check.type === "text_visible" || check.type === "text_absent") {
|
|
9236
9292
|
const key = textKey(check);
|
|
9237
9293
|
const expectedVisible = check.type === "text_visible";
|
|
9238
|
-
const
|
|
9294
|
+
const results = viewports.map((viewport) => {
|
|
9239
9295
|
const fromEvidence = viewport.text_matches?.[key];
|
|
9240
|
-
|
|
9296
|
+
const matched = typeof fromEvidence === "boolean" ? fromEvidence : matchText(viewport.body_text_sample || "", check);
|
|
9297
|
+
const failedAgainstExpectation = matched !== expectedVisible;
|
|
9298
|
+
return {
|
|
9299
|
+
viewport: viewport.name,
|
|
9300
|
+
matched,
|
|
9301
|
+
samples: failedAgainstExpectation ? textCheckFailureSamples(viewport, check) : []
|
|
9302
|
+
};
|
|
9241
9303
|
});
|
|
9304
|
+
const matches = results.map((result) => result.matched);
|
|
9242
9305
|
const failed = matches.filter((matched) => matched !== expectedVisible).length;
|
|
9243
9306
|
return {
|
|
9244
9307
|
type: check.type,
|
|
@@ -9247,7 +9310,8 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
9247
9310
|
evidence: {
|
|
9248
9311
|
text: check.text || null,
|
|
9249
9312
|
pattern: check.pattern || null,
|
|
9250
|
-
matches
|
|
9313
|
+
matches,
|
|
9314
|
+
viewports: results.map((result) => toJsonValue(result))
|
|
9251
9315
|
},
|
|
9252
9316
|
message: failed ? `Text assertion failed in ${failed} viewport(s).` : void 0
|
|
9253
9317
|
};
|
|
@@ -9818,6 +9882,48 @@ function textMatches(sample, check) {
|
|
|
9818
9882
|
}
|
|
9819
9883
|
return String(sample || "").includes(check.text || "");
|
|
9820
9884
|
}
|
|
9885
|
+
function compactTextEvidenceSample(value) {
|
|
9886
|
+
return String(value || "").replace(/\s+/g, " ").trim();
|
|
9887
|
+
}
|
|
9888
|
+
function textSampleAroundMatch(sample, index, length) {
|
|
9889
|
+
if (index < 0) return undefined;
|
|
9890
|
+
const source = String(sample || "");
|
|
9891
|
+
const context = 120;
|
|
9892
|
+
const start = Math.max(0, index - context);
|
|
9893
|
+
const end = Math.min(source.length, index + Math.max(length, 1) + context);
|
|
9894
|
+
const prefix = start > 0 ? "..." : "";
|
|
9895
|
+
const suffix = end < source.length ? "..." : "";
|
|
9896
|
+
const compacted = compactTextEvidenceSample(prefix + source.slice(start, end) + suffix);
|
|
9897
|
+
return compacted ? compacted.slice(0, 240) : undefined;
|
|
9898
|
+
}
|
|
9899
|
+
function textMatchSamples(sample, check) {
|
|
9900
|
+
const source = String(sample || "");
|
|
9901
|
+
if (!source) return [];
|
|
9902
|
+
if (check.pattern) {
|
|
9903
|
+
try {
|
|
9904
|
+
const flags = Array.from(new Set(String(check.flags || "").replace(/[gy]/g, "").split(""))).join("");
|
|
9905
|
+
const match = new RegExp(check.pattern, flags).exec(source);
|
|
9906
|
+
const sampleText = match ? textSampleAroundMatch(source, match.index, match[0] ? match[0].length : 1) : undefined;
|
|
9907
|
+
return sampleText ? [sampleText] : [];
|
|
9908
|
+
} catch { return []; }
|
|
9909
|
+
}
|
|
9910
|
+
const text = check.text || "";
|
|
9911
|
+
if (!text) return [];
|
|
9912
|
+
const sampleText = textSampleAroundMatch(source, source.indexOf(text), text.length);
|
|
9913
|
+
return sampleText ? [sampleText] : [];
|
|
9914
|
+
}
|
|
9915
|
+
function textCheckFailureSamples(viewport, check) {
|
|
9916
|
+
const key = check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
|
|
9917
|
+
const captured = viewport && viewport.text_match_samples && Array.isArray(viewport.text_match_samples[key]) ? viewport.text_match_samples[key] : [];
|
|
9918
|
+
const capturedSamples = captured
|
|
9919
|
+
.map((sample) => compactTextEvidenceSample(sample).slice(0, 240))
|
|
9920
|
+
.filter(Boolean);
|
|
9921
|
+
if (capturedSamples.length) return capturedSamples.slice(0, 3);
|
|
9922
|
+
const matchedSamples = textMatchSamples(viewport && viewport.body_text_sample || "", check);
|
|
9923
|
+
if (matchedSamples.length) return matchedSamples.slice(0, 3);
|
|
9924
|
+
const fallback = compactTextEvidenceSample(viewport && viewport.body_text_sample || "").slice(0, 240);
|
|
9925
|
+
return fallback ? [fallback] : [];
|
|
9926
|
+
}
|
|
9821
9927
|
function allowedMessageSample(input) {
|
|
9822
9928
|
if (!input || typeof input !== "object" || Array.isArray(input)) return String(input || "");
|
|
9823
9929
|
const parts = [
|
|
@@ -10895,13 +11001,22 @@ function assessProfile(profile, evidence) {
|
|
|
10895
11001
|
if (check.type === "text_visible" || check.type === "text_absent") {
|
|
10896
11002
|
const key = check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
|
|
10897
11003
|
const expectedVisible = check.type === "text_visible";
|
|
10898
|
-
const
|
|
11004
|
+
const results = checkViewports.map((viewport) => {
|
|
11005
|
+
const matched = viewport.text_matches && typeof viewport.text_matches[key] === "boolean" ? viewport.text_matches[key] : textMatches(viewport.body_text_sample || "", check);
|
|
11006
|
+
const failedAgainstExpectation = matched !== expectedVisible;
|
|
11007
|
+
return {
|
|
11008
|
+
viewport: viewport.name,
|
|
11009
|
+
matched,
|
|
11010
|
+
samples: failedAgainstExpectation ? textCheckFailureSamples(viewport, check) : [],
|
|
11011
|
+
};
|
|
11012
|
+
});
|
|
11013
|
+
const matches = results.map((result) => result.matched);
|
|
10899
11014
|
const failed = matches.filter((matched) => matched !== expectedVisible).length;
|
|
10900
11015
|
checks.push({
|
|
10901
11016
|
type: check.type,
|
|
10902
11017
|
label: check.label || check.type,
|
|
10903
11018
|
status: failed ? "failed" : "passed",
|
|
10904
|
-
evidence: { text: check.text, pattern: check.pattern, matches },
|
|
11019
|
+
evidence: { text: check.text, pattern: check.pattern, matches, viewports: results },
|
|
10905
11020
|
message: failed ? "Text assertion failed in " + failed + " viewport(s)." : undefined,
|
|
10906
11021
|
});
|
|
10907
11022
|
continue;
|
|
@@ -11221,6 +11336,36 @@ function textMatches(sample, check) {
|
|
|
11221
11336
|
}
|
|
11222
11337
|
return String(sample || "").includes(check.text || "");
|
|
11223
11338
|
}
|
|
11339
|
+
function compactTextEvidenceSample(value) {
|
|
11340
|
+
return String(value || "").replace(/\s+/g, " ").trim();
|
|
11341
|
+
}
|
|
11342
|
+
function textSampleAroundMatch(sample, index, length) {
|
|
11343
|
+
if (index < 0) return undefined;
|
|
11344
|
+
const source = String(sample || "");
|
|
11345
|
+
const context = 120;
|
|
11346
|
+
const start = Math.max(0, index - context);
|
|
11347
|
+
const end = Math.min(source.length, index + Math.max(length, 1) + context);
|
|
11348
|
+
const prefix = start > 0 ? "..." : "";
|
|
11349
|
+
const suffix = end < source.length ? "..." : "";
|
|
11350
|
+
const compacted = compactTextEvidenceSample(prefix + source.slice(start, end) + suffix);
|
|
11351
|
+
return compacted ? compacted.slice(0, 240) : undefined;
|
|
11352
|
+
}
|
|
11353
|
+
function textMatchSamples(sample, check) {
|
|
11354
|
+
const source = String(sample || "");
|
|
11355
|
+
if (!source) return [];
|
|
11356
|
+
if (check.pattern) {
|
|
11357
|
+
try {
|
|
11358
|
+
const flags = Array.from(new Set(String(check.flags || "").replace(/[gy]/g, "").split(""))).join("");
|
|
11359
|
+
const match = new RegExp(check.pattern, flags).exec(source);
|
|
11360
|
+
const sampleText = match ? textSampleAroundMatch(source, match.index, match[0] ? match[0].length : 1) : undefined;
|
|
11361
|
+
return sampleText ? [sampleText] : [];
|
|
11362
|
+
} catch { return []; }
|
|
11363
|
+
}
|
|
11364
|
+
const text = check.text || "";
|
|
11365
|
+
if (!text) return [];
|
|
11366
|
+
const sampleText = textSampleAroundMatch(source, source.indexOf(text), text.length);
|
|
11367
|
+
return sampleText ? [sampleText] : [];
|
|
11368
|
+
}
|
|
11224
11369
|
function profileCheckAppliesToViewport(check, viewport) {
|
|
11225
11370
|
if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
|
|
11226
11371
|
return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
|
|
@@ -11698,23 +11843,75 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
11698
11843
|
const requestedSteps = setupNumber(action.steps, 8);
|
|
11699
11844
|
const steps = Math.min(100, Math.max(1, Math.floor(requestedSteps || 8)));
|
|
11700
11845
|
const durationMs = setupNumber(action.duration_ms ?? action.durationMs, 0);
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11846
|
+
const pointerType = String(action.pointer_type || action.pointerType || "mouse").trim().toLowerCase();
|
|
11847
|
+
if (pointerType === "touch" || pointerType === "pen") {
|
|
11848
|
+
const localStart = {
|
|
11849
|
+
x: coordinate(fromX, box.width),
|
|
11850
|
+
y: coordinate(fromY, box.height),
|
|
11851
|
+
};
|
|
11852
|
+
const localEnd = {
|
|
11853
|
+
x: coordinate(toX, box.width),
|
|
11854
|
+
y: coordinate(toY, box.height),
|
|
11855
|
+
};
|
|
11856
|
+
await target.evaluate(async (element, payload) => {
|
|
11857
|
+
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
11858
|
+
const rect = element.getBoundingClientRect();
|
|
11859
|
+
const pointerId = payload.pointerType === "touch" ? 11 : 12;
|
|
11860
|
+
const point = (progress) => ({
|
|
11861
|
+
clientX: rect.left + payload.start.x + (payload.end.x - payload.start.x) * progress,
|
|
11862
|
+
clientY: rect.top + payload.start.y + (payload.end.y - payload.start.y) * progress,
|
|
11863
|
+
});
|
|
11864
|
+
const dispatch = (type, progress) => {
|
|
11865
|
+
const coords = point(progress);
|
|
11866
|
+
element.dispatchEvent(new PointerEvent(type, {
|
|
11867
|
+
bubbles: true,
|
|
11868
|
+
cancelable: true,
|
|
11869
|
+
composed: true,
|
|
11870
|
+
pointerId,
|
|
11871
|
+
pointerType: payload.pointerType,
|
|
11872
|
+
isPrimary: true,
|
|
11873
|
+
buttons: type === "pointerup" ? 0 : 1,
|
|
11874
|
+
button: type === "pointerup" ? 0 : 0,
|
|
11875
|
+
clientX: coords.clientX,
|
|
11876
|
+
clientY: coords.clientY,
|
|
11877
|
+
}));
|
|
11878
|
+
};
|
|
11879
|
+
dispatch("pointerover", 0);
|
|
11880
|
+
dispatch("pointerenter", 0);
|
|
11881
|
+
dispatch("pointerdown", 0);
|
|
11882
|
+
for (let step = 1; step <= payload.steps; step += 1) {
|
|
11883
|
+
dispatch("pointermove", step / payload.steps);
|
|
11884
|
+
if (payload.durationMs && payload.steps > 1) await wait(payload.durationMs / payload.steps);
|
|
11712
11885
|
}
|
|
11713
|
-
|
|
11714
|
-
|
|
11886
|
+
dispatch("pointerup", 1);
|
|
11887
|
+
dispatch("pointerout", 1);
|
|
11888
|
+
dispatch("pointerleave", 1);
|
|
11889
|
+
}, {
|
|
11890
|
+
pointerType,
|
|
11891
|
+
start: localStart,
|
|
11892
|
+
end: localEnd,
|
|
11893
|
+
steps,
|
|
11894
|
+
durationMs,
|
|
11895
|
+
});
|
|
11896
|
+
} else {
|
|
11897
|
+
await page.mouse.move(start.x, start.y);
|
|
11898
|
+
await page.mouse.down();
|
|
11899
|
+
try {
|
|
11900
|
+
if (durationMs && steps > 1) {
|
|
11901
|
+
for (let step = 1; step <= steps; step += 1) {
|
|
11902
|
+
const progress = step / steps;
|
|
11903
|
+
await page.mouse.move(
|
|
11904
|
+
start.x + (end.x - start.x) * progress,
|
|
11905
|
+
start.y + (end.y - start.y) * progress,
|
|
11906
|
+
);
|
|
11907
|
+
await page.waitForTimeout(durationMs / steps);
|
|
11908
|
+
}
|
|
11909
|
+
} else {
|
|
11910
|
+
await page.mouse.move(end.x, end.y, { steps });
|
|
11911
|
+
}
|
|
11912
|
+
} finally {
|
|
11913
|
+
await page.mouse.up().catch(() => {});
|
|
11715
11914
|
}
|
|
11716
|
-
} finally {
|
|
11717
|
-
await page.mouse.up().catch(() => {});
|
|
11718
11915
|
}
|
|
11719
11916
|
return {
|
|
11720
11917
|
...base,
|
|
@@ -11727,6 +11924,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
11727
11924
|
from_y: fromY,
|
|
11728
11925
|
to_x: toX,
|
|
11729
11926
|
to_y: toY,
|
|
11927
|
+
pointer_type: pointerType,
|
|
11730
11928
|
steps,
|
|
11731
11929
|
duration_ms: durationMs || undefined,
|
|
11732
11930
|
};
|
|
@@ -13172,6 +13370,7 @@ async function captureViewport(viewport) {
|
|
|
13172
13370
|
const frames = {};
|
|
13173
13371
|
const text_sequences = {};
|
|
13174
13372
|
const text_matches = {};
|
|
13373
|
+
const text_match_samples = {};
|
|
13175
13374
|
const http_statuses = {};
|
|
13176
13375
|
const link_statuses = {};
|
|
13177
13376
|
for (const check of profile.checks || []) {
|
|
@@ -13193,7 +13392,10 @@ async function captureViewport(viewport) {
|
|
|
13193
13392
|
text_sequences[check.selector] = await selectorTextSequence(check.selector);
|
|
13194
13393
|
}
|
|
13195
13394
|
if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
|
|
13196
|
-
|
|
13395
|
+
const key = textKey(check);
|
|
13396
|
+
const sample = dom.body_text || dom.body_text_sample || "";
|
|
13397
|
+
text_matches[key] = textMatches(sample, check);
|
|
13398
|
+
text_match_samples[key] = textMatchSamples(sample, check);
|
|
13197
13399
|
}
|
|
13198
13400
|
if ((check.type === "frame_text_visible" || check.type === "frame_url_equals" || check.type === "frame_url_matches" || check.type === "frame_no_horizontal_overflow") && check.selector) {
|
|
13199
13401
|
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
@@ -13270,6 +13472,7 @@ async function captureViewport(viewport) {
|
|
|
13270
13472
|
frames,
|
|
13271
13473
|
text_sequences,
|
|
13272
13474
|
text_matches,
|
|
13475
|
+
text_match_samples,
|
|
13273
13476
|
http_statuses,
|
|
13274
13477
|
link_statuses,
|
|
13275
13478
|
route_inventory: routeInventory,
|
package/dist/cli.js
CHANGED