@jsenv/test 1.1.2 → 1.1.4

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.
Files changed (50) hide show
  1. package/dist/jsenv_test.js +4 -2
  2. package/package.json +3 -3
  3. package/src/coverage/babel_plugin_instrument.js +15 -15
  4. package/src/coverage/coverage_reporter_html_directory.js +10 -10
  5. package/src/coverage/coverage_reporter_json_file.js +7 -7
  6. package/src/coverage/coverage_reporter_text_log.js +8 -8
  7. package/src/coverage/empty_coverage_factory.js +24 -24
  8. package/src/coverage/file_by_file_coverage.js +10 -10
  9. package/src/coverage/istanbul_coverage_composition.js +16 -16
  10. package/src/coverage/istanbul_coverage_map_from_coverage.js +8 -8
  11. package/src/coverage/list_files_not_covered.js +4 -4
  12. package/src/coverage/missing_coverage.js +17 -17
  13. package/src/coverage/report_to_coverage.js +52 -52
  14. package/src/coverage/v8_and_istanbul.js +17 -16
  15. package/src/coverage/v8_coverage.js +8 -8
  16. package/src/coverage/v8_coverage_composition.js +12 -12
  17. package/src/coverage/v8_coverage_node_directory.js +42 -42
  18. package/src/coverage/v8_coverage_to_istanbul.js +45 -45
  19. package/src/execution/execute.js +21 -21
  20. package/src/execution/execute_steps.js +129 -129
  21. package/src/execution/execute_test_plan.js +72 -68
  22. package/src/execution/execution_colors.js +2 -2
  23. package/src/execution/execution_steps.js +20 -20
  24. package/src/execution/gc.js +5 -5
  25. package/src/execution/logs_file_execution.js +126 -126
  26. package/src/execution/logs_file_execution.test.mjs +11 -11
  27. package/src/execution/run.js +51 -51
  28. package/src/execution/web_server_param.js +24 -24
  29. package/src/main.js +7 -7
  30. package/src/runtime_browsers/chromium.js +7 -7
  31. package/src/runtime_browsers/firefox.js +10 -10
  32. package/src/runtime_browsers/middleware_istanbul.js +23 -23
  33. package/src/runtime_browsers/middleware_js_supervisor.js +32 -32
  34. package/src/runtime_browsers/using_playwright.js +186 -186
  35. package/src/runtime_browsers/webkit.js +11 -11
  36. package/src/runtime_node/child_exec_options.js +43 -43
  37. package/src/runtime_node/controllable_child_process.mjs +47 -47
  38. package/src/runtime_node/controllable_worker_thread.mjs +37 -37
  39. package/src/runtime_node/exec_options.js +26 -26
  40. package/src/runtime_node/execute_using_dynamic_import.js +26 -26
  41. package/src/runtime_node/exit_codes.js +4 -4
  42. package/src/runtime_node/importmap_node_loader.mjs +24 -24
  43. package/src/runtime_node/importmap_node_loader_file_url.js +1 -1
  44. package/src/runtime_node/kill_process_tree.js +30 -30
  45. package/src/runtime_node/no_experimental_warnings.cjs +4 -4
  46. package/src/runtime_node/no_experimental_warnings_file_url.js +1 -1
  47. package/src/runtime_node/node_child_process.js +128 -128
  48. package/src/runtime_node/node_execution_performance.js +28 -28
  49. package/src/runtime_node/node_worker_thread.js +108 -108
  50. package/src/runtime_node/profiler_v8_coverage.js +21 -21
@@ -1,16 +1,16 @@
1
- import { existsSync } from "node:fs"
2
- import { memoryUsage } from "node:process"
3
- import { takeCoverage } from "node:v8"
4
- import stripAnsi from "strip-ansi"
5
- import { urlToFileSystemPath } from "@jsenv/urls"
6
- import { createLog, startSpinner } from "@jsenv/log"
7
- import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
8
- import { ensureEmptyDirectory, writeFileSync } from "@jsenv/filesystem"
1
+ import { existsSync } from "node:fs";
2
+ import { memoryUsage } from "node:process";
3
+ import { takeCoverage } from "node:v8";
4
+ import stripAnsi from "strip-ansi";
5
+ import { urlToFileSystemPath } from "@jsenv/urls";
6
+ import { createLog, startSpinner } from "@jsenv/log";
7
+ import { Abort, raceProcessTeardownEvents } from "@jsenv/abort";
8
+ import { ensureEmptyDirectory, writeFileSync } from "@jsenv/filesystem";
9
9
 
