qunitx-cli 0.10.0 → 0.15.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/README.md +7 -0
- package/dist/cli.js +182 -43
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -188,6 +188,13 @@ All CLI flags can also be set in `package.json` under the `qunitx` key, so you d
|
|
|
188
188
|
|
|
189
189
|
CLI flags always override `package.json` values when both are present.
|
|
190
190
|
|
|
191
|
+
### Environment variables
|
|
192
|
+
|
|
193
|
+
| Variable | Description |
|
|
194
|
+
|------------------|---------------------------------------------------------------------------------------------------------------|
|
|
195
|
+
| `CHROME_BIN` | Path to the Chrome/Chromium executable. Required on systems where Chrome is not on `PATH` (e.g. many CI environments). Set automatically when using `browser-actions/setup-chrome` in GitHub Actions. |
|
|
196
|
+
| `QUNITX_BROWSER` | Browser engine to use (`chromium`, `firefox`, `webkit`). Equivalent to `--browser` on the CLI. Useful in CI matrix jobs. |
|
|
197
|
+
|
|
191
198
|
If you do not provide any HTML template, qunitx falls back to its built-in `test/tests.html` boilerplate internally, so `qunitx init` is optional.
|
|
192
199
|
|
|
193
200
|
You can also pass a custom HTML file on the CLI:
|
package/dist/cli.js
CHANGED
|
@@ -129,7 +129,13 @@ var init_early_chrome = __esm({
|
|
|
129
129
|
openWatchMode = openFromArgv && watchFromArgv;
|
|
130
130
|
earlyChromeProcRef = null;
|
|
131
131
|
if (!openWatchMode) {
|
|
132
|
-
process.on("exit", () =>
|
|
132
|
+
process.on("exit", () => {
|
|
133
|
+
if (!earlyChromeProcRef) return;
|
|
134
|
+
try {
|
|
135
|
+
earlyChromeProcRef.kill("SIGKILL");
|
|
136
|
+
} catch {
|
|
137
|
+
}
|
|
138
|
+
});
|
|
133
139
|
}
|
|
134
140
|
perfLog("early-chrome.js: module evaluated");
|
|
135
141
|
earlyBrowserPromise = isRunCommand && browserFromArgv === "chromium" ? findChrome().then((chromePath) => {
|
|
@@ -676,17 +682,38 @@ function setupWebServer(config, cachedContent) {
|
|
|
676
682
|
socket.on("message", function message(data) {
|
|
677
683
|
const { event, details, abort } = JSON.parse(data);
|
|
678
684
|
if (event === "wsOpen") {
|
|
685
|
+
config._phase = "loading";
|
|
679
686
|
config._onWsOpen?.();
|
|
680
687
|
} else if (event === "connection") {
|
|
688
|
+
config._phase = "running";
|
|
681
689
|
if (!config._groupMode) console.log("TAP version 13");
|
|
690
|
+
if (config.debug && config._groupMode) {
|
|
691
|
+
const allFiles = Object.keys(config.fsTree);
|
|
692
|
+
const relFiles = allFiles.map((f) => f.replace(`${config.projectRoot}/`, ""));
|
|
693
|
+
const shown = relFiles.slice(0, 2);
|
|
694
|
+
const rest = relFiles.length - shown.length;
|
|
695
|
+
const fileList = rest > 0 ? `${shown.join(" ")} +${rest} more` : shown.join(" ");
|
|
696
|
+
console.log("#", blue(`\u2500\u2500 ${fileList} \u2500\u2500`));
|
|
697
|
+
}
|
|
682
698
|
config._resetTestTimeout?.();
|
|
683
699
|
} else if (event === "testEnd" && !abort) {
|
|
684
700
|
if (details.status === "failed") {
|
|
685
701
|
config.lastFailedTestFiles = config.lastRanTestFiles;
|
|
686
702
|
}
|
|
703
|
+
if (config.debug && details.runtime > config.timeout * 0.8) {
|
|
704
|
+
console.log(
|
|
705
|
+
`# SLOW (${details.runtime.toFixed(0)}ms / ${config.timeout}ms timeout): ${details.fullName.join(" | ")}`
|
|
706
|
+
);
|
|
707
|
+
}
|
|
687
708
|
config._resetTestTimeout?.();
|
|
688
709
|
TAPDisplayTestResult(config.COUNTER, details);
|
|
689
710
|
} else if (event === "done") {
|
|
711
|
+
config._phase = "done";
|
|
712
|
+
if (config.debug && config._groupMode) {
|
|
713
|
+
console.log(
|
|
714
|
+
`# group done: ${details.passed} passed, ${details.failed} failed (${details.runtime}ms)`
|
|
715
|
+
);
|
|
716
|
+
}
|
|
690
717
|
if (typeof config._testRunDone === "function") {
|
|
691
718
|
config._testRunDone();
|
|
692
719
|
config._testRunDone = null;
|
|
@@ -695,10 +722,34 @@ function setupWebServer(config, cachedContent) {
|
|
|
695
722
|
});
|
|
696
723
|
});
|
|
697
724
|
server.get("/tests.js", (_req, res) => {
|
|
725
|
+
const bytes = cachedContent.allTestCode?.length ?? null;
|
|
726
|
+
console.log(
|
|
727
|
+
`# [HTTPServer] GET /tests.js \u2192 ${bytes !== null ? `${bytes} bytes` : "NOT READY (allTestCode is null)"}`
|
|
728
|
+
);
|
|
729
|
+
if (bytes === null) {
|
|
730
|
+
res.writeHead(503, { "Content-Type": "application/javascript", "Cache-Control": "no-store" });
|
|
731
|
+
res.end(
|
|
732
|
+
'console.error("[qunitx] /tests.js requested before bundle was built \u2014 allTestCode is null");'
|
|
733
|
+
);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
config._onTestsJsServed?.();
|
|
698
737
|
res.writeHead(200, { "Content-Type": "application/javascript", "Cache-Control": "no-store" });
|
|
699
738
|
res.end(cachedContent.allTestCode);
|
|
700
739
|
});
|
|
701
740
|
server.get("/filtered-tests.js", (_req, res) => {
|
|
741
|
+
const bytes = cachedContent.filteredTestCode?.length ?? null;
|
|
742
|
+
console.log(
|
|
743
|
+
`# [HTTPServer] GET /filtered-tests.js \u2192 ${bytes !== null ? `${bytes} bytes` : "NOT READY (filteredTestCode is null)"}`
|
|
744
|
+
);
|
|
745
|
+
if (bytes === null) {
|
|
746
|
+
res.writeHead(503, { "Content-Type": "application/javascript", "Cache-Control": "no-store" });
|
|
747
|
+
res.end(
|
|
748
|
+
'console.error("[qunitx] /filtered-tests.js requested before bundle was built \u2014 filteredTestCode is null");'
|
|
749
|
+
);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
config._onTestsJsServed?.();
|
|
702
753
|
res.writeHead(200, { "Content-Type": "application/javascript", "Cache-Control": "no-store" });
|
|
703
754
|
res.end(cachedContent.filteredTestCode);
|
|
704
755
|
});
|
|
@@ -936,6 +987,7 @@ var init_web_server = __esm({
|
|
|
936
987
|
init_find_internal_assets_from_html();
|
|
937
988
|
init_html_content_marker();
|
|
938
989
|
init_display_test_result();
|
|
990
|
+
init_color();
|
|
939
991
|
init_path_exists();
|
|
940
992
|
init_http();
|
|
941
993
|
fsPromise = fs7.promises;
|
|
@@ -1002,7 +1054,9 @@ async function setupBrowser(config, cachedContent, existingBrowser = null) {
|
|
|
1002
1054
|
window.IS_PLAYWRIGHT = true;
|
|
1003
1055
|
});
|
|
1004
1056
|
page.on("console", async (msg) => {
|
|
1005
|
-
|
|
1057
|
+
const type = msg.type();
|
|
1058
|
+
const alwaysShow = type === "warning" || type === "error";
|
|
1059
|
+
if (!alwaysShow && !config.debug) return;
|
|
1006
1060
|
try {
|
|
1007
1061
|
const values = await Promise.all(msg.args().map((arg) => arg.jsonValue()));
|
|
1008
1062
|
console.log(...values);
|
|
@@ -1090,7 +1144,7 @@ async function runUserModule(modulePath, params, scriptPosition) {
|
|
|
1090
1144
|
console.log("#", red(`QUnitX ${scriptPosition} script failed:`));
|
|
1091
1145
|
console.trace(error);
|
|
1092
1146
|
console.error(error);
|
|
1093
|
-
|
|
1147
|
+
process.stdout.write("", () => process.exit(1));
|
|
1094
1148
|
}
|
|
1095
1149
|
}
|
|
1096
1150
|
var init_run_user_module = __esm({
|
|
@@ -1121,23 +1175,31 @@ import esbuild from "esbuild";
|
|
|
1121
1175
|
async function buildTestBundle(config, cachedContent) {
|
|
1122
1176
|
const { projectRoot, output } = config;
|
|
1123
1177
|
const allTestFilePaths = Object.keys(config.fsTree);
|
|
1178
|
+
if (allTestFilePaths.length === 0) {
|
|
1179
|
+
console.log("# [buildTestBundle] fsTree is empty \u2014 skipping build (no test files found)");
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
const outfile = `${projectRoot}/${output}/tests.js`;
|
|
1124
1183
|
await Promise.all([
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1184
|
+
buildWithOverlayfsRetry(
|
|
1185
|
+
{
|
|
1186
|
+
stdin: {
|
|
1187
|
+
contents: allTestFilePaths.map((f) => `import "${f}";`).join(""),
|
|
1188
|
+
resolveDir: process.cwd()
|
|
1189
|
+
},
|
|
1190
|
+
bundle: true,
|
|
1191
|
+
logLevel: "error",
|
|
1192
|
+
outfile,
|
|
1193
|
+
keepNames: true,
|
|
1194
|
+
sourcemap: config.debug ? "inline" : config.watch ? "linked" : false,
|
|
1195
|
+
// Signal the runtime that all test modules are registered. The runtime's maybeStart()
|
|
1196
|
+
// waits for both this event and the WebSocket 'open' event before calling QUnit.start().
|
|
1197
|
+
// Dispatching from the bundle (rather than from a script onload attr) is reliable across
|
|
1198
|
+
// all browsers and does not require changes to user test code.
|
|
1199
|
+
footer: { js: 'window.dispatchEvent(new CustomEvent("qunitx:tests-ready"));' }
|
|
1129
1200
|
},
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
outfile: `${projectRoot}/${output}/tests.js`,
|
|
1133
|
-
keepNames: true,
|
|
1134
|
-
sourcemap: config.debug ? "inline" : config.watch ? "linked" : false,
|
|
1135
|
-
// Signal the runtime that all test modules are registered. The runtime's maybeStart()
|
|
1136
|
-
// waits for both this event and the WebSocket 'open' event before calling QUnit.start().
|
|
1137
|
-
// Dispatching from the bundle (rather than from a script onload attr) is reliable across
|
|
1138
|
-
// all browsers and does not require changes to user test code.
|
|
1139
|
-
footer: { js: 'window.dispatchEvent(new CustomEvent("qunitx:tests-ready"));' }
|
|
1140
|
-
}),
|
|
1201
|
+
outfile
|
|
1202
|
+
),
|
|
1141
1203
|
Promise.all(
|
|
1142
1204
|
cachedContent.htmlPathsToRunTests.map(async (htmlPath) => {
|
|
1143
1205
|
const targetPath = `${config.projectRoot}/${config.output}${htmlPath}`;
|
|
@@ -1148,7 +1210,7 @@ async function buildTestBundle(config, cachedContent) {
|
|
|
1148
1210
|
})
|
|
1149
1211
|
)
|
|
1150
1212
|
]);
|
|
1151
|
-
cachedContent.allTestCode = await fs8.readFile(
|
|
1213
|
+
cachedContent.allTestCode = await fs8.readFile(outfile);
|
|
1152
1214
|
}
|
|
1153
1215
|
async function runTestsInBrowser(config, cachedContent = {}, connections, targetTestFilesToFilter) {
|
|
1154
1216
|
const { projectRoot, output } = config;
|
|
@@ -1162,6 +1224,9 @@ async function runTestsInBrowser(config, cachedContent = {}, connections, target
|
|
|
1162
1224
|
if (!cachedContent.allTestCode) {
|
|
1163
1225
|
await buildTestBundle(config, cachedContent);
|
|
1164
1226
|
}
|
|
1227
|
+
if (!cachedContent.allTestCode) {
|
|
1228
|
+
return connections;
|
|
1229
|
+
}
|
|
1165
1230
|
if (runHasFilter) {
|
|
1166
1231
|
const outputPath = `${projectRoot}/${output}/filtered-tests.js`;
|
|
1167
1232
|
await buildFilteredTests(targetTestFilesToFilter, outputPath, config);
|
|
@@ -1204,17 +1269,42 @@ async function runTestsInBrowser(config, cachedContent = {}, connections, target
|
|
|
1204
1269
|
return connections;
|
|
1205
1270
|
}
|
|
1206
1271
|
function buildFilteredTests(filteredTests, outputPath, config) {
|
|
1207
|
-
return
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1272
|
+
return buildWithOverlayfsRetry(
|
|
1273
|
+
{
|
|
1274
|
+
stdin: {
|
|
1275
|
+
contents: filteredTests.map((f) => `import "${f}";`).join(""),
|
|
1276
|
+
resolveDir: process.cwd()
|
|
1277
|
+
},
|
|
1278
|
+
bundle: true,
|
|
1279
|
+
logLevel: "error",
|
|
1280
|
+
outfile: outputPath,
|
|
1281
|
+
sourcemap: config.debug ? "inline" : config.watch ? "linked" : false,
|
|
1282
|
+
footer: { js: 'window.dispatchEvent(new CustomEvent("qunitx:tests-ready"));' }
|
|
1211
1283
|
},
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1284
|
+
outputPath
|
|
1285
|
+
);
|
|
1286
|
+
}
|
|
1287
|
+
async function buildWithOverlayfsRetry(options, outfile) {
|
|
1288
|
+
const RETRY_DELAY_MS = 100;
|
|
1289
|
+
const MAX_RETRIES = 3;
|
|
1290
|
+
const EMPTY_BUNDLE_THRESHOLD = 500;
|
|
1291
|
+
let result = await esbuild.build(options);
|
|
1292
|
+
for (let retry = 1; retry <= MAX_RETRIES; retry++) {
|
|
1293
|
+
const bytes2 = (await fs8.stat(outfile)).size;
|
|
1294
|
+
if (bytes2 >= EMPTY_BUNDLE_THRESHOLD) return result;
|
|
1295
|
+
console.log(
|
|
1296
|
+
`# [buildWithOverlayfsRetry] bundle is ${bytes2} bytes (< ${EMPTY_BUNDLE_THRESHOLD}) on attempt ${retry}/${MAX_RETRIES} \u2014 overlayfs flush race, retrying in ${RETRY_DELAY_MS}ms`
|
|
1297
|
+
);
|
|
1298
|
+
await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));
|
|
1299
|
+
result = await esbuild.build(options);
|
|
1300
|
+
}
|
|
1301
|
+
const bytes = (await fs8.stat(outfile)).size;
|
|
1302
|
+
if (bytes < EMPTY_BUNDLE_THRESHOLD) {
|
|
1303
|
+
console.log(
|
|
1304
|
+
`# [buildWithOverlayfsRetry] bundle is ${bytes} bytes after ${MAX_RETRIES} retries \u2014 proceeding`
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
return result;
|
|
1218
1308
|
}
|
|
1219
1309
|
async function runTestInsideHTMLFile(filePath, { page, server, browser }, config) {
|
|
1220
1310
|
let QUNIT_RESULT;
|
|
@@ -1233,6 +1323,10 @@ async function runTestInsideHTMLFile(filePath, { page, server, browser }, config
|
|
|
1233
1323
|
clearTimeout(timeoutHandle);
|
|
1234
1324
|
timeoutHandle = setTimeout(resolveTestRace, config.timeout * 3);
|
|
1235
1325
|
};
|
|
1326
|
+
config._onTestsJsServed = () => {
|
|
1327
|
+
clearTimeout(timeoutHandle);
|
|
1328
|
+
timeoutHandle = setTimeout(resolveTestRace, config.timeout * 4);
|
|
1329
|
+
};
|
|
1236
1330
|
config._resetTestTimeout = () => {
|
|
1237
1331
|
wsConnected = true;
|
|
1238
1332
|
clearTimeout(timeoutHandle);
|
|
@@ -1256,6 +1350,7 @@ async function runTestInsideHTMLFile(filePath, { page, server, browser }, config
|
|
|
1256
1350
|
} finally {
|
|
1257
1351
|
clearTimeout(timeoutHandle);
|
|
1258
1352
|
config._onWsOpen = null;
|
|
1353
|
+
config._onTestsJsServed = null;
|
|
1259
1354
|
config._resetTestTimeout = null;
|
|
1260
1355
|
config._testRunDone = null;
|
|
1261
1356
|
}
|
|
@@ -1341,6 +1436,20 @@ function setupFileWatchers(testFileLookupPaths, config, onEventFunc, onFinishFun
|
|
|
1341
1436
|
onFinishFunc
|
|
1342
1437
|
);
|
|
1343
1438
|
} catch {
|
|
1439
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1440
|
+
try {
|
|
1441
|
+
const s = await stat(fullPath);
|
|
1442
|
+
handleWatchEvent(
|
|
1443
|
+
config,
|
|
1444
|
+
extensions,
|
|
1445
|
+
s.isDirectory() ? "addDir" : "add",
|
|
1446
|
+
fullPath,
|
|
1447
|
+
onEventFunc,
|
|
1448
|
+
onFinishFunc
|
|
1449
|
+
);
|
|
1450
|
+
return;
|
|
1451
|
+
} catch {
|
|
1452
|
+
}
|
|
1344
1453
|
if (!(config.fsTree && fullPath in config.fsTree)) return;
|
|
1345
1454
|
handleWatchEvent(config, extensions, "unlink", fullPath, onEventFunc, onFinishFunc);
|
|
1346
1455
|
}
|
|
@@ -1383,6 +1492,7 @@ function setupFileWatchers(testFileLookupPaths, config, onEventFunc, onFinishFun
|
|
|
1383
1492
|
function handleWatchEvent(config, extensions, event, filePath, onEventFunc, onFinishFunc) {
|
|
1384
1493
|
const isFileEvent = extensions.some((ext) => filePath.endsWith(`.${ext}`));
|
|
1385
1494
|
if (!isFileEvent && event !== "unlinkDir") return;
|
|
1495
|
+
if (event === "change" && config._building && config._justAddedFiles?.has(filePath)) return;
|
|
1386
1496
|
mutateFSTree(config.fsTree, event, filePath);
|
|
1387
1497
|
console.log(
|
|
1388
1498
|
"#",
|
|
@@ -1395,6 +1505,7 @@ function handleWatchEvent(config, extensions, event, filePath, onEventFunc, onFi
|
|
|
1395
1505
|
);
|
|
1396
1506
|
if (!config._building) {
|
|
1397
1507
|
config._building = true;
|
|
1508
|
+
config._justAddedFiles = event === "add" ? /* @__PURE__ */ new Set([filePath]) : /* @__PURE__ */ new Set();
|
|
1398
1509
|
const result = onEventFunc(event, filePath);
|
|
1399
1510
|
if (!(result instanceof Promise)) {
|
|
1400
1511
|
config._building = false;
|
|
@@ -1413,6 +1524,7 @@ function handleWatchEvent(config, extensions, event, filePath, onEventFunc, onFi
|
|
|
1413
1524
|
}
|
|
1414
1525
|
});
|
|
1415
1526
|
} else {
|
|
1527
|
+
if (event === "add") config._justAddedFiles?.add(filePath);
|
|
1416
1528
|
config._pendingBuildTrigger = () => handleWatchEvent(config, extensions, event, filePath, onEventFunc, onFinishFunc);
|
|
1417
1529
|
}
|
|
1418
1530
|
}
|
|
@@ -1507,7 +1619,7 @@ function setupKeyboardEvents(config, cachedContent, connections) {
|
|
|
1507
1619
|
});
|
|
1508
1620
|
}
|
|
1509
1621
|
function abortBrowserQUnit(_config, connections) {
|
|
1510
|
-
connections.server.publish("abort"
|
|
1622
|
+
connections.server.publish("abort");
|
|
1511
1623
|
}
|
|
1512
1624
|
var init_keyboard_events = __esm({
|
|
1513
1625
|
"lib/setup/keyboard-events.ts"() {
|
|
@@ -1584,11 +1696,21 @@ async function run(config) {
|
|
|
1584
1696
|
if (["change", "unlink", "unlinkDir"].includes(event)) {
|
|
1585
1697
|
if (event === "change" && !(file in config.fsTree)) return;
|
|
1586
1698
|
cachedContent.allTestCode = null;
|
|
1699
|
+
if (config.debug) {
|
|
1700
|
+
console.log(
|
|
1701
|
+
`# Rerun triggered: ${event} \u2192 ${file.replace(`${config.projectRoot}/`, "")}`
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1587
1704
|
return await runTestsInBrowser(config, cachedContent, connections);
|
|
1588
1705
|
}
|
|
1706
|
+
if (config.debug) {
|
|
1707
|
+
console.log(
|
|
1708
|
+
`# Rerun triggered: ${event} \u2192 ${file.replace(`${config.projectRoot}/`, "")}`
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1589
1711
|
await runTestsInBrowser(config, cachedContent, connections, [file]);
|
|
1590
1712
|
},
|
|
1591
|
-
(_path, _event) => connections.server.publish("refresh"
|
|
1713
|
+
(_path, _event) => connections.server.publish("refresh")
|
|
1592
1714
|
);
|
|
1593
1715
|
await watcherReady;
|
|
1594
1716
|
}
|
|
@@ -1604,10 +1726,14 @@ async function run(config) {
|
|
|
1604
1726
|
fsTree: Object.fromEntries(groupFiles.map((f) => [f, config.fsTree[f]])),
|
|
1605
1727
|
// Single group keeps the root output dir for backward-compatible file paths.
|
|
1606
1728
|
output: groupCount === 1 ? config.output : `${config.output}/group-${i}`,
|
|
1607
|
-
_groupMode: true
|
|
1729
|
+
_groupMode: true,
|
|
1730
|
+
_phase: "bundling"
|
|
1608
1731
|
}));
|
|
1609
1732
|
const groupCachedContents = groups.map(() => ({ ...cachedContent }));
|
|
1610
1733
|
console.log("TAP version 13");
|
|
1734
|
+
console.log(
|
|
1735
|
+
`# Running ${allFiles.length} test file${allFiles.length === 1 ? "" : "s"} across ${groupCount} group${groupCount === 1 ? "" : "s"}`
|
|
1736
|
+
);
|
|
1611
1737
|
const [browser] = await Promise.all([
|
|
1612
1738
|
launchBrowser(config),
|
|
1613
1739
|
Promise.all(
|
|
@@ -1629,14 +1755,22 @@ async function run(config) {
|
|
|
1629
1755
|
const groupResults = await Promise.allSettled(
|
|
1630
1756
|
groupConfigs.map((groupConfig, i) => {
|
|
1631
1757
|
const groupTimeout = new Promise((_, reject) => {
|
|
1632
|
-
const t = setTimeout(
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1758
|
+
const t = setTimeout(() => {
|
|
1759
|
+
const files = Object.keys(groupConfig.fsTree).map(
|
|
1760
|
+
(f) => f.replace(`${groupConfig.projectRoot}/`, "")
|
|
1761
|
+
);
|
|
1762
|
+
reject(
|
|
1763
|
+
new Error(
|
|
1764
|
+
`Group ${i} timed out after ${GROUP_TIMEOUT_MS / 1e3}s in phase '${groupConfig._phase ?? "unknown"}'
|
|
1765
|
+
Files: ${files.join(", ")}`
|
|
1766
|
+
)
|
|
1767
|
+
);
|
|
1768
|
+
}, GROUP_TIMEOUT_MS);
|
|
1636
1769
|
t.unref();
|
|
1637
1770
|
});
|
|
1638
1771
|
return Promise.race([
|
|
1639
1772
|
(async () => {
|
|
1773
|
+
groupConfig._phase = "connecting";
|
|
1640
1774
|
const connections = await setupBrowser(groupConfig, groupCachedContents[i], browser);
|
|
1641
1775
|
groupConfig.expressApp = connections.server;
|
|
1642
1776
|
if (config.before) {
|
|
@@ -1794,7 +1928,7 @@ init_color();
|
|
|
1794
1928
|
var package_default = {
|
|
1795
1929
|
name: "qunitx-cli",
|
|
1796
1930
|
type: "module",
|
|
1797
|
-
version: "0.
|
|
1931
|
+
version: "0.15.0",
|
|
1798
1932
|
description: "Browser runner for QUnitx: run your qunitx tests in google-chrome",
|
|
1799
1933
|
author: "Izel Nakri",
|
|
1800
1934
|
license: "MIT",
|
|
@@ -1824,8 +1958,11 @@ var package_default = {
|
|
|
1824
1958
|
"changelog:preview": "git-cliff",
|
|
1825
1959
|
"changelog:update": "git-cliff --output CHANGELOG.md",
|
|
1826
1960
|
postinstall: "PLAYWRIGHT_SKIP_DOWNLOAD=true deno install --allow-scripts=npm:playwright-core || true",
|
|
1827
|
-
test:
|
|
1828
|
-
"test:
|
|
1961
|
+
test: "node --experimental-strip-types test/setup.ts && FORCE_COLOR=0 node --experimental-strip-types --test test/**/*-test.ts",
|
|
1962
|
+
"test:debug": "node --experimental-strip-types test/setup.ts && QUNITX_DEBUG=1 node --experimental-strip-types --test test/**/*-test.ts",
|
|
1963
|
+
dev: "node --experimental-strip-types test/setup.ts && node --experimental-strip-types --test --watch test/**/*-test.ts",
|
|
1964
|
+
"test:browser": "node --experimental-strip-types test/setup.ts && FORCE_COLOR=0 node --experimental-strip-types --test test/flags/*-test.ts test/inputs/*-test.ts",
|
|
1965
|
+
"test:release": "bash scripts/test-release.sh",
|
|
1829
1966
|
"test:sanity-first": "./cli.ts test/helpers/failing-tests.js test/helpers/failing-tests.ts",
|
|
1830
1967
|
"test:sanity-second": "./cli.ts test/helpers/passing-tests.js test/helpers/passing-tests.ts"
|
|
1831
1968
|
},
|
|
@@ -1841,15 +1978,15 @@ var package_default = {
|
|
|
1841
1978
|
url: "git+https://github.com/izelnakri/qunitx-cli.git"
|
|
1842
1979
|
},
|
|
1843
1980
|
dependencies: {
|
|
1844
|
-
esbuild: "^0.
|
|
1845
|
-
"playwright-core": "^1.
|
|
1981
|
+
esbuild: "^0.28.0",
|
|
1982
|
+
"playwright-core": "^1.59.1",
|
|
1846
1983
|
ws: "^8.20.0"
|
|
1847
1984
|
},
|
|
1848
1985
|
devDependencies: {
|
|
1849
1986
|
cors: "^2.8.6",
|
|
1850
1987
|
express: "^5.2.1",
|
|
1851
1988
|
"js-yaml": "^4.1.1",
|
|
1852
|
-
prettier: "^3.8.
|
|
1989
|
+
prettier: "^3.8.2",
|
|
1853
1990
|
qunitx: "^1.2.1",
|
|
1854
1991
|
typescript: "^6.0.2"
|
|
1855
1992
|
},
|
|
@@ -2214,7 +2351,9 @@ async function setupConfig() {
|
|
|
2214
2351
|
lastRanTestFiles: null,
|
|
2215
2352
|
COUNTER: { testCount: 0, failCount: 0, skipCount: 0, passCount: 0, errorCount: 0 },
|
|
2216
2353
|
_testRunDone: null,
|
|
2217
|
-
_resetTestTimeout: null
|
|
2354
|
+
_resetTestTimeout: null,
|
|
2355
|
+
_onWsOpen: null,
|
|
2356
|
+
_onTestsJsServed: null
|
|
2218
2357
|
};
|
|
2219
2358
|
config.htmlPaths = normalizeHTMLPaths(config.projectRoot, config.htmlPaths);
|
|
2220
2359
|
config.fsTree = await buildFSTree(config.testFileLookupPaths, config);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qunitx-cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.15.0",
|
|
5
5
|
"description": "Browser runner for QUnitx: run your qunitx tests in google-chrome",
|
|
6
6
|
"author": "Izel Nakri",
|
|
7
7
|
"license": "MIT",
|
|
@@ -31,8 +31,11 @@
|
|
|
31
31
|
"changelog:preview": "git-cliff",
|
|
32
32
|
"changelog:update": "git-cliff --output CHANGELOG.md",
|
|
33
33
|
"postinstall": "PLAYWRIGHT_SKIP_DOWNLOAD=true deno install --allow-scripts=npm:playwright-core || true",
|
|
34
|
-
"test": "node --experimental-strip-types test/setup.ts && FORCE_COLOR=0 node --experimental-strip-types --test
|
|
35
|
-
"test:
|
|
34
|
+
"test": "node --experimental-strip-types test/setup.ts && FORCE_COLOR=0 node --experimental-strip-types --test test/**/*-test.ts",
|
|
35
|
+
"test:debug": "node --experimental-strip-types test/setup.ts && QUNITX_DEBUG=1 node --experimental-strip-types --test test/**/*-test.ts",
|
|
36
|
+
"dev": "node --experimental-strip-types test/setup.ts && node --experimental-strip-types --test --watch test/**/*-test.ts",
|
|
37
|
+
"test:browser": "node --experimental-strip-types test/setup.ts && FORCE_COLOR=0 node --experimental-strip-types --test test/flags/*-test.ts test/inputs/*-test.ts",
|
|
38
|
+
"test:release": "bash scripts/test-release.sh",
|
|
36
39
|
"test:sanity-first": "./cli.ts test/helpers/failing-tests.js test/helpers/failing-tests.ts",
|
|
37
40
|
"test:sanity-second": "./cli.ts test/helpers/passing-tests.js test/helpers/passing-tests.ts"
|
|
38
41
|
},
|
|
@@ -48,15 +51,15 @@
|
|
|
48
51
|
"url": "git+https://github.com/izelnakri/qunitx-cli.git"
|
|
49
52
|
},
|
|
50
53
|
"dependencies": {
|
|
51
|
-
"esbuild": "^0.
|
|
52
|
-
"playwright-core": "^1.
|
|
54
|
+
"esbuild": "^0.28.0",
|
|
55
|
+
"playwright-core": "^1.59.1",
|
|
53
56
|
"ws": "^8.20.0"
|
|
54
57
|
},
|
|
55
58
|
"devDependencies": {
|
|
56
59
|
"cors": "^2.8.6",
|
|
57
60
|
"express": "^5.2.1",
|
|
58
61
|
"js-yaml": "^4.1.1",
|
|
59
|
-
"prettier": "^3.8.
|
|
62
|
+
"prettier": "^3.8.2",
|
|
60
63
|
"qunitx": "^1.2.1",
|
|
61
64
|
"typescript": "^6.0.2"
|
|
62
65
|
},
|