@riddledc/riddle-proof 0.7.8 → 0.7.9
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 +12 -1
- package/dist/{chunk-7NMAU4DP.js → chunk-NUSUGO2P.js} +221 -2
- package/dist/cli.cjs +220 -2
- package/dist/cli.js +1 -1
- package/dist/index.cjs +222 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/profile.cjs +222 -2
- package/dist/profile.d.cts +17 -1
- package/dist/profile.d.ts +17 -1
- package/dist/profile.js +3 -1
- package/dist/proof-run-engine.d.cts +3 -3
- package/dist/proof-run-engine.d.ts +3 -3
- package/examples/profiles/page-content-basic.json +4 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2917,6 +2917,7 @@ __export(index_exports, {
|
|
|
2917
2917
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES: () => RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
2918
2918
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: () => RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
2919
2919
|
RIDDLE_PROOF_PROFILE_RESULT_VERSION: () => RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
2920
|
+
RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: () => RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
|
|
2920
2921
|
RIDDLE_PROOF_PROFILE_STATUSES: () => RIDDLE_PROOF_PROFILE_STATUSES,
|
|
2921
2922
|
RIDDLE_PROOF_PROFILE_VERSION: () => RIDDLE_PROOF_PROFILE_VERSION,
|
|
2922
2923
|
RIDDLE_PROOF_RUN_CARD_VERSION: () => RIDDLE_PROOF_RUN_CARD_VERSION,
|
|
@@ -8525,6 +8526,12 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
8525
8526
|
"no_mobile_horizontal_overflow",
|
|
8526
8527
|
"no_fatal_console_errors"
|
|
8527
8528
|
];
|
|
8529
|
+
var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
8530
|
+
"click",
|
|
8531
|
+
"wait",
|
|
8532
|
+
"wait_for_selector",
|
|
8533
|
+
"wait_for_text"
|
|
8534
|
+
];
|
|
8528
8535
|
var DEFAULT_VIEWPORTS = [
|
|
8529
8536
|
{ name: "desktop", width: 1280, height: 800 }
|
|
8530
8537
|
];
|
|
@@ -8577,6 +8584,41 @@ function normalizeViewports(value) {
|
|
|
8577
8584
|
function isSupportedCheckType(value) {
|
|
8578
8585
|
return RIDDLE_PROOF_PROFILE_CHECK_TYPES.includes(value);
|
|
8579
8586
|
}
|
|
8587
|
+
function normalizeSetupActionType(value, index) {
|
|
8588
|
+
const normalized = String(value || "").trim().replace(/-/g, "_");
|
|
8589
|
+
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
8590
|
+
return normalized;
|
|
8591
|
+
}
|
|
8592
|
+
throw new Error(`target.setup_actions[${index}].type ${value || "(missing)"} is not supported. Supported actions: ${RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.join(", ")}`);
|
|
8593
|
+
}
|
|
8594
|
+
function normalizeSetupAction(input, index) {
|
|
8595
|
+
if (!isRecord2(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
8596
|
+
const type = normalizeSetupActionType(stringValue5(input.type), index);
|
|
8597
|
+
const selector = stringValue5(input.selector);
|
|
8598
|
+
if ((type === "click" || type === "wait_for_selector" || type === "wait_for_text") && !selector) {
|
|
8599
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
|
|
8600
|
+
}
|
|
8601
|
+
if (type === "wait_for_text" && !stringValue5(input.text) && !stringValue5(input.pattern)) {
|
|
8602
|
+
throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
|
|
8603
|
+
}
|
|
8604
|
+
return {
|
|
8605
|
+
type,
|
|
8606
|
+
selector,
|
|
8607
|
+
text: stringValue5(input.text),
|
|
8608
|
+
pattern: stringValue5(input.pattern),
|
|
8609
|
+
flags: stringValue5(input.flags),
|
|
8610
|
+
index: numberValue3(input.index),
|
|
8611
|
+
ms: numberValue3(input.ms) ?? numberValue3(input.wait_ms) ?? numberValue3(input.waitMs),
|
|
8612
|
+
timeout_ms: numberValue3(input.timeout_ms) ?? numberValue3(input.timeoutMs),
|
|
8613
|
+
after_ms: numberValue3(input.after_ms) ?? numberValue3(input.afterMs),
|
|
8614
|
+
continue_on_failure: input.continue_on_failure === true || input.continueOnFailure === true
|
|
8615
|
+
};
|
|
8616
|
+
}
|
|
8617
|
+
function normalizeSetupActions(value) {
|
|
8618
|
+
if (value === void 0) return void 0;
|
|
8619
|
+
if (!Array.isArray(value)) throw new Error("target.setup_actions must be an array.");
|
|
8620
|
+
return value.map(normalizeSetupAction);
|
|
8621
|
+
}
|
|
8580
8622
|
function normalizeCheck(input, index) {
|
|
8581
8623
|
if (!isRecord2(input)) throw new Error(`checks[${index}] must be an object.`);
|
|
8582
8624
|
const type = stringValue5(input.type);
|
|
@@ -8644,7 +8686,8 @@ function normalizeRiddleProofProfile(input, options = {}) {
|
|
|
8644
8686
|
viewports: options.viewports?.length ? options.viewports : normalizeViewports(targetInput.viewports),
|
|
8645
8687
|
auth: stringValue5(targetInput.auth) || "none",
|
|
8646
8688
|
wait_for_selector: stringValue5(targetInput.wait_for_selector) || stringValue5(targetInput.waitForSelector),
|
|
8647
|
-
wait_ms: numberValue3(targetInput.wait_ms) ?? numberValue3(targetInput.waitMs)
|
|
8689
|
+
wait_ms: numberValue3(targetInput.wait_ms) ?? numberValue3(targetInput.waitMs),
|
|
8690
|
+
setup_actions: normalizeSetupActions(targetInput.setup_actions ?? targetInput.setupActions)
|
|
8648
8691
|
},
|
|
8649
8692
|
checks,
|
|
8650
8693
|
artifacts: Array.isArray(input.artifacts) ? input.artifacts.map((item) => String(item)).filter(Boolean) : ["screenshot", "console", "dom_summary", "proof_json"],
|
|
@@ -8817,6 +8860,48 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
8817
8860
|
message: "Unsupported check type."
|
|
8818
8861
|
};
|
|
8819
8862
|
}
|
|
8863
|
+
function assessSetupActionsFromEvidence(profile, evidence) {
|
|
8864
|
+
if (!profile.target.setup_actions?.length) return void 0;
|
|
8865
|
+
const actionCount = profile.target.setup_actions.length;
|
|
8866
|
+
const failed = [];
|
|
8867
|
+
const viewports = evidence.viewports || [];
|
|
8868
|
+
for (const viewport of viewports) {
|
|
8869
|
+
const results = viewport.setup_action_results || [];
|
|
8870
|
+
for (const result of results) {
|
|
8871
|
+
if (result.ok === false) {
|
|
8872
|
+
failed.push({
|
|
8873
|
+
viewport: viewport.name,
|
|
8874
|
+
action: result.action ?? result.type ?? null,
|
|
8875
|
+
selector: result.selector ?? null,
|
|
8876
|
+
reason: result.reason ?? result.error ?? null
|
|
8877
|
+
});
|
|
8878
|
+
}
|
|
8879
|
+
}
|
|
8880
|
+
if (results.length < actionCount && results.every((result) => result.ok !== false)) {
|
|
8881
|
+
failed.push({
|
|
8882
|
+
viewport: viewport.name,
|
|
8883
|
+
action: "setup_actions",
|
|
8884
|
+
selector: null,
|
|
8885
|
+
reason: `missing setup action results: ${results.length}/${actionCount}`
|
|
8886
|
+
});
|
|
8887
|
+
}
|
|
8888
|
+
}
|
|
8889
|
+
return {
|
|
8890
|
+
type: "setup_actions_succeeded",
|
|
8891
|
+
label: "setup actions succeeded",
|
|
8892
|
+
status: failed.length ? "failed" : "passed",
|
|
8893
|
+
evidence: {
|
|
8894
|
+
action_count: actionCount,
|
|
8895
|
+
viewports: viewports.map((viewport) => ({
|
|
8896
|
+
name: viewport.name,
|
|
8897
|
+
ok: (viewport.setup_action_results || []).length >= actionCount && (viewport.setup_action_results || []).every((result) => result.ok !== false),
|
|
8898
|
+
result_count: (viewport.setup_action_results || []).length
|
|
8899
|
+
})),
|
|
8900
|
+
failed
|
|
8901
|
+
},
|
|
8902
|
+
message: failed.length ? `Setup actions failed in ${failed.length} viewport action(s).` : void 0
|
|
8903
|
+
};
|
|
8904
|
+
}
|
|
8820
8905
|
function profileStatusFromEvidence(evidence, checks) {
|
|
8821
8906
|
if (!evidence) return "proof_insufficient";
|
|
8822
8907
|
const viewports = evidence.viewports || [];
|
|
@@ -8828,7 +8913,10 @@ function profileStatusFromEvidence(evidence, checks) {
|
|
|
8828
8913
|
}
|
|
8829
8914
|
function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
|
|
8830
8915
|
const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
|
|
8831
|
-
const checks = evidence ?
|
|
8916
|
+
const checks = evidence ? [
|
|
8917
|
+
assessSetupActionsFromEvidence(profile, evidence),
|
|
8918
|
+
...profile.checks.map((check) => assessCheckFromEvidence(check, evidence))
|
|
8919
|
+
].filter((check) => Boolean(check)) : [];
|
|
8832
8920
|
const status = profileStatusFromEvidence(evidence, checks);
|
|
8833
8921
|
const firstViewport = evidence?.viewports?.[0];
|
|
8834
8922
|
const screenshots = (evidence?.viewports || []).map((viewport) => viewport.screenshot_label).filter((label) => Boolean(label));
|
|
@@ -8942,6 +9030,47 @@ function textMatches(sample, check) {
|
|
|
8942
9030
|
function assessProfile(profile, evidence) {
|
|
8943
9031
|
const checks = [];
|
|
8944
9032
|
const viewports = evidence.viewports || [];
|
|
9033
|
+
if (profile.target && Array.isArray(profile.target.setup_actions) && profile.target.setup_actions.length) {
|
|
9034
|
+
const actionCount = profile.target.setup_actions.length;
|
|
9035
|
+
const failed = [];
|
|
9036
|
+
for (const viewport of viewports) {
|
|
9037
|
+
const results = viewport.setup_action_results || [];
|
|
9038
|
+
for (const result of results) {
|
|
9039
|
+
if (result && result.ok === false) {
|
|
9040
|
+
failed.push({
|
|
9041
|
+
viewport: viewport.name,
|
|
9042
|
+
action: result.action || result.type || null,
|
|
9043
|
+
selector: result.selector || null,
|
|
9044
|
+
reason: result.reason || result.error || null,
|
|
9045
|
+
});
|
|
9046
|
+
}
|
|
9047
|
+
}
|
|
9048
|
+
if (results.length < actionCount && results.every((result) => !result || result.ok !== false)) {
|
|
9049
|
+
failed.push({
|
|
9050
|
+
viewport: viewport.name,
|
|
9051
|
+
action: "setup_actions",
|
|
9052
|
+
selector: null,
|
|
9053
|
+
reason: "missing setup action results: " + results.length + "/" + actionCount,
|
|
9054
|
+
});
|
|
9055
|
+
}
|
|
9056
|
+
}
|
|
9057
|
+
checks.push({
|
|
9058
|
+
type: "setup_actions_succeeded",
|
|
9059
|
+
label: "setup actions succeeded",
|
|
9060
|
+
status: failed.length ? "failed" : "passed",
|
|
9061
|
+
evidence: {
|
|
9062
|
+
action_count: actionCount,
|
|
9063
|
+
viewports: viewports.map((viewport) => ({
|
|
9064
|
+
name: viewport.name,
|
|
9065
|
+
ok: (viewport.setup_action_results || []).length >= actionCount
|
|
9066
|
+
&& (viewport.setup_action_results || []).every((result) => !result || result.ok !== false),
|
|
9067
|
+
result_count: (viewport.setup_action_results || []).length,
|
|
9068
|
+
})),
|
|
9069
|
+
failed,
|
|
9070
|
+
},
|
|
9071
|
+
message: failed.length ? "Setup actions failed in " + failed.length + " viewport action(s)." : undefined,
|
|
9072
|
+
});
|
|
9073
|
+
}
|
|
8945
9074
|
for (const check of profile.checks || []) {
|
|
8946
9075
|
if (check.type === "route_loaded") {
|
|
8947
9076
|
const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
|
|
@@ -9104,6 +9233,92 @@ function textMatches(sample, check) {
|
|
|
9104
9233
|
}
|
|
9105
9234
|
return String(sample || "").includes(check.text || "");
|
|
9106
9235
|
}
|
|
9236
|
+
function setupActionType(action) {
|
|
9237
|
+
return String(action && action.type ? action.type : "").replace(/-/g, "_");
|
|
9238
|
+
}
|
|
9239
|
+
function setupNumber(value, fallback) {
|
|
9240
|
+
const number = Number(value);
|
|
9241
|
+
return Number.isFinite(number) && number >= 0 ? number : fallback;
|
|
9242
|
+
}
|
|
9243
|
+
function setupTextMatches(sample, action) {
|
|
9244
|
+
if (action.pattern) {
|
|
9245
|
+
try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
|
|
9246
|
+
}
|
|
9247
|
+
return String(sample || "").includes(action.text || "");
|
|
9248
|
+
}
|
|
9249
|
+
async function setupLocatorText(locator, index) {
|
|
9250
|
+
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
9251
|
+
}
|
|
9252
|
+
async function executeSetupAction(action, ordinal) {
|
|
9253
|
+
const type = setupActionType(action);
|
|
9254
|
+
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
|
|
9255
|
+
const timeout = setupNumber(action.timeout_ms, 5000);
|
|
9256
|
+
try {
|
|
9257
|
+
if (type === "wait") {
|
|
9258
|
+
const ms = setupNumber(action.ms, 500);
|
|
9259
|
+
await page.waitForTimeout(ms);
|
|
9260
|
+
return { ...base, ok: true, ms };
|
|
9261
|
+
}
|
|
9262
|
+
if (type === "wait_for_selector") {
|
|
9263
|
+
await page.waitForSelector(action.selector, { state: "visible", timeout });
|
|
9264
|
+
return { ...base, ok: true, timeout_ms: timeout };
|
|
9265
|
+
}
|
|
9266
|
+
if (type === "click") {
|
|
9267
|
+
const locator = page.locator(action.selector);
|
|
9268
|
+
const count = await locator.count();
|
|
9269
|
+
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
9270
|
+
let targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
9271
|
+
let matchedText = null;
|
|
9272
|
+
if (action.text || action.pattern) {
|
|
9273
|
+
targetIndex = -1;
|
|
9274
|
+
for (let index = 0; index < count; index += 1) {
|
|
9275
|
+
const text = await setupLocatorText(locator, index);
|
|
9276
|
+
if (setupTextMatches(text, action)) {
|
|
9277
|
+
targetIndex = index;
|
|
9278
|
+
matchedText = text;
|
|
9279
|
+
break;
|
|
9280
|
+
}
|
|
9281
|
+
}
|
|
9282
|
+
if (targetIndex < 0) return { ...base, reason: "text_not_found", count };
|
|
9283
|
+
}
|
|
9284
|
+
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
9285
|
+
await locator.nth(targetIndex).click({ timeout });
|
|
9286
|
+
return { ...base, ok: true, count, target_index: targetIndex, text: matchedText };
|
|
9287
|
+
}
|
|
9288
|
+
if (type === "wait_for_text") {
|
|
9289
|
+
const locator = page.locator(action.selector);
|
|
9290
|
+
const startedAt = Date.now();
|
|
9291
|
+
let lastText = "";
|
|
9292
|
+
while (Date.now() - startedAt <= timeout) {
|
|
9293
|
+
const count = await locator.count().catch(() => 0);
|
|
9294
|
+
for (let index = 0; index < count; index += 1) {
|
|
9295
|
+
const text = await setupLocatorText(locator, index);
|
|
9296
|
+
lastText = text || lastText;
|
|
9297
|
+
if (setupTextMatches(text, action)) {
|
|
9298
|
+
return { ...base, ok: true, text, target_index: index, timeout_ms: timeout };
|
|
9299
|
+
}
|
|
9300
|
+
}
|
|
9301
|
+
await page.waitForTimeout(100);
|
|
9302
|
+
}
|
|
9303
|
+
return { ...base, reason: "text_not_found", text: lastText, timeout_ms: timeout };
|
|
9304
|
+
}
|
|
9305
|
+
return { ...base, reason: "unsupported_action" };
|
|
9306
|
+
} catch (error) {
|
|
9307
|
+
return { ...base, error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
9308
|
+
}
|
|
9309
|
+
}
|
|
9310
|
+
async function executeSetupActions(actions) {
|
|
9311
|
+
const results = [];
|
|
9312
|
+
for (let index = 0; index < (actions || []).length; index += 1) {
|
|
9313
|
+
const action = actions[index] || {};
|
|
9314
|
+
const result = await executeSetupAction(action, index);
|
|
9315
|
+
results.push(result);
|
|
9316
|
+
const afterMs = setupNumber(action.after_ms, 0);
|
|
9317
|
+
if (afterMs) await page.waitForTimeout(afterMs);
|
|
9318
|
+
if (result.ok === false && action.continue_on_failure !== true) break;
|
|
9319
|
+
}
|
|
9320
|
+
return results;
|
|
9321
|
+
}
|
|
9107
9322
|
function expectedPathFor(check) {
|
|
9108
9323
|
return check.expected_path || new URL(targetUrl).pathname || "/";
|
|
9109
9324
|
}
|
|
@@ -9138,6 +9353,9 @@ async function captureViewport(viewport) {
|
|
|
9138
9353
|
if (!navigationError && profile.target.wait_ms) {
|
|
9139
9354
|
await page.waitForTimeout(profile.target.wait_ms);
|
|
9140
9355
|
}
|
|
9356
|
+
const setupActionResults = (!navigationError && !waitError)
|
|
9357
|
+
? await executeSetupActions(profile.target.setup_actions || [])
|
|
9358
|
+
: [];
|
|
9141
9359
|
const dom = await page.evaluate(() => {
|
|
9142
9360
|
const body = document.body;
|
|
9143
9361
|
const documentElement = document.documentElement;
|
|
@@ -9199,6 +9417,7 @@ async function captureViewport(viewport) {
|
|
|
9199
9417
|
overflow_px: Math.max(0, (dom.scroll_width || 0) - (dom.client_width || viewport.width)),
|
|
9200
9418
|
selectors,
|
|
9201
9419
|
text_matches,
|
|
9420
|
+
setup_action_results: setupActionResults,
|
|
9202
9421
|
screenshot_label: screenshotLabel,
|
|
9203
9422
|
navigation_error: navigationError,
|
|
9204
9423
|
wait_error: waitError,
|
|
@@ -9544,6 +9763,7 @@ function createRiddleApiClient(config = {}) {
|
|
|
9544
9763
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
9545
9764
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
9546
9765
|
RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
9766
|
+
RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
|
|
9547
9767
|
RIDDLE_PROOF_PROFILE_STATUSES,
|
|
9548
9768
|
RIDDLE_PROOF_PROFILE_VERSION,
|
|
9549
9769
|
RIDDLE_PROOF_RUN_CARD_VERSION,
|
package/dist/index.d.cts
CHANGED
|
@@ -10,5 +10,5 @@ export { CreateCaptureDiagnosticInput, DEFAULT_DIAGNOSTIC_ARRAY_LIMIT, DEFAULT_D
|
|
|
10
10
|
export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION, RIDDLE_PROOF_VISUAL_SESSION_VERSION, VisualProofSessionMismatch, buildVisualProofSession, compareVisualProofSessionFingerprint, parseVisualProofSession, visualSessionFingerprint, visualSessionFingerprintBasis } from './proof-session.cjs';
|
|
11
11
|
export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.cjs';
|
|
12
12
|
export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.cjs';
|
|
13
|
-
export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRunner, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileTargetUrl, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
|
|
13
|
+
export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileTargetUrl, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
|
|
14
14
|
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobResult, RiddlePreviewDeployResult, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -10,5 +10,5 @@ export { CreateCaptureDiagnosticInput, DEFAULT_DIAGNOSTIC_ARRAY_LIMIT, DEFAULT_D
|
|
|
10
10
|
export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_VERSION, RIDDLE_PROOF_VISUAL_SESSION_VERSION, VisualProofSessionMismatch, buildVisualProofSession, compareVisualProofSessionFingerprint, parseVisualProofSession, visualSessionFingerprint, visualSessionFingerprintBasis } from './proof-session.js';
|
|
11
11
|
export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.js';
|
|
12
12
|
export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.js';
|
|
13
|
-
export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRunner, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileTargetUrl, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
|
|
13
|
+
export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileTargetUrl, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
|
|
14
14
|
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobResult, RiddlePreviewDeployResult, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
42
42
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
43
43
|
RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
44
|
+
RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
|
|
44
45
|
RIDDLE_PROOF_PROFILE_STATUSES,
|
|
45
46
|
RIDDLE_PROOF_PROFILE_VERSION,
|
|
46
47
|
assessRiddleProofProfileEvidence,
|
|
@@ -55,7 +56,7 @@ import {
|
|
|
55
56
|
resolveRiddleProofProfileTargetUrl,
|
|
56
57
|
slugifyRiddleProofProfileName,
|
|
57
58
|
summarizeRiddleProofProfileResult
|
|
58
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-NUSUGO2P.js";
|
|
59
60
|
import {
|
|
60
61
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
61
62
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
|
@@ -153,6 +154,7 @@ export {
|
|
|
153
154
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
154
155
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
155
156
|
RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
157
|
+
RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
|
|
156
158
|
RIDDLE_PROOF_PROFILE_STATUSES,
|
|
157
159
|
RIDDLE_PROOF_PROFILE_VERSION,
|
|
158
160
|
RIDDLE_PROOF_RUN_CARD_VERSION,
|
package/dist/profile.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(profile_exports, {
|
|
|
23
23
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES: () => RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
24
24
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: () => RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
25
25
|
RIDDLE_PROOF_PROFILE_RESULT_VERSION: () => RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
26
|
+
RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: () => RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
|
|
26
27
|
RIDDLE_PROOF_PROFILE_STATUSES: () => RIDDLE_PROOF_PROFILE_STATUSES,
|
|
27
28
|
RIDDLE_PROOF_PROFILE_VERSION: () => RIDDLE_PROOF_PROFILE_VERSION,
|
|
28
29
|
assessRiddleProofProfileEvidence: () => assessRiddleProofProfileEvidence,
|
|
@@ -60,6 +61,12 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
60
61
|
"no_mobile_horizontal_overflow",
|
|
61
62
|
"no_fatal_console_errors"
|
|
62
63
|
];
|
|
64
|
+
var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
65
|
+
"click",
|
|
66
|
+
"wait",
|
|
67
|
+
"wait_for_selector",
|
|
68
|
+
"wait_for_text"
|
|
69
|
+
];
|
|
63
70
|
var DEFAULT_VIEWPORTS = [
|
|
64
71
|
{ name: "desktop", width: 1280, height: 800 }
|
|
65
72
|
];
|
|
@@ -112,6 +119,41 @@ function normalizeViewports(value) {
|
|
|
112
119
|
function isSupportedCheckType(value) {
|
|
113
120
|
return RIDDLE_PROOF_PROFILE_CHECK_TYPES.includes(value);
|
|
114
121
|
}
|
|
122
|
+
function normalizeSetupActionType(value, index) {
|
|
123
|
+
const normalized = String(value || "").trim().replace(/-/g, "_");
|
|
124
|
+
if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
|
|
125
|
+
return normalized;
|
|
126
|
+
}
|
|
127
|
+
throw new Error(`target.setup_actions[${index}].type ${value || "(missing)"} is not supported. Supported actions: ${RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.join(", ")}`);
|
|
128
|
+
}
|
|
129
|
+
function normalizeSetupAction(input, index) {
|
|
130
|
+
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
131
|
+
const type = normalizeSetupActionType(stringValue(input.type), index);
|
|
132
|
+
const selector = stringValue(input.selector);
|
|
133
|
+
if ((type === "click" || type === "wait_for_selector" || type === "wait_for_text") && !selector) {
|
|
134
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
|
|
135
|
+
}
|
|
136
|
+
if (type === "wait_for_text" && !stringValue(input.text) && !stringValue(input.pattern)) {
|
|
137
|
+
throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
type,
|
|
141
|
+
selector,
|
|
142
|
+
text: stringValue(input.text),
|
|
143
|
+
pattern: stringValue(input.pattern),
|
|
144
|
+
flags: stringValue(input.flags),
|
|
145
|
+
index: numberValue(input.index),
|
|
146
|
+
ms: numberValue(input.ms) ?? numberValue(input.wait_ms) ?? numberValue(input.waitMs),
|
|
147
|
+
timeout_ms: numberValue(input.timeout_ms) ?? numberValue(input.timeoutMs),
|
|
148
|
+
after_ms: numberValue(input.after_ms) ?? numberValue(input.afterMs),
|
|
149
|
+
continue_on_failure: input.continue_on_failure === true || input.continueOnFailure === true
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function normalizeSetupActions(value) {
|
|
153
|
+
if (value === void 0) return void 0;
|
|
154
|
+
if (!Array.isArray(value)) throw new Error("target.setup_actions must be an array.");
|
|
155
|
+
return value.map(normalizeSetupAction);
|
|
156
|
+
}
|
|
115
157
|
function normalizeCheck(input, index) {
|
|
116
158
|
if (!isRecord(input)) throw new Error(`checks[${index}] must be an object.`);
|
|
117
159
|
const type = stringValue(input.type);
|
|
@@ -179,7 +221,8 @@ function normalizeRiddleProofProfile(input, options = {}) {
|
|
|
179
221
|
viewports: options.viewports?.length ? options.viewports : normalizeViewports(targetInput.viewports),
|
|
180
222
|
auth: stringValue(targetInput.auth) || "none",
|
|
181
223
|
wait_for_selector: stringValue(targetInput.wait_for_selector) || stringValue(targetInput.waitForSelector),
|
|
182
|
-
wait_ms: numberValue(targetInput.wait_ms) ?? numberValue(targetInput.waitMs)
|
|
224
|
+
wait_ms: numberValue(targetInput.wait_ms) ?? numberValue(targetInput.waitMs),
|
|
225
|
+
setup_actions: normalizeSetupActions(targetInput.setup_actions ?? targetInput.setupActions)
|
|
183
226
|
},
|
|
184
227
|
checks,
|
|
185
228
|
artifacts: Array.isArray(input.artifacts) ? input.artifacts.map((item) => String(item)).filter(Boolean) : ["screenshot", "console", "dom_summary", "proof_json"],
|
|
@@ -352,6 +395,48 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
352
395
|
message: "Unsupported check type."
|
|
353
396
|
};
|
|
354
397
|
}
|
|
398
|
+
function assessSetupActionsFromEvidence(profile, evidence) {
|
|
399
|
+
if (!profile.target.setup_actions?.length) return void 0;
|
|
400
|
+
const actionCount = profile.target.setup_actions.length;
|
|
401
|
+
const failed = [];
|
|
402
|
+
const viewports = evidence.viewports || [];
|
|
403
|
+
for (const viewport of viewports) {
|
|
404
|
+
const results = viewport.setup_action_results || [];
|
|
405
|
+
for (const result of results) {
|
|
406
|
+
if (result.ok === false) {
|
|
407
|
+
failed.push({
|
|
408
|
+
viewport: viewport.name,
|
|
409
|
+
action: result.action ?? result.type ?? null,
|
|
410
|
+
selector: result.selector ?? null,
|
|
411
|
+
reason: result.reason ?? result.error ?? null
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (results.length < actionCount && results.every((result) => result.ok !== false)) {
|
|
416
|
+
failed.push({
|
|
417
|
+
viewport: viewport.name,
|
|
418
|
+
action: "setup_actions",
|
|
419
|
+
selector: null,
|
|
420
|
+
reason: `missing setup action results: ${results.length}/${actionCount}`
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
type: "setup_actions_succeeded",
|
|
426
|
+
label: "setup actions succeeded",
|
|
427
|
+
status: failed.length ? "failed" : "passed",
|
|
428
|
+
evidence: {
|
|
429
|
+
action_count: actionCount,
|
|
430
|
+
viewports: viewports.map((viewport) => ({
|
|
431
|
+
name: viewport.name,
|
|
432
|
+
ok: (viewport.setup_action_results || []).length >= actionCount && (viewport.setup_action_results || []).every((result) => result.ok !== false),
|
|
433
|
+
result_count: (viewport.setup_action_results || []).length
|
|
434
|
+
})),
|
|
435
|
+
failed
|
|
436
|
+
},
|
|
437
|
+
message: failed.length ? `Setup actions failed in ${failed.length} viewport action(s).` : void 0
|
|
438
|
+
};
|
|
439
|
+
}
|
|
355
440
|
function profileStatusFromEvidence(evidence, checks) {
|
|
356
441
|
if (!evidence) return "proof_insufficient";
|
|
357
442
|
const viewports = evidence.viewports || [];
|
|
@@ -363,7 +448,10 @@ function profileStatusFromEvidence(evidence, checks) {
|
|
|
363
448
|
}
|
|
364
449
|
function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
|
|
365
450
|
const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
|
|
366
|
-
const checks = evidence ?
|
|
451
|
+
const checks = evidence ? [
|
|
452
|
+
assessSetupActionsFromEvidence(profile, evidence),
|
|
453
|
+
...profile.checks.map((check) => assessCheckFromEvidence(check, evidence))
|
|
454
|
+
].filter((check) => Boolean(check)) : [];
|
|
367
455
|
const status = profileStatusFromEvidence(evidence, checks);
|
|
368
456
|
const firstViewport = evidence?.viewports?.[0];
|
|
369
457
|
const screenshots = (evidence?.viewports || []).map((viewport) => viewport.screenshot_label).filter((label) => Boolean(label));
|
|
@@ -477,6 +565,47 @@ function textMatches(sample, check) {
|
|
|
477
565
|
function assessProfile(profile, evidence) {
|
|
478
566
|
const checks = [];
|
|
479
567
|
const viewports = evidence.viewports || [];
|
|
568
|
+
if (profile.target && Array.isArray(profile.target.setup_actions) && profile.target.setup_actions.length) {
|
|
569
|
+
const actionCount = profile.target.setup_actions.length;
|
|
570
|
+
const failed = [];
|
|
571
|
+
for (const viewport of viewports) {
|
|
572
|
+
const results = viewport.setup_action_results || [];
|
|
573
|
+
for (const result of results) {
|
|
574
|
+
if (result && result.ok === false) {
|
|
575
|
+
failed.push({
|
|
576
|
+
viewport: viewport.name,
|
|
577
|
+
action: result.action || result.type || null,
|
|
578
|
+
selector: result.selector || null,
|
|
579
|
+
reason: result.reason || result.error || null,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (results.length < actionCount && results.every((result) => !result || result.ok !== false)) {
|
|
584
|
+
failed.push({
|
|
585
|
+
viewport: viewport.name,
|
|
586
|
+
action: "setup_actions",
|
|
587
|
+
selector: null,
|
|
588
|
+
reason: "missing setup action results: " + results.length + "/" + actionCount,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
checks.push({
|
|
593
|
+
type: "setup_actions_succeeded",
|
|
594
|
+
label: "setup actions succeeded",
|
|
595
|
+
status: failed.length ? "failed" : "passed",
|
|
596
|
+
evidence: {
|
|
597
|
+
action_count: actionCount,
|
|
598
|
+
viewports: viewports.map((viewport) => ({
|
|
599
|
+
name: viewport.name,
|
|
600
|
+
ok: (viewport.setup_action_results || []).length >= actionCount
|
|
601
|
+
&& (viewport.setup_action_results || []).every((result) => !result || result.ok !== false),
|
|
602
|
+
result_count: (viewport.setup_action_results || []).length,
|
|
603
|
+
})),
|
|
604
|
+
failed,
|
|
605
|
+
},
|
|
606
|
+
message: failed.length ? "Setup actions failed in " + failed.length + " viewport action(s)." : undefined,
|
|
607
|
+
});
|
|
608
|
+
}
|
|
480
609
|
for (const check of profile.checks || []) {
|
|
481
610
|
if (check.type === "route_loaded") {
|
|
482
611
|
const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
|
|
@@ -639,6 +768,92 @@ function textMatches(sample, check) {
|
|
|
639
768
|
}
|
|
640
769
|
return String(sample || "").includes(check.text || "");
|
|
641
770
|
}
|
|
771
|
+
function setupActionType(action) {
|
|
772
|
+
return String(action && action.type ? action.type : "").replace(/-/g, "_");
|
|
773
|
+
}
|
|
774
|
+
function setupNumber(value, fallback) {
|
|
775
|
+
const number = Number(value);
|
|
776
|
+
return Number.isFinite(number) && number >= 0 ? number : fallback;
|
|
777
|
+
}
|
|
778
|
+
function setupTextMatches(sample, action) {
|
|
779
|
+
if (action.pattern) {
|
|
780
|
+
try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
|
|
781
|
+
}
|
|
782
|
+
return String(sample || "").includes(action.text || "");
|
|
783
|
+
}
|
|
784
|
+
async function setupLocatorText(locator, index) {
|
|
785
|
+
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
786
|
+
}
|
|
787
|
+
async function executeSetupAction(action, ordinal) {
|
|
788
|
+
const type = setupActionType(action);
|
|
789
|
+
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
|
|
790
|
+
const timeout = setupNumber(action.timeout_ms, 5000);
|
|
791
|
+
try {
|
|
792
|
+
if (type === "wait") {
|
|
793
|
+
const ms = setupNumber(action.ms, 500);
|
|
794
|
+
await page.waitForTimeout(ms);
|
|
795
|
+
return { ...base, ok: true, ms };
|
|
796
|
+
}
|
|
797
|
+
if (type === "wait_for_selector") {
|
|
798
|
+
await page.waitForSelector(action.selector, { state: "visible", timeout });
|
|
799
|
+
return { ...base, ok: true, timeout_ms: timeout };
|
|
800
|
+
}
|
|
801
|
+
if (type === "click") {
|
|
802
|
+
const locator = page.locator(action.selector);
|
|
803
|
+
const count = await locator.count();
|
|
804
|
+
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
805
|
+
let targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
806
|
+
let matchedText = null;
|
|
807
|
+
if (action.text || action.pattern) {
|
|
808
|
+
targetIndex = -1;
|
|
809
|
+
for (let index = 0; index < count; index += 1) {
|
|
810
|
+
const text = await setupLocatorText(locator, index);
|
|
811
|
+
if (setupTextMatches(text, action)) {
|
|
812
|
+
targetIndex = index;
|
|
813
|
+
matchedText = text;
|
|
814
|
+
break;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
if (targetIndex < 0) return { ...base, reason: "text_not_found", count };
|
|
818
|
+
}
|
|
819
|
+
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
820
|
+
await locator.nth(targetIndex).click({ timeout });
|
|
821
|
+
return { ...base, ok: true, count, target_index: targetIndex, text: matchedText };
|
|
822
|
+
}
|
|
823
|
+
if (type === "wait_for_text") {
|
|
824
|
+
const locator = page.locator(action.selector);
|
|
825
|
+
const startedAt = Date.now();
|
|
826
|
+
let lastText = "";
|
|
827
|
+
while (Date.now() - startedAt <= timeout) {
|
|
828
|
+
const count = await locator.count().catch(() => 0);
|
|
829
|
+
for (let index = 0; index < count; index += 1) {
|
|
830
|
+
const text = await setupLocatorText(locator, index);
|
|
831
|
+
lastText = text || lastText;
|
|
832
|
+
if (setupTextMatches(text, action)) {
|
|
833
|
+
return { ...base, ok: true, text, target_index: index, timeout_ms: timeout };
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
await page.waitForTimeout(100);
|
|
837
|
+
}
|
|
838
|
+
return { ...base, reason: "text_not_found", text: lastText, timeout_ms: timeout };
|
|
839
|
+
}
|
|
840
|
+
return { ...base, reason: "unsupported_action" };
|
|
841
|
+
} catch (error) {
|
|
842
|
+
return { ...base, error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
async function executeSetupActions(actions) {
|
|
846
|
+
const results = [];
|
|
847
|
+
for (let index = 0; index < (actions || []).length; index += 1) {
|
|
848
|
+
const action = actions[index] || {};
|
|
849
|
+
const result = await executeSetupAction(action, index);
|
|
850
|
+
results.push(result);
|
|
851
|
+
const afterMs = setupNumber(action.after_ms, 0);
|
|
852
|
+
if (afterMs) await page.waitForTimeout(afterMs);
|
|
853
|
+
if (result.ok === false && action.continue_on_failure !== true) break;
|
|
854
|
+
}
|
|
855
|
+
return results;
|
|
856
|
+
}
|
|
642
857
|
function expectedPathFor(check) {
|
|
643
858
|
return check.expected_path || new URL(targetUrl).pathname || "/";
|
|
644
859
|
}
|
|
@@ -673,6 +888,9 @@ async function captureViewport(viewport) {
|
|
|
673
888
|
if (!navigationError && profile.target.wait_ms) {
|
|
674
889
|
await page.waitForTimeout(profile.target.wait_ms);
|
|
675
890
|
}
|
|
891
|
+
const setupActionResults = (!navigationError && !waitError)
|
|
892
|
+
? await executeSetupActions(profile.target.setup_actions || [])
|
|
893
|
+
: [];
|
|
676
894
|
const dom = await page.evaluate(() => {
|
|
677
895
|
const body = document.body;
|
|
678
896
|
const documentElement = document.documentElement;
|
|
@@ -734,6 +952,7 @@ async function captureViewport(viewport) {
|
|
|
734
952
|
overflow_px: Math.max(0, (dom.scroll_width || 0) - (dom.client_width || viewport.width)),
|
|
735
953
|
selectors,
|
|
736
954
|
text_matches,
|
|
955
|
+
setup_action_results: setupActionResults,
|
|
737
956
|
screenshot_label: screenshotLabel,
|
|
738
957
|
navigation_error: navigationError,
|
|
739
958
|
wait_error: waitError,
|
|
@@ -831,6 +1050,7 @@ function extractRiddleProofProfileResult(input) {
|
|
|
831
1050
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
832
1051
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
833
1052
|
RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
1053
|
+
RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
|
|
834
1054
|
RIDDLE_PROOF_PROFILE_STATUSES,
|
|
835
1055
|
RIDDLE_PROOF_PROFILE_VERSION,
|
|
836
1056
|
assessRiddleProofProfileEvidence,
|