10
- import { reportToCoverage } from "../coverage/report_to_coverage.js"
11
- import { run } from "./run.js"
12
- import { ensureGlobalGc } from "./gc.js"
13
- import { createExecutionLog, createSummaryLog } from "./logs_file_execution.js"
10
+ import { reportToCoverage } from "../coverage/report_to_coverage.js";
11
+ import { run } from "./run.js";
12
+ import { ensureGlobalGc } from "./gc.js";
13
+ import { createExecutionLog, createSummaryLog } from "./logs_file_execution.js";
14
14
 
15
15
  export const executeSteps = async (
16
16
  executionSteps,
@@ -51,15 +51,15 @@ export const executeSteps = async (
51
51
  ) => {
52
52
  executionSteps = executionSteps.filter(
53
53
  (executionStep) => !executionStep.runtime?.disabled,
54
- )
54
+ );
55
55
 
56
- const executePlanReturnValue = {}
57
- const report = {}
58
- const callbacks = []
59
- const stopAfterAllSignal = { notify: () => {} }
56
+ const executePlanReturnValue = {};
57
+ const report = {};
58
+ const callbacks = [];
59
+ const stopAfterAllSignal = { notify: () => {} };
60
60
 
61
- const multipleExecutionsOperation = Abort.startOperation()
62
- multipleExecutionsOperation.addAbortSignal(signal)
61
+ const multipleExecutionsOperation = Abort.startOperation();
62
+ multipleExecutionsOperation.addAbortSignal(signal);
63
63
  if (handleSIGINT) {
64
64
  multipleExecutionsOperation.addAbortSource((abort) => {
65
65
  return raceProcessTeardownEvents(
@@ -67,33 +67,33 @@ export const executeSteps = async (
67
67
  SIGINT: true,
68
68
  },
69
69
  () => {
70
- logger.debug(`SIGINT abort`)
71
- abort()
70
+ logger.debug(`SIGINT abort`);
71
+ abort();
72
72
  },
73
- )
74
- })
73
+ );
74
+ });
75
75
  }
76
- const failFastAbortController = new AbortController()
76
+ const failFastAbortController = new AbortController();
77
77
  if (failFast) {
78
- multipleExecutionsOperation.addAbortSignal(failFastAbortController.signal)
78
+ multipleExecutionsOperation.addAbortSignal(failFastAbortController.signal);
79
79
  }
80
80
 
81
81
  try {
82
82
  if (gcBetweenExecutions) {
83
- ensureGlobalGc()
83
+ ensureGlobalGc();
84
84
  }
85
85
 
86
86
  if (coverageEnabled) {
87
87
  // when runned multiple times, we don't want to keep previous files in this directory
88
- await ensureEmptyDirectory(coverageTempDirectoryUrl)
88
+ await ensureEmptyDirectory(coverageTempDirectoryUrl);
89
89
  callbacks.push(async () => {
90
90
  if (multipleExecutionsOperation.signal.aborted) {
91
91
  // don't try to do the coverage stuff
92
- return
92
+ return;
93
93
  }
94
94
  try {
95
95
  if (coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
96
- takeCoverage()
96
+ takeCoverage();
97
97
  // conceptually we don't need coverage anymore so it would be
98
98
  // good to call v8.stopCoverage()
99
99
  // but it logs a strange message about "result is not an object"
@@ -106,15 +106,15 @@ export const executeSteps = async (
106
106
  coverageIncludeMissing,
107
107
  coverageMethodForBrowsers,
108
108
  coverageV8ConflictWarning,
109
- })
110
- executePlanReturnValue.planCoverage = planCoverage
109
+ });
110
+ executePlanReturnValue.planCoverage = planCoverage;
111
111
  } catch (e) {
112
112
  if (Abort.isAbortError(e)) {
113
- return
113
+ return;
114
114
  }
115
- throw e
115
+ throw e;
116
116
  }
117
- })
117
+ });
118
118
  }
119
119
 
120
120
  const runtimeParams = {
@@ -126,16 +126,16 @@ export const executeSteps = async (
126
126
  coverageMethodForBrowsers,
127
127
  coverageMethodForNodeJs,
128
128
  stopAfterAllSignal,
129
- }
129
+ };
130
130
 
131
131
  if (logMergeForCompletedExecutions && !process.stdout.isTTY) {
132
- logMergeForCompletedExecutions = false
132
+ logMergeForCompletedExecutions = false;
133
133
  logger.debug(
134
134
  `Force logMergeForCompletedExecutions to false because process.stdout.isTTY is false`,
135
- )
135
+ );
136
136
  }
