@jsenv/test 1.6.0 → 1.6.2

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.
@@ -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,89 +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(
2841
- new URL(
2842
- "./worker_importing_module_starting_web_server.mjs",
2843
- import.meta.url,
2844
- ),
2845
- {
2846
- workerData: {
2847
- url: String(webServer.moduleUrl),
2848
- },
2849
- env: {
2850
- IMPORTED_BY_TEST_PLAN: "1",
2851
- },
2852
- stdin: true,
2853
- stdout: true,
2854
- },
2855
- );
2856
- let errorReceived = false;
2857
- const errorPromise = new Promise((resolve, reject) => {
2858
- worker.on("error", (e) => {
2859
- errorReceived = true;
2860
- reject(e);
2861
- });
2862
- });
2863
-
2864
- const killWorker = async () => {
2865
- await worker.terminate();
2866
- };
2867
-
2868
- const startOperation = Abort.startOperation();
2869
- startOperation.addAbortSignal(signal);
2870
- const timeoutAbortSource = startOperation.timeout(allocatedMs);
2871
- startOperation.addAbortCallback(killWorker);
2872
- teardown.addCallback(killWorker);
2873
-
2874
- const startedPromise = (async () => {
2875
- const logScale = [100, 250, 500];
2876
- // eslint-disable-next-line no-constant-condition
2877
- while (true) {
2878
- if (errorReceived) {
2879
- break;
2880
- }
2881
- const connected = await pingServer(webServer.origin);
2882
- if (connected) {
2883
- break;
2884
- }
2885
-
2886
- startOperation.throwIfAborted();
2887
- const delay = logScale.shift() || 1000;
2888
- logger.debug(`Waiting ${delay}ms`);
2889
- await new Promise((x) => setTimeout(x, delay));
2890
- }
2891
- })();
2892
-
2893
- try {
2894
- await Promise.race([errorPromise, startedPromise]);
2895
- } catch (e) {
2896
- if (Abort.isAbortError(e)) {
2897
- if (timeoutAbortSource.signal.aborted) {
2898
- // aborted by timeout
2899
- throw new Error(
2900
- `"${webServer.moduleUrl}" did not start a server in less than ${allocatedMs}ms (webServer.moduleUrl)`,
2901
- );
2902
- }
2903
- if (signal.aborted) {
2904
- // aborted from outside
2905
- return;
2906
- }
2907
- }
2908
- throw e;
2909
- } finally {
2910
- await startOperation.end();
2911
- }
2912
- };
2913
-
2914
2831
  const startServerUsingCommand = async (
2915
2832
  webServer,
2916
2833
  { signal, allocatedMs, logger, teardown },
@@ -2951,7 +2868,7 @@ const startServerUsingCommand = async (
2951
2868
  let processClosed = false;
2952
2869
  const closedPromise = new Promise((resolve) => {
2953
2870
  spawnedProcess.once("exit", (exitCode, signal) => {
2954
- logger.info(
2871
+ logger.debug(
2955
2872
  `[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`,
2956
2873
  );
2957
2874
  processClosed = true;
@@ -2959,14 +2876,14 @@ const startServerUsingCommand = async (
2959
2876
  });
2960
2877
  });
2961
2878
  const killProcess = async () => {
2962
- logger.info(`[pid=${spawnedProcess.pid}] <kill>`);
2879
+ logger.debug(`[pid=${spawnedProcess.pid}] <kill>`);
2963
2880
  if (!spawnedProcess.pid || spawnedProcess.killed || processClosed) {
2964
- logger.info(
2881
+ logger.debug(
2965
2882
  `[pid=${spawnedProcess.pid}] <skipped force kill spawnedProcess.killed=${spawnedProcess.killed} processClosed=${processClosed}>`,
2966
2883
  );
2967
2884
  return;
2968
2885
  }
2969
- logger.info(`[pid=${spawnedProcess.pid}] <will force kill>`);
2886
+ logger.debug(`[pid=${spawnedProcess.pid}] <will force kill>`);
2970
2887
  // Force kill the browser.
2971
2888
  try {
2972
2889
  if (process.platform === "win32") {
@@ -2979,7 +2896,9 @@ const startServerUsingCommand = async (
2979
2896
  taskkillProcess.stderr.toString(),
2980
2897
  ];
2981
2898
  if (stdout)
2982
- logger.info(`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout}`);
2899
+ logger.debug(
2900
+ `[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout}`,
2901
+ );
2983
2902
  if (stderr)
2984
2903
  logger.info(`[pid=${spawnedProcess.pid}] taskkill stderr: ${stderr}`);
2985
2904
  } else {
@@ -3025,7 +2944,7 @@ const startServerUsingCommand = async (
3025
2944
  if (timeoutAbortSource.signal.aborted) {
3026
2945
  // aborted by timeout
3027
2946
  throw new Error(
3028
- `"${webServer.command}" command did not start a server in less than ${allocatedMs}ms (webServer.command)`,
2947
+ `"${webServer.command}" command did not start a server in less than ${allocatedMs}ms`,
3029
2948
  );
3030
2949
  }
3031
2950
  if (signal.aborted) {
@@ -3039,6 +2958,19 @@ const startServerUsingCommand = async (
3039
2958
  }
3040
2959
  };
3041
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
+
3042
2974
  const basicFetch = async (
3043
2975
  url,
3044
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.0",
3
+ "version": "1.6.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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.info(
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.info(`[pid=${spawnedProcess.pid}] <kill>`);
54
+ logger.debug(`[pid=${spawnedProcess.pid}] <kill>`);
55
55
  if (!spawnedProcess.pid || spawnedProcess.killed || processClosed) {
56
- logger.info(
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.info(`[pid=${spawnedProcess.pid}] <will force kill>`);
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.info(`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout}`);
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 (webServer.command)`,
122
+ `"${webServer.command}" command did not start a server in less than ${allocatedMs}ms`,
121
123
  );
122
124
  }
123
125
  if (signal.aborted) {
@@ -1,88 +1,17 @@
1
1
  import { existsSync } from "node:fs";
2
- import { Worker } from "node:worker_threads";
3
- import { Abort } from "@jsenv/abort";
2
+ import { fileURLToPath } from "node:url";
4
3
 
5
- import { pingServer } from "../../helpers/ping_server.js";
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
- const worker = new Worker(
17
- new URL(
18
- "./worker_importing_module_starting_web_server.mjs",
19
- import.meta.url,
20
- ),
10
+ return startServerUsingCommand(
21
11
  {
22
- workerData: {
23
- url: String(webServer.moduleUrl),
24
- },
25
- env: {
26
- IMPORTED_BY_TEST_PLAN: "1",
27
- },
28
- stdin: true,
29
- stdout: true,
12
+ ...webServer,
13
+ command: `node ${fileURLToPath(webServer.moduleUrl)}`,
30
14
  },
15
+ params,
31
16
  );
32
- let errorReceived = false;
33
- const errorPromise = new Promise((resolve, reject) => {
34
- worker.on("error", (e) => {
35
- errorReceived = true;
36
- reject(e);
37
- });
38
- });
39
-
40
- const killWorker = async () => {
41
- await worker.terminate();
42
- };
43
-
44
- const startOperation = Abort.startOperation();
45
- startOperation.addAbortSignal(signal);
46
- const timeoutAbortSource = startOperation.timeout(allocatedMs);
47
- startOperation.addAbortCallback(killWorker);
48
- teardown.addCallback(killWorker);
49
-
50
- const startedPromise = (async () => {
51
- const logScale = [100, 250, 500];
52
- // eslint-disable-next-line no-constant-condition
53
- while (true) {
54
- if (errorReceived) {
55
- break;
56
- }
57
- const connected = await pingServer(webServer.origin);
58
- if (connected) {
59
- break;
60
- }
61
-
62
- startOperation.throwIfAborted();
63
- const delay = logScale.shift() || 1000;
64
- logger.debug(`Waiting ${delay}ms`);
65
- await new Promise((x) => setTimeout(x, delay));
66
- }
67
- })();
68
-
69
- try {
70
- await Promise.race([errorPromise, startedPromise]);
71
- } catch (e) {
72
- if (Abort.isAbortError(e)) {
73
- if (timeoutAbortSource.signal.aborted) {
74
- // aborted by timeout
75
- throw new Error(
76
- `"${webServer.moduleUrl}" did not start a server in less than ${allocatedMs}ms (webServer.moduleUrl)`,
77
- );
78
- }
79
- if (signal.aborted) {
80
- // aborted from outside
81
- return;
82
- }
83
- }
84
- throw e;
85
- } finally {
86
- await startOperation.end();
87
- }
88
17
  };
@@ -1,5 +0,0 @@
1
- import { parentPort, workerData } from "node:worker_threads";
2
-
3
- const { url } = workerData;
4
- await import(url);
5
- parentPort.postMessage("done");