@lvce-editor/test-with-playwright-worker 22.7.0 → 22.8.0
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/svgScreenshot.js +7120 -0
- package/dist/workerMain.js +324 -160
- package/package.json +11 -2
package/dist/workerMain.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { join, dirname, basename } from 'node:path';
|
|
2
|
-
import { readFile, writeFile, readdir,
|
|
3
|
-
import { pathToFileURL } from 'node:url';
|
|
2
|
+
import { readFile, writeFile, readdir, mkdir, rm, access, mkdtemp } from 'node:fs/promises';
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
|
+
import IstanbulCoverage from 'istanbul-lib-coverage';
|
|
5
|
+
import v8ToIstanbul from 'v8-to-istanbul';
|
|
6
|
+
import IstanbulReport from 'istanbul-lib-report';
|
|
7
|
+
import IstanbulReports from 'istanbul-reports';
|
|
4
8
|
import net from 'node:net';
|
|
5
9
|
import os, { tmpdir } from 'node:os';
|
|
6
|
-
import { fork
|
|
7
|
-
import { createInterface } from 'node:readline';
|
|
10
|
+
import { fork } from 'node:child_process';
|
|
8
11
|
import { createRequire } from 'node:module';
|
|
9
12
|
|
|
10
13
|
const require$1 = createRequire(import.meta.url);
|
|
@@ -120,7 +123,7 @@ const Object$1 = 1;
|
|
|
120
123
|
const Number$1 = 2;
|
|
121
124
|
const Array$1 = 3;
|
|
122
125
|
const String$1 = 4;
|
|
123
|
-
const Boolean = 5;
|
|
126
|
+
const Boolean$1 = 5;
|
|
124
127
|
const Function = 6;
|
|
125
128
|
const Null = 7;
|
|
126
129
|
const Unknown = 8;
|
|
@@ -141,7 +144,7 @@ const getType = value => {
|
|
|
141
144
|
}
|
|
142
145
|
return Object$1;
|
|
143
146
|
case 'boolean':
|
|
144
|
-
return Boolean;
|
|
147
|
+
return Boolean$1;
|
|
145
148
|
default:
|
|
146
149
|
return Unknown;
|
|
147
150
|
}
|
|
@@ -166,7 +169,7 @@ const string = value => {
|
|
|
166
169
|
};
|
|
167
170
|
const boolean = value => {
|
|
168
171
|
const type = getType(value);
|
|
169
|
-
if (type !== Boolean) {
|
|
172
|
+
if (type !== Boolean$1) {
|
|
170
173
|
throw new AssertionError('expected value to be of type boolean');
|
|
171
174
|
}
|
|
172
175
|
};
|
|
@@ -945,7 +948,7 @@ const E_NO_TEST_FILES = 'E_NO_TEST_FILES';
|
|
|
945
948
|
* @param {any} error
|
|
946
949
|
*/
|
|
947
950
|
const isEnoentError = error => {
|
|
948
|
-
return error && error.code === ENOENT;
|
|
951
|
+
return Boolean(error && error.code === ENOENT);
|
|
949
952
|
};
|
|
950
953
|
|
|
951
954
|
/**
|
|
@@ -988,6 +991,96 @@ const getTests = async testSrc => {
|
|
|
988
991
|
|
|
989
992
|
const Cli = 6001;
|
|
990
993
|
|
|
994
|
+
const browserScriptCache = {};
|
|
995
|
+
const fileExtensionRegex = /\.[^.]+$/;
|
|
996
|
+
const tagBoundaryRegex = />\s*</g;
|
|
997
|
+
const getBrowserScriptCandidates = () => {
|
|
998
|
+
return [fileURLToPath(new URL('svgScreenshot.js', import.meta.url)), fileURLToPath(new URL('../../../../../dist/test-with-playwright-worker/dist/svgScreenshot.js', import.meta.url))];
|
|
999
|
+
};
|
|
1000
|
+
const readBrowserScript = async () => {
|
|
1001
|
+
for (const candidate of getBrowserScriptCandidates()) {
|
|
1002
|
+
try {
|
|
1003
|
+
await access(candidate);
|
|
1004
|
+
return await readFile(candidate, 'utf8');
|
|
1005
|
+
} catch {
|
|
1006
|
+
// Try the next development or distribution path.
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
throw new Error('[test-with-playwright] SVG screenshot browser script not found; run npm run build');
|
|
1010
|
+
};
|
|
1011
|
+
const getBrowserScript = () => {
|
|
1012
|
+
browserScriptCache.promise ||= readBrowserScript();
|
|
1013
|
+
return browserScriptCache.promise;
|
|
1014
|
+
};
|
|
1015
|
+
const capture = async (page, selector) => {
|
|
1016
|
+
const browserScript = await getBrowserScript();
|
|
1017
|
+
await page.evaluate(browserScript);
|
|
1018
|
+
return page.evaluate(async selector => {
|
|
1019
|
+
const api = globalThis.SvgScreenshot;
|
|
1020
|
+
if (!api) {
|
|
1021
|
+
throw new Error('SVG screenshot browser API was not initialized');
|
|
1022
|
+
}
|
|
1023
|
+
return api.capture(selector);
|
|
1024
|
+
}, selector);
|
|
1025
|
+
};
|
|
1026
|
+
const formatSvg = svg => {
|
|
1027
|
+
return `${svg.replaceAll(tagBoundaryRegex, '>\n<').trim()}\n`;
|
|
1028
|
+
};
|
|
1029
|
+
const getSnapshotName = (test, name) => {
|
|
1030
|
+
const fileName = basename(test).replace(fileExtensionRegex, '');
|
|
1031
|
+
return `${fileName}.${name}.svg`;
|
|
1032
|
+
};
|
|
1033
|
+
const captureSvgScreenshot = async ({
|
|
1034
|
+
options,
|
|
1035
|
+
page,
|
|
1036
|
+
test
|
|
1037
|
+
}) => {
|
|
1038
|
+
const svg = await capture(page, options.selector);
|
|
1039
|
+
await compareSvgScreenshot({
|
|
1040
|
+
options,
|
|
1041
|
+
svg,
|
|
1042
|
+
test
|
|
1043
|
+
});
|
|
1044
|
+
};
|
|
1045
|
+
const compareSvgScreenshot = async ({
|
|
1046
|
+
options,
|
|
1047
|
+
svg,
|
|
1048
|
+
test
|
|
1049
|
+
}) => {
|
|
1050
|
+
const formattedSvg = formatSvg(svg);
|
|
1051
|
+
const snapshotPath = join(options.directory, getSnapshotName(test, options.name));
|
|
1052
|
+
const actualPath = `${snapshotPath}.actual`;
|
|
1053
|
+
if (options.update) {
|
|
1054
|
+
await mkdir(options.directory, {
|
|
1055
|
+
recursive: true
|
|
1056
|
+
});
|
|
1057
|
+
await writeFile(snapshotPath, formattedSvg);
|
|
1058
|
+
await rm(actualPath, {
|
|
1059
|
+
force: true
|
|
1060
|
+
});
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
let expected;
|
|
1064
|
+
try {
|
|
1065
|
+
expected = await readFile(snapshotPath, 'utf8');
|
|
1066
|
+
} catch (error) {
|
|
1067
|
+
if (isEnoentError(error)) {
|
|
1068
|
+
throw new Error(`[test-with-playwright] SVG screenshot is missing: ${snapshotPath}. Run with --update-svg-screenshots to create it.`);
|
|
1069
|
+
}
|
|
1070
|
+
throw error;
|
|
1071
|
+
}
|
|
1072
|
+
if (expected !== formattedSvg) {
|
|
1073
|
+
await mkdir(options.directory, {
|
|
1074
|
+
recursive: true
|
|
1075
|
+
});
|
|
1076
|
+
await writeFile(actualPath, formattedSvg);
|
|
1077
|
+
throw new Error(`[test-with-playwright] SVG screenshot differs: ${snapshotPath}. Actual output: ${actualPath}`);
|
|
1078
|
+
}
|
|
1079
|
+
await rm(actualPath, {
|
|
1080
|
+
force: true
|
|
1081
|
+
});
|
|
1082
|
+
};
|
|
1083
|
+
|
|
991
1084
|
const Pass$1 = 1;
|
|
992
1085
|
const Skip$1 = 2;
|
|
993
1086
|
const Fail$1 = 3;
|
|
@@ -1017,6 +1110,7 @@ const withTimeout = async (promise, timeout) => {
|
|
|
1017
1110
|
const runElectronTest = async ({
|
|
1018
1111
|
electronApp,
|
|
1019
1112
|
page,
|
|
1113
|
+
svgScreenshotOptions,
|
|
1020
1114
|
test,
|
|
1021
1115
|
testSrc,
|
|
1022
1116
|
timeout
|
|
@@ -1043,6 +1137,13 @@ const runElectronTest = async ({
|
|
|
1043
1137
|
Locator: page.locator.bind(page),
|
|
1044
1138
|
page
|
|
1045
1139
|
}), timeout);
|
|
1140
|
+
if (svgScreenshotOptions) {
|
|
1141
|
+
await captureSvgScreenshot({
|
|
1142
|
+
options: svgScreenshotOptions,
|
|
1143
|
+
page,
|
|
1144
|
+
test
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1046
1147
|
const end = performance.now();
|
|
1047
1148
|
return {
|
|
1048
1149
|
end,
|
|
@@ -1098,6 +1199,7 @@ const runElectronTests = async ({
|
|
|
1098
1199
|
onFinalResult,
|
|
1099
1200
|
onResult,
|
|
1100
1201
|
page,
|
|
1202
|
+
svgScreenshotOptions,
|
|
1101
1203
|
tests,
|
|
1102
1204
|
testSrc,
|
|
1103
1205
|
timeout
|
|
@@ -1113,7 +1215,10 @@ const runElectronTests = async ({
|
|
|
1113
1215
|
page,
|
|
1114
1216
|
test,
|
|
1115
1217
|
testSrc,
|
|
1116
|
-
timeout
|
|
1218
|
+
timeout,
|
|
1219
|
+
...(svgScreenshotOptions && {
|
|
1220
|
+
svgScreenshotOptions
|
|
1221
|
+
})
|
|
1117
1222
|
});
|
|
1118
1223
|
await onResult(result);
|
|
1119
1224
|
const resultCounts = getResultCounts$2(result.status);
|
|
@@ -1138,19 +1243,16 @@ const Fail = 'fail';
|
|
|
1138
1243
|
const getTestState = (testOverlayState, text) => {
|
|
1139
1244
|
switch (testOverlayState) {
|
|
1140
1245
|
case Fail:
|
|
1141
|
-
// @ts-ignore
|
|
1142
1246
|
return {
|
|
1143
1247
|
error: text,
|
|
1144
1248
|
status: Fail$1
|
|
1145
1249
|
};
|
|
1146
1250
|
case Pass:
|
|
1147
|
-
// @ts-ignore
|
|
1148
1251
|
return {
|
|
1149
1252
|
error: '',
|
|
1150
1253
|
status: Pass$1
|
|
1151
1254
|
};
|
|
1152
1255
|
case Skip:
|
|
1153
|
-
// @ts-ignore
|
|
1154
1256
|
return {
|
|
1155
1257
|
error: '',
|
|
1156
1258
|
status: Skip$1
|
|
@@ -1177,6 +1279,7 @@ const getUrlFromTestFile = (absolutePath, port, traceFocus) => {
|
|
|
1177
1279
|
const runTest = async ({
|
|
1178
1280
|
page,
|
|
1179
1281
|
port,
|
|
1282
|
+
svgScreenshotOptions,
|
|
1180
1283
|
test,
|
|
1181
1284
|
testSrc,
|
|
1182
1285
|
timeout,
|
|
@@ -1199,6 +1302,13 @@ const runTest = async ({
|
|
|
1199
1302
|
const testOverlayState = await testOverlay.getAttribute('data-state');
|
|
1200
1303
|
// @ts-ignore
|
|
1201
1304
|
const testState = getTestState(testOverlayState, text || '');
|
|
1305
|
+
if (testState.status === Pass$1 && svgScreenshotOptions) {
|
|
1306
|
+
await captureSvgScreenshot({
|
|
1307
|
+
options: svgScreenshotOptions,
|
|
1308
|
+
page,
|
|
1309
|
+
test
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1202
1312
|
const end = performance.now();
|
|
1203
1313
|
return {
|
|
1204
1314
|
// @ts-ignore
|
|
@@ -1261,6 +1371,7 @@ const runTests = async ({
|
|
|
1261
1371
|
onResult,
|
|
1262
1372
|
page,
|
|
1263
1373
|
port,
|
|
1374
|
+
svgScreenshotOptions,
|
|
1264
1375
|
tests,
|
|
1265
1376
|
testSrc,
|
|
1266
1377
|
timeout,
|
|
@@ -1279,7 +1390,10 @@ const runTests = async ({
|
|
|
1279
1390
|
test,
|
|
1280
1391
|
testSrc,
|
|
1281
1392
|
timeout,
|
|
1282
|
-
traceFocus: traceFocus ?? false
|
|
1393
|
+
traceFocus: traceFocus ?? false,
|
|
1394
|
+
...(svgScreenshotOptions && {
|
|
1395
|
+
svgScreenshotOptions
|
|
1396
|
+
})
|
|
1283
1397
|
});
|
|
1284
1398
|
await onResult(result);
|
|
1285
1399
|
// @ts-ignore
|
|
@@ -1459,6 +1573,108 @@ const runTestsWithReusedPage = async ({
|
|
|
1459
1573
|
});
|
|
1460
1574
|
};
|
|
1461
1575
|
|
|
1576
|
+
const externalSourceMapCommentRegex = /(?:\/\/[#@]\s*sourceMappingURL=(?!data:).*?$|\/\*[#@]\s*sourceMappingURL=(?!data:).*?\*\/)/gm;
|
|
1577
|
+
const temporaryServerRootRegex = /^\/[a-f\d]{7,}(?=\/(?:js|packages)\/)/;
|
|
1578
|
+
const normalizeCoveragePath = path => {
|
|
1579
|
+
return path.replace(temporaryServerRootRegex, '');
|
|
1580
|
+
};
|
|
1581
|
+
const normalizeCoverageData = coverageData => {
|
|
1582
|
+
const normalized = Object.create(null);
|
|
1583
|
+
for (const data of Object.values(coverageData)) {
|
|
1584
|
+
const path = normalizeCoveragePath(data.path);
|
|
1585
|
+
normalized[path] = {
|
|
1586
|
+
...data,
|
|
1587
|
+
path
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
return normalized;
|
|
1591
|
+
};
|
|
1592
|
+
const getCoveragePath = url => {
|
|
1593
|
+
try {
|
|
1594
|
+
return decodeURIComponent(new URL(url).pathname);
|
|
1595
|
+
} catch {
|
|
1596
|
+
return url;
|
|
1597
|
+
}
|
|
1598
|
+
};
|
|
1599
|
+
const isTestScript = url => {
|
|
1600
|
+
try {
|
|
1601
|
+
return new URL(url).pathname.startsWith('/tests/');
|
|
1602
|
+
} catch {
|
|
1603
|
+
return false;
|
|
1604
|
+
}
|
|
1605
|
+
};
|
|
1606
|
+
const addEntryToCoverageMap = async (coverageMap, entry) => {
|
|
1607
|
+
if (!entry.source || !entry.url || isTestScript(entry.url)) {
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
const source = entry.source.replaceAll(externalSourceMapCommentRegex, '');
|
|
1611
|
+
const converter = v8ToIstanbul(getCoveragePath(entry.url), 0, {
|
|
1612
|
+
source
|
|
1613
|
+
});
|
|
1614
|
+
await converter.load();
|
|
1615
|
+
converter.applyCoverage(entry.functions);
|
|
1616
|
+
coverageMap.merge(normalizeCoverageData(converter.toIstanbul()));
|
|
1617
|
+
};
|
|
1618
|
+
const createJavascriptCoverage = async entries => {
|
|
1619
|
+
const coverageMap = IstanbulCoverage.createCoverageMap();
|
|
1620
|
+
for (const entry of entries) {
|
|
1621
|
+
await addEntryToCoverageMap(coverageMap, entry);
|
|
1622
|
+
}
|
|
1623
|
+
return coverageMap;
|
|
1624
|
+
};
|
|
1625
|
+
|
|
1626
|
+
const executeReport = (coverageMap, directory, name) => {
|
|
1627
|
+
const context = IstanbulReport.createContext({
|
|
1628
|
+
coverageMap,
|
|
1629
|
+
dir: directory
|
|
1630
|
+
});
|
|
1631
|
+
IstanbulReports.create(name).execute(context);
|
|
1632
|
+
};
|
|
1633
|
+
const writeJavascriptCoverage = async (coverageMap, directory) => {
|
|
1634
|
+
await rm(directory, {
|
|
1635
|
+
force: true,
|
|
1636
|
+
recursive: true
|
|
1637
|
+
});
|
|
1638
|
+
await mkdir(directory, {
|
|
1639
|
+
recursive: true
|
|
1640
|
+
});
|
|
1641
|
+
executeReport(coverageMap, directory, 'json');
|
|
1642
|
+
executeReport(coverageMap, directory, 'json-summary');
|
|
1643
|
+
executeReport(coverageMap, directory, 'lcovonly');
|
|
1644
|
+
const context = IstanbulReport.createContext({
|
|
1645
|
+
coverageMap,
|
|
1646
|
+
dir: directory
|
|
1647
|
+
});
|
|
1648
|
+
IstanbulReports.create('text', {
|
|
1649
|
+
file: 'coverage.txt'
|
|
1650
|
+
}).execute(context);
|
|
1651
|
+
const summaryText = await readFile(join(directory, 'coverage.txt'), 'utf8');
|
|
1652
|
+
const summary = summaryText.trimEnd();
|
|
1653
|
+
console.info(`[test-with-playwright] JavaScript coverage written to ${directory}\n${summary}`);
|
|
1654
|
+
};
|
|
1655
|
+
|
|
1656
|
+
const runWithJavascriptCoverage = async ({
|
|
1657
|
+
coverage,
|
|
1658
|
+
cwd,
|
|
1659
|
+
page,
|
|
1660
|
+
run
|
|
1661
|
+
}) => {
|
|
1662
|
+
if (!coverage) {
|
|
1663
|
+
await run();
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
await page.coverage.startJSCoverage({
|
|
1667
|
+
resetOnNavigation: false
|
|
1668
|
+
});
|
|
1669
|
+
try {
|
|
1670
|
+
await run();
|
|
1671
|
+
} finally {
|
|
1672
|
+
const entries = await page.coverage.stopJSCoverage();
|
|
1673
|
+
const coverageMap = await createJavascriptCoverage(entries);
|
|
1674
|
+
await writeJavascriptCoverage(coverageMap, join(cwd, 'coverage'));
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
1677
|
+
|
|
1462
1678
|
class Locked extends Error {
|
|
1463
1679
|
constructor(port) {
|
|
1464
1680
|
super(`${port} is locked`);
|
|
@@ -1760,101 +1976,26 @@ const getElectronProcessArgs = ({
|
|
|
1760
1976
|
platform = process.platform,
|
|
1761
1977
|
userDataDir
|
|
1762
1978
|
}) => {
|
|
1763
|
-
return [
|
|
1979
|
+
return [...(platform === 'linux' ? ['--no-sandbox'] : []), ...args, `--user-data-dir=${userDataDir}`];
|
|
1764
1980
|
};
|
|
1765
1981
|
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1768
|
-
const electronConnectionTimeout = 120_000;
|
|
1769
|
-
const devtoolsRegex = /^DevTools listening on (ws:\/\/.*)$/;
|
|
1770
|
-
const waitForDevtoolsEndpoint = async child => {
|
|
1771
|
-
const {
|
|
1772
|
-
stderr
|
|
1773
|
-
} = child;
|
|
1774
|
-
if (!stderr) {
|
|
1775
|
-
throw new Error('Electron stderr is unavailable');
|
|
1776
|
-
}
|
|
1777
|
-
const lines = createInterface({
|
|
1778
|
-
input: stderr
|
|
1779
|
-
});
|
|
1780
|
-
const {
|
|
1781
|
-
promise,
|
|
1782
|
-
reject,
|
|
1783
|
-
resolve
|
|
1784
|
-
} = Promise.withResolvers();
|
|
1785
|
-
const stderrLines = [];
|
|
1786
|
-
const onExit = () => {
|
|
1787
|
-
const details = stderrLines.length > 0 ? `: ${stderrLines.join('\n')}` : '';
|
|
1788
|
-
reject(new Error(`Electron exited before DevTools endpoint was available${details}`));
|
|
1789
|
-
};
|
|
1790
|
-
const onLine = line => {
|
|
1791
|
-
stderrLines.push(line);
|
|
1792
|
-
const match = line.match(devtoolsRegex);
|
|
1793
|
-
if (match) {
|
|
1794
|
-
resolve(match[1]);
|
|
1795
|
-
}
|
|
1796
|
-
};
|
|
1797
|
-
child.once('exit', onExit);
|
|
1798
|
-
lines.on('line', onLine);
|
|
1799
|
-
try {
|
|
1800
|
-
return await promise;
|
|
1801
|
-
} finally {
|
|
1802
|
-
child.off('exit', onExit);
|
|
1803
|
-
lines.off('line', onLine);
|
|
1804
|
-
lines.close();
|
|
1805
|
-
}
|
|
1806
|
-
};
|
|
1807
|
-
const getFirstPage = async browser => {
|
|
1808
|
-
const context = browser.contexts()[0];
|
|
1809
|
-
const pages = context.pages();
|
|
1810
|
-
if (pages.length > 0) {
|
|
1811
|
-
return pages[0];
|
|
1812
|
-
}
|
|
1813
|
-
return context.waitForEvent('page', {
|
|
1814
|
-
timeout: 15_000
|
|
1815
|
-
});
|
|
1816
|
-
};
|
|
1817
|
-
const waitForChildExit = async child => {
|
|
1818
|
-
if (child.exitCode !== null || child.signalCode !== null) {
|
|
1819
|
-
return;
|
|
1820
|
-
}
|
|
1821
|
-
await new Promise(resolve => {
|
|
1822
|
-
const timeout = setTimeout(resolve, 5000);
|
|
1823
|
-
child.once('exit', () => {
|
|
1824
|
-
clearTimeout(timeout);
|
|
1825
|
-
resolve();
|
|
1826
|
-
});
|
|
1827
|
-
});
|
|
1828
|
-
};
|
|
1829
|
-
const stopElectronProcess = async child => {
|
|
1830
|
-
if (child.exitCode === null && child.signalCode === null) {
|
|
1831
|
-
child.kill(SIGINT);
|
|
1832
|
-
await waitForChildExit(child);
|
|
1833
|
-
}
|
|
1834
|
-
if (child.exitCode === null && child.signalCode === null) {
|
|
1835
|
-
child.kill('SIGKILL');
|
|
1836
|
-
await waitForChildExit(child);
|
|
1837
|
-
}
|
|
1838
|
-
};
|
|
1982
|
+
const electronLaunchTimeout = 120_000;
|
|
1839
1983
|
const closeElectron = async ({
|
|
1840
|
-
|
|
1841
|
-
child,
|
|
1984
|
+
electronApp,
|
|
1842
1985
|
userDataDir
|
|
1843
1986
|
}) => {
|
|
1844
1987
|
try {
|
|
1845
|
-
await
|
|
1988
|
+
await electronApp.close();
|
|
1846
1989
|
} catch {
|
|
1847
1990
|
// ignore close errors during cleanup
|
|
1848
1991
|
}
|
|
1849
|
-
await stopElectronProcess(child);
|
|
1850
1992
|
await rm(userDataDir, {
|
|
1851
1993
|
force: true,
|
|
1852
1994
|
recursive: true
|
|
1853
1995
|
});
|
|
1854
1996
|
};
|
|
1855
1997
|
const createElectronLaunch = ({
|
|
1856
|
-
|
|
1857
|
-
child,
|
|
1998
|
+
electronApp,
|
|
1858
1999
|
page,
|
|
1859
2000
|
signal,
|
|
1860
2001
|
userDataDir
|
|
@@ -1869,8 +2010,7 @@ const createElectronLaunch = ({
|
|
|
1869
2010
|
process.off('SIGINT', handleSigint);
|
|
1870
2011
|
process.off('SIGTERM', handleSigterm);
|
|
1871
2012
|
await closeElectron({
|
|
1872
|
-
|
|
1873
|
-
child,
|
|
2013
|
+
electronApp,
|
|
1874
2014
|
userDataDir
|
|
1875
2015
|
});
|
|
1876
2016
|
};
|
|
@@ -1895,13 +2035,6 @@ const createElectronLaunch = ({
|
|
|
1895
2035
|
signal.addEventListener('abort', handleAbort);
|
|
1896
2036
|
process.once('SIGINT', handleSigint);
|
|
1897
2037
|
process.once('SIGTERM', handleSigterm);
|
|
1898
|
-
const electronApp = {
|
|
1899
|
-
close: dispose,
|
|
1900
|
-
process: () => {
|
|
1901
|
-
return child;
|
|
1902
|
-
},
|
|
1903
|
-
[Symbol.asyncDispose]: dispose
|
|
1904
|
-
};
|
|
1905
2038
|
return {
|
|
1906
2039
|
electronApp,
|
|
1907
2040
|
page,
|
|
@@ -1918,44 +2051,44 @@ const startElectron = async ({
|
|
|
1918
2051
|
args: launchOptions.args,
|
|
1919
2052
|
userDataDir
|
|
1920
2053
|
});
|
|
1921
|
-
|
|
1922
|
-
env: launchOptions.env,
|
|
1923
|
-
stdio: ['ignore', 'ignore', 'pipe']
|
|
1924
|
-
});
|
|
1925
|
-
let browser;
|
|
2054
|
+
let electronApp;
|
|
1926
2055
|
try {
|
|
1927
|
-
const endpoint = await waitForDevtoolsEndpoint(child);
|
|
1928
2056
|
const {
|
|
1929
|
-
|
|
2057
|
+
_electron
|
|
1930
2058
|
} = await import('@playwright/test');
|
|
1931
|
-
|
|
1932
|
-
|
|
2059
|
+
electronApp = await _electron.launch({
|
|
2060
|
+
args: [...args],
|
|
2061
|
+
env: launchOptions.env,
|
|
2062
|
+
executablePath: launchOptions.executablePath,
|
|
2063
|
+
timeout: electronLaunchTimeout
|
|
2064
|
+
});
|
|
2065
|
+
const page = await electronApp.firstWindow({
|
|
2066
|
+
timeout: electronLaunchTimeout
|
|
1933
2067
|
});
|
|
1934
|
-
const page = await getFirstPage(browser);
|
|
1935
2068
|
return createElectronLaunch({
|
|
1936
|
-
|
|
1937
|
-
child,
|
|
2069
|
+
electronApp,
|
|
1938
2070
|
page,
|
|
1939
2071
|
signal,
|
|
1940
2072
|
userDataDir
|
|
1941
2073
|
});
|
|
1942
2074
|
} catch (error) {
|
|
1943
|
-
if (
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
2075
|
+
if (electronApp) {
|
|
2076
|
+
await closeElectron({
|
|
2077
|
+
electronApp,
|
|
2078
|
+
userDataDir
|
|
2079
|
+
});
|
|
2080
|
+
} else {
|
|
2081
|
+
await rm(userDataDir, {
|
|
2082
|
+
force: true,
|
|
2083
|
+
recursive: true
|
|
2084
|
+
});
|
|
1949
2085
|
}
|
|
1950
|
-
await stopElectronProcess(child);
|
|
1951
|
-
await rm(userDataDir, {
|
|
1952
|
-
force: true,
|
|
1953
|
-
recursive: true
|
|
1954
|
-
});
|
|
1955
2086
|
throw error;
|
|
1956
2087
|
}
|
|
1957
2088
|
};
|
|
1958
2089
|
|
|
2090
|
+
const SIGINT = 'SIGINT';
|
|
2091
|
+
|
|
1959
2092
|
const tearDownTests = async ({
|
|
1960
2093
|
child,
|
|
1961
2094
|
controller,
|
|
@@ -1982,8 +2115,9 @@ const tearDownTests = async ({
|
|
|
1982
2115
|
* @param {boolean} traceFocus
|
|
1983
2116
|
* @param {string} filter
|
|
1984
2117
|
* @param {boolean} reusePage
|
|
2118
|
+
* @param {boolean} coverage
|
|
1985
2119
|
*/
|
|
1986
|
-
const runAllTests = async (extensionPath, testPath, cwd, browser, headless, timeout, runtimeOptions, traceFocus, filter, reusePage) => {
|
|
2120
|
+
const runAllTests = async (extensionPath, testPath, cwd, browser, headless, timeout, runtimeOptions, traceFocus, filter, reusePage, svgScreenshotOptions, coverage) => {
|
|
1987
2121
|
string(extensionPath);
|
|
1988
2122
|
string(testPath);
|
|
1989
2123
|
string(cwd);
|
|
@@ -1992,6 +2126,10 @@ const runAllTests = async (extensionPath, testPath, cwd, browser, headless, time
|
|
|
1992
2126
|
number(timeout);
|
|
1993
2127
|
object(runtimeOptions);
|
|
1994
2128
|
boolean(reusePage);
|
|
2129
|
+
boolean(coverage);
|
|
2130
|
+
if (svgScreenshotOptions !== undefined) {
|
|
2131
|
+
object(svgScreenshotOptions);
|
|
2132
|
+
}
|
|
1995
2133
|
const rpc = get(Cli);
|
|
1996
2134
|
const controller = new AbortController();
|
|
1997
2135
|
const {
|
|
@@ -2013,15 +2151,25 @@ const runAllTests = async (extensionPath, testPath, cwd, browser, headless, time
|
|
|
2013
2151
|
runtimeOptions,
|
|
2014
2152
|
signal
|
|
2015
2153
|
});
|
|
2016
|
-
await
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
onFinalResult,
|
|
2020
|
-
onResult,
|
|
2154
|
+
await runWithJavascriptCoverage({
|
|
2155
|
+
coverage,
|
|
2156
|
+
cwd,
|
|
2021
2157
|
page: electron.page,
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2158
|
+
run: async () => {
|
|
2159
|
+
await runElectronTests({
|
|
2160
|
+
...filterOption,
|
|
2161
|
+
electronApp: electron.electronApp,
|
|
2162
|
+
onFinalResult,
|
|
2163
|
+
onResult,
|
|
2164
|
+
page: electron.page,
|
|
2165
|
+
tests,
|
|
2166
|
+
testSrc,
|
|
2167
|
+
timeout,
|
|
2168
|
+
...(svgScreenshotOptions && {
|
|
2169
|
+
svgScreenshotOptions
|
|
2170
|
+
})
|
|
2171
|
+
});
|
|
2172
|
+
}
|
|
2025
2173
|
});
|
|
2026
2174
|
return;
|
|
2027
2175
|
}
|
|
@@ -2039,39 +2187,55 @@ const runAllTests = async (extensionPath, testPath, cwd, browser, headless, time
|
|
|
2039
2187
|
signal,
|
|
2040
2188
|
testPath
|
|
2041
2189
|
});
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2190
|
+
try {
|
|
2191
|
+
if (reusePage) {
|
|
2192
|
+
await runWithJavascriptCoverage({
|
|
2193
|
+
coverage,
|
|
2194
|
+
cwd,
|
|
2195
|
+
page,
|
|
2196
|
+
run: async () => {
|
|
2197
|
+
await runTestsWithReusedPage({
|
|
2198
|
+
...filterOption,
|
|
2199
|
+
onFinalResult,
|
|
2200
|
+
onResult,
|
|
2201
|
+
page,
|
|
2202
|
+
port,
|
|
2203
|
+
timeout,
|
|
2204
|
+
traceFocus
|
|
2205
|
+
});
|
|
2206
|
+
}
|
|
2207
|
+
});
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
const tests = await getTests(testSrc);
|
|
2211
|
+
await runWithJavascriptCoverage({
|
|
2212
|
+
coverage,
|
|
2213
|
+
cwd,
|
|
2047
2214
|
page,
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2215
|
+
run: async () => {
|
|
2216
|
+
await runTests({
|
|
2217
|
+
...filterOption,
|
|
2218
|
+
headless,
|
|
2219
|
+
onFinalResult,
|
|
2220
|
+
onResult,
|
|
2221
|
+
page,
|
|
2222
|
+
port,
|
|
2223
|
+
tests,
|
|
2224
|
+
testSrc,
|
|
2225
|
+
timeout,
|
|
2226
|
+
traceFocus,
|
|
2227
|
+
...(svgScreenshotOptions && {
|
|
2228
|
+
svgScreenshotOptions
|
|
2229
|
+
})
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2051
2232
|
});
|
|
2233
|
+
} finally {
|
|
2052
2234
|
await tearDownTests({
|
|
2053
2235
|
child,
|
|
2054
2236
|
controller
|
|
2055
2237
|
});
|
|
2056
|
-
return;
|
|
2057
2238
|
}
|
|
2058
|
-
const tests = await getTests(testSrc);
|
|
2059
|
-
await runTests({
|
|
2060
|
-
...filterOption,
|
|
2061
|
-
headless,
|
|
2062
|
-
onFinalResult,
|
|
2063
|
-
onResult,
|
|
2064
|
-
page,
|
|
2065
|
-
port,
|
|
2066
|
-
tests,
|
|
2067
|
-
testSrc,
|
|
2068
|
-
timeout,
|
|
2069
|
-
traceFocus
|
|
2070
|
-
});
|
|
2071
|
-
await tearDownTests({
|
|
2072
|
-
child,
|
|
2073
|
-
controller
|
|
2074
|
-
});
|
|
2075
2239
|
};
|
|
2076
2240
|
|
|
2077
2241
|
const RunAllTests = 'RunAllTests';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/test-with-playwright-worker",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.8.0",
|
|
4
4
|
"description": "Worker package for test-with-playwright",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,7 +13,16 @@
|
|
|
13
13
|
"main": "dist/workerMain.js",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@playwright/test": "1.61.1",
|
|
16
|
-
"get-port": "^7.2.0"
|
|
16
|
+
"get-port": "^7.2.0",
|
|
17
|
+
"istanbul-lib-coverage": "^3.2.2",
|
|
18
|
+
"istanbul-lib-report": "^3.0.1",
|
|
19
|
+
"istanbul-reports": "^3.2.0",
|
|
20
|
+
"v8-to-istanbul": "^9.3.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/istanbul-lib-coverage": "^2.0.6",
|
|
24
|
+
"@types/istanbul-lib-report": "^3.0.3",
|
|
25
|
+
"@types/istanbul-reports": "^3.0.4"
|
|
17
26
|
},
|
|
18
27
|
"engines": {
|
|
19
28
|
"node": ">=24"
|