137
- const debugLogsEnabled = logger.levels.debug
138
- const executionLogsEnabled = logger.levels.info
137
+ const debugLogsEnabled = logger.levels.debug;
138
+ const executionLogsEnabled = logger.levels.info;
139
139
  const executionSpinner =
140
140
  logRefresh &&
141
141
  !debugLogsEnabled &&
@@ -144,11 +144,11 @@ export const executeSteps = async (
144
144
  // if there is an error during execution npm will mess up the output
145
145
  // (happens when npm runs several command in a workspace)
146
146
  // so we enable spinner only when !process.exitCode (no error so far)
147
- process.exitCode !== 1
147
+ process.exitCode !== 1;
148
148
 
149
- const startMs = Date.now()
150
- let rawOutput = ""
151
- let executionLog = createLog({ newLine: "" })
149
+ const startMs = Date.now();
150
+ let rawOutput = "";
151
+ let executionLog = createLog({ newLine: "" });
152
152
  const counters = {
153
153
  total: executionSteps.length,
154
154
  aborted: 0,
@@ -156,18 +156,18 @@ export const executeSteps = async (
156
156
  failed: 0,
157
157
  completed: 0,
158
158
  done: 0,
159
- }
159
+ };
160
160
  await executeInParallel({
161
161
  multipleExecutionsOperation,
162
162
  maxExecutionsInParallel,
163
163
  cooldownBetweenExecutions,
164
164
  executionSteps,
165
165
  start: async (paramsFromStep) => {
166
- const executionIndex = executionSteps.indexOf(paramsFromStep)
167
- const { executionName, fileRelativeUrl, runtime } = paramsFromStep
168
- const runtimeType = runtime.type
169
- const runtimeName = runtime.name
170
- const runtimeVersion = runtime.version
166
+ const executionIndex = executionSteps.indexOf(paramsFromStep);
167
+ const { executionName, fileRelativeUrl, runtime } = paramsFromStep;
168
+ const runtimeType = runtime.type;
169
+ const runtimeName = runtime.name;
170
+ const runtimeVersion = runtime.version;
171
171
  const executionParams = {
172
172
  measurePerformance: false,
173
173
  collectPerformance: false,
@@ -178,7 +178,7 @@ export const executeSteps = async (
178
178
  fileRelativeUrl,
179
179
  ...paramsFromStep.runtimeParams,
180
180
  },
181
- }
181
+ };
182
182
  const beforeExecutionInfo = {
183
183
  fileRelativeUrl,
184
184
  runtimeType,
@@ -190,8 +190,8 @@ export const executeSteps = async (
190
190
  executionResult: {
191
191
  status: "executing",
192
192
  },
193
- }
194
- let spinner
193
+ };
194
+ let spinner;
195
195
  if (executionSpinner) {
196
196
  spinner = startSpinner({
197
197
  log: executionLog,
@@ -208,14 +208,14 @@ export const executeSteps = async (
208
208
  ...(logMemoryHeapUsage
209
209
  ? { memoryHeap: memoryUsage().heapUsed }
210
210
  : {}),
211
- })
211
+ });
212
212
  },
213
- })
213
+ });
214
214
  }
215
- beforeExecutionCallback(beforeExecutionInfo)
215
+ beforeExecutionCallback(beforeExecutionInfo);
216
216
 
217
- const fileUrl = `${rootDirectoryUrl}${fileRelativeUrl}`
218
- let executionResult
217
+ const fileUrl = `${rootDirectoryUrl}${fileRelativeUrl}`;
218
+ let executionResult;
219
219
  if (existsSync(new URL(fileUrl))) {
220
220
  executionResult = await run({
221
221
  signal: multipleExecutionsOperation.signal,
@@ -234,7 +234,7 @@ export const executeSteps = async (
234
234
  ...runtimeParams,
235
235
  ...executionParams.runtimeParams,
236
236
  },
237
- })
237
+ });
238
238
  } else {
239
239
  executionResult = {
240
240
  status: "failed",
@@ -243,16 +243,16 @@ export const executeSteps = async (
243
243
  `No file at ${fileRelativeUrl} for execution "${executionName}"`,
244
244
  ),
245
245
  ],
246
- }
246
+ };
247
247
  }
