@riddledc/riddle-proof 0.7.90 → 0.7.92
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-4FMBHM4E.js → chunk-2SGLFPFX.js} +34 -5
- package/dist/{chunk-6RQGBHJ5.js → chunk-OI57LO6Y.js} +9 -2
- package/dist/cli.cjs +49 -9
- package/dist/cli.js +9 -4
- package/dist/index.cjs +44 -7
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -2
- package/dist/profile.cjs +34 -5
- package/dist/profile.js +1 -1
- package/dist/riddle-client.cjs +10 -2
- package/dist/riddle-client.d.cts +5 -1
- package/dist/riddle-client.d.ts +5 -1
- package/dist/riddle-client.js +3 -1
- package/package.json +1 -1
|
@@ -3097,6 +3097,10 @@ function textMatches(sample, check) {
|
|
|
3097
3097
|
}
|
|
3098
3098
|
return String(sample || "").includes(check.text || "");
|
|
3099
3099
|
}
|
|
3100
|
+
function profileCheckAppliesToViewport(check, viewport) {
|
|
3101
|
+
if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
|
|
3102
|
+
return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
|
|
3103
|
+
}
|
|
3100
3104
|
function setupActionType(action) {
|
|
3101
3105
|
return String(action && action.type ? action.type : "").replace(/-/g, "_");
|
|
3102
3106
|
}
|
|
@@ -3114,6 +3118,30 @@ function setupTextMatches(sample, action) {
|
|
|
3114
3118
|
}
|
|
3115
3119
|
return String(sample || "").includes(action.text || "");
|
|
3116
3120
|
}
|
|
3121
|
+
async function waitForAnyVisibleSelector(context, selector, timeout) {
|
|
3122
|
+
const deadline = Date.now() + setupNumber(timeout, 15000);
|
|
3123
|
+
let lastReason = "selector_not_found";
|
|
3124
|
+
while (Date.now() <= deadline) {
|
|
3125
|
+
try {
|
|
3126
|
+
const locator = context.locator(selector);
|
|
3127
|
+
const count = await locator.count();
|
|
3128
|
+
if (!count) {
|
|
3129
|
+
lastReason = "selector_not_found";
|
|
3130
|
+
} else {
|
|
3131
|
+
lastReason = "no_visible_match";
|
|
3132
|
+
for (let index = 0; index < count; index += 1) {
|
|
3133
|
+
if (await locator.nth(index).isVisible().catch(() => false)) {
|
|
3134
|
+
return { ok: true, count, index };
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
} catch (error) {
|
|
3139
|
+
lastReason = String(error && error.message ? error.message : error).slice(0, 500);
|
|
3140
|
+
}
|
|
3141
|
+
await page.waitForTimeout(200);
|
|
3142
|
+
}
|
|
3143
|
+
throw new Error("No visible match for selector " + selector + ": " + lastReason);
|
|
3144
|
+
}
|
|
3117
3145
|
function setupHasOwn(action, key) {
|
|
3118
3146
|
return Boolean(action) && Object.keys(action).includes(key);
|
|
3119
3147
|
}
|
|
@@ -3447,7 +3475,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
3447
3475
|
if (type === "wait_for_selector") {
|
|
3448
3476
|
const scope = await setupActionScope(action, timeout);
|
|
3449
3477
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
3450
|
-
await scope.context
|
|
3478
|
+
await waitForAnyVisibleSelector(scope.context, action.selector, timeout);
|
|
3451
3479
|
return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
|
|
3452
3480
|
}
|
|
3453
3481
|
if (type === "drag") {
|
|
@@ -4463,7 +4491,7 @@ async function collectRouteInventory(check, viewport) {
|
|
|
4463
4491
|
try {
|
|
4464
4492
|
await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 90000 });
|
|
4465
4493
|
if (profile.target.wait_for_selector) {
|
|
4466
|
-
await page
|
|
4494
|
+
await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000).catch(() => {});
|
|
4467
4495
|
}
|
|
4468
4496
|
const index = await findInventoryLinkIndex(check, expectedRoute.path);
|
|
4469
4497
|
if (index < 0) {
|
|
@@ -4522,7 +4550,7 @@ async function captureViewport(viewport) {
|
|
|
4522
4550
|
}
|
|
4523
4551
|
if (!navigationError && profile.target.wait_for_selector) {
|
|
4524
4552
|
try {
|
|
4525
|
-
await page
|
|
4553
|
+
await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000);
|
|
4526
4554
|
} catch (error) {
|
|
4527
4555
|
waitError = String(error && error.message ? error.message : error).slice(0, 1000);
|
|
4528
4556
|
}
|
|
@@ -4626,6 +4654,7 @@ async function captureViewport(viewport) {
|
|
|
4626
4654
|
const text_matches = {};
|
|
4627
4655
|
const link_statuses = {};
|
|
4628
4656
|
for (const check of profile.checks || []) {
|
|
4657
|
+
if (!profileCheckAppliesToViewport(check, viewport)) continue;
|
|
4629
4658
|
if (
|
|
4630
4659
|
(
|
|
4631
4660
|
check.type === "selector_visible"
|
|
@@ -4661,7 +4690,7 @@ async function captureViewport(viewport) {
|
|
|
4661
4690
|
pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
|
|
4662
4691
|
}
|
|
4663
4692
|
let routeInventory;
|
|
4664
|
-
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
|
|
4693
|
+
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory" && profileCheckAppliesToViewport(check, viewport));
|
|
4665
4694
|
const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
|
|
4666
4695
|
if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
|
|
4667
4696
|
try {
|
|
@@ -4766,7 +4795,7 @@ function buildProfileEvidence(currentViewports) {
|
|
|
4766
4795
|
})),
|
|
4767
4796
|
})),
|
|
4768
4797
|
link_status: currentViewports
|
|
4769
|
-
.filter((viewport) => viewport.link_statuses)
|
|
4798
|
+
.filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
|
|
4770
4799
|
.map((viewport) => ({
|
|
4771
4800
|
viewport: viewport.name,
|
|
4772
4801
|
selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
|
|
@@ -48,12 +48,13 @@ async function riddleRequestJson(config, pathname, init = {}) {
|
|
|
48
48
|
if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
|
|
49
49
|
return json ?? text;
|
|
50
50
|
}
|
|
51
|
-
async function
|
|
51
|
+
async function deployRiddlePreview(config, directory, label, framework = "static") {
|
|
52
52
|
if (!directory?.trim()) throw new Error("directory is required");
|
|
53
53
|
if (!label?.trim()) throw new Error("label is required");
|
|
54
|
+
if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
|
|
54
55
|
const created = await riddleRequestJson(config, "/v1/preview", {
|
|
55
56
|
method: "POST",
|
|
56
|
-
body: JSON.stringify({ framework
|
|
57
|
+
body: JSON.stringify({ framework, label })
|
|
57
58
|
});
|
|
58
59
|
const id = String(created.id || "");
|
|
59
60
|
const uploadUrl = String(created.upload_url || "");
|
|
@@ -80,6 +81,7 @@ async function deployRiddleStaticPreview(config, directory, label) {
|
|
|
80
81
|
ok: true,
|
|
81
82
|
id: String(published.id || id),
|
|
82
83
|
label,
|
|
84
|
+
framework,
|
|
83
85
|
preview_url: String(published.preview_url || ""),
|
|
84
86
|
file_count: typeof published.file_count === "number" ? published.file_count : void 0,
|
|
85
87
|
total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
|
|
@@ -87,6 +89,9 @@ async function deployRiddleStaticPreview(config, directory, label) {
|
|
|
87
89
|
raw: published
|
|
88
90
|
};
|
|
89
91
|
}
|
|
92
|
+
async function deployRiddleStaticPreview(config, directory, label) {
|
|
93
|
+
return deployRiddlePreview(config, directory, label, "static");
|
|
94
|
+
}
|
|
90
95
|
function createTarball(directory, label, exclude = []) {
|
|
91
96
|
const scratch = mkdtempSync(path.join(tmpdir(), "riddle-upload-"));
|
|
92
97
|
const tarball = path.join(scratch, `${label}.tar.gz`);
|
|
@@ -318,6 +323,7 @@ async function pollRiddleJob(config, jobId, options = {}) {
|
|
|
318
323
|
function createRiddleApiClient(config = {}) {
|
|
319
324
|
return {
|
|
320
325
|
requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
|
|
326
|
+
deployPreview: (directory, label, framework = "static") => deployRiddlePreview(config, directory, label, framework),
|
|
321
327
|
deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
|
|
322
328
|
runScript: (input) => runRiddleScript(config, input),
|
|
323
329
|
runServerPreview: (input) => runRiddleServerPreview(config, input),
|
|
@@ -331,6 +337,7 @@ export {
|
|
|
331
337
|
RiddleApiError,
|
|
332
338
|
resolveRiddleApiKey,
|
|
333
339
|
riddleRequestJson,
|
|
340
|
+
deployRiddlePreview,
|
|
334
341
|
deployRiddleStaticPreview,
|
|
335
342
|
parseRiddleViewport,
|
|
336
343
|
runRiddleServerPreview,
|
package/dist/cli.cjs
CHANGED
|
@@ -6609,12 +6609,13 @@ async function riddleRequestJson(config, pathname, init = {}) {
|
|
|
6609
6609
|
if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
|
|
6610
6610
|
return json ?? text;
|
|
6611
6611
|
}
|
|
6612
|
-
async function
|
|
6612
|
+
async function deployRiddlePreview(config, directory, label, framework = "static") {
|
|
6613
6613
|
if (!directory?.trim()) throw new Error("directory is required");
|
|
6614
6614
|
if (!label?.trim()) throw new Error("label is required");
|
|
6615
|
+
if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
|
|
6615
6616
|
const created = await riddleRequestJson(config, "/v1/preview", {
|
|
6616
6617
|
method: "POST",
|
|
6617
|
-
body: JSON.stringify({ framework
|
|
6618
|
+
body: JSON.stringify({ framework, label })
|
|
6618
6619
|
});
|
|
6619
6620
|
const id = String(created.id || "");
|
|
6620
6621
|
const uploadUrl = String(created.upload_url || "");
|
|
@@ -6641,6 +6642,7 @@ async function deployRiddleStaticPreview(config, directory, label) {
|
|
|
6641
6642
|
ok: true,
|
|
6642
6643
|
id: String(published.id || id),
|
|
6643
6644
|
label,
|
|
6645
|
+
framework,
|
|
6644
6646
|
preview_url: String(published.preview_url || ""),
|
|
6645
6647
|
file_count: typeof published.file_count === "number" ? published.file_count : void 0,
|
|
6646
6648
|
total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
|
|
@@ -6648,6 +6650,9 @@ async function deployRiddleStaticPreview(config, directory, label) {
|
|
|
6648
6650
|
raw: published
|
|
6649
6651
|
};
|
|
6650
6652
|
}
|
|
6653
|
+
async function deployRiddleStaticPreview(config, directory, label) {
|
|
6654
|
+
return deployRiddlePreview(config, directory, label, "static");
|
|
6655
|
+
}
|
|
6651
6656
|
function createTarball(directory, label, exclude = []) {
|
|
6652
6657
|
const scratch = (0, import_node_fs5.mkdtempSync)(import_node_path5.default.join((0, import_node_os2.tmpdir)(), "riddle-upload-"));
|
|
6653
6658
|
const tarball = import_node_path5.default.join(scratch, `${label}.tar.gz`);
|
|
@@ -6879,6 +6884,7 @@ async function pollRiddleJob(config, jobId, options = {}) {
|
|
|
6879
6884
|
function createRiddleApiClient(config = {}) {
|
|
6880
6885
|
return {
|
|
6881
6886
|
requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
|
|
6887
|
+
deployPreview: (directory, label, framework = "static") => deployRiddlePreview(config, directory, label, framework),
|
|
6882
6888
|
deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
|
|
6883
6889
|
runScript: (input) => runRiddleScript(config, input),
|
|
6884
6890
|
runServerPreview: (input) => runRiddleServerPreview(config, input),
|
|
@@ -9968,6 +9974,10 @@ function textMatches(sample, check) {
|
|
|
9968
9974
|
}
|
|
9969
9975
|
return String(sample || "").includes(check.text || "");
|
|
9970
9976
|
}
|
|
9977
|
+
function profileCheckAppliesToViewport(check, viewport) {
|
|
9978
|
+
if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
|
|
9979
|
+
return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
|
|
9980
|
+
}
|
|
9971
9981
|
function setupActionType(action) {
|
|
9972
9982
|
return String(action && action.type ? action.type : "").replace(/-/g, "_");
|
|
9973
9983
|
}
|
|
@@ -9985,6 +9995,30 @@ function setupTextMatches(sample, action) {
|
|
|
9985
9995
|
}
|
|
9986
9996
|
return String(sample || "").includes(action.text || "");
|
|
9987
9997
|
}
|
|
9998
|
+
async function waitForAnyVisibleSelector(context, selector, timeout) {
|
|
9999
|
+
const deadline = Date.now() + setupNumber(timeout, 15000);
|
|
10000
|
+
let lastReason = "selector_not_found";
|
|
10001
|
+
while (Date.now() <= deadline) {
|
|
10002
|
+
try {
|
|
10003
|
+
const locator = context.locator(selector);
|
|
10004
|
+
const count = await locator.count();
|
|
10005
|
+
if (!count) {
|
|
10006
|
+
lastReason = "selector_not_found";
|
|
10007
|
+
} else {
|
|
10008
|
+
lastReason = "no_visible_match";
|
|
10009
|
+
for (let index = 0; index < count; index += 1) {
|
|
10010
|
+
if (await locator.nth(index).isVisible().catch(() => false)) {
|
|
10011
|
+
return { ok: true, count, index };
|
|
10012
|
+
}
|
|
10013
|
+
}
|
|
10014
|
+
}
|
|
10015
|
+
} catch (error) {
|
|
10016
|
+
lastReason = String(error && error.message ? error.message : error).slice(0, 500);
|
|
10017
|
+
}
|
|
10018
|
+
await page.waitForTimeout(200);
|
|
10019
|
+
}
|
|
10020
|
+
throw new Error("No visible match for selector " + selector + ": " + lastReason);
|
|
10021
|
+
}
|
|
9988
10022
|
function setupHasOwn(action, key) {
|
|
9989
10023
|
return Boolean(action) && Object.keys(action).includes(key);
|
|
9990
10024
|
}
|
|
@@ -10318,7 +10352,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
10318
10352
|
if (type === "wait_for_selector") {
|
|
10319
10353
|
const scope = await setupActionScope(action, timeout);
|
|
10320
10354
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
10321
|
-
await scope.context
|
|
10355
|
+
await waitForAnyVisibleSelector(scope.context, action.selector, timeout);
|
|
10322
10356
|
return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
|
|
10323
10357
|
}
|
|
10324
10358
|
if (type === "drag") {
|
|
@@ -11334,7 +11368,7 @@ async function collectRouteInventory(check, viewport) {
|
|
|
11334
11368
|
try {
|
|
11335
11369
|
await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 90000 });
|
|
11336
11370
|
if (profile.target.wait_for_selector) {
|
|
11337
|
-
await page
|
|
11371
|
+
await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000).catch(() => {});
|
|
11338
11372
|
}
|
|
11339
11373
|
const index = await findInventoryLinkIndex(check, expectedRoute.path);
|
|
11340
11374
|
if (index < 0) {
|
|
@@ -11393,7 +11427,7 @@ async function captureViewport(viewport) {
|
|
|
11393
11427
|
}
|
|
11394
11428
|
if (!navigationError && profile.target.wait_for_selector) {
|
|
11395
11429
|
try {
|
|
11396
|
-
await page
|
|
11430
|
+
await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000);
|
|
11397
11431
|
} catch (error) {
|
|
11398
11432
|
waitError = String(error && error.message ? error.message : error).slice(0, 1000);
|
|
11399
11433
|
}
|
|
@@ -11497,6 +11531,7 @@ async function captureViewport(viewport) {
|
|
|
11497
11531
|
const text_matches = {};
|
|
11498
11532
|
const link_statuses = {};
|
|
11499
11533
|
for (const check of profile.checks || []) {
|
|
11534
|
+
if (!profileCheckAppliesToViewport(check, viewport)) continue;
|
|
11500
11535
|
if (
|
|
11501
11536
|
(
|
|
11502
11537
|
check.type === "selector_visible"
|
|
@@ -11532,7 +11567,7 @@ async function captureViewport(viewport) {
|
|
|
11532
11567
|
pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
|
|
11533
11568
|
}
|
|
11534
11569
|
let routeInventory;
|
|
11535
|
-
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
|
|
11570
|
+
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory" && profileCheckAppliesToViewport(check, viewport));
|
|
11536
11571
|
const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
|
|
11537
11572
|
if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
|
|
11538
11573
|
try {
|
|
@@ -11637,7 +11672,7 @@ function buildProfileEvidence(currentViewports) {
|
|
|
11637
11672
|
})),
|
|
11638
11673
|
})),
|
|
11639
11674
|
link_status: currentViewports
|
|
11640
|
-
.filter((viewport) => viewport.link_statuses)
|
|
11675
|
+
.filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
|
|
11641
11676
|
.map((viewport) => ({
|
|
11642
11677
|
viewport: viewport.name,
|
|
11643
11678
|
selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
|
|
@@ -11792,7 +11827,7 @@ function usage() {
|
|
|
11792
11827
|
" riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
|
|
11793
11828
|
" riddle-proof-loop status --state-path <path>",
|
|
11794
11829
|
" riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--quiet]",
|
|
11795
|
-
" riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
|
|
11830
|
+
" riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
|
|
11796
11831
|
" riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
|
|
11797
11832
|
" riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
|
|
11798
11833
|
" riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
|
|
@@ -11856,6 +11891,11 @@ function optionNumber(options, ...keys) {
|
|
|
11856
11891
|
function profileOutputDirOption(options) {
|
|
11857
11892
|
return optionString(options, "output") ?? optionString(options, "outputDir");
|
|
11858
11893
|
}
|
|
11894
|
+
function previewFrameworkOption(options) {
|
|
11895
|
+
const framework = optionString(options, "framework") ?? "static";
|
|
11896
|
+
if (framework === "spa" || framework === "static") return framework;
|
|
11897
|
+
throw new Error("--framework must be spa or static.");
|
|
11898
|
+
}
|
|
11859
11899
|
function readStdin() {
|
|
11860
11900
|
return (0, import_node_fs6.readFileSync)(0, "utf-8");
|
|
11861
11901
|
}
|
|
@@ -12568,7 +12608,7 @@ async function main() {
|
|
|
12568
12608
|
if (command === "riddle-preview-deploy") {
|
|
12569
12609
|
const buildDir = positional[1];
|
|
12570
12610
|
const label = positional[2];
|
|
12571
|
-
const result = await createRiddleApiClient(riddleClientConfig(options)).
|
|
12611
|
+
const result = await createRiddleApiClient(riddleClientConfig(options)).deployPreview(buildDir, label, previewFrameworkOption(options));
|
|
12572
12612
|
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
12573
12613
|
`);
|
|
12574
12614
|
return;
|
package/dist/cli.js
CHANGED
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
profileStatusExitCode,
|
|
11
11
|
resolveRiddleProofProfileTargetUrl,
|
|
12
12
|
resolveRiddleProofProfileTimeoutSec
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2SGLFPFX.js";
|
|
14
14
|
import {
|
|
15
15
|
createRiddleApiClient,
|
|
16
16
|
parseRiddleViewport
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-OI57LO6Y.js";
|
|
18
18
|
import {
|
|
19
19
|
createDisabledRiddleProofAgentAdapter,
|
|
20
20
|
readRiddleProofRunStatus,
|
|
@@ -45,7 +45,7 @@ function usage() {
|
|
|
45
45
|
" riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
|
|
46
46
|
" riddle-proof-loop status --state-path <path>",
|
|
47
47
|
" riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--quiet]",
|
|
48
|
-
" riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
|
|
48
|
+
" riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
|
|
49
49
|
" riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
|
|
50
50
|
" riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
|
|
51
51
|
" riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
|
|
@@ -109,6 +109,11 @@ function optionNumber(options, ...keys) {
|
|
|
109
109
|
function profileOutputDirOption(options) {
|
|
110
110
|
return optionString(options, "output") ?? optionString(options, "outputDir");
|
|
111
111
|
}
|
|
112
|
+
function previewFrameworkOption(options) {
|
|
113
|
+
const framework = optionString(options, "framework") ?? "static";
|
|
114
|
+
if (framework === "spa" || framework === "static") return framework;
|
|
115
|
+
throw new Error("--framework must be spa or static.");
|
|
116
|
+
}
|
|
112
117
|
function readStdin() {
|
|
113
118
|
return readFileSync(0, "utf-8");
|
|
114
119
|
}
|
|
@@ -821,7 +826,7 @@ async function main() {
|
|
|
821
826
|
if (command === "riddle-preview-deploy") {
|
|
822
827
|
const buildDir = positional[1];
|
|
823
828
|
const label = positional[2];
|
|
824
|
-
const result = await createRiddleApiClient(riddleClientConfig(options)).
|
|
829
|
+
const result = await createRiddleApiClient(riddleClientConfig(options)).deployPreview(buildDir, label, previewFrameworkOption(options));
|
|
825
830
|
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
826
831
|
`);
|
|
827
832
|
return;
|
package/dist/index.cjs
CHANGED
|
@@ -2968,6 +2968,7 @@ __export(index_exports, {
|
|
|
2968
2968
|
createRunResult: () => createRunResult,
|
|
2969
2969
|
createRunState: () => createRunState,
|
|
2970
2970
|
createRunStatusSnapshot: () => createRunStatusSnapshot,
|
|
2971
|
+
deployRiddlePreview: () => deployRiddlePreview,
|
|
2971
2972
|
deployRiddleStaticPreview: () => deployRiddleStaticPreview,
|
|
2972
2973
|
extractBasicGameplayEvidence: () => extractBasicGameplayEvidence,
|
|
2973
2974
|
extractPlayabilityEvidence: () => extractPlayabilityEvidence,
|
|
@@ -11825,6 +11826,10 @@ function textMatches(sample, check) {
|
|
|
11825
11826
|
}
|
|
11826
11827
|
return String(sample || "").includes(check.text || "");
|
|
11827
11828
|
}
|
|
11829
|
+
function profileCheckAppliesToViewport(check, viewport) {
|
|
11830
|
+
if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
|
|
11831
|
+
return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
|
|
11832
|
+
}
|
|
11828
11833
|
function setupActionType(action) {
|
|
11829
11834
|
return String(action && action.type ? action.type : "").replace(/-/g, "_");
|
|
11830
11835
|
}
|
|
@@ -11842,6 +11847,30 @@ function setupTextMatches(sample, action) {
|
|
|
11842
11847
|
}
|
|
11843
11848
|
return String(sample || "").includes(action.text || "");
|
|
11844
11849
|
}
|
|
11850
|
+
async function waitForAnyVisibleSelector(context, selector, timeout) {
|
|
11851
|
+
const deadline = Date.now() + setupNumber(timeout, 15000);
|
|
11852
|
+
let lastReason = "selector_not_found";
|
|
11853
|
+
while (Date.now() <= deadline) {
|
|
11854
|
+
try {
|
|
11855
|
+
const locator = context.locator(selector);
|
|
11856
|
+
const count = await locator.count();
|
|
11857
|
+
if (!count) {
|
|
11858
|
+
lastReason = "selector_not_found";
|
|
11859
|
+
} else {
|
|
11860
|
+
lastReason = "no_visible_match";
|
|
11861
|
+
for (let index = 0; index < count; index += 1) {
|
|
11862
|
+
if (await locator.nth(index).isVisible().catch(() => false)) {
|
|
11863
|
+
return { ok: true, count, index };
|
|
11864
|
+
}
|
|
11865
|
+
}
|
|
11866
|
+
}
|
|
11867
|
+
} catch (error) {
|
|
11868
|
+
lastReason = String(error && error.message ? error.message : error).slice(0, 500);
|
|
11869
|
+
}
|
|
11870
|
+
await page.waitForTimeout(200);
|
|
11871
|
+
}
|
|
11872
|
+
throw new Error("No visible match for selector " + selector + ": " + lastReason);
|
|
11873
|
+
}
|
|
11845
11874
|
function setupHasOwn(action, key) {
|
|
11846
11875
|
return Boolean(action) && Object.keys(action).includes(key);
|
|
11847
11876
|
}
|
|
@@ -12175,7 +12204,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
12175
12204
|
if (type === "wait_for_selector") {
|
|
12176
12205
|
const scope = await setupActionScope(action, timeout);
|
|
12177
12206
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
12178
|
-
await scope.context
|
|
12207
|
+
await waitForAnyVisibleSelector(scope.context, action.selector, timeout);
|
|
12179
12208
|
return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
|
|
12180
12209
|
}
|
|
12181
12210
|
if (type === "drag") {
|
|
@@ -13191,7 +13220,7 @@ async function collectRouteInventory(check, viewport) {
|
|
|
13191
13220
|
try {
|
|
13192
13221
|
await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 90000 });
|
|
13193
13222
|
if (profile.target.wait_for_selector) {
|
|
13194
|
-
await page
|
|
13223
|
+
await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000).catch(() => {});
|
|
13195
13224
|
}
|
|
13196
13225
|
const index = await findInventoryLinkIndex(check, expectedRoute.path);
|
|
13197
13226
|
if (index < 0) {
|
|
@@ -13250,7 +13279,7 @@ async function captureViewport(viewport) {
|
|
|
13250
13279
|
}
|
|
13251
13280
|
if (!navigationError && profile.target.wait_for_selector) {
|
|
13252
13281
|
try {
|
|
13253
|
-
await page
|
|
13282
|
+
await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000);
|
|
13254
13283
|
} catch (error) {
|
|
13255
13284
|
waitError = String(error && error.message ? error.message : error).slice(0, 1000);
|
|
13256
13285
|
}
|
|
@@ -13354,6 +13383,7 @@ async function captureViewport(viewport) {
|
|
|
13354
13383
|
const text_matches = {};
|
|
13355
13384
|
const link_statuses = {};
|
|
13356
13385
|
for (const check of profile.checks || []) {
|
|
13386
|
+
if (!profileCheckAppliesToViewport(check, viewport)) continue;
|
|
13357
13387
|
if (
|
|
13358
13388
|
(
|
|
13359
13389
|
check.type === "selector_visible"
|
|
@@ -13389,7 +13419,7 @@ async function captureViewport(viewport) {
|
|
|
13389
13419
|
pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
|
|
13390
13420
|
}
|
|
13391
13421
|
let routeInventory;
|
|
13392
|
-
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
|
|
13422
|
+
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory" && profileCheckAppliesToViewport(check, viewport));
|
|
13393
13423
|
const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
|
|
13394
13424
|
if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
|
|
13395
13425
|
try {
|
|
@@ -13494,7 +13524,7 @@ function buildProfileEvidence(currentViewports) {
|
|
|
13494
13524
|
})),
|
|
13495
13525
|
})),
|
|
13496
13526
|
link_status: currentViewports
|
|
13497
|
-
.filter((viewport) => viewport.link_statuses)
|
|
13527
|
+
.filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
|
|
13498
13528
|
.map((viewport) => ({
|
|
13499
13529
|
viewport: viewport.name,
|
|
13500
13530
|
selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
|
|
@@ -13689,12 +13719,13 @@ async function riddleRequestJson(config, pathname, init = {}) {
|
|
|
13689
13719
|
if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
|
|
13690
13720
|
return json ?? text;
|
|
13691
13721
|
}
|
|
13692
|
-
async function
|
|
13722
|
+
async function deployRiddlePreview(config, directory, label, framework = "static") {
|
|
13693
13723
|
if (!directory?.trim()) throw new Error("directory is required");
|
|
13694
13724
|
if (!label?.trim()) throw new Error("label is required");
|
|
13725
|
+
if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
|
|
13695
13726
|
const created = await riddleRequestJson(config, "/v1/preview", {
|
|
13696
13727
|
method: "POST",
|
|
13697
|
-
body: JSON.stringify({ framework
|
|
13728
|
+
body: JSON.stringify({ framework, label })
|
|
13698
13729
|
});
|
|
13699
13730
|
const id = String(created.id || "");
|
|
13700
13731
|
const uploadUrl = String(created.upload_url || "");
|
|
@@ -13721,6 +13752,7 @@ async function deployRiddleStaticPreview(config, directory, label) {
|
|
|
13721
13752
|
ok: true,
|
|
13722
13753
|
id: String(published.id || id),
|
|
13723
13754
|
label,
|
|
13755
|
+
framework,
|
|
13724
13756
|
preview_url: String(published.preview_url || ""),
|
|
13725
13757
|
file_count: typeof published.file_count === "number" ? published.file_count : void 0,
|
|
13726
13758
|
total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
|
|
@@ -13728,6 +13760,9 @@ async function deployRiddleStaticPreview(config, directory, label) {
|
|
|
13728
13760
|
raw: published
|
|
13729
13761
|
};
|
|
13730
13762
|
}
|
|
13763
|
+
async function deployRiddleStaticPreview(config, directory, label) {
|
|
13764
|
+
return deployRiddlePreview(config, directory, label, "static");
|
|
13765
|
+
}
|
|
13731
13766
|
function createTarball(directory, label, exclude = []) {
|
|
13732
13767
|
const scratch = (0, import_node_fs5.mkdtempSync)(import_node_path5.default.join((0, import_node_os2.tmpdir)(), "riddle-upload-"));
|
|
13733
13768
|
const tarball = import_node_path5.default.join(scratch, `${label}.tar.gz`);
|
|
@@ -13959,6 +13994,7 @@ async function pollRiddleJob(config, jobId, options = {}) {
|
|
|
13959
13994
|
function createRiddleApiClient(config = {}) {
|
|
13960
13995
|
return {
|
|
13961
13996
|
requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
|
|
13997
|
+
deployPreview: (directory, label, framework = "static") => deployRiddlePreview(config, directory, label, framework),
|
|
13962
13998
|
deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
|
|
13963
13999
|
runScript: (input) => runRiddleScript(config, input),
|
|
13964
14000
|
runServerPreview: (input) => runRiddleServerPreview(config, input),
|
|
@@ -14036,6 +14072,7 @@ function createRiddleApiClient(config = {}) {
|
|
|
14036
14072
|
createRunResult,
|
|
14037
14073
|
createRunState,
|
|
14038
14074
|
createRunStatusSnapshot,
|
|
14075
|
+
deployRiddlePreview,
|
|
14039
14076
|
deployRiddleStaticPreview,
|
|
14040
14077
|
extractBasicGameplayEvidence,
|
|
14041
14078
|
extractPlayabilityEvidence,
|
package/dist/index.d.cts
CHANGED
|
@@ -11,4 +11,4 @@ export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_V
|
|
|
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, BasicGameplayBoundsOffender, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayResponsiveViewportEvidence, 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
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, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
|
|
14
|
-
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
|
|
14
|
+
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -11,4 +11,4 @@ export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_V
|
|
|
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, BasicGameplayBoundsOffender, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayResponsiveViewportEvidence, 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
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, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
|
|
14
|
-
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
|
|
14
|
+
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
|
package/dist/index.js
CHANGED
|
@@ -58,12 +58,13 @@ import {
|
|
|
58
58
|
resolveRiddleProofProfileTimeoutSec,
|
|
59
59
|
slugifyRiddleProofProfileName,
|
|
60
60
|
summarizeRiddleProofProfileResult
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-2SGLFPFX.js";
|
|
62
62
|
import {
|
|
63
63
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
64
64
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
|
65
65
|
RiddleApiError,
|
|
66
66
|
createRiddleApiClient,
|
|
67
|
+
deployRiddlePreview,
|
|
67
68
|
deployRiddleStaticPreview,
|
|
68
69
|
isTerminalRiddleJobStatus,
|
|
69
70
|
parseRiddleViewport,
|
|
@@ -72,7 +73,7 @@ import {
|
|
|
72
73
|
riddleRequestJson,
|
|
73
74
|
runRiddleScript,
|
|
74
75
|
runRiddleServerPreview
|
|
75
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-OI57LO6Y.js";
|
|
76
77
|
import {
|
|
77
78
|
DEFAULT_DIAGNOSTIC_ARRAY_LIMIT,
|
|
78
79
|
DEFAULT_DIAGNOSTIC_HISTORY_LIMIT,
|
|
@@ -207,6 +208,7 @@ export {
|
|
|
207
208
|
createRunResult,
|
|
208
209
|
createRunState,
|
|
209
210
|
createRunStatusSnapshot,
|
|
211
|
+
deployRiddlePreview,
|
|
210
212
|
deployRiddleStaticPreview,
|
|
211
213
|
extractBasicGameplayEvidence,
|
|
212
214
|
extractPlayabilityEvidence,
|
package/dist/profile.cjs
CHANGED
|
@@ -3140,6 +3140,10 @@ function textMatches(sample, check) {
|
|
|
3140
3140
|
}
|
|
3141
3141
|
return String(sample || "").includes(check.text || "");
|
|
3142
3142
|
}
|
|
3143
|
+
function profileCheckAppliesToViewport(check, viewport) {
|
|
3144
|
+
if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
|
|
3145
|
+
return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
|
|
3146
|
+
}
|
|
3143
3147
|
function setupActionType(action) {
|
|
3144
3148
|
return String(action && action.type ? action.type : "").replace(/-/g, "_");
|
|
3145
3149
|
}
|
|
@@ -3157,6 +3161,30 @@ function setupTextMatches(sample, action) {
|
|
|
3157
3161
|
}
|
|
3158
3162
|
return String(sample || "").includes(action.text || "");
|
|
3159
3163
|
}
|
|
3164
|
+
async function waitForAnyVisibleSelector(context, selector, timeout) {
|
|
3165
|
+
const deadline = Date.now() + setupNumber(timeout, 15000);
|
|
3166
|
+
let lastReason = "selector_not_found";
|
|
3167
|
+
while (Date.now() <= deadline) {
|
|
3168
|
+
try {
|
|
3169
|
+
const locator = context.locator(selector);
|
|
3170
|
+
const count = await locator.count();
|
|
3171
|
+
if (!count) {
|
|
3172
|
+
lastReason = "selector_not_found";
|
|
3173
|
+
} else {
|
|
3174
|
+
lastReason = "no_visible_match";
|
|
3175
|
+
for (let index = 0; index < count; index += 1) {
|
|
3176
|
+
if (await locator.nth(index).isVisible().catch(() => false)) {
|
|
3177
|
+
return { ok: true, count, index };
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
} catch (error) {
|
|
3182
|
+
lastReason = String(error && error.message ? error.message : error).slice(0, 500);
|
|
3183
|
+
}
|
|
3184
|
+
await page.waitForTimeout(200);
|
|
3185
|
+
}
|
|
3186
|
+
throw new Error("No visible match for selector " + selector + ": " + lastReason);
|
|
3187
|
+
}
|
|
3160
3188
|
function setupHasOwn(action, key) {
|
|
3161
3189
|
return Boolean(action) && Object.keys(action).includes(key);
|
|
3162
3190
|
}
|
|
@@ -3490,7 +3518,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
3490
3518
|
if (type === "wait_for_selector") {
|
|
3491
3519
|
const scope = await setupActionScope(action, timeout);
|
|
3492
3520
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
3493
|
-
await scope.context
|
|
3521
|
+
await waitForAnyVisibleSelector(scope.context, action.selector, timeout);
|
|
3494
3522
|
return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
|
|
3495
3523
|
}
|
|
3496
3524
|
if (type === "drag") {
|
|
@@ -4506,7 +4534,7 @@ async function collectRouteInventory(check, viewport) {
|
|
|
4506
4534
|
try {
|
|
4507
4535
|
await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 90000 });
|
|
4508
4536
|
if (profile.target.wait_for_selector) {
|
|
4509
|
-
await page
|
|
4537
|
+
await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000).catch(() => {});
|
|
4510
4538
|
}
|
|
4511
4539
|
const index = await findInventoryLinkIndex(check, expectedRoute.path);
|
|
4512
4540
|
if (index < 0) {
|
|
@@ -4565,7 +4593,7 @@ async function captureViewport(viewport) {
|
|
|
4565
4593
|
}
|
|
4566
4594
|
if (!navigationError && profile.target.wait_for_selector) {
|
|
4567
4595
|
try {
|
|
4568
|
-
await page
|
|
4596
|
+
await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000);
|
|
4569
4597
|
} catch (error) {
|
|
4570
4598
|
waitError = String(error && error.message ? error.message : error).slice(0, 1000);
|
|
4571
4599
|
}
|
|
@@ -4669,6 +4697,7 @@ async function captureViewport(viewport) {
|
|
|
4669
4697
|
const text_matches = {};
|
|
4670
4698
|
const link_statuses = {};
|
|
4671
4699
|
for (const check of profile.checks || []) {
|
|
4700
|
+
if (!profileCheckAppliesToViewport(check, viewport)) continue;
|
|
4672
4701
|
if (
|
|
4673
4702
|
(
|
|
4674
4703
|
check.type === "selector_visible"
|
|
@@ -4704,7 +4733,7 @@ async function captureViewport(viewport) {
|
|
|
4704
4733
|
pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
|
|
4705
4734
|
}
|
|
4706
4735
|
let routeInventory;
|
|
4707
|
-
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
|
|
4736
|
+
const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory" && profileCheckAppliesToViewport(check, viewport));
|
|
4708
4737
|
const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
|
|
4709
4738
|
if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
|
|
4710
4739
|
try {
|
|
@@ -4809,7 +4838,7 @@ function buildProfileEvidence(currentViewports) {
|
|
|
4809
4838
|
})),
|
|
4810
4839
|
})),
|
|
4811
4840
|
link_status: currentViewports
|
|
4812
|
-
.filter((viewport) => viewport.link_statuses)
|
|
4841
|
+
.filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
|
|
4813
4842
|
.map((viewport) => ({
|
|
4814
4843
|
viewport: viewport.name,
|
|
4815
4844
|
selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
|
package/dist/profile.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
resolveRiddleProofProfileTimeoutSec,
|
|
20
20
|
slugifyRiddleProofProfileName,
|
|
21
21
|
summarizeRiddleProofProfileResult
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2SGLFPFX.js";
|
|
23
23
|
export {
|
|
24
24
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
25
25
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
package/dist/riddle-client.cjs
CHANGED
|
@@ -34,6 +34,7 @@ __export(riddle_client_exports, {
|
|
|
34
34
|
DEFAULT_RIDDLE_API_KEY_FILE: () => DEFAULT_RIDDLE_API_KEY_FILE,
|
|
35
35
|
RiddleApiError: () => RiddleApiError,
|
|
36
36
|
createRiddleApiClient: () => createRiddleApiClient,
|
|
37
|
+
deployRiddlePreview: () => deployRiddlePreview,
|
|
37
38
|
deployRiddleStaticPreview: () => deployRiddleStaticPreview,
|
|
38
39
|
isTerminalRiddleJobStatus: () => isTerminalRiddleJobStatus,
|
|
39
40
|
parseRiddleViewport: () => parseRiddleViewport,
|
|
@@ -93,12 +94,13 @@ async function riddleRequestJson(config, pathname, init = {}) {
|
|
|
93
94
|
if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
|
|
94
95
|
return json ?? text;
|
|
95
96
|
}
|
|
96
|
-
async function
|
|
97
|
+
async function deployRiddlePreview(config, directory, label, framework = "static") {
|
|
97
98
|
if (!directory?.trim()) throw new Error("directory is required");
|
|
98
99
|
if (!label?.trim()) throw new Error("label is required");
|
|
100
|
+
if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
|
|
99
101
|
const created = await riddleRequestJson(config, "/v1/preview", {
|
|
100
102
|
method: "POST",
|
|
101
|
-
body: JSON.stringify({ framework
|
|
103
|
+
body: JSON.stringify({ framework, label })
|
|
102
104
|
});
|
|
103
105
|
const id = String(created.id || "");
|
|
104
106
|
const uploadUrl = String(created.upload_url || "");
|
|
@@ -125,6 +127,7 @@ async function deployRiddleStaticPreview(config, directory, label) {
|
|
|
125
127
|
ok: true,
|
|
126
128
|
id: String(published.id || id),
|
|
127
129
|
label,
|
|
130
|
+
framework,
|
|
128
131
|
preview_url: String(published.preview_url || ""),
|
|
129
132
|
file_count: typeof published.file_count === "number" ? published.file_count : void 0,
|
|
130
133
|
total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
|
|
@@ -132,6 +135,9 @@ async function deployRiddleStaticPreview(config, directory, label) {
|
|
|
132
135
|
raw: published
|
|
133
136
|
};
|
|
134
137
|
}
|
|
138
|
+
async function deployRiddleStaticPreview(config, directory, label) {
|
|
139
|
+
return deployRiddlePreview(config, directory, label, "static");
|
|
140
|
+
}
|
|
135
141
|
function createTarball(directory, label, exclude = []) {
|
|
136
142
|
const scratch = (0, import_node_fs.mkdtempSync)(import_node_path.default.join((0, import_node_os.tmpdir)(), "riddle-upload-"));
|
|
137
143
|
const tarball = import_node_path.default.join(scratch, `${label}.tar.gz`);
|
|
@@ -363,6 +369,7 @@ async function pollRiddleJob(config, jobId, options = {}) {
|
|
|
363
369
|
function createRiddleApiClient(config = {}) {
|
|
364
370
|
return {
|
|
365
371
|
requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
|
|
372
|
+
deployPreview: (directory, label, framework = "static") => deployRiddlePreview(config, directory, label, framework),
|
|
366
373
|
deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
|
|
367
374
|
runScript: (input) => runRiddleScript(config, input),
|
|
368
375
|
runServerPreview: (input) => runRiddleServerPreview(config, input),
|
|
@@ -375,6 +382,7 @@ function createRiddleApiClient(config = {}) {
|
|
|
375
382
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
|
376
383
|
RiddleApiError,
|
|
377
384
|
createRiddleApiClient,
|
|
385
|
+
deployRiddlePreview,
|
|
378
386
|
deployRiddleStaticPreview,
|
|
379
387
|
isTerminalRiddleJobStatus,
|
|
380
388
|
parseRiddleViewport,
|
package/dist/riddle-client.d.cts
CHANGED
|
@@ -32,10 +32,12 @@ interface RiddlePollJobOptions {
|
|
|
32
32
|
progressEveryMs?: number;
|
|
33
33
|
onProgress?: (snapshot: RiddlePollProgressSnapshot) => void | Promise<void>;
|
|
34
34
|
}
|
|
35
|
+
type RiddlePreviewFramework = "spa" | "static";
|
|
35
36
|
interface RiddlePreviewDeployResult {
|
|
36
37
|
ok: true;
|
|
37
38
|
id: string;
|
|
38
39
|
label: string;
|
|
40
|
+
framework: RiddlePreviewFramework;
|
|
39
41
|
preview_url: string;
|
|
40
42
|
file_count?: number;
|
|
41
43
|
total_bytes?: number;
|
|
@@ -101,6 +103,7 @@ declare class RiddleApiError extends Error {
|
|
|
101
103
|
}
|
|
102
104
|
declare function resolveRiddleApiKey(config?: RiddleClientConfig): string;
|
|
103
105
|
declare function riddleRequestJson<T = unknown>(config: RiddleClientConfig, pathname: string, init?: RequestInit): Promise<T>;
|
|
106
|
+
declare function deployRiddlePreview(config: RiddleClientConfig, directory: string, label: string, framework?: RiddlePreviewFramework): Promise<RiddlePreviewDeployResult>;
|
|
104
107
|
declare function deployRiddleStaticPreview(config: RiddleClientConfig, directory: string, label: string): Promise<RiddlePreviewDeployResult>;
|
|
105
108
|
declare function parseRiddleViewport(value?: string): {
|
|
106
109
|
width: number;
|
|
@@ -112,10 +115,11 @@ declare function isTerminalRiddleJobStatus(status: unknown): boolean;
|
|
|
112
115
|
declare function pollRiddleJob(config: RiddleClientConfig, jobId: string, options?: RiddlePollJobOptions): Promise<RiddlePollJobResult>;
|
|
113
116
|
declare function createRiddleApiClient(config?: RiddleClientConfig): {
|
|
114
117
|
requestJson: <T = unknown>(pathname: string, init?: RequestInit) => Promise<T>;
|
|
118
|
+
deployPreview: (directory: string, label: string, framework?: RiddlePreviewFramework) => Promise<RiddlePreviewDeployResult>;
|
|
115
119
|
deployStaticPreview: (directory: string, label: string) => Promise<RiddlePreviewDeployResult>;
|
|
116
120
|
runScript: (input: RiddleRunScriptInput) => Promise<Record<string, unknown>>;
|
|
117
121
|
runServerPreview: (input: RiddleServerPreviewInput) => Promise<RiddleServerPreviewResult>;
|
|
118
122
|
pollJob: (jobId: string, options?: RiddlePollJobOptions) => Promise<RiddlePollJobResult>;
|
|
119
123
|
};
|
|
120
124
|
|
|
121
|
-
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
|
|
125
|
+
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddlePreviewFramework, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
|
package/dist/riddle-client.d.ts
CHANGED
|
@@ -32,10 +32,12 @@ interface RiddlePollJobOptions {
|
|
|
32
32
|
progressEveryMs?: number;
|
|
33
33
|
onProgress?: (snapshot: RiddlePollProgressSnapshot) => void | Promise<void>;
|
|
34
34
|
}
|
|
35
|
+
type RiddlePreviewFramework = "spa" | "static";
|
|
35
36
|
interface RiddlePreviewDeployResult {
|
|
36
37
|
ok: true;
|
|
37
38
|
id: string;
|
|
38
39
|
label: string;
|
|
40
|
+
framework: RiddlePreviewFramework;
|
|
39
41
|
preview_url: string;
|
|
40
42
|
file_count?: number;
|
|
41
43
|
total_bytes?: number;
|
|
@@ -101,6 +103,7 @@ declare class RiddleApiError extends Error {
|
|
|
101
103
|
}
|
|
102
104
|
declare function resolveRiddleApiKey(config?: RiddleClientConfig): string;
|
|
103
105
|
declare function riddleRequestJson<T = unknown>(config: RiddleClientConfig, pathname: string, init?: RequestInit): Promise<T>;
|
|
106
|
+
declare function deployRiddlePreview(config: RiddleClientConfig, directory: string, label: string, framework?: RiddlePreviewFramework): Promise<RiddlePreviewDeployResult>;
|
|
104
107
|
declare function deployRiddleStaticPreview(config: RiddleClientConfig, directory: string, label: string): Promise<RiddlePreviewDeployResult>;
|
|
105
108
|
declare function parseRiddleViewport(value?: string): {
|
|
106
109
|
width: number;
|
|
@@ -112,10 +115,11 @@ declare function isTerminalRiddleJobStatus(status: unknown): boolean;
|
|
|
112
115
|
declare function pollRiddleJob(config: RiddleClientConfig, jobId: string, options?: RiddlePollJobOptions): Promise<RiddlePollJobResult>;
|
|
113
116
|
declare function createRiddleApiClient(config?: RiddleClientConfig): {
|
|
114
117
|
requestJson: <T = unknown>(pathname: string, init?: RequestInit) => Promise<T>;
|
|
118
|
+
deployPreview: (directory: string, label: string, framework?: RiddlePreviewFramework) => Promise<RiddlePreviewDeployResult>;
|
|
115
119
|
deployStaticPreview: (directory: string, label: string) => Promise<RiddlePreviewDeployResult>;
|
|
116
120
|
runScript: (input: RiddleRunScriptInput) => Promise<Record<string, unknown>>;
|
|
117
121
|
runServerPreview: (input: RiddleServerPreviewInput) => Promise<RiddleServerPreviewResult>;
|
|
118
122
|
pollJob: (jobId: string, options?: RiddlePollJobOptions) => Promise<RiddlePollJobResult>;
|
|
119
123
|
};
|
|
120
124
|
|
|
121
|
-
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
|
|
125
|
+
export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddlePreviewFramework, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
|
package/dist/riddle-client.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
|
4
4
|
RiddleApiError,
|
|
5
5
|
createRiddleApiClient,
|
|
6
|
+
deployRiddlePreview,
|
|
6
7
|
deployRiddleStaticPreview,
|
|
7
8
|
isTerminalRiddleJobStatus,
|
|
8
9
|
parseRiddleViewport,
|
|
@@ -11,12 +12,13 @@ import {
|
|
|
11
12
|
riddleRequestJson,
|
|
12
13
|
runRiddleScript,
|
|
13
14
|
runRiddleServerPreview
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-OI57LO6Y.js";
|
|
15
16
|
export {
|
|
16
17
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
17
18
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
|
18
19
|
RiddleApiError,
|
|
19
20
|
createRiddleApiClient,
|
|
21
|
+
deployRiddlePreview,
|
|
20
22
|
deployRiddleStaticPreview,
|
|
21
23
|
isTerminalRiddleJobStatus,
|
|
22
24
|
parseRiddleViewport,
|