@riddledc/riddle-proof 0.7.7 → 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 +16 -4
- package/dist/basic-gameplay.cjs +4 -0
- package/dist/basic-gameplay.d.cts +1 -1
- package/dist/basic-gameplay.d.ts +1 -1
- package/dist/basic-gameplay.js +1 -1
- package/dist/{chunk-AHW7SL3W.js → chunk-5A4SL6CX.js} +4 -0
- 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 +226 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -2
- 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,
|
|
@@ -7818,6 +7819,10 @@ var BASIC_GAMEPLAY_ACTION_TYPES = [
|
|
|
7818
7819
|
"repeat",
|
|
7819
7820
|
"click",
|
|
7820
7821
|
"click-by-text",
|
|
7822
|
+
"canvas-click",
|
|
7823
|
+
"canvas-pointer-down",
|
|
7824
|
+
"canvas-pointer-move",
|
|
7825
|
+
"canvas-pointer-up",
|
|
7821
7826
|
"wait-for-text",
|
|
7822
7827
|
"window-call",
|
|
7823
7828
|
"evaluate"
|
|
@@ -8521,6 +8526,12 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
8521
8526
|
"no_mobile_horizontal_overflow",
|
|
8522
8527
|
"no_fatal_console_errors"
|
|
8523
8528
|
];
|
|
8529
|
+
var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
8530
|
+
"click",
|
|
8531
|
+
"wait",
|
|
8532
|
+
"wait_for_selector",
|
|
8533
|
+
"wait_for_text"
|
|
8534
|
+
];
|
|
8524
8535
|
var DEFAULT_VIEWPORTS = [
|
|
8525
8536
|
{ name: "desktop", width: 1280, height: 800 }
|
|
8526
8537
|
];
|
|
@@ -8573,6 +8584,41 @@ function normalizeViewports(value) {
|
|
|
8573
8584
|
function isSupportedCheckType(value) {
|
|
8574
8585
|
return RIDDLE_PROOF_PROFILE_CHECK_TYPES.includes(value);
|
|
8575
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
|
+
}
|
|
8576
8622
|
function normalizeCheck(input, index) {
|
|
8577
8623
|
if (!isRecord2(input)) throw new Error(`checks[${index}] must be an object.`);
|
|
8578
8624
|
const type = stringValue5(input.type);
|
|
@@ -8640,7 +8686,8 @@ function normalizeRiddleProofProfile(input, options = {}) {
|
|
|
8640
8686
|
viewports: options.viewports?.length ? options.viewports : normalizeViewports(targetInput.viewports),
|
|
8641
8687
|
auth: stringValue5(targetInput.auth) || "none",
|
|
8642
8688
|
wait_for_selector: stringValue5(targetInput.wait_for_selector) || stringValue5(targetInput.waitForSelector),
|
|
8643
|
-
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)
|
|
8644
8691
|
},
|
|
8645
8692
|
checks,
|
|
8646
8693
|
artifacts: Array.isArray(input.artifacts) ? input.artifacts.map((item) => String(item)).filter(Boolean) : ["screenshot", "console", "dom_summary", "proof_json"],
|
|
@@ -8813,6 +8860,48 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
8813
8860
|
message: "Unsupported check type."
|
|
8814
8861
|
};
|
|
8815
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
|
+
}
|
|
8816
8905
|
function profileStatusFromEvidence(evidence, checks) {
|
|
8817
8906
|
if (!evidence) return "proof_insufficient";
|
|
8818
8907
|
const viewports = evidence.viewports || [];
|
|
@@ -8824,7 +8913,10 @@ function profileStatusFromEvidence(evidence, checks) {
|
|
|
8824
8913
|
}
|
|
8825
8914
|
function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
|
|
8826
8915
|
const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
|
|
8827
|
-
const checks = evidence ?
|
|
8916
|
+
const checks = evidence ? [
|
|
8917
|
+
assessSetupActionsFromEvidence(profile, evidence),
|
|
8918
|
+
...profile.checks.map((check) => assessCheckFromEvidence(check, evidence))
|
|
8919
|
+
].filter((check) => Boolean(check)) : [];
|
|
8828
8920
|
const status = profileStatusFromEvidence(evidence, checks);
|
|
8829
8921
|
const firstViewport = evidence?.viewports?.[0];
|
|
8830
8922
|
const screenshots = (evidence?.viewports || []).map((viewport) => viewport.screenshot_label).filter((label) => Boolean(label));
|
|
@@ -8938,6 +9030,47 @@ function textMatches(sample, check) {
|
|
|
8938
9030
|
function assessProfile(profile, evidence) {
|
|
8939
9031
|
const checks = [];
|
|
8940
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
|
+
}
|
|
8941
9074
|
for (const check of profile.checks || []) {
|
|
8942
9075
|
if (check.type === "route_loaded") {
|
|
8943
9076
|
const expectedPath = check.expected_path || new URL(evidence.target_url).pathname || "/";
|
|
@@ -9100,6 +9233,92 @@ function textMatches(sample, check) {
|
|
|
9100
9233
|
}
|
|
9101
9234
|
return String(sample || "").includes(check.text || "");
|
|
9102
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
|
+
}
|
|
9103
9322
|
function expectedPathFor(check) {
|
|
9104
9323
|
return check.expected_path || new URL(targetUrl).pathname || "/";
|
|
9105
9324
|
}
|
|
@@ -9134,6 +9353,9 @@ async function captureViewport(viewport) {
|
|
|
9134
9353
|
if (!navigationError && profile.target.wait_ms) {
|
|
9135
9354
|
await page.waitForTimeout(profile.target.wait_ms);
|
|
9136
9355
|
}
|
|
9356
|
+
const setupActionResults = (!navigationError && !waitError)
|
|
9357
|
+
? await executeSetupActions(profile.target.setup_actions || [])
|
|
9358
|
+
: [];
|
|
9137
9359
|
const dom = await page.evaluate(() => {
|
|
9138
9360
|
const body = document.body;
|
|
9139
9361
|
const documentElement = document.documentElement;
|
|
@@ -9195,6 +9417,7 @@ async function captureViewport(viewport) {
|
|
|
9195
9417
|
overflow_px: Math.max(0, (dom.scroll_width || 0) - (dom.client_width || viewport.width)),
|
|
9196
9418
|
selectors,
|
|
9197
9419
|
text_matches,
|
|
9420
|
+
setup_action_results: setupActionResults,
|
|
9198
9421
|
screenshot_label: screenshotLabel,
|
|
9199
9422
|
navigation_error: navigationError,
|
|
9200
9423
|
wait_error: waitError,
|
|
@@ -9540,6 +9763,7 @@ function createRiddleApiClient(config = {}) {
|
|
|
9540
9763
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
9541
9764
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
9542
9765
|
RIDDLE_PROOF_PROFILE_RESULT_VERSION,
|
|
9766
|
+
RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES,
|
|
9543
9767
|
RIDDLE_PROOF_PROFILE_STATUSES,
|
|
9544
9768
|
RIDDLE_PROOF_PROFILE_VERSION,
|
|
9545
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
|
@@ -36,11 +36,12 @@ import {
|
|
|
36
36
|
extractBasicGameplayEvidence,
|
|
37
37
|
resolveBasicGameplayProgressionCheckWithArtifactScreenshots,
|
|
38
38
|
sanitizeBasicGameplayJsonString
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-5A4SL6CX.js";
|
|
40
40
|
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,
|