248
- counters.done++
249
- const fileReport = report[fileRelativeUrl]
248
+ counters.done++;
249
+ const fileReport = report[fileRelativeUrl];
250
250
  if (fileReport) {
251
- fileReport[executionName] = executionResult
251
+ fileReport[executionName] = executionResult;
252
252
  } else {
253
253
  report[fileRelativeUrl] = {
254
254
  [executionName]: executionResult,
255
- }
255
+ };
256
256
  }
257
257
 
258
258
  const afterExecutionInfo = {
@@ -260,20 +260,20 @@ export const executeSteps = async (
260
260
  runtimeVersion: runtime.version,
261
261
  endMs: Date.now(),
262
262
  executionResult,
263
- }
264
- afterExecutionCallback(afterExecutionInfo)
263
+ };
264
+ afterExecutionCallback(afterExecutionInfo);
265
265
 
266
266
  if (executionResult.status === "aborted") {
267
- counters.aborted++
267
+ counters.aborted++;
268
268
  } else if (executionResult.status === "timedout") {
269
- counters.timedout++
269
+ counters.timedout++;
270
270
  } else if (executionResult.status === "failed") {
271
- counters.failed++
271
+ counters.failed++;
272
272
  } else if (executionResult.status === "completed") {
273
- counters.completed++
273
+ counters.completed++;
274
274
  }
275
275
  if (gcBetweenExecutions) {
276
- global.gc()
276
+ global.gc();
277
277
  }
278
278
  if (executionLogsEnabled) {
279
279
  const log = createExecutionLog(afterExecutionInfo, {
@@ -289,91 +289,91 @@ export const executeSteps = async (
289
289
  ...(logMemoryHeapUsage
290
290
  ? { memoryHeap: memoryUsage().heapUsed }
291
291
  : {}),
292
- })
292
+ });
293
293
  // replace spinner with this execution result
294
- if (spinner) spinner.stop()
295
- executionLog.write(log)
296
- rawOutput += stripAnsi(log)
294
+ if (spinner) spinner.stop();
295
+ executionLog.write(log);
296
+ rawOutput += stripAnsi(log);
297
297
 
298
298
  const canOverwriteLog = canOverwriteLogGetter({
299
299
  logMergeForCompletedExecutions,
300
300
  executionResult,
301
- })
301
+ });
302
302
  if (canOverwriteLog) {
303
303
  // nothing to do, we reuse the current executionLog object
304
304
  } else {
305
- executionLog.destroy()
306
- executionLog = createLog({ newLine: "" })
305
+ executionLog.destroy();
306
+ executionLog = createLog({ newLine: "" });
307
307
  }
308
308
  }
309
- const isLastExecutionLog = executionIndex === executionSteps.length - 1
309
+ const isLastExecutionLog = executionIndex === executionSteps.length - 1;
310
310
  const cancelRemaining =
311
311
  failFast &&
312
312
  executionResult.status !== "completed" &&
313
- counters.done < counters.total
313
+ counters.done < counters.total;
314
314
  if (isLastExecutionLog && logger.levels.info) {
315
- executionLog.write("\n")
315
+ executionLog.write("\n");
316
316
  }
317
317
 
318
318
  if (cancelRemaining) {
319
- logger.info(`"failFast" enabled -> cancel remaining executions`)
320
- failFastAbortController.abort()
319
+ logger.info(`"failFast" enabled -> cancel remaining executions`);
320
+ failFastAbortController.abort();
321
321
  }
322
322
  },
323
- })
323
+ });
324
324
  if (!keepRunning) {
325
- logger.debug("stopAfterAllSignal.notify()")
326
- await stopAfterAllSignal.notify()
325
+ logger.debug("stopAfterAllSignal.notify()");
326
+ await stopAfterAllSignal.notify();
327
327
  }
328
328
 
329
- counters.cancelled = counters.total - counters.done
329
+ counters.cancelled = counters.total - counters.done;
330
330
  const summary = {
331
331
  counters,
332
332
  // when execution is aborted, the remaining executions are "cancelled"
333
333
  duration: Date.now() - startMs,
334
- }
334
+ };
335
335
  if (logSummary) {
336
- const summaryLog = createSummaryLog(summary)
337
- rawOutput += stripAnsi(summaryLog)
338
- logger.info(summaryLog)
336
+ const summaryLog = createSummaryLog(summary);
337
+ rawOutput += stripAnsi(summaryLog);
338
+ logger.info(summaryLog);
339
339
  }
