@lvce-editor/test-with-playwright-worker 22.36.1 → 22.36.3
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/coverageWorkerMain.js +23 -4
- package/dist/workerMain.js +215 -23
- package/package.json +1 -1
|
@@ -460,6 +460,9 @@ const restoreExistingError = (error, currentStack) => {
|
|
|
460
460
|
};
|
|
461
461
|
const restoreMethodNotFoundError = (error, currentStack) => {
|
|
462
462
|
const restoredError = new JsonRpcError(error.message);
|
|
463
|
+
Object.assign(restoredError, {
|
|
464
|
+
code: error.code
|
|
465
|
+
});
|
|
463
466
|
const parentStack = getParentStack(error);
|
|
464
467
|
setStack(restoredError, `${parentStack}${NewLine}${currentStack}`);
|
|
465
468
|
return restoredError;
|
|
@@ -479,9 +482,13 @@ const applyDataProperties = (restoredError, error) => {
|
|
|
479
482
|
// @ts-ignore
|
|
480
483
|
restoredError.codeFrame = error.data.codeFrame;
|
|
481
484
|
}
|
|
482
|
-
if (error.data.code) {
|
|
485
|
+
if (typeof error.data.code === 'string' || typeof error.data.code === 'number') {
|
|
483
486
|
// @ts-ignore
|
|
484
|
-
restoredError
|
|
487
|
+
Object.defineProperty(restoredError, 'code', {
|
|
488
|
+
configurable: true,
|
|
489
|
+
value: error.data.code,
|
|
490
|
+
writable: true
|
|
491
|
+
});
|
|
485
492
|
}
|
|
486
493
|
if (error.data.type) {
|
|
487
494
|
// @ts-ignore
|
|
@@ -503,6 +510,13 @@ const applyDirectProperties = (restoredError, error) => {
|
|
|
503
510
|
};
|
|
504
511
|
const restoreMessageError = (error, _currentStack) => {
|
|
505
512
|
const restoredError = constructError(error.message, error.type, error.name);
|
|
513
|
+
if (typeof error.code === 'string' || typeof error.code === 'number') {
|
|
514
|
+
Object.defineProperty(restoredError, 'code', {
|
|
515
|
+
configurable: true,
|
|
516
|
+
value: error.code,
|
|
517
|
+
writable: true
|
|
518
|
+
});
|
|
519
|
+
}
|
|
506
520
|
if (error.data) {
|
|
507
521
|
applyDataProperties(restoredError, error);
|
|
508
522
|
} else {
|
|
@@ -581,7 +595,7 @@ const getErrorProperty = (error, prettyError) => {
|
|
|
581
595
|
return {
|
|
582
596
|
code: Custom,
|
|
583
597
|
data: {
|
|
584
|
-
code: prettyError.code,
|
|
598
|
+
code: prettyError.code ?? error?.code,
|
|
585
599
|
codeFrame: prettyError.codeFrame,
|
|
586
600
|
name: prettyError.name,
|
|
587
601
|
stack: getStack(prettyError),
|
|
@@ -618,7 +632,12 @@ const getErrorResponseSimple = (id, error) => {
|
|
|
618
632
|
return {
|
|
619
633
|
error: {
|
|
620
634
|
code: Custom,
|
|
621
|
-
data: error
|
|
635
|
+
data: error instanceof Error ? {
|
|
636
|
+
...error,
|
|
637
|
+
code: 'code' in error ? error.code : undefined,
|
|
638
|
+
stack: error.stack,
|
|
639
|
+
type: error.name
|
|
640
|
+
} : error,
|
|
622
641
|
// @ts-ignore
|
|
623
642
|
message: error.message
|
|
624
643
|
},
|
package/dist/workerMain.js
CHANGED
|
@@ -721,6 +721,9 @@ const restoreExistingError = (error, currentStack) => {
|
|
|
721
721
|
};
|
|
722
722
|
const restoreMethodNotFoundError = (error, currentStack) => {
|
|
723
723
|
const restoredError = new JsonRpcError(error.message);
|
|
724
|
+
Object.assign(restoredError, {
|
|
725
|
+
code: error.code
|
|
726
|
+
});
|
|
724
727
|
const parentStack = getParentStack(error);
|
|
725
728
|
setStack(restoredError, `${parentStack}${NewLine}${currentStack}`);
|
|
726
729
|
return restoredError;
|
|
@@ -740,9 +743,13 @@ const applyDataProperties = (restoredError, error) => {
|
|
|
740
743
|
// @ts-ignore
|
|
741
744
|
restoredError.codeFrame = error.data.codeFrame;
|
|
742
745
|
}
|
|
743
|
-
if (error.data.code) {
|
|
746
|
+
if (typeof error.data.code === 'string' || typeof error.data.code === 'number') {
|
|
744
747
|
// @ts-ignore
|
|
745
|
-
restoredError
|
|
748
|
+
Object.defineProperty(restoredError, 'code', {
|
|
749
|
+
configurable: true,
|
|
750
|
+
value: error.data.code,
|
|
751
|
+
writable: true
|
|
752
|
+
});
|
|
746
753
|
}
|
|
747
754
|
if (error.data.type) {
|
|
748
755
|
// @ts-ignore
|
|
@@ -764,6 +771,13 @@ const applyDirectProperties = (restoredError, error) => {
|
|
|
764
771
|
};
|
|
765
772
|
const restoreMessageError = (error, _currentStack) => {
|
|
766
773
|
const restoredError = constructError(error.message, error.type, error.name);
|
|
774
|
+
if (typeof error.code === 'string' || typeof error.code === 'number') {
|
|
775
|
+
Object.defineProperty(restoredError, 'code', {
|
|
776
|
+
configurable: true,
|
|
777
|
+
value: error.code,
|
|
778
|
+
writable: true
|
|
779
|
+
});
|
|
780
|
+
}
|
|
767
781
|
if (error.data) {
|
|
768
782
|
applyDataProperties(restoredError, error);
|
|
769
783
|
} else {
|
|
@@ -842,7 +856,7 @@ const getErrorProperty = (error, prettyError) => {
|
|
|
842
856
|
return {
|
|
843
857
|
code: Custom,
|
|
844
858
|
data: {
|
|
845
|
-
code: prettyError.code,
|
|
859
|
+
code: prettyError.code ?? error?.code,
|
|
846
860
|
codeFrame: prettyError.codeFrame,
|
|
847
861
|
name: prettyError.name,
|
|
848
862
|
stack: getStack(prettyError),
|
|
@@ -879,7 +893,12 @@ const getErrorResponseSimple = (id, error) => {
|
|
|
879
893
|
return {
|
|
880
894
|
error: {
|
|
881
895
|
code: Custom,
|
|
882
|
-
data: error
|
|
896
|
+
data: error instanceof Error ? {
|
|
897
|
+
...error,
|
|
898
|
+
code: 'code' in error ? error.code : undefined,
|
|
899
|
+
stack: error.stack,
|
|
900
|
+
type: error.name
|
|
901
|
+
} : error,
|
|
883
902
|
// @ts-ignore
|
|
884
903
|
message: error.message
|
|
885
904
|
},
|
|
@@ -1179,6 +1198,162 @@ const get = id => {
|
|
|
1179
1198
|
return rpcs[id];
|
|
1180
1199
|
};
|
|
1181
1200
|
|
|
1201
|
+
// This function is serialized by Playwright and must not close over module bindings.
|
|
1202
|
+
const install = () => {
|
|
1203
|
+
const limit = 5000;
|
|
1204
|
+
const payloadLimit = 8192;
|
|
1205
|
+
const entries = [];
|
|
1206
|
+
let sequence = 0;
|
|
1207
|
+
const channels = new WeakMap();
|
|
1208
|
+
let nextChannel = 0;
|
|
1209
|
+
const originalAdd = Object.getOwnPropertyDescriptor(EventTarget.prototype, 'addEventListener').value;
|
|
1210
|
+
const record = (kind, data) => {
|
|
1211
|
+
const entry = {
|
|
1212
|
+
...data,
|
|
1213
|
+
kind,
|
|
1214
|
+
sequence: sequence++,
|
|
1215
|
+
timestamp: performance.now()
|
|
1216
|
+
};
|
|
1217
|
+
entries[entry.sequence % limit] = entry;
|
|
1218
|
+
};
|
|
1219
|
+
const describe = target => {
|
|
1220
|
+
if (!(target instanceof Element)) {
|
|
1221
|
+
if (!(target instanceof Node)) return 'unknown';
|
|
1222
|
+
return `${target.nodeName}:${target.nodeValue || ''}`.slice(0, 200);
|
|
1223
|
+
}
|
|
1224
|
+
return `${target.tagName}#${target.id}.${target.getAttribute('class') || ''}`.slice(0, 200);
|
|
1225
|
+
};
|
|
1226
|
+
const serialize = value => {
|
|
1227
|
+
let truncated = false;
|
|
1228
|
+
const seen = new WeakSet();
|
|
1229
|
+
try {
|
|
1230
|
+
const text = JSON.stringify(value, (_key, item) => {
|
|
1231
|
+
if (typeof item === 'bigint') return `${item}n`;
|
|
1232
|
+
if (typeof item === 'string') {
|
|
1233
|
+
truncated ||= item.length > 2048;
|
|
1234
|
+
return item.slice(0, 2048);
|
|
1235
|
+
}
|
|
1236
|
+
if (typeof item !== 'object' || item === null) return item;
|
|
1237
|
+
if (seen.has(item)) return '[Circular]';
|
|
1238
|
+
seen.add(item);
|
|
1239
|
+
if (item instanceof MessagePort) return '[MessagePort]';
|
|
1240
|
+
if (item instanceof ArrayBuffer) return `[ArrayBuffer ${item.byteLength}]`;
|
|
1241
|
+
if (ArrayBuffer.isView(item)) return `[${item.constructor.name} ${item.byteLength}]`;
|
|
1242
|
+
return item;
|
|
1243
|
+
}) || '';
|
|
1244
|
+
return {
|
|
1245
|
+
payload: text.slice(0, payloadLimit),
|
|
1246
|
+
truncated: truncated || text.length > payloadLimit
|
|
1247
|
+
};
|
|
1248
|
+
} catch {
|
|
1249
|
+
return {
|
|
1250
|
+
payload: '[Unserializable]',
|
|
1251
|
+
truncated: true
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
};
|
|
1255
|
+
const observe = target => {
|
|
1256
|
+
const existing = channels.get(target);
|
|
1257
|
+
if (existing !== undefined) return existing;
|
|
1258
|
+
const channel = nextChannel++;
|
|
1259
|
+
channels.set(target, channel);
|
|
1260
|
+
Reflect.apply(originalAdd, target, ['message', event => {
|
|
1261
|
+
record('rpc-received', {
|
|
1262
|
+
channel,
|
|
1263
|
+
...serialize(event.data)
|
|
1264
|
+
});
|
|
1265
|
+
}]);
|
|
1266
|
+
return channel;
|
|
1267
|
+
};
|
|
1268
|
+
class EventHooks {
|
|
1269
|
+
addEventListener(...args) {
|
|
1270
|
+
if (args[0] === 'message' && (this instanceof MessagePort || this instanceof Worker)) observe(this);
|
|
1271
|
+
return Reflect.apply(originalAdd, this, args);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
Object.defineProperty(EventTarget.prototype, 'addEventListener', {
|
|
1275
|
+
...Object.getOwnPropertyDescriptor(EventTarget.prototype, 'addEventListener'),
|
|
1276
|
+
value: Object.getOwnPropertyDescriptor(EventHooks.prototype, 'addEventListener').value
|
|
1277
|
+
});
|
|
1278
|
+
for (const prototype of [MessagePort.prototype, Worker.prototype]) {
|
|
1279
|
+
const postDescriptor = Object.getOwnPropertyDescriptor(prototype, 'postMessage');
|
|
1280
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, 'onmessage');
|
|
1281
|
+
const originalSet = Object.getOwnPropertyDescriptor(descriptor, 'set').value;
|
|
1282
|
+
class PortHooks {
|
|
1283
|
+
postMessage(...args) {
|
|
1284
|
+
const channel = observe(this);
|
|
1285
|
+
const data = serialize(args[0]);
|
|
1286
|
+
const result = Reflect.apply(postDescriptor.value, this, args);
|
|
1287
|
+
record('rpc-sent', {
|
|
1288
|
+
channel,
|
|
1289
|
+
...data
|
|
1290
|
+
});
|
|
1291
|
+
return result;
|
|
1292
|
+
}
|
|
1293
|
+
set onmessage(listener) {
|
|
1294
|
+
observe(this);
|
|
1295
|
+
Reflect.apply(originalSet, this, [listener]);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
const hookDescriptor = Object.getOwnPropertyDescriptor(PortHooks.prototype, 'onmessage');
|
|
1299
|
+
Object.defineProperties(prototype, {
|
|
1300
|
+
onmessage: {
|
|
1301
|
+
...descriptor,
|
|
1302
|
+
set: Object.getOwnPropertyDescriptor(hookDescriptor, 'set').value
|
|
1303
|
+
},
|
|
1304
|
+
postMessage: {
|
|
1305
|
+
...postDescriptor,
|
|
1306
|
+
value: Object.getOwnPropertyDescriptor(PortHooks.prototype, 'postMessage').value
|
|
1307
|
+
}
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
for (const type of ['click', 'input', 'keydown', 'keyup', 'pointerdown', 'pointerup', 'pointerover', 'pointerout', 'focusin', 'focusout']) {
|
|
1311
|
+
document.addEventListener(type, event => {
|
|
1312
|
+
record('input', {
|
|
1313
|
+
event: type,
|
|
1314
|
+
key: event.key,
|
|
1315
|
+
target: describe(event.target),
|
|
1316
|
+
trusted: event.isTrusted
|
|
1317
|
+
});
|
|
1318
|
+
}, {
|
|
1319
|
+
capture: true,
|
|
1320
|
+
passive: true
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
const observer = new MutationObserver(mutations => {
|
|
1324
|
+
record('dom-mutation', {
|
|
1325
|
+
changes: mutations.slice(0, 10).map(mutation => ({
|
|
1326
|
+
added: [...mutation.addedNodes].slice(0, 2).map(describe),
|
|
1327
|
+
addedCount: mutation.addedNodes.length,
|
|
1328
|
+
attribute: mutation.attributeName,
|
|
1329
|
+
removed: [...mutation.removedNodes].slice(0, 2).map(describe),
|
|
1330
|
+
removedCount: mutation.removedNodes.length,
|
|
1331
|
+
target: describe(mutation.target),
|
|
1332
|
+
type: mutation.type,
|
|
1333
|
+
value: mutation.attributeName && mutation.target instanceof Element ? mutation.target.getAttribute(mutation.attributeName)?.slice(0, 200) : undefined
|
|
1334
|
+
})),
|
|
1335
|
+
count: mutations.length
|
|
1336
|
+
});
|
|
1337
|
+
});
|
|
1338
|
+
observer.observe(document, {
|
|
1339
|
+
attributes: true,
|
|
1340
|
+
characterData: true,
|
|
1341
|
+
childList: true,
|
|
1342
|
+
subtree: true
|
|
1343
|
+
});
|
|
1344
|
+
Object.defineProperty(globalThis, '__lvceTraceTimeline', {
|
|
1345
|
+
value: () => {
|
|
1346
|
+
const offset = sequence > limit ? sequence % limit : 0;
|
|
1347
|
+
return {
|
|
1348
|
+
dropped: Math.max(0, sequence - limit),
|
|
1349
|
+
entries: [...entries.slice(offset), ...entries.slice(0, offset)],
|
|
1350
|
+
limit,
|
|
1351
|
+
version: 1
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
};
|
|
1356
|
+
|
|
1182
1357
|
const HandleResult = 'HandleResult';
|
|
1183
1358
|
const HandleFinalResult = 'HandleFinalResult';
|
|
1184
1359
|
|
|
@@ -1249,19 +1424,26 @@ const exportTrace = async ({
|
|
|
1249
1424
|
page,
|
|
1250
1425
|
test
|
|
1251
1426
|
}) => {
|
|
1252
|
-
let
|
|
1427
|
+
let capture;
|
|
1253
1428
|
try {
|
|
1254
|
-
|
|
1255
|
-
return
|
|
1429
|
+
capture = await page.evaluate(traceSelector => {
|
|
1430
|
+
return {
|
|
1431
|
+
text: globalThis.document.querySelector(traceSelector)?.textContent || undefined,
|
|
1432
|
+
timeline: globalThis.__lvceTraceTimeline?.()
|
|
1433
|
+
};
|
|
1256
1434
|
}, selector);
|
|
1257
1435
|
} catch {
|
|
1258
1436
|
return false;
|
|
1259
1437
|
}
|
|
1260
|
-
if (!text) {
|
|
1438
|
+
if (!capture.text && !capture.timeline) {
|
|
1261
1439
|
return false;
|
|
1262
1440
|
}
|
|
1263
|
-
JSON.parse(text)
|
|
1264
|
-
|
|
1441
|
+
const trace = capture.text ? JSON.parse(capture.text) : {
|
|
1442
|
+
entries: [],
|
|
1443
|
+
version: 1
|
|
1444
|
+
};
|
|
1445
|
+
if (capture.timeline) trace.timeline = capture.timeline;
|
|
1446
|
+
await writeFile(join(directory, getFileName(test)), `${JSON.stringify(trace)}\n`);
|
|
1265
1447
|
return true;
|
|
1266
1448
|
};
|
|
1267
1449
|
|
|
@@ -2210,10 +2392,14 @@ const getElectronLaunchOptions = ({
|
|
|
2210
2392
|
args,
|
|
2211
2393
|
env,
|
|
2212
2394
|
executablePath
|
|
2213
|
-
}) => {
|
|
2395
|
+
}, profileRoot) => {
|
|
2214
2396
|
const launchEnv = {
|
|
2215
2397
|
...getProcessEnv(),
|
|
2216
|
-
...env
|
|
2398
|
+
...env,
|
|
2399
|
+
XDG_CACHE_HOME: join(profileRoot, 'cache'),
|
|
2400
|
+
XDG_CONFIG_HOME: join(profileRoot, 'config'),
|
|
2401
|
+
XDG_DATA_HOME: join(profileRoot, 'data'),
|
|
2402
|
+
XDG_STATE_HOME: join(profileRoot, 'state')
|
|
2217
2403
|
};
|
|
2218
2404
|
delete launchEnv['ELECTRON_RUN_AS_NODE'];
|
|
2219
2405
|
return {
|
|
@@ -2252,19 +2438,19 @@ const createElectronLaunch = ({
|
|
|
2252
2438
|
signal,
|
|
2253
2439
|
userDataDir
|
|
2254
2440
|
}) => {
|
|
2255
|
-
let
|
|
2256
|
-
const dispose =
|
|
2257
|
-
if (
|
|
2258
|
-
return;
|
|
2441
|
+
let disposal;
|
|
2442
|
+
const dispose = () => {
|
|
2443
|
+
if (disposal) {
|
|
2444
|
+
return disposal;
|
|
2259
2445
|
}
|
|
2260
|
-
disposed = true;
|
|
2261
2446
|
signal.removeEventListener('abort', handleAbort);
|
|
2262
2447
|
process.off('SIGINT', handleSigint);
|
|
2263
2448
|
process.off('SIGTERM', handleSigterm);
|
|
2264
|
-
|
|
2449
|
+
disposal = closeElectron({
|
|
2265
2450
|
electronApp,
|
|
2266
2451
|
userDataDir
|
|
2267
2452
|
});
|
|
2453
|
+
return disposal;
|
|
2268
2454
|
};
|
|
2269
2455
|
const handleAbort = () => {
|
|
2270
2456
|
void dispose();
|
|
@@ -2297,14 +2483,15 @@ const startElectron = async ({
|
|
|
2297
2483
|
runtimeOptions,
|
|
2298
2484
|
signal
|
|
2299
2485
|
}) => {
|
|
2300
|
-
const launchOptions = getElectronLaunchOptions(runtimeOptions);
|
|
2301
2486
|
const userDataDir = await mkdtemp(join(tmpdir(), 'test-with-playwright-electron-'));
|
|
2302
|
-
const args = getElectronProcessArgs({
|
|
2303
|
-
args: launchOptions.args,
|
|
2304
|
-
userDataDir
|
|
2305
|
-
});
|
|
2306
2487
|
let electronApp;
|
|
2307
2488
|
try {
|
|
2489
|
+
signal.throwIfAborted();
|
|
2490
|
+
const launchOptions = getElectronLaunchOptions(runtimeOptions, userDataDir);
|
|
2491
|
+
const args = getElectronProcessArgs({
|
|
2492
|
+
args: launchOptions.args,
|
|
2493
|
+
userDataDir
|
|
2494
|
+
});
|
|
2308
2495
|
const {
|
|
2309
2496
|
_electron
|
|
2310
2497
|
} = await import('@playwright/test');
|
|
@@ -2314,9 +2501,11 @@ const startElectron = async ({
|
|
|
2314
2501
|
executablePath: launchOptions.executablePath,
|
|
2315
2502
|
timeout: electronLaunchTimeout
|
|
2316
2503
|
});
|
|
2504
|
+
signal.throwIfAborted();
|
|
2317
2505
|
const page = await electronApp.firstWindow({
|
|
2318
2506
|
timeout: electronLaunchTimeout
|
|
2319
2507
|
});
|
|
2508
|
+
signal.throwIfAborted();
|
|
2320
2509
|
return createElectronLaunch({
|
|
2321
2510
|
electronApp,
|
|
2322
2511
|
page,
|
|
@@ -2446,6 +2635,9 @@ const runAllTests = async (extensionPath, testPath, cwd, browser, headless, time
|
|
|
2446
2635
|
testPath
|
|
2447
2636
|
});
|
|
2448
2637
|
try {
|
|
2638
|
+
if (traceRendererWorker) {
|
|
2639
|
+
await page.addInitScript(install);
|
|
2640
|
+
}
|
|
2449
2641
|
if (reusePage) {
|
|
2450
2642
|
await runWithJavascriptCoverage({
|
|
2451
2643
|
coverage,
|