@jsenv/test 2.1.3 → 3.0.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.
Files changed (46) hide show
  1. package/README.md +2 -1
  2. package/dist/js/exception.js +908 -0
  3. package/dist/js/execute_using_dynamic_import.js +76 -167
  4. package/dist/js/v8_coverage.js +4 -482
  5. package/dist/jsenv_test.js +4608 -2917
  6. package/dist/node_child_process_controlled.mjs +95 -76
  7. package/dist/node_worker_thread_controlled.mjs +72 -54
  8. package/package.json +23 -14
  9. package/src/coverage/generate_coverage.js +186 -0
  10. package/src/coverage/list_files_not_covered.js +2 -2
  11. package/src/coverage/missing_coverage.js +2 -2
  12. package/src/coverage/report_coverage_as_html.js +45 -0
  13. package/src/coverage/report_coverage_as_json.js +20 -0
  14. package/src/coverage/{coverage_reporter_text_log.js → report_coverage_in_console.js} +13 -7
  15. package/src/coverage/v8_and_istanbul.js +4 -4
  16. package/src/coverage/v8_coverage.js +2 -2
  17. package/src/execution/exception.js +151 -68
  18. package/src/execution/execute.js +24 -11
  19. package/src/execution/execute_test_plan.js +834 -750
  20. package/src/execution/format_error_for_terminal.js +187 -0
  21. package/src/execution/github_annotation_from_error.js +3 -3
  22. package/src/execution/junit_xml_file/report_as_junit_xml.js +149 -0
  23. package/src/execution/junit_xml_file/xml_generator.js +141 -0
  24. package/src/execution/reporters/reporter_list.js +687 -0
  25. package/src/execution/run.js +92 -30
  26. package/src/execution/web_server/start_using_command.js +2 -2
  27. package/src/execution/web_server_param.js +5 -5
  28. package/src/helpers/cpu_usage.js +142 -0
  29. package/src/helpers/cpu_usage.test_manual.js +7 -0
  30. package/src/main.js +8 -0
  31. package/src/runtime_browsers/chromium.js +1 -3
  32. package/src/runtime_browsers/firefox.js +0 -3
  33. package/src/runtime_browsers/middleware_istanbul.js +2 -2
  34. package/src/runtime_browsers/using_playwright.js +296 -220
  35. package/src/runtime_browsers/webkit.js +0 -3
  36. package/src/runtime_node/execute_using_dynamic_import.js +75 -28
  37. package/src/runtime_node/node_child_process.js +250 -139
  38. package/src/runtime_node/node_child_process_controlled.mjs +94 -75
  39. package/src/runtime_node/node_worker_thread.js +206 -120
  40. package/src/runtime_node/node_worker_thread_controlled.mjs +70 -53
  41. package/src/coverage/coverage_reporter_html_directory.js +0 -32
  42. package/src/coverage/coverage_reporter_json_file.js +0 -17
  43. package/src/coverage/report_to_coverage.js +0 -198
  44. package/src/execution/execution_colors.js +0 -10
  45. package/src/execution/execution_steps.js +0 -65
  46. package/src/execution/logs_file_execution.js +0 -495