340
340
  if (summary.counters.total !== summary.counters.completed) {
341
- const logFileUrl = new URL(logFileRelativeUrl, rootDirectoryUrl).href
342
- writeFileSync(logFileUrl, rawOutput)
343
- logger.info(`-> ${urlToFileSystemPath(logFileUrl)}`)
341
+ const logFileUrl = new URL(logFileRelativeUrl, rootDirectoryUrl).href;
342
+ writeFileSync(logFileUrl, rawOutput);
343
+ logger.info(`-> ${urlToFileSystemPath(logFileUrl)}`);
344
344
  }
345
- executePlanReturnValue.aborted = multipleExecutionsOperation.signal.aborted
346
- executePlanReturnValue.planSummary = summary
347
- executePlanReturnValue.planReport = report
345
+ executePlanReturnValue.aborted = multipleExecutionsOperation.signal.aborted;
346
+ executePlanReturnValue.planSummary = summary;
347
+ executePlanReturnValue.planReport = report;
348
348
  await callbacks.reduce(async (previous, callback) => {
349
- await previous
350
- await callback()
351
- }, Promise.resolve())
352
- return executePlanReturnValue
349
+ await previous;
350
+ await callback();
351
+ }, Promise.resolve());
352
+ return executePlanReturnValue;
353
353
  } finally {
354
- await multipleExecutionsOperation.end()
354
+ await multipleExecutionsOperation.end();
355
355
  }
356
- }
356
+ };
357
357
 
358
358
  const canOverwriteLogGetter = ({
359
359
  logMergeForCompletedExecutions,
360
360
  executionResult,
361
361
  }) => {
362
362
  if (!logMergeForCompletedExecutions) {
363
- return false
363
+ return false;
364
364
  }
365
365
  if (executionResult.status === "aborted") {
366
- return true
366
+ return true;
367
367
  }
368
368
  if (executionResult.status !== "completed") {
369
- return false
369
+ return false;
370
370
  }
371
- const { consoleCalls = [] } = executionResult
371
+ const { consoleCalls = [] } = executionResult;
372
372
  if (consoleCalls.length > 0) {
373
- return false
373
+ return false;
374
374
  }
375
- return true
376
- }
375
+ return true;
376
+ };
377
377
 
378
378
  const executeInParallel = async ({
379
379
  multipleExecutionsOperation,
@@ -382,46 +382,46 @@ const executeInParallel = async ({
382
382
  executionSteps,
383
383
  start,
384
384
  }) => {
385
- const executionResults = []
386
- let progressionIndex = 0
387
- let remainingExecutionCount = executionSteps.length
385
+ const executionResults = [];
386
+ let progressionIndex = 0;
387
+ let remainingExecutionCount = executionSteps.length;
388
388
 
389
389
  const nextChunk = async () => {
390
390
  if (multipleExecutionsOperation.signal.aborted) {
391
- return
391
+ return;
392
392
  }
393
- const outputPromiseArray = []
393
+ const outputPromiseArray = [];
394
394
  while (
395
395
  remainingExecutionCount > 0 &&
396
396
  outputPromiseArray.length < maxExecutionsInParallel
397
397
  ) {
398
- remainingExecutionCount--
399
- const outputPromise = executeOne(progressionIndex)
400
- progressionIndex++
401
- outputPromiseArray.push(outputPromise)
398
+ remainingExecutionCount--;
399
+ const outputPromise = executeOne(progressionIndex);
400
+ progressionIndex++;
401
+ outputPromiseArray.push(outputPromise);
402
402
  }
403
403
  if (outputPromiseArray.length) {
404
- await Promise.all(outputPromiseArray)
404
+ await Promise.all(outputPromiseArray);
405
405
  if (remainingExecutionCount > 0) {
406
- await nextChunk()
406
+ await nextChunk();
407
407
  }
408
408
  }
409
- }
409
+ };
410
410
 
411
411
  const executeOne = async (index) => {
412
- const input = executionSteps[index]
413
- const output = await start(input)
412
+ const input = executionSteps[index];
413
+ const output = await start(input);
414
414
  if (!multipleExecutionsOperation.signal.aborted) {
415
- executionResults[index] = output
415
+ executionResults[index] = output;
416
416
  }
417
417
  if (cooldownBetweenExecutions) {
418
418
  await new Promise((resolve) =>
419
419
  setTimeout(resolve, cooldownBetweenExecutions),
420
- )
420
+ );
421
421
  }
422
- }
422
+ };
423
423
 
424
- await nextChunk()
424
+ await nextChunk();
425
425
 
426
- return executionResults
427
- }
426
+ return executionResults;
427
+ };