@riddledc/riddle-proof 0.7.26 → 0.7.28
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-SDSBS64X.js → chunk-NUGGW7NX.js} +232 -2
- package/dist/cli.cjs +232 -2
- package/dist/cli.js +1 -1
- package/dist/index.cjs +232 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/profile.cjs +232 -2
- package/dist/profile.d.cts +19 -2
- package/dist/profile.d.ts +19 -2
- 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
|
@@ -22,6 +22,9 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
22
22
|
];
|
|
23
23
|
var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
|
|
24
24
|
"click",
|
|
25
|
+
"fill",
|
|
26
|
+
"set_input_value",
|
|
27
|
+
"local_storage",
|
|
25
28
|
"wait",
|
|
26
29
|
"wait_for_selector",
|
|
27
30
|
"wait_for_text"
|
|
@@ -35,6 +38,18 @@ function isRecord(value) {
|
|
|
35
38
|
function stringValue(value) {
|
|
36
39
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
37
40
|
}
|
|
41
|
+
function hasOwn(value, key) {
|
|
42
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
43
|
+
}
|
|
44
|
+
function stringFromOwn(input, ...keys) {
|
|
45
|
+
for (const key of keys) {
|
|
46
|
+
if (hasOwn(input, key)) {
|
|
47
|
+
const value = input[key];
|
|
48
|
+
if (value !== void 0 && value !== null) return String(value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
38
53
|
function numberValue(value) {
|
|
39
54
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
40
55
|
}
|
|
@@ -119,6 +134,11 @@ function jsonRecord(value) {
|
|
|
119
134
|
if (!isRecord(value)) return void 0;
|
|
120
135
|
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
|
|
121
136
|
}
|
|
137
|
+
function stringRecord(value) {
|
|
138
|
+
if (!isRecord(value)) return void 0;
|
|
139
|
+
const entries = Object.entries(value).map(([key, child]) => [key, String(child)]).filter(([key]) => key.trim());
|
|
140
|
+
return entries.length ? Object.fromEntries(entries) : void 0;
|
|
141
|
+
}
|
|
122
142
|
function toJsonValue(value) {
|
|
123
143
|
if (value === null || value === void 0) return null;
|
|
124
144
|
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
@@ -166,15 +186,30 @@ function normalizeSetupAction(input, index) {
|
|
|
166
186
|
if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
|
|
167
187
|
const type = normalizeSetupActionType(stringValue(input.type), index);
|
|
168
188
|
const selector = stringValue(input.selector);
|
|
169
|
-
if ((type === "click" || type === "wait_for_selector" || type === "wait_for_text") && !selector) {
|
|
189
|
+
if ((type === "click" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text") && !selector) {
|
|
170
190
|
throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
|
|
171
191
|
}
|
|
172
192
|
if (type === "wait_for_text" && !stringValue(input.text) && !stringValue(input.pattern)) {
|
|
173
193
|
throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
|
|
174
194
|
}
|
|
195
|
+
const value = stringFromOwn(input, "value", "input_value", "inputValue");
|
|
196
|
+
const hasJsonValue = hasOwn(input, "value_json") || hasOwn(input, "valueJson") || hasOwn(input, "json");
|
|
197
|
+
if ((type === "fill" || type === "set_input_value") && value === void 0 && !hasJsonValue) {
|
|
198
|
+
throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
|
|
199
|
+
}
|
|
200
|
+
const key = stringValue(input.key);
|
|
201
|
+
if (type === "local_storage" && !key) {
|
|
202
|
+
throw new Error(`target.setup_actions[${index}] local_storage requires key.`);
|
|
203
|
+
}
|
|
204
|
+
if (type === "local_storage" && value === void 0 && !hasJsonValue) {
|
|
205
|
+
throw new Error(`target.setup_actions[${index}] local_storage requires value.`);
|
|
206
|
+
}
|
|
175
207
|
return {
|
|
176
208
|
type,
|
|
177
209
|
selector,
|
|
210
|
+
key,
|
|
211
|
+
value,
|
|
212
|
+
value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
|
|
178
213
|
text: stringValue(input.text),
|
|
179
214
|
pattern: stringValue(input.pattern),
|
|
180
215
|
flags: stringValue(input.flags),
|
|
@@ -182,6 +217,7 @@ function normalizeSetupAction(input, index) {
|
|
|
182
217
|
ms: numberValue(input.ms) ?? numberValue(input.wait_ms) ?? numberValue(input.waitMs),
|
|
183
218
|
timeout_ms: numberValue(input.timeout_ms) ?? numberValue(input.timeoutMs),
|
|
184
219
|
after_ms: numberValue(input.after_ms) ?? numberValue(input.afterMs),
|
|
220
|
+
reload: input.reload === true,
|
|
185
221
|
continue_on_failure: input.continue_on_failure === true || input.continueOnFailure === true
|
|
186
222
|
};
|
|
187
223
|
}
|
|
@@ -190,6 +226,33 @@ function normalizeSetupActions(value) {
|
|
|
190
226
|
if (!Array.isArray(value)) throw new Error("target.setup_actions must be an array.");
|
|
191
227
|
return value.map(normalizeSetupAction);
|
|
192
228
|
}
|
|
229
|
+
function normalizeNetworkMock(input, index) {
|
|
230
|
+
if (!isRecord(input)) throw new Error(`target.network_mocks[${index}] must be an object.`);
|
|
231
|
+
const url = stringValue(input.url) || stringValue(input.glob) || stringValue(input.pattern);
|
|
232
|
+
if (!url) throw new Error(`target.network_mocks[${index}] requires url.`);
|
|
233
|
+
const status = numberValue(input.status) ?? 200;
|
|
234
|
+
if (!Number.isInteger(status) || status < 100 || status > 599) {
|
|
235
|
+
throw new Error(`target.network_mocks[${index}].status must be an HTTP status code.`);
|
|
236
|
+
}
|
|
237
|
+
const body = stringValue(input.body) ?? stringValue(input.body_text) ?? stringValue(input.bodyText);
|
|
238
|
+
const hasJsonBody = Object.prototype.hasOwnProperty.call(input, "body_json") || Object.prototype.hasOwnProperty.call(input, "bodyJson") || Object.prototype.hasOwnProperty.call(input, "json");
|
|
239
|
+
return {
|
|
240
|
+
label: normalizeName(input.label || input.name, `network-mock-${index + 1}`),
|
|
241
|
+
url,
|
|
242
|
+
method: stringValue(input.method)?.toUpperCase(),
|
|
243
|
+
status,
|
|
244
|
+
content_type: stringValue(input.content_type) || stringValue(input.contentType),
|
|
245
|
+
headers: stringRecord(input.headers),
|
|
246
|
+
body,
|
|
247
|
+
body_json: hasJsonBody ? toJsonValue(input.body_json ?? input.bodyJson ?? input.json) : void 0,
|
|
248
|
+
required: input.required === false ? false : true
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function normalizeNetworkMocks(value) {
|
|
252
|
+
if (value === void 0) return void 0;
|
|
253
|
+
if (!Array.isArray(value)) throw new Error("target.network_mocks must be an array.");
|
|
254
|
+
return value.map(normalizeNetworkMock);
|
|
255
|
+
}
|
|
193
256
|
function normalizeCheck(input, index) {
|
|
194
257
|
if (!isRecord(input)) throw new Error(`checks[${index}] must be an object.`);
|
|
195
258
|
const type = stringValue(input.type);
|
|
@@ -259,7 +322,8 @@ function normalizeRiddleProofProfile(input, options = {}) {
|
|
|
259
322
|
timeout_sec: timeoutSecValue(targetInput.timeout_sec) ?? timeoutSecValue(targetInput.timeoutSec) ?? timeoutSecValue(targetInput.riddle_timeout_sec) ?? timeoutSecValue(targetInput.riddleTimeoutSec),
|
|
260
323
|
wait_for_selector: stringValue(targetInput.wait_for_selector) || stringValue(targetInput.waitForSelector),
|
|
261
324
|
wait_ms: numberValue(targetInput.wait_ms) ?? numberValue(targetInput.waitMs),
|
|
262
|
-
setup_actions: normalizeSetupActions(targetInput.setup_actions ?? targetInput.setupActions)
|
|
325
|
+
setup_actions: normalizeSetupActions(targetInput.setup_actions ?? targetInput.setupActions),
|
|
326
|
+
network_mocks: normalizeNetworkMocks(targetInput.network_mocks ?? targetInput.networkMocks)
|
|
263
327
|
},
|
|
264
328
|
checks,
|
|
265
329
|
artifacts: Array.isArray(input.artifacts) ? input.artifacts.map((item) => String(item)).filter(Boolean) : ["screenshot", "console", "dom_summary", "proof_json"],
|
|
@@ -531,6 +595,50 @@ function assessSetupActionsFromEvidence(profile, evidence) {
|
|
|
531
595
|
message: failed.length ? `Setup actions failed in ${failed.length} viewport action(s).` : void 0
|
|
532
596
|
};
|
|
533
597
|
}
|
|
598
|
+
function assessNetworkMocksFromEvidence(profile, evidence) {
|
|
599
|
+
const mocks = profile.target.network_mocks || [];
|
|
600
|
+
if (!mocks.length) return void 0;
|
|
601
|
+
const events = evidence.network_mocks || [];
|
|
602
|
+
const failed = [];
|
|
603
|
+
const requiredMocks = mocks.filter((mock) => mock.required !== false);
|
|
604
|
+
for (const mock of requiredMocks) {
|
|
605
|
+
const hits = events.filter((event) => event.label === mock.label && event.ok !== false).length;
|
|
606
|
+
if (hits < 1) {
|
|
607
|
+
failed.push({
|
|
608
|
+
label: mock.label,
|
|
609
|
+
url: mock.url,
|
|
610
|
+
method: mock.method || null,
|
|
611
|
+
reason: "required_mock_not_hit"
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
for (const event of events) {
|
|
616
|
+
if (event.ok === false) {
|
|
617
|
+
failed.push({
|
|
618
|
+
label: event.label ?? null,
|
|
619
|
+
url: event.url ?? null,
|
|
620
|
+
method: event.method ?? null,
|
|
621
|
+
reason: event.reason ?? event.error ?? "mock_failed"
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
type: "network_mocks_succeeded",
|
|
627
|
+
label: "network mocks succeeded",
|
|
628
|
+
status: failed.length ? "failed" : "passed",
|
|
629
|
+
evidence: {
|
|
630
|
+
mock_count: mocks.length,
|
|
631
|
+
required_count: requiredMocks.length,
|
|
632
|
+
hit_count: events.filter((event) => event.ok !== false).length,
|
|
633
|
+
hits_by_label: Object.fromEntries(mocks.map((mock) => [
|
|
634
|
+
mock.label,
|
|
635
|
+
events.filter((event) => event.label === mock.label && event.ok !== false).length
|
|
636
|
+
])),
|
|
637
|
+
failed
|
|
638
|
+
},
|
|
639
|
+
message: failed.length ? `Network mocks failed or were not hit for ${failed.length} mock(s).` : void 0
|
|
640
|
+
};
|
|
641
|
+
}
|
|
534
642
|
function profileStatusFromEvidence(profile, evidence, checks) {
|
|
535
643
|
if (!evidence) return "proof_insufficient";
|
|
536
644
|
const viewports = evidence.viewports || [];
|
|
@@ -545,6 +653,7 @@ function profileStatusFromEvidence(profile, evidence, checks) {
|
|
|
545
653
|
function assessRiddleProofProfileEvidence(profile, evidence, options = {}) {
|
|
546
654
|
const capturedAt = evidence?.captured_at || (/* @__PURE__ */ new Date()).toISOString();
|
|
547
655
|
const checks = evidence ? [
|
|
656
|
+
assessNetworkMocksFromEvidence(profile, evidence),
|
|
548
657
|
assessSetupActionsFromEvidence(profile, evidence),
|
|
549
658
|
...profile.checks.map((check) => assessCheckFromEvidence(check, evidence))
|
|
550
659
|
].filter((check) => Boolean(check)) : [];
|
|
@@ -761,6 +870,49 @@ function horizontalBoundsOverflowPx(value) {
|
|
|
761
870
|
function assessProfile(profile, evidence) {
|
|
762
871
|
const checks = [];
|
|
763
872
|
const viewports = evidence.viewports || [];
|
|
873
|
+
if (profile.target && Array.isArray(profile.target.network_mocks) && profile.target.network_mocks.length) {
|
|
874
|
+
const events = evidence.network_mocks || [];
|
|
875
|
+
const requiredMocks = profile.target.network_mocks.filter((mock) => mock && mock.required !== false);
|
|
876
|
+
const failed = [];
|
|
877
|
+
for (const mock of requiredMocks) {
|
|
878
|
+
const hits = events.filter((event) => event && event.label === mock.label && event.ok !== false).length;
|
|
879
|
+
if (hits < 1) {
|
|
880
|
+
failed.push({
|
|
881
|
+
label: mock.label,
|
|
882
|
+
url: mock.url,
|
|
883
|
+
method: mock.method || null,
|
|
884
|
+
reason: "required_mock_not_hit",
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
for (const event of events) {
|
|
889
|
+
if (event && event.ok === false) {
|
|
890
|
+
failed.push({
|
|
891
|
+
label: event.label || null,
|
|
892
|
+
url: event.url || null,
|
|
893
|
+
method: event.method || null,
|
|
894
|
+
reason: event.reason || event.error || "mock_failed",
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
const hitsByLabel = {};
|
|
899
|
+
for (const mock of profile.target.network_mocks) {
|
|
900
|
+
hitsByLabel[mock.label] = events.filter((event) => event && event.label === mock.label && event.ok !== false).length;
|
|
901
|
+
}
|
|
902
|
+
checks.push({
|
|
903
|
+
type: "network_mocks_succeeded",
|
|
904
|
+
label: "network mocks succeeded",
|
|
905
|
+
status: failed.length ? "failed" : "passed",
|
|
906
|
+
evidence: {
|
|
907
|
+
mock_count: profile.target.network_mocks.length,
|
|
908
|
+
required_count: requiredMocks.length,
|
|
909
|
+
hit_count: events.filter((event) => event && event.ok !== false).length,
|
|
910
|
+
hits_by_label: hitsByLabel,
|
|
911
|
+
failed,
|
|
912
|
+
},
|
|
913
|
+
message: failed.length ? "Network mocks failed or were not hit for " + failed.length + " mock(s)." : undefined,
|
|
914
|
+
});
|
|
915
|
+
}
|
|
764
916
|
if (profile.target && Array.isArray(profile.target.setup_actions) && profile.target.setup_actions.length) {
|
|
765
917
|
const actionCount = profile.target.setup_actions.length;
|
|
766
918
|
const failed = [];
|
|
@@ -950,6 +1102,7 @@ const profileSlug = ${serializableSlug};
|
|
|
950
1102
|
const capturedAt = new Date().toISOString();
|
|
951
1103
|
const consoleEvents = [];
|
|
952
1104
|
const pageErrors = [];
|
|
1105
|
+
const networkMockEvents = [];
|
|
953
1106
|
page.on("console", (message) => {
|
|
954
1107
|
const type = message.type();
|
|
955
1108
|
if (type === "error" || type === "warning" || type === "assert") {
|
|
@@ -985,6 +1138,14 @@ function setupTextMatches(sample, action) {
|
|
|
985
1138
|
}
|
|
986
1139
|
return String(sample || "").includes(action.text || "");
|
|
987
1140
|
}
|
|
1141
|
+
function setupHasOwn(action, key) {
|
|
1142
|
+
return Boolean(action) && Object.keys(action).includes(key);
|
|
1143
|
+
}
|
|
1144
|
+
function setupActionValue(action) {
|
|
1145
|
+
if (setupHasOwn(action, "value_json")) return JSON.stringify(action.value_json);
|
|
1146
|
+
if (setupHasOwn(action, "value")) return String(action.value ?? "");
|
|
1147
|
+
return "";
|
|
1148
|
+
}
|
|
988
1149
|
async function setupLocatorText(locator, index) {
|
|
989
1150
|
return await locator.nth(index).textContent({ timeout: 1000 }).catch(() => "");
|
|
990
1151
|
}
|
|
@@ -996,6 +1157,49 @@ function compactSetupResultText(value) {
|
|
|
996
1157
|
async function setupLocatorVisible(locator, index) {
|
|
997
1158
|
return await locator.nth(index).isVisible({ timeout: 1000 }).catch(() => false);
|
|
998
1159
|
}
|
|
1160
|
+
async function registerNetworkMocks(mocks) {
|
|
1161
|
+
for (const mock of mocks || []) {
|
|
1162
|
+
await page.route(mock.url, async (route) => {
|
|
1163
|
+
const request = route.request();
|
|
1164
|
+
const method = request.method ? request.method() : "";
|
|
1165
|
+
if (mock.method && method.toUpperCase() !== String(mock.method).toUpperCase()) {
|
|
1166
|
+
await route.continue();
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
try {
|
|
1170
|
+
const headers = { ...(mock.headers || {}) };
|
|
1171
|
+
let body = mock.body || "";
|
|
1172
|
+
let contentType = mock.content_type || headers["content-type"] || headers["Content-Type"] || "text/plain";
|
|
1173
|
+
if (mock.body_json !== undefined) {
|
|
1174
|
+
body = JSON.stringify(mock.body_json);
|
|
1175
|
+
contentType = mock.content_type || headers["content-type"] || headers["Content-Type"] || "application/json";
|
|
1176
|
+
}
|
|
1177
|
+
networkMockEvents.push({
|
|
1178
|
+
ok: true,
|
|
1179
|
+
label: mock.label,
|
|
1180
|
+
url: request.url(),
|
|
1181
|
+
method,
|
|
1182
|
+
status: mock.status || 200,
|
|
1183
|
+
});
|
|
1184
|
+
await route.fulfill({
|
|
1185
|
+
status: mock.status || 200,
|
|
1186
|
+
headers,
|
|
1187
|
+
contentType,
|
|
1188
|
+
body,
|
|
1189
|
+
});
|
|
1190
|
+
} catch (error) {
|
|
1191
|
+
networkMockEvents.push({
|
|
1192
|
+
ok: false,
|
|
1193
|
+
label: mock.label,
|
|
1194
|
+
url: request.url(),
|
|
1195
|
+
method,
|
|
1196
|
+
error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
1197
|
+
});
|
|
1198
|
+
throw error;
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
999
1203
|
async function executeSetupAction(action, ordinal) {
|
|
1000
1204
|
const type = setupActionType(action);
|
|
1001
1205
|
const base = { ok: false, action: type || "unknown", ordinal, selector: action.selector || null };
|
|
@@ -1010,6 +1214,16 @@ async function executeSetupAction(action, ordinal) {
|
|
|
1010
1214
|
await page.waitForSelector(action.selector, { state: "visible", timeout });
|
|
1011
1215
|
return { ...base, ok: true, timeout_ms: timeout };
|
|
1012
1216
|
}
|
|
1217
|
+
if (type === "local_storage") {
|
|
1218
|
+
const value = setupActionValue(action);
|
|
1219
|
+
await page.evaluate(({ key, value }) => {
|
|
1220
|
+
window.localStorage.setItem(key, value);
|
|
1221
|
+
}, { key: action.key, value });
|
|
1222
|
+
if (action.reload === true) {
|
|
1223
|
+
await page.reload({ waitUntil: "domcontentloaded", timeout: 45000 });
|
|
1224
|
+
}
|
|
1225
|
+
return { ...base, ok: true, key: action.key, value_length: value.length, reload: action.reload === true };
|
|
1226
|
+
}
|
|
1013
1227
|
if (type === "click") {
|
|
1014
1228
|
const locator = page.locator(action.selector);
|
|
1015
1229
|
const count = await locator.count();
|
|
@@ -1042,6 +1256,16 @@ async function executeSetupAction(action, ordinal) {
|
|
|
1042
1256
|
await locator.nth(targetIndex).click({ timeout });
|
|
1043
1257
|
return { ...base, ok: true, count, target_index: targetIndex, text: matchedText };
|
|
1044
1258
|
}
|
|
1259
|
+
if (type === "fill" || type === "set_input_value") {
|
|
1260
|
+
const locator = page.locator(action.selector);
|
|
1261
|
+
const count = await locator.count();
|
|
1262
|
+
if (!count) return { ...base, reason: "selector_not_found", count };
|
|
1263
|
+
const targetIndex = Number.isInteger(action.index) ? action.index : 0;
|
|
1264
|
+
if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex };
|
|
1265
|
+
const value = setupActionValue(action);
|
|
1266
|
+
await locator.nth(targetIndex).fill(value, { timeout });
|
|
1267
|
+
return { ...base, ok: true, count, target_index: targetIndex, value_length: value.length };
|
|
1268
|
+
}
|
|
1045
1269
|
if (type === "wait_for_text") {
|
|
1046
1270
|
const locator = page.locator(action.selector);
|
|
1047
1271
|
const startedAt = Date.now();
|
|
@@ -1257,6 +1481,7 @@ function buildProfileEvidence(currentViewports) {
|
|
|
1257
1481
|
fatal_count: consoleEvents.filter((event) => event.type === "error" || event.type === "assert").length,
|
|
1258
1482
|
},
|
|
1259
1483
|
page_errors: pageErrors,
|
|
1484
|
+
network_mocks: networkMockEvents.slice(),
|
|
1260
1485
|
dom_summary: {
|
|
1261
1486
|
expected_viewport_count: expectedViewportCount,
|
|
1262
1487
|
viewport_count: currentViewports.length,
|
|
@@ -1266,6 +1491,8 @@ function buildProfileEvidence(currentViewports) {
|
|
|
1266
1491
|
overflow_px: currentViewports.map((viewport) => viewport.overflow_px),
|
|
1267
1492
|
bounds_overflow_px: currentViewports.map((viewport) => viewport.bounds_overflow_px),
|
|
1268
1493
|
overflow_offender_counts: currentViewports.map((viewport) => (viewport.overflow_offenders || []).length),
|
|
1494
|
+
network_mock_count: (profile.target.network_mocks || []).length,
|
|
1495
|
+
network_mock_hit_count: networkMockEvents.filter((event) => event.ok !== false).length,
|
|
1269
1496
|
},
|
|
1270
1497
|
};
|
|
1271
1498
|
}
|
|
@@ -1279,6 +1506,9 @@ async function saveProfileArtifacts(currentViewports) {
|
|
|
1279
1506
|
}
|
|
1280
1507
|
return result;
|
|
1281
1508
|
}
|
|
1509
|
+
await registerNetworkMocks(profile.target.network_mocks || []);
|
|
1510
|
+
consoleEvents.length = 0;
|
|
1511
|
+
pageErrors.length = 0;
|
|
1282
1512
|
let result = await saveProfileArtifacts(viewports);
|
|
1283
1513
|
for (const viewport of profile.target.viewports || []) {
|
|
1284
1514
|
viewports.push(await captureViewport(viewport));
|