@@ -1,495 +0,0 @@
1
- import wrapAnsi from "wrap-ansi";
2
- import {
3
- ANSI,
4
- UNICODE,
5
- msAsEllapsedTime,
6
- msAsDuration,
7
- byteAsMemoryUsage,
8
- } from "@jsenv/log";
9
-
10
- import { EXECUTION_COLORS } from "./execution_colors.js";
11
-
12
- export const createExecutionLog = (
13
- {
14
- executionIndex,
15
- fileRelativeUrl,
16
- runtimeName,
17
- runtimeVersion,
18
- executionParams,
19
- executionResult,
20
- startMs,
21
- endMs,
22
- nowMs,
23
- timeEllapsed,
24
- memoryHeap,
25
- counters,
26
- },
27
- {
28
- logShortForCompletedExecutions,
29
- logRuntime,
30
- logEachDuration,
31
- logTimeUsage,
32
- logMemoryHeapUsage,
33
- },
34
- ) => {
35
- const label = formatExecutionLabel(
36
- {
37
- executionIndex,
38
- executionParams,
39
- executionResult,
40
- timeEllapsed,
41
- memoryHeap,
42
- counters,
43
- },
44
- {
45
- logTimeUsage,
46
- logMemoryHeapUsage,
47
- },
48
- );
49
-
50
- const { status } = executionResult;
51
- let log;
52
- if (logShortForCompletedExecutions && status === "completed") {
53
- log = label;
54
- } else {
55
- log = formatExecution(
56
- {
57
- fileRelativeUrl,
58
- runtimeName,
59
- runtimeVersion,
60
- executionResult,
61
- startMs,
62
- endMs,
63
- nowMs,
64
- },
65
- {
66
- label,
67
- logRuntime,
68
- logEachDuration,
69
- },
70
- );
71
- }
72
-
73
- const { columns = 80 } = process.stdout;
74
- log = wrapAnsi(log, columns, {
75
- trim: false,
76
- hard: true,
77
- wordWrap: false,
78
- });
79
- if (endMs) {
80
- if (logShortForCompletedExecutions) {
81
- return `${log}\n`;
82
- }
83
- if (executionIndex === counters.total - 1) {
84
- return `${log}\n`;
85
- }
86
- return `${log}\n\n`;
87
- }
88
- return log;
89
- };
90
-
91
- export const formatExecution = (
92
- {
93
- fileRelativeUrl,
94
- runtimeName,
95
- runtimeVersion,
96
- executionResult,
97
- startMs,
98
- endMs,
99
- nowMs,
100
- },
101
- { label, logRuntime = true, logEachDuration = true } = {},
102
- ) => {
103
- const { status } = executionResult;
104
- const { consoleCalls = [], errors = [] } = executionResult;
105
- const consoleOutput = formatConsoleCalls(consoleCalls);
106
- const errorsOutput = formatErrors(errors);
107
-
108
- const details = {
109
- file: fileRelativeUrl,
110
- ...(logRuntime ? { runtime: `${runtimeName}/${runtimeVersion}` } : {}),
111
- ...(logEachDuration
112
- ? {
113
- duration:
114
- status === "executing"
115
- ? msAsEllapsedTime((nowMs || Date.now()) - startMs)
116
- : msAsDuration(endMs - startMs),
117
- }
118
- : {}),
119
- };
120
- let message = ``;
121
- message += label;
122
- Object.keys(details).forEach((key) => {
123
- message += `
124
- ${key}: ${details[key]}`;
125
- });
126
- if (consoleOutput) {
127
- message += `\n${consoleOutput}`;
128
- }
129
- if (errorsOutput) {
130
- message += `\n${errorsOutput}`;
131
- }
132
- return message;
133
- };
134
-
135
- export const formatExecutionLabel = (
136
- {
137
- executionIndex,
138
- executionParams,
139
- executionResult,
140
- timeEllapsed,
141
- memoryHeap,
142
- counters,
143
- },
144
- { logTimeUsage, logMemoryHeapUsage } = {},
145
- ) => {
146
- const { status } = executionResult;
147
- const descriptionFormatter = descriptionFormatters[status];
148
- const description = descriptionFormatter({
149
- index: executionIndex,
150
- total: counters.total,
151
- executionParams,
152
- });
153
- const intermediateSummaryText = createIntermediateSummary({
154
- executionIndex,
155
- counters,
156
- timeEllapsed,
157
- memoryHeap,
158
- logTimeUsage,
159
- logMemoryHeapUsage,
160
- });
161
- return `${description}${intermediateSummaryText}`;
162
- };
163
-
164
- const formatErrors = (errors) => {
165
- if (errors.length === 0) {
166
- return "";
167
- }
168
- const formatError = (error) => {
169
- if (error === null || error === undefined) {
170
- return String(error);
171
- }
172
- if (error) {
173
- return error.stack || error.message || error;
174
- }
175
- return error;
176
- };
177
-
178
- if (errors.length === 1) {
179
- return `${ANSI.color(`-------- error --------`, ANSI.RED)}
180
- ${formatError(errors[0])}
181
- ${ANSI.color(`-------------------------`, ANSI.RED)}`;
182
- }
183
-
184
- let output = [];
185
- errors.forEach((error) => {
186
- output.push(
187
- prefixFirstAndIndentRemainingLines({
188
- prefix: `${UNICODE.CIRCLE_CROSS} `,
189
- indentation: " ",
190
- text: formatError(error),
191
- }),
192
- );
193
- });
194
- return `${ANSI.color(`-------- errors (${errors.length}) --------`, ANSI.RED)}
195
- ${output.join(`\n`)}
196
- ${ANSI.color(`-------------------------`, ANSI.RED)}`;
197
- };
198
-
199
- export const formatSummaryLog = (
200
- summary,
201
- ) => `-------------- summary -----------------
202
- ${formatSummary(summary)}
203
- ----------------------------------------`;
204
-
205
- export const formatSummary = (summary) => `${createAllExecutionsSummary(
206
- summary,
207
- )}
208
- total duration: ${msAsDuration(summary.duration)}`;
209
-
210
- const createAllExecutionsSummary = ({ counters }) => {
211
- if (counters.total === 0) {
212
- return `no execution`;
213
- }
214
- const executionLabel =
215
- counters.total === 1 ? `1 execution` : `${counters.total} executions`;
216
- return `${executionLabel}: ${createStatusSummary({
217
- counters,
218
- })}`;
219
- };
220
-
221
- const createIntermediateSummary = ({
222
- executionIndex,
223
- counters,
224
- memoryHeap,
225
- timeEllapsed,
226
- logTimeUsage,
227
- logMemoryHeapUsage,
228
- }) => {
229
- const parts = [];
230
- if (executionIndex > 0 || counters.done > 0) {
231
- parts.push(
232
- createStatusSummary({
233
- counters: {
234
- ...counters,
235
- total: executionIndex + 1,
236
- },
237
- }),
238
- );
239
- }
240
- if (logTimeUsage && timeEllapsed) {
241
- parts.push(`duration: ${msAsEllapsedTime(timeEllapsed)}`);
242
- }
243
- if (logMemoryHeapUsage && memoryHeap) {
244
- parts.push(`memory heap: ${byteAsMemoryUsage(memoryHeap)}`);
245
- }
246
- if (parts.length === 0) {
247
- return "";
248
- }
249
- return ` (${parts.join(` / `)})`;
250
- };
251
-
252
- const createStatusSummary = ({ counters }) => {
253
- if (counters.aborted === counters.total) {
254
- return `all ${ANSI.color(`aborted`, EXECUTION_COLORS.aborted)}`;
255
- }
256
- if (counters.timedout === counters.total) {
257
- return `all ${ANSI.color(`timed out`, EXECUTION_COLORS.timedout)}`;
258
- }
259
- if (counters.failed === counters.total) {
260
- return `all ${ANSI.color(`failed`, EXECUTION_COLORS.failed)}`;
261
- }
262
- if (counters.completed === counters.total) {
263
- return `all ${ANSI.color(`completed`, EXECUTION_COLORS.completed)}`;
264
- }
265
- if (counters.cancelled === counters.total) {
266
- return `all ${ANSI.color(`cancelled`, EXECUTION_COLORS.cancelled)}`;
267
- }
268
- return createMixedDetails({
269
- counters,
270
- });
271
- };
272
-
273
- const createMixedDetails = ({ counters }) => {
274
- const parts = [];
275
- if (counters.timedout) {
276
- parts.push(
277
- `${counters.timedout} ${ANSI.color(
278
- `timed out`,
279
- EXECUTION_COLORS.timedout,
280
- )}`,
281
- );
282
- }
283
- if (counters.failed) {
284
- parts.push(
285
- `${counters.failed} ${ANSI.color(`failed`, EXECUTION_COLORS.failed)}`,
286
- );
287
- }
288
- if (counters.completed) {
289
- parts.push(
290
- `${counters.completed} ${ANSI.color(
291
- `completed`,
292
- EXECUTION_COLORS.completed,
293
- )}`,
294
- );
295
- }
296
- if (counters.aborted) {
297
- parts.push(
298
- `${counters.aborted} ${ANSI.color(`aborted`, EXECUTION_COLORS.aborted)}`,
299
- );
300
- }
301
- if (counters.cancelled) {
302
- parts.push(
303
- `${counters.cancelled} ${ANSI.color(
304
- `cancelled`,
305
- EXECUTION_COLORS.cancelled,
306
- )}`,
307
- );
308
- }
309
- return `${parts.join(", ")}`;
310
- };
311
-
312
- const descriptionFormatters = {
313
- executing: ({ index, total }) => {
314
- return ANSI.color(
315
- `executing ${padNumber(index, total)} of ${total}`,
316
- EXECUTION_COLORS.executing,
317
- );
318
- },
319
- aborted: ({ index, total }) => {
320
- return ANSI.color(
321
- `${UNICODE.FAILURE_RAW} execution ${padNumber(
322
- index,
323
- total,
324
- )} of ${total} aborted`,
325
- EXECUTION_COLORS.aborted,
326
- );
327
- },
328
- timedout: ({ index, total, executionParams }) => {
329
- return ANSI.color(
330
- `${UNICODE.FAILURE_RAW} execution ${padNumber(
331
- index,
332
- total,
333
- )} of ${total} timeout after ${executionParams.allocatedMs}ms`,
334
- EXECUTION_COLORS.timedout,
335
- );
336
- },
337
- failed: ({ index, total }) => {
338
- return ANSI.color(
339
- `${UNICODE.FAILURE_RAW} execution ${padNumber(
340
- index,
341
- total,
342
- )} of ${total} failed`,
343
- EXECUTION_COLORS.failed,
344
- );
345
- },
346
- completed: ({ index, total }) => {
347
- return ANSI.color(
348
- `${UNICODE.OK_RAW} execution ${padNumber(
349
- index,
350
- total,
351
- )} of ${total} completed`,
352
- EXECUTION_COLORS.completed,
353
- );
354
- },
355
- cancelled: ({ index, total }) => {
356
- return ANSI.color(
357
- `${UNICODE.FAILURE_RAW} execution ${padNumber(
358
- index,
359
- total,
360
- )} of ${total} cancelled`,
361
- EXECUTION_COLORS.cancelled,
362
- );
363
- },
364
- };
365
-
366
- const padNumber = (index, total) => {
367
- const number = index + 1;
368
- const numberWidth = String(number).length;
369
- const totalWith = String(total).length;
370
- let missingWidth = totalWith - numberWidth;
371
- let padded = "";
372
- while (missingWidth--) {
373
- padded += "0";
374
- }
375
- padded += number;
376
- return padded;
377
- };
378
-
379
- const formatConsoleCalls = (consoleCalls) => {
380
- if (consoleCalls.length === 0) {
381
- return "";
382
- }
383
- const repartition = {
384
- debug: 0,
385
- info: 0,
386
- warning: 0,
387
- error: 0,
388
- log: 0,
389
- };
390
- consoleCalls.forEach((consoleCall) => {
391
- repartition[consoleCall.type]++;
392
- });
393
- const consoleOutput = formatConsoleOutput(consoleCalls);
394
-
395
- return `${ANSI.color(
396
- `-------- ${formatConsoleSummary(repartition)} --------`,
397
- ANSI.GREY,
398
- )}
399
- ${consoleOutput}
400
- ${ANSI.color(`-------------------------`, ANSI.GREY)}`;
401
- };
402
-
403
- export const formatConsoleOutput = (consoleCalls) => {
404
- // inside Node.js you can do process.stdout.write()
405
- // and in that case the consoleCall is not suffixed with "\n"
406
- // we want to keep these calls together in the output
407
- const regroupedCalls = [];
408
- consoleCalls.forEach((consoleCall, index) => {
409
- if (index === 0) {
410
- regroupedCalls.push(consoleCall);
411
- return;
412
- }
413
- const previousCall = consoleCalls[index - 1];
414
- if (previousCall.type !== consoleCall.type) {
415
- regroupedCalls.push(consoleCall);
416
- return;
417
- }
418
- if (previousCall.text.endsWith("\n")) {
419
- regroupedCalls.push(consoleCall);
420
- return;
421
- }
422
- if (previousCall.text.endsWith("\r")) {
423
- regroupedCalls.push(consoleCall);
424
- return;
425
- }
426
- const previousRegroupedCallIndex = regroupedCalls.length - 1;
427
- const previousRegroupedCall = regroupedCalls[previousRegroupedCallIndex];
428
- previousRegroupedCall.text = `${previousRegroupedCall.text}${consoleCall.text}`;
429
- });
430
-
431
- let consoleOutput = ``;
432
- regroupedCalls.forEach((regroupedCall, index) => {
433
- const text = regroupedCall.text;
434
- const textFormatted = prefixFirstAndIndentRemainingLines({
435
- prefix: CONSOLE_ICONS[regroupedCall.type],
436
- text,
437
- trimLines: true,
438
- trimLastLine: index === regroupedCalls.length - 1,
439
- });
440
- consoleOutput += textFormatted;
441
- });
442
- return consoleOutput;
443
- };
444
-
445
- const prefixFirstAndIndentRemainingLines = ({
446
- prefix,
447
- indentation = " ",
448
- text,
449
- trimLines,
450
- trimLastLine,
451
- }) => {
452
- const lines = text.split(/\r?\n/);
453
- const firstLine = lines.shift();
454
- let result = `${prefix} ${firstLine}`;
455
- let i = 0;
456
- while (i < lines.length) {
457
- const line = trimLines ? lines[i].trim() : lines[i];
458
- i++;
459
- result += line.length
460
- ? `\n${indentation}${line}`
461
- : trimLastLine && i === lines.length
462
- ? ""
463
- : `\n`;
464
- }
465
- return result;
466
- };
467
-
468
- const CONSOLE_ICONS = {
469
- debug: UNICODE.DEBUG,
470
- info: UNICODE.INFO,
471
- warning: UNICODE.WARNING,
472
- error: UNICODE.FAILURE,
473
- log: " ",
474
- };
475
-
476
- const formatConsoleSummary = (repartition) => {
477
- const { debug, info, warning, error } = repartition;
478
- const parts = [];
479
- if (error) {
480
- parts.push(`${CONSOLE_ICONS.error} ${error}`);
481
- }
482
- if (warning) {
483
- parts.push(`${CONSOLE_ICONS.warning} ${warning}`);
484
- }
485
- if (info) {
486
- parts.push(`${CONSOLE_ICONS.info} ${info}`);
487
- }
488
- if (debug) {
489
- parts.push(`${CONSOLE_ICONS.debug} ${debug}`);
490
- }
491
- if (parts.length === 0) {
492
- return `console`;
493
- }
494
- return `console (${parts.join(" ")})`;
495
- };