@jsenv/test 1.6.1 → 1.6.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/jsenv_test.js
CHANGED
|
@@ -8,9 +8,8 @@ import os from "node:os";
|
|
|
8
8
|
import tty from "node:tty";
|
|
9
9
|
import stringWidth from "string-width";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
|
-
import { Worker } from "node:worker_threads";
|
|
12
|
-
import { createServer } from "node:net";
|
|
13
11
|
import { spawn, spawnSync, fork } from "node:child_process";
|
|
12
|
+
import { createServer } from "node:net";
|
|
14
13
|
import v8, { takeCoverage } from "node:v8";
|
|
15
14
|
import stripAnsi from "strip-ansi";
|
|
16
15
|
import { applyBabelPlugins } from "@jsenv/ast";
|
|
@@ -20,6 +19,7 @@ import wrapAnsi from "wrap-ansi";
|
|
|
20
19
|
import { injectSupervisorIntoHTML, supervisorFileUrl } from "@jsenv/plugin-supervisor";
|
|
21
20
|
import { SOURCEMAP, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
22
21
|
import { findFreePort } from "@jsenv/server";
|
|
22
|
+
import { Worker } from "node:worker_threads";
|
|
23
23
|
|
|
24
24
|
/*
|
|
25
25
|
* See callback_race.md
|
|
@@ -2828,80 +2828,6 @@ const pingServer = async (url) => {
|
|
|
2828
2828
|
return false;
|
|
2829
2829
|
};
|
|
2830
2830
|
|
|
2831
|
-
const startServerUsingModuleUrl = async (
|
|
2832
|
-
webServer,
|
|
2833
|
-
{ signal, teardown, logger, allocatedMs },
|
|
2834
|
-
) => {
|
|
2835
|
-
if (!existsSync(new URL(webServer.moduleUrl))) {
|
|
2836
|
-
throw new Error(
|
|
2837
|
-
`webServer.moduleUrl does not lead to a file at "${webServer.moduleUrl}"`,
|
|
2838
|
-
);
|
|
2839
|
-
}
|
|
2840
|
-
const worker = new Worker(webServer.moduleUrl, {
|
|
2841
|
-
env: {
|
|
2842
|
-
// IMPORTED_BY_TEST_PLAN: "1",
|
|
2843
|
-
},
|
|
2844
|
-
stdin: true,
|
|
2845
|
-
stdout: true,
|
|
2846
|
-
});
|
|
2847
|
-
let errorReceived = false;
|
|
2848
|
-
const errorPromise = new Promise((resolve, reject) => {
|
|
2849
|
-
worker.on("error", (e) => {
|
|
2850
|
-
errorReceived = true;
|
|
2851
|
-
reject(e);
|
|
2852
|
-
});
|
|
2853
|
-
});
|
|
2854
|
-
|
|
2855
|
-
const killWorker = async () => {
|
|
2856
|
-
await worker.terminate();
|
|
2857
|
-
};
|
|
2858
|
-
|
|
2859
|
-
const startOperation = Abort.startOperation();
|
|
2860
|
-
startOperation.addAbortSignal(signal);
|
|
2861
|
-
const timeoutAbortSource = startOperation.timeout(allocatedMs);
|
|
2862
|
-
startOperation.addAbortCallback(killWorker);
|
|
2863
|
-
teardown.addCallback(killWorker);
|
|
2864
|
-
|
|
2865
|
-
const startedPromise = (async () => {
|
|
2866
|
-
const logScale = [100, 250, 500];
|
|
2867
|
-
// eslint-disable-next-line no-constant-condition
|
|
2868
|
-
while (true) {
|
|
2869
|
-
if (errorReceived) {
|
|
2870
|
-
break;
|
|
2871
|
-
}
|
|
2872
|
-
const connected = await pingServer(webServer.origin);
|
|
2873
|
-
if (connected) {
|
|
2874
|
-
break;
|
|
2875
|
-
}
|
|
2876
|
-
|
|
2877
|
-
startOperation.throwIfAborted();
|
|
2878
|
-
const delay = logScale.shift() || 1000;
|
|
2879
|
-
logger.debug(`Waiting ${delay}ms`);
|
|
2880
|
-
await new Promise((x) => setTimeout(x, delay));
|
|
2881
|
-
}
|
|
2882
|
-
})();
|
|
2883
|
-
|
|
2884
|
-
try {
|
|
2885
|
-
await Promise.race([errorPromise, startedPromise]);
|
|
2886
|
-
} catch (e) {
|
|
2887
|
-
if (Abort.isAbortError(e)) {
|
|
2888
|
-
if (timeoutAbortSource.signal.aborted) {
|
|
2889
|
-
// aborted by timeout
|
|
2890
|
-
throw new Error(
|
|
2891
|
-
`"${webServer.moduleUrl}" did not start a server in less than ${allocatedMs}ms (webServer.moduleUrl)`,
|
|
2892
|
-
);
|
|
2893
|
-
}
|
|
2894
|
-
if (signal.aborted) {
|
|
2895
|
-
// aborted from outside
|
|
2896
|
-
return;
|
|
2897
|
-
}
|
|
2898
|
-
}
|
|
2899
|
-
throw e;
|
|
2900
|
-
} finally {
|
|
2901
|
-
await startOperation.end();
|
|
2902
|
-
}
|
|
2903
|
-
};
|
|
2904
|
-
|
|
2905
2831
|
const startServerUsingCommand = async (
|
|
2906
2832
|
webServer,
|
|
2907
2833
|
{ signal, allocatedMs, logger, teardown },
|
|
@@ -2942,7 +2868,7 @@ const startServerUsingCommand = async (
|
|
|
2942
2868
|
let processClosed = false;
|
|
2943
2869
|
const closedPromise = new Promise((resolve) => {
|
|
2944
2870
|
spawnedProcess.once("exit", (exitCode, signal) => {
|
|
2945
|
-
logger.
|
|
2871
|
+
logger.debug(
|
|
2946
2872
|
`[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`,
|
|
2947
2873
|
);
|
|
2948
2874
|
processClosed = true;
|
|
@@ -2950,14 +2876,14 @@ const startServerUsingCommand = async (
|
|
|
2950
2876
|
});
|
|
2951
2877
|
});
|
|
2952
2878
|
const killProcess = async () => {
|
|
2953
|
-
logger.
|
|
2879
|
+
logger.debug(`[pid=${spawnedProcess.pid}] <kill>`);
|
|
2954
2880
|
if (!spawnedProcess.pid || spawnedProcess.killed || processClosed) {
|
|
2955
|
-
logger.
|
|
2881
|
+
logger.debug(
|
|
2956
2882
|
`[pid=${spawnedProcess.pid}] <skipped force kill spawnedProcess.killed=${spawnedProcess.killed} processClosed=${processClosed}>`,
|
|
2957
2883
|
);
|
|
2958
2884
|
return;
|
|
2959
2885
|
}
|
|
2960
|
-
logger.
|
|
2886
|
+
logger.debug(`[pid=${spawnedProcess.pid}] <will force kill>`);
|
|
2961
2887
|
// Force kill the browser.
|
|
2962
2888
|
try {
|
|
2963
2889
|
if (process.platform === "win32") {
|
|
@@ -2970,7 +2896,9 @@ const startServerUsingCommand = async (
|
|
|
2970
2896
|
taskkillProcess.stderr.toString(),
|
|
2971
2897
|
];
|
|
2972
2898
|
if (stdout)
|
|
2973
|
-
logger.
|
|
2899
|
+
logger.debug(
|
|
2900
|
+
`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout}`,
|
|
2901
|
+
);
|
|
2974
2902
|
if (stderr)
|
|
2975
2903
|
logger.info(`[pid=${spawnedProcess.pid}] taskkill stderr: ${stderr}`);
|
|
2976
2904
|
} else {
|
|
@@ -3016,7 +2944,7 @@ const startServerUsingCommand = async (
|
|
|
3016
2944
|
if (timeoutAbortSource.signal.aborted) {
|
|
3017
2945
|
// aborted by timeout
|
|
3018
2946
|
throw new Error(
|
|
3019
|
-
`"${webServer.command}" command did not start a server in less than ${allocatedMs}ms
|
|
2947
|
+
`"${webServer.command}" command did not start a server in less than ${allocatedMs}ms`,
|
|
3020
2948
|
);
|
|
3021
2949
|
}
|
|
3022
2950
|
if (signal.aborted) {
|
|
@@ -3030,6 +2958,19 @@ const startServerUsingCommand = async (
|
|
|
3030
2958
|
}
|
|
3031
2959
|
};
|
|
3032
2960
|
|
|
2961
|
+
const startServerUsingModuleUrl = async (webServer, params) => {
|
|
2962
|
+
if (!existsSync(new URL(webServer.moduleUrl))) {
|
|
2963
|
+
throw new Error(`"${webServer.moduleUrl}" does not lead to a file`);
|
|
2964
|
+
}
|
|
2965
|
+
return startServerUsingCommand(
|
|
2966
|
+
{
|
|
2967
|
+
...webServer,
|
|
2968
|
+
command: `node ${fileURLToPath(webServer.moduleUrl)}`,
|
|
2969
|
+
},
|
|
2970
|
+
params,
|
|
2971
|
+
);
|
|
2972
|
+
};
|
|
2973
|
+
|
|
3033
2974
|
const basicFetch = async (
|
|
3034
2975
|
url,
|
|
3035
2976
|
{ rejectUnauthorized = true, method = "GET", headers = {} } = {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/test",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@jsenv/abort": "4.2.4",
|
|
37
|
-
"@jsenv/ast": "5.1.
|
|
37
|
+
"@jsenv/ast": "5.1.3",
|
|
38
38
|
"@jsenv/filesystem": "4.2.6",
|
|
39
39
|
"@jsenv/log": "3.4.0",
|
|
40
|
-
"@jsenv/plugin-supervisor": "1.3.
|
|
40
|
+
"@jsenv/plugin-supervisor": "1.3.3",
|
|
41
41
|
"@jsenv/urls": "2.2.1",
|
|
42
42
|
"@jsenv/url-meta": "8.1.0",
|
|
43
43
|
"@jsenv/uneval": "1.6.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"istanbul-lib-instrument": "6.0.0",
|
|
48
48
|
"istanbul-lib-report": "3.0.1",
|
|
49
49
|
"istanbul-reports": "3.1.6",
|
|
50
|
-
"@paralleldrive/cuid2": "2.2.
|
|
50
|
+
"@paralleldrive/cuid2": "2.2.2",
|
|
51
51
|
"@c88/v8-coverage": "0.1.1",
|
|
52
52
|
"strip-ansi": "7.1.0",
|
|
53
53
|
"wrap-ansi": "8.1.0",
|
|
@@ -43,7 +43,7 @@ export const startServerUsingCommand = async (
|
|
|
43
43
|
let processClosed = false;
|
|
44
44
|
const closedPromise = new Promise((resolve) => {
|
|
45
45
|
spawnedProcess.once("exit", (exitCode, signal) => {
|
|
46
|
-
logger.
|
|
46
|
+
logger.debug(
|
|
47
47
|
`[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`,
|
|
48
48
|
);
|
|
49
49
|
processClosed = true;
|
|
@@ -51,14 +51,14 @@ export const startServerUsingCommand = async (
|
|
|
51
51
|
});
|
|
52
52
|
});
|
|
53
53
|
const killProcess = async () => {
|
|
54
|
-
logger.
|
|
54
|
+
logger.debug(`[pid=${spawnedProcess.pid}] <kill>`);
|
|
55
55
|
if (!spawnedProcess.pid || spawnedProcess.killed || processClosed) {
|
|
56
|
-
logger.
|
|
56
|
+
logger.debug(
|
|
57
57
|
`[pid=${spawnedProcess.pid}] <skipped force kill spawnedProcess.killed=${spawnedProcess.killed} processClosed=${processClosed}>`,
|
|
58
58
|
);
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
|
-
logger.
|
|
61
|
+
logger.debug(`[pid=${spawnedProcess.pid}] <will force kill>`);
|
|
62
62
|
// Force kill the browser.
|
|
63
63
|
try {
|
|
64
64
|
if (process.platform === "win32") {
|
|
@@ -71,7 +71,9 @@ export const startServerUsingCommand = async (
|
|
|
71
71
|
taskkillProcess.stderr.toString(),
|
|
72
72
|
];
|
|
73
73
|
if (stdout)
|
|
74
|
-
logger.
|
|
74
|
+
logger.debug(
|
|
75
|
+
`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout}`,
|
|
76
|
+
);
|
|
75
77
|
if (stderr)
|
|
76
78
|
logger.info(`[pid=${spawnedProcess.pid}] taskkill stderr: ${stderr}`);
|
|
77
79
|
} else {
|
|
@@ -117,7 +119,7 @@ export const startServerUsingCommand = async (
|
|
|
117
119
|
if (timeoutAbortSource.signal.aborted) {
|
|
118
120
|
// aborted by timeout
|
|
119
121
|
throw new Error(
|
|
120
|
-
`"${webServer.command}" command did not start a server in less than ${allocatedMs}ms
|
|
122
|
+
`"${webServer.command}" command did not start a server in less than ${allocatedMs}ms`,
|
|
121
123
|
);
|
|
122
124
|
}
|
|
123
125
|
if (signal.aborted) {
|
|
@@ -1,79 +1,17 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import {
|
|
3
|
-
import { Abort } from "@jsenv/abort";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
4
3
|
|
|
5
|
-
import {
|
|
4
|
+
import { startServerUsingCommand } from "./start_using_command.js";
|
|
6
5
|
|
|
7
|
-
export const startServerUsingModuleUrl = async (
|
|
8
|
-
webServer,
|
|
9
|
-
{ signal, teardown, logger, allocatedMs },
|
|
10
|
-
) => {
|
|
6
|
+
export const startServerUsingModuleUrl = async (webServer, params) => {
|
|
11
7
|
if (!existsSync(new URL(webServer.moduleUrl))) {
|
|
12
|
-
throw new Error(
|
|
13
|
-
`webServer.moduleUrl does not lead to a file at "${webServer.moduleUrl}"`,
|
|
14
|
-
);
|
|
8
|
+
throw new Error(`"${webServer.moduleUrl}" does not lead to a file`);
|
|
15
9
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
return startServerUsingCommand(
|
|
11
|
+
{
|
|
12
|
+
...webServer,
|
|
13
|
+
command: `node ${fileURLToPath(webServer.moduleUrl)}`,
|
|
19
14
|
},
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
23
|
-
let errorReceived = false;
|
|
24
|
-
const errorPromise = new Promise((resolve, reject) => {
|
|
25
|
-
worker.on("error", (e) => {
|
|
26
|
-
errorReceived = true;
|
|
27
|
-
reject(e);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const killWorker = async () => {
|
|
32
|
-
await worker.terminate();
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const startOperation = Abort.startOperation();
|
|
36
|
-
startOperation.addAbortSignal(signal);
|
|
37
|
-
const timeoutAbortSource = startOperation.timeout(allocatedMs);
|
|
38
|
-
startOperation.addAbortCallback(killWorker);
|
|
39
|
-
teardown.addCallback(killWorker);
|
|
40
|
-
|
|
41
|
-
const startedPromise = (async () => {
|
|
42
|
-
const logScale = [100, 250, 500];
|
|
43
|
-
// eslint-disable-next-line no-constant-condition
|
|
44
|
-
while (true) {
|
|
45
|
-
if (errorReceived) {
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
const connected = await pingServer(webServer.origin);
|
|
49
|
-
if (connected) {
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
startOperation.throwIfAborted();
|
|
54
|
-
const delay = logScale.shift() || 1000;
|
|
55
|
-
logger.debug(`Waiting ${delay}ms`);
|
|
56
|
-
await new Promise((x) => setTimeout(x, delay));
|
|
57
|
-
}
|
|
58
|
-
})();
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
await Promise.race([errorPromise, startedPromise]);
|
|
62
|
-
} catch (e) {
|
|
63
|
-
if (Abort.isAbortError(e)) {
|
|
64
|
-
if (timeoutAbortSource.signal.aborted) {
|
|
65
|
-
// aborted by timeout
|
|
66
|
-
throw new Error(
|
|
67
|
-
`"${webServer.moduleUrl}" did not start a server in less than ${allocatedMs}ms (webServer.moduleUrl)`,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
if (signal.aborted) {
|
|
71
|
-
// aborted from outside
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
throw e;
|
|
76
|
-
} finally {
|
|
77
|
-
await startOperation.end();
|
|
78
|
-
}
|
|
15
|
+
params,
|
|
16
|
+
);
|
|
79
17
|
};
|