@riddledc/riddle-proof 0.7.48 → 0.7.50
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-V2KNQTQD.js → chunk-5FHHNCX4.js} +107 -2
- package/dist/cli.cjs +107 -2
- package/dist/cli.js +1 -1
- package/dist/index.cjs +107 -2
- package/dist/index.js +1 -1
- package/dist/profile.cjs +107 -2
- package/dist/profile.d.cts +5 -1
- package/dist/profile.d.ts +5 -1
- package/dist/profile.js +1 -1
- package/dist/proof-run-engine.d.cts +3 -3
- package/dist/proof-run-engine.d.ts +3 -3
- package/package.json +1 -1
|
@@ -40,7 +40,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
40
40
|
"clear_storage",
|
|
41
41
|
"wait",
|
|
42
42
|
"wait_for_selector",
|
|
43
|
-
"wait_for_text"
|
|
43
|
+
"wait_for_text",
|
|
44
|
+
"window_call"
|
|
44
45
|
];
|
|
45
46
|
var DEFAULT_VIEWPORTS = [
|
|
46
47
|
{ name: "desktop", width: 1280, height: 800 }
|
|
@@ -63,6 +64,12 @@ function stringFromOwn(input, ...keys) {
|
|
|
63
64
|
}
|
|
64
65
|
return void 0;
|
|
65
66
|
}
|
|
67
|
+
function valueFromOwn(input, ...keys) {
|
|
68
|
+
for (const key of keys) {
|
|
69
|
+
if (hasOwn(input, key)) return input[key];
|
|
70
|
+
}
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
66
73
|
function numberValue(value) {
|
|
67
74
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
68
75
|
}
|
|
@@ -204,6 +211,14 @@ function normalizeSetupActionStorage(value, index) {
|
|
|
204
211
|
if (normalized === "both" || normalized === "all") return "both";
|
|
205
212
|
throw new Error(`target.setup_actions[${index}].storage ${String(value)} is not supported. Supported storage values: local, session, both.`);
|
|
206
213
|
}
|
|
214
|
+
function normalizeSetupActionArgs(input, index) {
|
|
215
|
+
const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
|
|
216
|
+
if (argsInput === void 0) return void 0;
|
|
217
|
+
if (!Array.isArray(argsInput)) {
|
|
218
|
+
throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
|
|
219
|
+
}
|
|
220
|
+
return argsInput.map(toJsonValue);
|
|
221
|
+
}
|
|
207
222
|
function normalizeSetupAction(input, index) {
|
|
208
223
|
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
209
224
|
const type = normalizeSetupActionType(stringValue(input.type), index);
|
|
@@ -233,12 +248,21 @@ function normalizeSetupAction(input, index) {
|
|
|
233
248
|
if ((type === "local_storage" || type === "session_storage") && value === void 0 && !hasJsonValue) {
|
|
234
249
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
235
250
|
}
|
|
251
|
+
const path = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath");
|
|
252
|
+
if (type === "window_call" && !path) {
|
|
253
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
|
|
254
|
+
}
|
|
255
|
+
const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
256
|
+
const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
|
|
236
257
|
return {
|
|
237
258
|
type,
|
|
238
259
|
selector,
|
|
239
260
|
key,
|
|
240
261
|
value,
|
|
241
262
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
263
|
+
path,
|
|
264
|
+
args,
|
|
265
|
+
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
242
266
|
text: stringValue(input.text),
|
|
243
267
|
pattern: stringValue(input.pattern),
|
|
244
268
|
flags: stringValue(input.flags),
|
|
@@ -329,6 +353,7 @@ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
|
|
|
329
353
|
headers: stringRecord(input.headers) || defaults.headers,
|
|
330
354
|
body,
|
|
331
355
|
body_json: hasJsonBody ? toJsonValue(input.body_json ?? input.bodyJson ?? input.json) : defaults.body_json,
|
|
356
|
+
delay_ms: normalizeNetworkMockDelay(input, label, defaults.delay_ms),
|
|
332
357
|
capture_request_body: requestBody.capture_request_body,
|
|
333
358
|
request_body_contains: requestBody.request_body_contains,
|
|
334
359
|
request_body_patterns: requestBody.request_body_patterns,
|
|
@@ -336,6 +361,16 @@ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
|
|
|
336
361
|
request_body_not_patterns: requestBody.request_body_not_patterns
|
|
337
362
|
};
|
|
338
363
|
}
|
|
364
|
+
function normalizeNetworkMockDelay(input, label, defaultValue) {
|
|
365
|
+
const value = numberValue(
|
|
366
|
+
input.delay_ms ?? input.delayMs ?? input.wait_ms ?? input.waitMs ?? input.latency_ms ?? input.latencyMs
|
|
367
|
+
) ?? defaultValue;
|
|
368
|
+
if (value === void 0) return void 0;
|
|
369
|
+
if (!Number.isInteger(value) || value < 0 || value > 6e4) {
|
|
370
|
+
throw new Error(`${label}.delay_ms must be an integer from 0 to 60000.`);
|
|
371
|
+
}
|
|
372
|
+
return value;
|
|
373
|
+
}
|
|
339
374
|
function normalizeNetworkMockResponses(value, mockIndex, defaults) {
|
|
340
375
|
if (value === void 0) return void 0;
|
|
341
376
|
if (!Array.isArray(value)) throw new Error(`target.network_mocks[${mockIndex}].responses must be an array.`);
|
|
@@ -346,7 +381,8 @@ function normalizeNetworkMockResponses(value, mockIndex, defaults) {
|
|
|
346
381
|
content_type: defaults.content_type,
|
|
347
382
|
headers: defaults.headers,
|
|
348
383
|
body: defaults.body,
|
|
349
|
-
body_json: defaults.body_json
|
|
384
|
+
body_json: defaults.body_json,
|
|
385
|
+
delay_ms: defaults.delay_ms
|
|
350
386
|
};
|
|
351
387
|
return value.map((response, responseIndex) => {
|
|
352
388
|
if (!isRecord(response)) {
|
|
@@ -1927,6 +1963,19 @@ function setupActionValue(action) {
|
|
|
1927
1963
|
if (setupHasOwn(action, "value")) return String(action.value ?? "");
|
|
1928
1964
|
return "";
|
|
1929
1965
|
}
|
|
1966
|
+
function setupJsonValue(value) {
|
|
1967
|
+
if (value === null || value === undefined) return null;
|
|
1968
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
1969
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
1970
|
+
if (Array.isArray(value)) return value.map(setupJsonValue);
|
|
1971
|
+
if (typeof value === "object") {
|
|
1972
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, setupJsonValue(child)]));
|
|
1973
|
+
}
|
|
1974
|
+
return String(value);
|
|
1975
|
+
}
|
|
1976
|
+
function setupValuesEqual(left, right) {
|
|
1977
|
+
return JSON.stringify(setupJsonValue(left)) === JSON.stringify(setupJsonValue(right));
|
|
1978
|
+
}
|
|
1930
1979
|
async function setupLocatorText(locator, index) {
|
|
1931
1980
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
1932
1981
|
}
|
|
@@ -2045,6 +2094,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
2045
2094
|
const requestBody = shouldCaptureRequestBody && request.postData ? request.postData() || "" : "";
|
|
2046
2095
|
const requestBodyFailures = shouldCaptureRequestBody ? networkMockRequestBodyFailures(requestBody, mock, responseBodyContract) : [];
|
|
2047
2096
|
const status = response.status || mock.status || 200;
|
|
2097
|
+
const delayMs = numberValue(response.delay_ms) || 0;
|
|
2048
2098
|
const event = {
|
|
2049
2099
|
ok: true,
|
|
2050
2100
|
label: mock.label,
|
|
@@ -2057,6 +2107,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
2057
2107
|
method,
|
|
2058
2108
|
status,
|
|
2059
2109
|
};
|
|
2110
|
+
if (delayMs) event.delay_ms = delayMs;
|
|
2060
2111
|
if (shouldCaptureRequestBody) {
|
|
2061
2112
|
event.request_body_matches = requestBodyFailures.length === 0;
|
|
2062
2113
|
event.request_body_failures = requestBodyFailures;
|
|
@@ -2064,6 +2115,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
2064
2115
|
event.request_body_sample = compactNetworkMockRequestBody(requestBody);
|
|
2065
2116
|
}
|
|
2066
2117
|
networkMockEvents.push(event);
|
|
2118
|
+
if (delayMs) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2067
2119
|
await route.fulfill({
|
|
2068
2120
|
status,
|
|
2069
2121
|
headers,
|
|
@@ -2119,6 +2171,59 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2119
2171
|
}
|
|
2120
2172
|
return { ...base, ok: true, storage, reload: action.reload === true };
|
|
2121
2173
|
}
|
|
2174
|
+
if (type === "window_call") {
|
|
2175
|
+
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
2176
|
+
const args = Array.isArray(action.args) ? action.args : [];
|
|
2177
|
+
if (!path) return { ...base, path, reason: "missing_path" };
|
|
2178
|
+
const result = await page.evaluate(async ({ path, args }) => {
|
|
2179
|
+
const toJsonValue = (value) => {
|
|
2180
|
+
if (value === null || value === undefined) return null;
|
|
2181
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
2182
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
2183
|
+
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
2184
|
+
if (typeof value === "object") {
|
|
2185
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
2186
|
+
}
|
|
2187
|
+
return String(value);
|
|
2188
|
+
};
|
|
2189
|
+
const pathParts = String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
2190
|
+
let parent = window;
|
|
2191
|
+
let current = window;
|
|
2192
|
+
for (const part of pathParts) {
|
|
2193
|
+
parent = current;
|
|
2194
|
+
current = current?.[part];
|
|
2195
|
+
}
|
|
2196
|
+
if (typeof current !== "function") return { ok: false, reason: "missing_function" };
|
|
2197
|
+
try {
|
|
2198
|
+
const returned = await current.apply(parent, Array.isArray(args) ? args : []);
|
|
2199
|
+
return { ok: true, returned: toJsonValue(returned) };
|
|
2200
|
+
} catch (error) {
|
|
2201
|
+
return { ok: false, reason: "function_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
2202
|
+
}
|
|
2203
|
+
}, { path, args });
|
|
2204
|
+
const hasExpectation = setupHasOwn(action, "expect_return")
|
|
2205
|
+
|| setupHasOwn(action, "expectReturn")
|
|
2206
|
+
|| setupHasOwn(action, "expected_return")
|
|
2207
|
+
|| setupHasOwn(action, "expectedReturn");
|
|
2208
|
+
const expected = setupHasOwn(action, "expect_return")
|
|
2209
|
+
? action.expect_return
|
|
2210
|
+
: setupHasOwn(action, "expectReturn")
|
|
2211
|
+
? action.expectReturn
|
|
2212
|
+
: setupHasOwn(action, "expected_return")
|
|
2213
|
+
? action.expected_return
|
|
2214
|
+
: action.expectedReturn;
|
|
2215
|
+
const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
|
|
2216
|
+
return {
|
|
2217
|
+
...base,
|
|
2218
|
+
ok: Boolean(result.ok && expectationMet),
|
|
2219
|
+
path,
|
|
2220
|
+
arg_count: args.length,
|
|
2221
|
+
returned: setupJsonValue(result.returned),
|
|
2222
|
+
expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
|
|
2223
|
+
reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
|
|
2224
|
+
error: result.error || undefined,
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2122
2227
|
if (type === "click") {
|
|
2123
2228
|
const locator = page.locator(action.selector);
|
|
2124
2229
|
const count = await locator.count();
|
package/dist/cli.cjs
CHANGED
|
@@ -6913,7 +6913,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
6913
6913
|
"clear_storage",
|
|
6914
6914
|
"wait",
|
|
6915
6915
|
"wait_for_selector",
|
|
6916
|
-
"wait_for_text"
|
|
6916
|
+
"wait_for_text",
|
|
6917
|
+
"window_call"
|
|
6917
6918
|
];
|
|
6918
6919
|
var DEFAULT_VIEWPORTS = [
|
|
6919
6920
|
{ name: "desktop", width: 1280, height: 800 }
|
|
@@ -6936,6 +6937,12 @@ function stringFromOwn(input, ...keys) {
|
|
|
6936
6937
|
}
|
|
6937
6938
|
return void 0;
|
|
6938
6939
|
}
|
|
6940
|
+
function valueFromOwn(input, ...keys) {
|
|
6941
|
+
for (const key of keys) {
|
|
6942
|
+
if (hasOwn(input, key)) return input[key];
|
|
6943
|
+
}
|
|
6944
|
+
return void 0;
|
|
6945
|
+
}
|
|
6939
6946
|
function numberValue(value) {
|
|
6940
6947
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
6941
6948
|
}
|
|
@@ -7077,6 +7084,14 @@ function normalizeSetupActionStorage(value, index) {
|
|
|
7077
7084
|
if (normalized === "both" || normalized === "all") return "both";
|
|
7078
7085
|
throw new Error(`target.setup_actions[${index}].storage ${String(value)} is not supported. Supported storage values: local, session, both.`);
|
|
7079
7086
|
}
|
|
7087
|
+
function normalizeSetupActionArgs(input, index) {
|
|
7088
|
+
const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
|
|
7089
|
+
if (argsInput === void 0) return void 0;
|
|
7090
|
+
if (!Array.isArray(argsInput)) {
|
|
7091
|
+
throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
|
|
7092
|
+
}
|
|
7093
|
+
return argsInput.map(toJsonValue);
|
|
7094
|
+
}
|
|
7080
7095
|
function normalizeSetupAction(input, index) {
|
|
7081
7096
|
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
7082
7097
|
const type = normalizeSetupActionType(stringValue2(input.type), index);
|
|
@@ -7106,12 +7121,21 @@ function normalizeSetupAction(input, index) {
|
|
|
7106
7121
|
if ((type === "local_storage" || type === "session_storage") && value === void 0 && !hasJsonValue) {
|
|
7107
7122
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
7108
7123
|
}
|
|
7124
|
+
const path7 = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath");
|
|
7125
|
+
if (type === "window_call" && !path7) {
|
|
7126
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
|
|
7127
|
+
}
|
|
7128
|
+
const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
7129
|
+
const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
|
|
7109
7130
|
return {
|
|
7110
7131
|
type,
|
|
7111
7132
|
selector,
|
|
7112
7133
|
key,
|
|
7113
7134
|
value,
|
|
7114
7135
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
7136
|
+
path: path7,
|
|
7137
|
+
args,
|
|
7138
|
+
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
7115
7139
|
text: stringValue2(input.text),
|
|
7116
7140
|
pattern: stringValue2(input.pattern),
|
|
7117
7141
|
flags: stringValue2(input.flags),
|
|
@@ -7202,6 +7226,7 @@ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
|
|
|
7202
7226
|
headers: stringRecord(input.headers) || defaults.headers,
|
|
7203
7227
|
body,
|
|
7204
7228
|
body_json: hasJsonBody ? toJsonValue(input.body_json ?? input.bodyJson ?? input.json) : defaults.body_json,
|
|
7229
|
+
delay_ms: normalizeNetworkMockDelay(input, label, defaults.delay_ms),
|
|
7205
7230
|
capture_request_body: requestBody.capture_request_body,
|
|
7206
7231
|
request_body_contains: requestBody.request_body_contains,
|
|
7207
7232
|
request_body_patterns: requestBody.request_body_patterns,
|
|
@@ -7209,6 +7234,16 @@ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
|
|
|
7209
7234
|
request_body_not_patterns: requestBody.request_body_not_patterns
|
|
7210
7235
|
};
|
|
7211
7236
|
}
|
|
7237
|
+
function normalizeNetworkMockDelay(input, label, defaultValue) {
|
|
7238
|
+
const value = numberValue(
|
|
7239
|
+
input.delay_ms ?? input.delayMs ?? input.wait_ms ?? input.waitMs ?? input.latency_ms ?? input.latencyMs
|
|
7240
|
+
) ?? defaultValue;
|
|
7241
|
+
if (value === void 0) return void 0;
|
|
7242
|
+
if (!Number.isInteger(value) || value < 0 || value > 6e4) {
|
|
7243
|
+
throw new Error(`${label}.delay_ms must be an integer from 0 to 60000.`);
|
|
7244
|
+
}
|
|
7245
|
+
return value;
|
|
7246
|
+
}
|
|
7212
7247
|
function normalizeNetworkMockResponses(value, mockIndex, defaults) {
|
|
7213
7248
|
if (value === void 0) return void 0;
|
|
7214
7249
|
if (!Array.isArray(value)) throw new Error(`target.network_mocks[${mockIndex}].responses must be an array.`);
|
|
@@ -7219,7 +7254,8 @@ function normalizeNetworkMockResponses(value, mockIndex, defaults) {
|
|
|
7219
7254
|
content_type: defaults.content_type,
|
|
7220
7255
|
headers: defaults.headers,
|
|
7221
7256
|
body: defaults.body,
|
|
7222
|
-
body_json: defaults.body_json
|
|
7257
|
+
body_json: defaults.body_json,
|
|
7258
|
+
delay_ms: defaults.delay_ms
|
|
7223
7259
|
};
|
|
7224
7260
|
return value.map((response, responseIndex) => {
|
|
7225
7261
|
if (!isRecord(response)) {
|
|
@@ -8784,6 +8820,19 @@ function setupActionValue(action) {
|
|
|
8784
8820
|
if (setupHasOwn(action, "value")) return String(action.value ?? "");
|
|
8785
8821
|
return "";
|
|
8786
8822
|
}
|
|
8823
|
+
function setupJsonValue(value) {
|
|
8824
|
+
if (value === null || value === undefined) return null;
|
|
8825
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
8826
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
8827
|
+
if (Array.isArray(value)) return value.map(setupJsonValue);
|
|
8828
|
+
if (typeof value === "object") {
|
|
8829
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, setupJsonValue(child)]));
|
|
8830
|
+
}
|
|
8831
|
+
return String(value);
|
|
8832
|
+
}
|
|
8833
|
+
function setupValuesEqual(left, right) {
|
|
8834
|
+
return JSON.stringify(setupJsonValue(left)) === JSON.stringify(setupJsonValue(right));
|
|
8835
|
+
}
|
|
8787
8836
|
async function setupLocatorText(locator, index) {
|
|
8788
8837
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
8789
8838
|
}
|
|
@@ -8902,6 +8951,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
8902
8951
|
const requestBody = shouldCaptureRequestBody && request.postData ? request.postData() || "" : "";
|
|
8903
8952
|
const requestBodyFailures = shouldCaptureRequestBody ? networkMockRequestBodyFailures(requestBody, mock, responseBodyContract) : [];
|
|
8904
8953
|
const status = response.status || mock.status || 200;
|
|
8954
|
+
const delayMs = numberValue(response.delay_ms) || 0;
|
|
8905
8955
|
const event = {
|
|
8906
8956
|
ok: true,
|
|
8907
8957
|
label: mock.label,
|
|
@@ -8914,6 +8964,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
8914
8964
|
method,
|
|
8915
8965
|
status,
|
|
8916
8966
|
};
|
|
8967
|
+
if (delayMs) event.delay_ms = delayMs;
|
|
8917
8968
|
if (shouldCaptureRequestBody) {
|
|
8918
8969
|
event.request_body_matches = requestBodyFailures.length === 0;
|
|
8919
8970
|
event.request_body_failures = requestBodyFailures;
|
|
@@ -8921,6 +8972,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
8921
8972
|
event.request_body_sample = compactNetworkMockRequestBody(requestBody);
|
|
8922
8973
|
}
|
|
8923
8974
|
networkMockEvents.push(event);
|
|
8975
|
+
if (delayMs) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
8924
8976
|
await route.fulfill({
|
|
8925
8977
|
status,
|
|
8926
8978
|
headers,
|
|
@@ -8976,6 +9028,59 @@ async function executeSetupAction(action, ordinal) {
|
|
|
8976
9028
|
}
|
|
8977
9029
|
return { ...base, ok: true, storage, reload: action.reload === true };
|
|
8978
9030
|
}
|
|
9031
|
+
if (type === "window_call") {
|
|
9032
|
+
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
9033
|
+
const args = Array.isArray(action.args) ? action.args : [];
|
|
9034
|
+
if (!path) return { ...base, path, reason: "missing_path" };
|
|
9035
|
+
const result = await page.evaluate(async ({ path, args }) => {
|
|
9036
|
+
const toJsonValue = (value) => {
|
|
9037
|
+
if (value === null || value === undefined) return null;
|
|
9038
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
9039
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
9040
|
+
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
9041
|
+
if (typeof value === "object") {
|
|
9042
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
9043
|
+
}
|
|
9044
|
+
return String(value);
|
|
9045
|
+
};
|
|
9046
|
+
const pathParts = String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
9047
|
+
let parent = window;
|
|
9048
|
+
let current = window;
|
|
9049
|
+
for (const part of pathParts) {
|
|
9050
|
+
parent = current;
|
|
9051
|
+
current = current?.[part];
|
|
9052
|
+
}
|
|
9053
|
+
if (typeof current !== "function") return { ok: false, reason: "missing_function" };
|
|
9054
|
+
try {
|
|
9055
|
+
const returned = await current.apply(parent, Array.isArray(args) ? args : []);
|
|
9056
|
+
return { ok: true, returned: toJsonValue(returned) };
|
|
9057
|
+
} catch (error) {
|
|
9058
|
+
return { ok: false, reason: "function_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
9059
|
+
}
|
|
9060
|
+
}, { path, args });
|
|
9061
|
+
const hasExpectation = setupHasOwn(action, "expect_return")
|
|
9062
|
+
|| setupHasOwn(action, "expectReturn")
|
|
9063
|
+
|| setupHasOwn(action, "expected_return")
|
|
9064
|
+
|| setupHasOwn(action, "expectedReturn");
|
|
9065
|
+
const expected = setupHasOwn(action, "expect_return")
|
|
9066
|
+
? action.expect_return
|
|
9067
|
+
: setupHasOwn(action, "expectReturn")
|
|
9068
|
+
? action.expectReturn
|
|
9069
|
+
: setupHasOwn(action, "expected_return")
|
|
9070
|
+
? action.expected_return
|
|
9071
|
+
: action.expectedReturn;
|
|
9072
|
+
const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
|
|
9073
|
+
return {
|
|
9074
|
+
...base,
|
|
9075
|
+
ok: Boolean(result.ok && expectationMet),
|
|
9076
|
+
path,
|
|
9077
|
+
arg_count: args.length,
|
|
9078
|
+
returned: setupJsonValue(result.returned),
|
|
9079
|
+
expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
|
|
9080
|
+
reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
|
|
9081
|
+
error: result.error || undefined,
|
|
9082
|
+
};
|
|
9083
|
+
}
|
|
8979
9084
|
if (type === "click") {
|
|
8980
9085
|
const locator = page.locator(action.selector);
|
|
8981
9086
|
const count = await locator.count();
|
package/dist/cli.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -8754,7 +8754,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
8754
8754
|
"clear_storage",
|
|
8755
8755
|
"wait",
|
|
8756
8756
|
"wait_for_selector",
|
|
8757
|
-
"wait_for_text"
|
|
8757
|
+
"wait_for_text",
|
|
8758
|
+
"window_call"
|
|
8758
8759
|
];
|
|
8759
8760
|
var DEFAULT_VIEWPORTS = [
|
|
8760
8761
|
{ name: "desktop", width: 1280, height: 800 }
|
|
@@ -8777,6 +8778,12 @@ function stringFromOwn(input, ...keys) {
|
|
|
8777
8778
|
}
|
|
8778
8779
|
return void 0;
|
|
8779
8780
|
}
|
|
8781
|
+
function valueFromOwn(input, ...keys) {
|
|
8782
|
+
for (const key of keys) {
|
|
8783
|
+
if (hasOwn(input, key)) return input[key];
|
|
8784
|
+
}
|
|
8785
|
+
return void 0;
|
|
8786
|
+
}
|
|
8780
8787
|
function numberValue3(value) {
|
|
8781
8788
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8782
8789
|
}
|
|
@@ -8918,6 +8925,14 @@ function normalizeSetupActionStorage(value, index) {
|
|
|
8918
8925
|
if (normalized === "both" || normalized === "all") return "both";
|
|
8919
8926
|
throw new Error(`target.setup_actions[${index}].storage ${String(value)} is not supported. Supported storage values: local, session, both.`);
|
|
8920
8927
|
}
|
|
8928
|
+
function normalizeSetupActionArgs(input, index) {
|
|
8929
|
+
const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
|
|
8930
|
+
if (argsInput === void 0) return void 0;
|
|
8931
|
+
if (!Array.isArray(argsInput)) {
|
|
8932
|
+
throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
|
|
8933
|
+
}
|
|
8934
|
+
return argsInput.map(toJsonValue);
|
|
8935
|
+
}
|
|
8921
8936
|
function normalizeSetupAction(input, index) {
|
|
8922
8937
|
if (!isRecord2(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
8923
8938
|
const type = normalizeSetupActionType(stringValue5(input.type), index);
|
|
@@ -8947,12 +8962,21 @@ function normalizeSetupAction(input, index) {
|
|
|
8947
8962
|
if ((type === "local_storage" || type === "session_storage") && value === void 0 && !hasJsonValue) {
|
|
8948
8963
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
8949
8964
|
}
|
|
8965
|
+
const path6 = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath");
|
|
8966
|
+
if (type === "window_call" && !path6) {
|
|
8967
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
|
|
8968
|
+
}
|
|
8969
|
+
const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
8970
|
+
const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
|
|
8950
8971
|
return {
|
|
8951
8972
|
type,
|
|
8952
8973
|
selector,
|
|
8953
8974
|
key,
|
|
8954
8975
|
value,
|
|
8955
8976
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
8977
|
+
path: path6,
|
|
8978
|
+
args,
|
|
8979
|
+
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
8956
8980
|
text: stringValue5(input.text),
|
|
8957
8981
|
pattern: stringValue5(input.pattern),
|
|
8958
8982
|
flags: stringValue5(input.flags),
|
|
@@ -9043,6 +9067,7 @@ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
|
|
|
9043
9067
|
headers: stringRecord(input.headers) || defaults.headers,
|
|
9044
9068
|
body,
|
|
9045
9069
|
body_json: hasJsonBody ? toJsonValue(input.body_json ?? input.bodyJson ?? input.json) : defaults.body_json,
|
|
9070
|
+
delay_ms: normalizeNetworkMockDelay(input, label, defaults.delay_ms),
|
|
9046
9071
|
capture_request_body: requestBody.capture_request_body,
|
|
9047
9072
|
request_body_contains: requestBody.request_body_contains,
|
|
9048
9073
|
request_body_patterns: requestBody.request_body_patterns,
|
|
@@ -9050,6 +9075,16 @@ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
|
|
|
9050
9075
|
request_body_not_patterns: requestBody.request_body_not_patterns
|
|
9051
9076
|
};
|
|
9052
9077
|
}
|
|
9078
|
+
function normalizeNetworkMockDelay(input, label, defaultValue) {
|
|
9079
|
+
const value = numberValue3(
|
|
9080
|
+
input.delay_ms ?? input.delayMs ?? input.wait_ms ?? input.waitMs ?? input.latency_ms ?? input.latencyMs
|
|
9081
|
+
) ?? defaultValue;
|
|
9082
|
+
if (value === void 0) return void 0;
|
|
9083
|
+
if (!Number.isInteger(value) || value < 0 || value > 6e4) {
|
|
9084
|
+
throw new Error(`${label}.delay_ms must be an integer from 0 to 60000.`);
|
|
9085
|
+
}
|
|
9086
|
+
return value;
|
|
9087
|
+
}
|
|
9053
9088
|
function normalizeNetworkMockResponses(value, mockIndex, defaults) {
|
|
9054
9089
|
if (value === void 0) return void 0;
|
|
9055
9090
|
if (!Array.isArray(value)) throw new Error(`target.network_mocks[${mockIndex}].responses must be an array.`);
|
|
@@ -9060,7 +9095,8 @@ function normalizeNetworkMockResponses(value, mockIndex, defaults) {
|
|
|
9060
9095
|
content_type: defaults.content_type,
|
|
9061
9096
|
headers: defaults.headers,
|
|
9062
9097
|
body: defaults.body,
|
|
9063
|
-
body_json: defaults.body_json
|
|
9098
|
+
body_json: defaults.body_json,
|
|
9099
|
+
delay_ms: defaults.delay_ms
|
|
9064
9100
|
};
|
|
9065
9101
|
return value.map((response, responseIndex) => {
|
|
9066
9102
|
if (!isRecord2(response)) {
|
|
@@ -10641,6 +10677,19 @@ function setupActionValue(action) {
|
|
|
10641
10677
|
if (setupHasOwn(action, "value")) return String(action.value ?? "");
|
|
10642
10678
|
return "";
|
|
10643
10679
|
}
|
|
10680
|
+
function setupJsonValue(value) {
|
|
10681
|
+
if (value === null || value === undefined) return null;
|
|
10682
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
10683
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
10684
|
+
if (Array.isArray(value)) return value.map(setupJsonValue);
|
|
10685
|
+
if (typeof value === "object") {
|
|
10686
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, setupJsonValue(child)]));
|
|
10687
|
+
}
|
|
10688
|
+
return String(value);
|
|
10689
|
+
}
|
|
10690
|
+
function setupValuesEqual(left, right) {
|
|
10691
|
+
return JSON.stringify(setupJsonValue(left)) === JSON.stringify(setupJsonValue(right));
|
|
10692
|
+
}
|
|
10644
10693
|
async function setupLocatorText(locator, index) {
|
|
10645
10694
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
10646
10695
|
}
|
|
@@ -10759,6 +10808,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
10759
10808
|
const requestBody = shouldCaptureRequestBody && request.postData ? request.postData() || "" : "";
|
|
10760
10809
|
const requestBodyFailures = shouldCaptureRequestBody ? networkMockRequestBodyFailures(requestBody, mock, responseBodyContract) : [];
|
|
10761
10810
|
const status = response.status || mock.status || 200;
|
|
10811
|
+
const delayMs = numberValue(response.delay_ms) || 0;
|
|
10762
10812
|
const event = {
|
|
10763
10813
|
ok: true,
|
|
10764
10814
|
label: mock.label,
|
|
@@ -10771,6 +10821,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
10771
10821
|
method,
|
|
10772
10822
|
status,
|
|
10773
10823
|
};
|
|
10824
|
+
if (delayMs) event.delay_ms = delayMs;
|
|
10774
10825
|
if (shouldCaptureRequestBody) {
|
|
10775
10826
|
event.request_body_matches = requestBodyFailures.length === 0;
|
|
10776
10827
|
event.request_body_failures = requestBodyFailures;
|
|
@@ -10778,6 +10829,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
10778
10829
|
event.request_body_sample = compactNetworkMockRequestBody(requestBody);
|
|
10779
10830
|
}
|
|
10780
10831
|
networkMockEvents.push(event);
|
|
10832
|
+
if (delayMs) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
10781
10833
|
await route.fulfill({
|
|
10782
10834
|
status,
|
|
10783
10835
|
headers,
|
|
@@ -10833,6 +10885,59 @@ async function executeSetupAction(action, ordinal) {
|
|
|
10833
10885
|
}
|
|
10834
10886
|
return { ...base, ok: true, storage, reload: action.reload === true };
|
|
10835
10887
|
}
|
|
10888
|
+
if (type === "window_call") {
|
|
10889
|
+
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
10890
|
+
const args = Array.isArray(action.args) ? action.args : [];
|
|
10891
|
+
if (!path) return { ...base, path, reason: "missing_path" };
|
|
10892
|
+
const result = await page.evaluate(async ({ path, args }) => {
|
|
10893
|
+
const toJsonValue = (value) => {
|
|
10894
|
+
if (value === null || value === undefined) return null;
|
|
10895
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
10896
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
10897
|
+
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
10898
|
+
if (typeof value === "object") {
|
|
10899
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
10900
|
+
}
|
|
10901
|
+
return String(value);
|
|
10902
|
+
};
|
|
10903
|
+
const pathParts = String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
10904
|
+
let parent = window;
|
|
10905
|
+
let current = window;
|
|
10906
|
+
for (const part of pathParts) {
|
|
10907
|
+
parent = current;
|
|
10908
|
+
current = current?.[part];
|
|
10909
|
+
}
|
|
10910
|
+
if (typeof current !== "function") return { ok: false, reason: "missing_function" };
|
|
10911
|
+
try {
|
|
10912
|
+
const returned = await current.apply(parent, Array.isArray(args) ? args : []);
|
|
10913
|
+
return { ok: true, returned: toJsonValue(returned) };
|
|
10914
|
+
} catch (error) {
|
|
10915
|
+
return { ok: false, reason: "function_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
10916
|
+
}
|
|
10917
|
+
}, { path, args });
|
|
10918
|
+
const hasExpectation = setupHasOwn(action, "expect_return")
|
|
10919
|
+
|| setupHasOwn(action, "expectReturn")
|
|
10920
|
+
|| setupHasOwn(action, "expected_return")
|
|
10921
|
+
|| setupHasOwn(action, "expectedReturn");
|
|
10922
|
+
const expected = setupHasOwn(action, "expect_return")
|
|
10923
|
+
? action.expect_return
|
|
10924
|
+
: setupHasOwn(action, "expectReturn")
|
|
10925
|
+
? action.expectReturn
|
|
10926
|
+
: setupHasOwn(action, "expected_return")
|
|
10927
|
+
? action.expected_return
|
|
10928
|
+
: action.expectedReturn;
|
|
10929
|
+
const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
|
|
10930
|
+
return {
|
|
10931
|
+
...base,
|
|
10932
|
+
ok: Boolean(result.ok && expectationMet),
|
|
10933
|
+
path,
|
|
10934
|
+
arg_count: args.length,
|
|
10935
|
+
returned: setupJsonValue(result.returned),
|
|
10936
|
+
expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
|
|
10937
|
+
reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
|
|
10938
|
+
error: result.error || undefined,
|
|
10939
|
+
};
|
|
10940
|
+
}
|
|
10836
10941
|
if (type === "click") {
|
|
10837
10942
|
const locator = page.locator(action.selector);
|
|
10838
10943
|
const count = await locator.count();
|
package/dist/index.js
CHANGED
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
resolveRiddleProofProfileTimeoutSec,
|
|
59
59
|
slugifyRiddleProofProfileName,
|
|
60
60
|
summarizeRiddleProofProfileResult
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-5FHHNCX4.js";
|
|
62
62
|
import {
|
|
63
63
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
64
64
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
package/dist/profile.cjs
CHANGED
|
@@ -83,7 +83,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
|
83
83
|
"clear_storage",
|
|
84
84
|
"wait",
|
|
85
85
|
"wait_for_selector",
|
|
86
|
-
"wait_for_text"
|
|
86
|
+
"wait_for_text",
|
|
87
|
+
"window_call"
|
|
87
88
|
];
|
|
88
89
|
var DEFAULT_VIEWPORTS = [
|
|
89
90
|
{ name: "desktop", width: 1280, height: 800 }
|
|
@@ -106,6 +107,12 @@ function stringFromOwn(input, ...keys) {
|
|
|
106
107
|
}
|
|
107
108
|
return void 0;
|
|
108
109
|
}
|
|
110
|
+
function valueFromOwn(input, ...keys) {
|
|
111
|
+
for (const key of keys) {
|
|
112
|
+
if (hasOwn(input, key)) return input[key];
|
|
113
|
+
}
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
109
116
|
function numberValue(value) {
|
|
110
117
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
111
118
|
}
|
|
@@ -247,6 +254,14 @@ function normalizeSetupActionStorage(value, index) {
|
|
|
247
254
|
if (normalized === "both" || normalized === "all") return "both";
|
|
248
255
|
throw new Error(`target.setup_actions[${index}].storage ${String(value)} is not supported. Supported storage values: local, session, both.`);
|
|
249
256
|
}
|
|
257
|
+
function normalizeSetupActionArgs(input, index) {
|
|
258
|
+
const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
|
|
259
|
+
if (argsInput === void 0) return void 0;
|
|
260
|
+
if (!Array.isArray(argsInput)) {
|
|
261
|
+
throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
|
|
262
|
+
}
|
|
263
|
+
return argsInput.map(toJsonValue);
|
|
264
|
+
}
|
|
250
265
|
function normalizeSetupAction(input, index) {
|
|
251
266
|
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
252
267
|
const type = normalizeSetupActionType(stringValue(input.type), index);
|
|
@@ -276,12 +291,21 @@ function normalizeSetupAction(input, index) {
|
|
|
276
291
|
if ((type === "local_storage" || type === "session_storage") && value === void 0 && !hasJsonValue) {
|
|
277
292
|
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
278
293
|
}
|
|
294
|
+
const path = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath");
|
|
295
|
+
if (type === "window_call" && !path) {
|
|
296
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
|
|
297
|
+
}
|
|
298
|
+
const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
|
|
299
|
+
const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
|
|
279
300
|
return {
|
|
280
301
|
type,
|
|
281
302
|
selector,
|
|
282
303
|
key,
|
|
283
304
|
value,
|
|
284
305
|
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
306
|
+
path,
|
|
307
|
+
args,
|
|
308
|
+
expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
|
|
285
309
|
text: stringValue(input.text),
|
|
286
310
|
pattern: stringValue(input.pattern),
|
|
287
311
|
flags: stringValue(input.flags),
|
|
@@ -372,6 +396,7 @@ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
|
|
|
372
396
|
headers: stringRecord(input.headers) || defaults.headers,
|
|
373
397
|
body,
|
|
374
398
|
body_json: hasJsonBody ? toJsonValue(input.body_json ?? input.bodyJson ?? input.json) : defaults.body_json,
|
|
399
|
+
delay_ms: normalizeNetworkMockDelay(input, label, defaults.delay_ms),
|
|
375
400
|
capture_request_body: requestBody.capture_request_body,
|
|
376
401
|
request_body_contains: requestBody.request_body_contains,
|
|
377
402
|
request_body_patterns: requestBody.request_body_patterns,
|
|
@@ -379,6 +404,16 @@ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
|
|
|
379
404
|
request_body_not_patterns: requestBody.request_body_not_patterns
|
|
380
405
|
};
|
|
381
406
|
}
|
|
407
|
+
function normalizeNetworkMockDelay(input, label, defaultValue) {
|
|
408
|
+
const value = numberValue(
|
|
409
|
+
input.delay_ms ?? input.delayMs ?? input.wait_ms ?? input.waitMs ?? input.latency_ms ?? input.latencyMs
|
|
410
|
+
) ?? defaultValue;
|
|
411
|
+
if (value === void 0) return void 0;
|
|
412
|
+
if (!Number.isInteger(value) || value < 0 || value > 6e4) {
|
|
413
|
+
throw new Error(`${label}.delay_ms must be an integer from 0 to 60000.`);
|
|
414
|
+
}
|
|
415
|
+
return value;
|
|
416
|
+
}
|
|
382
417
|
function normalizeNetworkMockResponses(value, mockIndex, defaults) {
|
|
383
418
|
if (value === void 0) return void 0;
|
|
384
419
|
if (!Array.isArray(value)) throw new Error(`target.network_mocks[${mockIndex}].responses must be an array.`);
|
|
@@ -389,7 +424,8 @@ function normalizeNetworkMockResponses(value, mockIndex, defaults) {
|
|
|
389
424
|
content_type: defaults.content_type,
|
|
390
425
|
headers: defaults.headers,
|
|
391
426
|
body: defaults.body,
|
|
392
|
-
body_json: defaults.body_json
|
|
427
|
+
body_json: defaults.body_json,
|
|
428
|
+
delay_ms: defaults.delay_ms
|
|
393
429
|
};
|
|
394
430
|
return value.map((response, responseIndex) => {
|
|
395
431
|
if (!isRecord(response)) {
|
|
@@ -1970,6 +2006,19 @@ function setupActionValue(action) {
|
|
|
1970
2006
|
if (setupHasOwn(action, "value")) return String(action.value ?? "");
|
|
1971
2007
|
return "";
|
|
1972
2008
|
}
|
|
2009
|
+
function setupJsonValue(value) {
|
|
2010
|
+
if (value === null || value === undefined) return null;
|
|
2011
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
2012
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
2013
|
+
if (Array.isArray(value)) return value.map(setupJsonValue);
|
|
2014
|
+
if (typeof value === "object") {
|
|
2015
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, setupJsonValue(child)]));
|
|
2016
|
+
}
|
|
2017
|
+
return String(value);
|
|
2018
|
+
}
|
|
2019
|
+
function setupValuesEqual(left, right) {
|
|
2020
|
+
return JSON.stringify(setupJsonValue(left)) === JSON.stringify(setupJsonValue(right));
|
|
2021
|
+
}
|
|
1973
2022
|
async function setupLocatorText(locator, index) {
|
|
1974
2023
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
1975
2024
|
}
|
|
@@ -2088,6 +2137,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
2088
2137
|
const requestBody = shouldCaptureRequestBody && request.postData ? request.postData() || "" : "";
|
|
2089
2138
|
const requestBodyFailures = shouldCaptureRequestBody ? networkMockRequestBodyFailures(requestBody, mock, responseBodyContract) : [];
|
|
2090
2139
|
const status = response.status || mock.status || 200;
|
|
2140
|
+
const delayMs = numberValue(response.delay_ms) || 0;
|
|
2091
2141
|
const event = {
|
|
2092
2142
|
ok: true,
|
|
2093
2143
|
label: mock.label,
|
|
@@ -2100,6 +2150,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
2100
2150
|
method,
|
|
2101
2151
|
status,
|
|
2102
2152
|
};
|
|
2153
|
+
if (delayMs) event.delay_ms = delayMs;
|
|
2103
2154
|
if (shouldCaptureRequestBody) {
|
|
2104
2155
|
event.request_body_matches = requestBodyFailures.length === 0;
|
|
2105
2156
|
event.request_body_failures = requestBodyFailures;
|
|
@@ -2107,6 +2158,7 @@ async function registerNetworkMocks(mocks) {
|
|
|
2107
2158
|
event.request_body_sample = compactNetworkMockRequestBody(requestBody);
|
|
2108
2159
|
}
|
|
2109
2160
|
networkMockEvents.push(event);
|
|
2161
|
+
if (delayMs) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2110
2162
|
await route.fulfill({
|
|
2111
2163
|
status,
|
|
2112
2164
|
headers,
|
|
@@ -2162,6 +2214,59 @@ async function executeSetupAction(action, ordinal) {
|
|
|
2162
2214
|
}
|
|
2163
2215
|
return { ...base, ok: true, storage, reload: action.reload === true };
|
|
2164
2216
|
}
|
|
2217
|
+
if (type === "window_call") {
|
|
2218
|
+
const path = String(action.path || action.function_path || action.functionPath || "");
|
|
2219
|
+
const args = Array.isArray(action.args) ? action.args : [];
|
|
2220
|
+
if (!path) return { ...base, path, reason: "missing_path" };
|
|
2221
|
+
const result = await page.evaluate(async ({ path, args }) => {
|
|
2222
|
+
const toJsonValue = (value) => {
|
|
2223
|
+
if (value === null || value === undefined) return null;
|
|
2224
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
2225
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
2226
|
+
if (Array.isArray(value)) return value.map(toJsonValue);
|
|
2227
|
+
if (typeof value === "object") {
|
|
2228
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
2229
|
+
}
|
|
2230
|
+
return String(value);
|
|
2231
|
+
};
|
|
2232
|
+
const pathParts = String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
|
|
2233
|
+
let parent = window;
|
|
2234
|
+
let current = window;
|
|
2235
|
+
for (const part of pathParts) {
|
|
2236
|
+
parent = current;
|
|
2237
|
+
current = current?.[part];
|
|
2238
|
+
}
|
|
2239
|
+
if (typeof current !== "function") return { ok: false, reason: "missing_function" };
|
|
2240
|
+
try {
|
|
2241
|
+
const returned = await current.apply(parent, Array.isArray(args) ? args : []);
|
|
2242
|
+
return { ok: true, returned: toJsonValue(returned) };
|
|
2243
|
+
} catch (error) {
|
|
2244
|
+
return { ok: false, reason: "function_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
|
|
2245
|
+
}
|
|
2246
|
+
}, { path, args });
|
|
2247
|
+
const hasExpectation = setupHasOwn(action, "expect_return")
|
|
2248
|
+
|| setupHasOwn(action, "expectReturn")
|
|
2249
|
+
|| setupHasOwn(action, "expected_return")
|
|
2250
|
+
|| setupHasOwn(action, "expectedReturn");
|
|
2251
|
+
const expected = setupHasOwn(action, "expect_return")
|
|
2252
|
+
? action.expect_return
|
|
2253
|
+
: setupHasOwn(action, "expectReturn")
|
|
2254
|
+
? action.expectReturn
|
|
2255
|
+
: setupHasOwn(action, "expected_return")
|
|
2256
|
+
? action.expected_return
|
|
2257
|
+
: action.expectedReturn;
|
|
2258
|
+
const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
|
|
2259
|
+
return {
|
|
2260
|
+
...base,
|
|
2261
|
+
ok: Boolean(result.ok && expectationMet),
|
|
2262
|
+
path,
|
|
2263
|
+
arg_count: args.length,
|
|
2264
|
+
returned: setupJsonValue(result.returned),
|
|
2265
|
+
expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
|
|
2266
|
+
reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
|
|
2267
|
+
error: result.error || undefined,
|
|
2268
|
+
};
|
|
2269
|
+
}
|
|
2165
2270
|
if (type === "click") {
|
|
2166
2271
|
const locator = page.locator(action.selector);
|
|
2167
2272
|
const count = await locator.count();
|
package/dist/profile.d.cts
CHANGED
|
@@ -5,7 +5,7 @@ declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evide
|
|
|
5
5
|
declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
|
|
6
6
|
declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
|
|
7
7
|
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
8
|
-
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text"];
|
|
8
|
+
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
11
11
|
type RiddleProofProfileSetupActionType = typeof RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES[number];
|
|
@@ -23,6 +23,9 @@ interface RiddleProofProfileSetupAction {
|
|
|
23
23
|
key?: string;
|
|
24
24
|
value?: string;
|
|
25
25
|
value_json?: JsonValue;
|
|
26
|
+
path?: string;
|
|
27
|
+
args?: JsonValue[];
|
|
28
|
+
expect_return?: JsonValue;
|
|
26
29
|
text?: string;
|
|
27
30
|
pattern?: string;
|
|
28
31
|
flags?: string;
|
|
@@ -42,6 +45,7 @@ interface RiddleProofProfileNetworkMockResponse {
|
|
|
42
45
|
headers?: Record<string, string>;
|
|
43
46
|
body?: string;
|
|
44
47
|
body_json?: JsonValue;
|
|
48
|
+
delay_ms?: number;
|
|
45
49
|
capture_request_body?: boolean;
|
|
46
50
|
request_body_contains?: string[];
|
|
47
51
|
request_body_patterns?: string[];
|
package/dist/profile.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evide
|
|
|
5
5
|
declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
|
|
6
6
|
declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
|
|
7
7
|
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
8
|
-
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text"];
|
|
8
|
+
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "local_storage", "session_storage", "clear_storage", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
11
11
|
type RiddleProofProfileSetupActionType = typeof RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES[number];
|
|
@@ -23,6 +23,9 @@ interface RiddleProofProfileSetupAction {
|
|
|
23
23
|
key?: string;
|
|
24
24
|
value?: string;
|
|
25
25
|
value_json?: JsonValue;
|
|
26
|
+
path?: string;
|
|
27
|
+
args?: JsonValue[];
|
|
28
|
+
expect_return?: JsonValue;
|
|
26
29
|
text?: string;
|
|
27
30
|
pattern?: string;
|
|
28
31
|
flags?: string;
|
|
@@ -42,6 +45,7 @@ interface RiddleProofProfileNetworkMockResponse {
|
|
|
42
45
|
headers?: Record<string, string>;
|
|
43
46
|
body?: string;
|
|
44
47
|
body_json?: JsonValue;
|
|
48
|
+
delay_ms?: number;
|
|
45
49
|
capture_request_body?: boolean;
|
|
46
50
|
request_body_contains?: string[];
|
|
47
51
|
request_body_patterns?: string[];
|
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-5FHHNCX4.js";
|
|
23
23
|
export {
|
|
24
24
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
25
25
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
@@ -292,7 +292,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
292
292
|
blocking?: boolean;
|
|
293
293
|
details?: Record<string, unknown>;
|
|
294
294
|
ok: boolean;
|
|
295
|
-
action: "
|
|
295
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
296
296
|
state_path: string;
|
|
297
297
|
stage: any;
|
|
298
298
|
summary: string;
|
|
@@ -382,7 +382,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
382
382
|
continueWithStage?: WorkflowStage | null;
|
|
383
383
|
blocking?: boolean;
|
|
384
384
|
details?: Record<string, unknown>;
|
|
385
|
-
action: "
|
|
385
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
386
386
|
state_path: string;
|
|
387
387
|
stage: any;
|
|
388
388
|
checkpoint: string;
|
|
@@ -659,7 +659,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
659
659
|
error?: undefined;
|
|
660
660
|
} | {
|
|
661
661
|
ok: boolean;
|
|
662
|
-
action: "
|
|
662
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|
|
@@ -292,7 +292,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
292
292
|
blocking?: boolean;
|
|
293
293
|
details?: Record<string, unknown>;
|
|
294
294
|
ok: boolean;
|
|
295
|
-
action: "
|
|
295
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
296
296
|
state_path: string;
|
|
297
297
|
stage: any;
|
|
298
298
|
summary: string;
|
|
@@ -382,7 +382,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
382
382
|
continueWithStage?: WorkflowStage | null;
|
|
383
383
|
blocking?: boolean;
|
|
384
384
|
details?: Record<string, unknown>;
|
|
385
|
-
action: "
|
|
385
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
386
386
|
state_path: string;
|
|
387
387
|
stage: any;
|
|
388
388
|
checkpoint: string;
|
|
@@ -659,7 +659,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
659
659
|
error?: undefined;
|
|
660
660
|
} | {
|
|
661
661
|
ok: boolean;
|
|
662
|
-
action: "
|
|
662
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|