@jsenv/core 23.3.0 → 23.5.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/package.json +5 -5
- package/readme.md +4 -4
- package/src/execute.js +0 -6
- package/src/executeTestPlan.js +12 -10
- package/src/internal/browser-launcher/executeHtmlFile.js +20 -16
- package/src/internal/compiling/createCompiledFileService.js +13 -1
- package/src/internal/executing/coverage/babel_plugin_instrument.js +1 -0
- package/src/internal/executing/coverage/reportToCoverage.js +160 -119
- package/src/internal/executing/{coverage → coverage_missing}/createEmptyCoverage.js +0 -0
- package/src/internal/executing/coverage_missing/list_files_not_covered.js +20 -0
- package/src/internal/executing/coverage_missing/missing_coverage.js +46 -0
- package/src/internal/executing/{coverage → coverage_missing}/relativeUrlToEmptyCoverage.js +12 -8
- package/src/internal/executing/{coverage/generateCoverageHtmlDirectory.js → coverage_reporter/coverage_reporter_html_directory.js} +11 -4
- package/src/internal/executing/{coverage/generateCoverageJsonFile.js → coverage_reporter/coverage_reporter_json_file.js} +0 -0
- package/src/internal/executing/{coverage/generateCoverageTextLog.js → coverage_reporter/coverage_reporter_text_log.js} +4 -2
- package/src/internal/executing/{coverage → coverage_reporter}/istanbulCoverageMapFromCoverage.js +0 -0
- package/src/internal/executing/{coverage/normalizeIstanbulCoverage.js → coverage_utils/file_by_file_coverage.js} +9 -7
- package/src/internal/executing/coverage_utils/istanbul_coverage_composition.js +28 -0
- package/src/internal/executing/coverage_utils/v8_and_istanbul.js +38 -0
- package/src/internal/executing/coverage_utils/v8_coverage_composition.js +23 -0
- package/src/internal/executing/coverage_utils/v8_coverage_from_directory.js +77 -0
- package/src/internal/executing/{coverage/istanbulCoverageFromV8Coverage.js → coverage_utils/v8_coverage_to_istanbul.js} +38 -17
- package/src/internal/executing/createSummaryLog.js +5 -9
- package/src/internal/executing/executeConcurrently.js +199 -115
- package/src/internal/executing/executePlan.js +8 -5
- package/src/internal/executing/executionLogs.js +66 -37
- package/src/internal/executing/execution_colors.js +2 -1
- package/src/internal/executing/launchAndExecute.js +63 -58
- package/src/internal/logs/msAsDuration.js +4 -3
- package/src/launchBrowser.js +8 -8
- package/src/launchNode.js +5 -93
- package/src/internal/executing/coverage/composeIstanbulCoverages.js +0 -108
- package/src/internal/executing/coverage/composeV8Coverages.js +0 -20
- package/src/internal/executing/coverage/istanbulCoverageFromCoverages.js +0 -43
- package/src/internal/executing/coverage/v8CoverageFromAllV8Coverages.js +0 -40
- package/src/internal/executing/coverage/v8CoverageFromNodeV8Directory.js +0 -67
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
2
|
import wrapAnsi from "wrap-ansi"
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import { createLog } from "@jsenv/log"
|
|
3
|
+
import cuid from "cuid"
|
|
4
|
+
import { loggerToLevels } from "@jsenv/logger"
|
|
5
|
+
import { createLog, startSpinner } from "@jsenv/log"
|
|
6
|
+
import {
|
|
7
|
+
urlToFileSystemPath,
|
|
8
|
+
resolveUrl,
|
|
9
|
+
writeDirectory,
|
|
10
|
+
ensureEmptyDirectory,
|
|
11
|
+
normalizeStructuredMetaMap,
|
|
12
|
+
urlToMeta,
|
|
13
|
+
} from "@jsenv/filesystem"
|
|
14
|
+
import { Abort } from "@jsenv/abort"
|
|
6
15
|
|
|
7
16
|
import { launchAndExecute } from "../executing/launchAndExecute.js"
|
|
8
17
|
import { reportToCoverage } from "./coverage/reportToCoverage.js"
|
|
9
|
-
import {
|
|
18
|
+
import { formatExecuting, formatExecutionResult } from "./executionLogs.js"
|
|
10
19
|
import { createSummaryLog } from "./createSummaryLog.js"
|
|
11
20
|
|
|
12
21
|
export const executeConcurrently = async (
|
|
@@ -24,39 +33,107 @@ export const executeConcurrently = async (
|
|
|
24
33
|
babelPluginMap,
|
|
25
34
|
|
|
26
35
|
defaultMsAllocatedPerExecution = 30000,
|
|
36
|
+
cooldownBetweenExecutions = 0,
|
|
27
37
|
maxExecutionsInParallel = 1,
|
|
28
38
|
completedExecutionLogMerging,
|
|
29
39
|
completedExecutionLogAbbreviation,
|
|
30
|
-
measureGlobalDuration = true,
|
|
31
40
|
|
|
32
41
|
coverage,
|
|
33
42
|
coverageConfig,
|
|
34
43
|
coverageIncludeMissing,
|
|
35
44
|
coverageForceIstanbul,
|
|
36
|
-
|
|
45
|
+
coverageV8ConflictWarning,
|
|
46
|
+
coverageTempDirectoryRelativeUrl,
|
|
47
|
+
runtimeSupport,
|
|
37
48
|
|
|
38
|
-
mainFileNotFoundCallback = ({ fileRelativeUrl }) => {
|
|
39
|
-
logger.error(
|
|
40
|
-
new Error(
|
|
41
|
-
createDetailedMessage(`an execution main file does not exists.`, {
|
|
42
|
-
["file relative path"]: fileRelativeUrl,
|
|
43
|
-
}),
|
|
44
|
-
),
|
|
45
|
-
)
|
|
46
|
-
},
|
|
47
49
|
beforeExecutionCallback = () => {},
|
|
48
50
|
afterExecutionCallback = () => {},
|
|
49
51
|
|
|
50
52
|
logSummary,
|
|
51
53
|
},
|
|
52
54
|
) => {
|
|
55
|
+
if (completedExecutionLogMerging && !process.stdout.isTTY) {
|
|
56
|
+
completedExecutionLogMerging = false
|
|
57
|
+
logger.debug(
|
|
58
|
+
`Force completedExecutionLogMerging to false because process.stdout.isTTY is false`,
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
const executionLogsEnabled = loggerToLevels(logger).info
|
|
62
|
+
const executionSpinner = executionLogsEnabled && process.stdout.isTTY
|
|
63
|
+
|
|
53
64
|
const startMs = Date.now()
|
|
54
65
|
|
|
55
66
|
const report = {}
|
|
56
67
|
const executionCount = executionSteps.length
|
|
57
68
|
|
|
58
|
-
let
|
|
59
|
-
|
|
69
|
+
let transformReturnValue = (value) => value
|
|
70
|
+
|
|
71
|
+
const coverageTempDirectoryUrl = resolveUrl(
|
|
72
|
+
coverageTempDirectoryRelativeUrl,
|
|
73
|
+
projectDirectoryUrl,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
const structuredMetaMapForCover = normalizeStructuredMetaMap(
|
|
77
|
+
{
|
|
78
|
+
cover: coverageConfig,
|
|
79
|
+
},
|
|
80
|
+
projectDirectoryUrl,
|
|
81
|
+
)
|
|
82
|
+
const coverageIgnorePredicate = (url) => {
|
|
83
|
+
return !urlToMeta({
|
|
84
|
+
url: resolveUrl(url, projectDirectoryUrl),
|
|
85
|
+
structuredMetaMap: structuredMetaMapForCover,
|
|
86
|
+
}).cover
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (coverage) {
|
|
90
|
+
// in case runned multiple times, we don't want to keep writing lot of files in this directory
|
|
91
|
+
if (!process.env.NODE_V8_COVERAGE) {
|
|
92
|
+
await ensureEmptyDirectory(coverageTempDirectoryUrl)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (runtimeSupport.node) {
|
|
96
|
+
// v8 coverage is written in a directoy and auto propagate to subprocesses
|
|
97
|
+
// through process.env.NODE_V8_COVERAGE.
|
|
98
|
+
if (!coverageForceIstanbul && !process.env.NODE_V8_COVERAGE) {
|
|
99
|
+
const v8CoverageDirectory = resolveUrl(
|
|
100
|
+
`./node_v8/${cuid()}`,
|
|
101
|
+
coverageTempDirectoryUrl,
|
|
102
|
+
)
|
|
103
|
+
await writeDirectory(v8CoverageDirectory, { allowUseless: true })
|
|
104
|
+
process.env.NODE_V8_COVERAGE = urlToFileSystemPath(v8CoverageDirectory)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
transformReturnValue = async (value) => {
|
|
109
|
+
if (multipleExecutionsOperation.signal.aborted) {
|
|
110
|
+
// don't try to do the coverage stuff
|
|
111
|
+
return value
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
value.coverage = await reportToCoverage(value.report, {
|
|
116
|
+
signal: multipleExecutionsOperation.signal,
|
|
117
|
+
logger,
|
|
118
|
+
projectDirectoryUrl,
|
|
119
|
+
babelPluginMap,
|
|
120
|
+
coverageConfig,
|
|
121
|
+
coverageIncludeMissing,
|
|
122
|
+
coverageForceIstanbul,
|
|
123
|
+
coverageIgnorePredicate,
|
|
124
|
+
coverageV8ConflictWarning,
|
|
125
|
+
})
|
|
126
|
+
} catch (e) {
|
|
127
|
+
if (Abort.isAbortError(e)) {
|
|
128
|
+
return value
|
|
129
|
+
}
|
|
130
|
+
throw e
|
|
131
|
+
}
|
|
132
|
+
return value
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
let executionLog = createLog({ newLine: "around" })
|
|
60
137
|
let abortedCount = 0
|
|
61
138
|
let timedoutCount = 0
|
|
62
139
|
let erroredCount = 0
|
|
@@ -64,18 +141,19 @@ export const executeConcurrently = async (
|
|
|
64
141
|
const executionsDone = await executeInParallel({
|
|
65
142
|
multipleExecutionsOperation,
|
|
66
143
|
maxExecutionsInParallel,
|
|
144
|
+
cooldownBetweenExecutions,
|
|
67
145
|
executionSteps,
|
|
68
146
|
start: async (paramsFromStep) => {
|
|
69
147
|
const executionIndex = executionSteps.indexOf(paramsFromStep)
|
|
70
|
-
const { executionName, fileRelativeUrl } = paramsFromStep
|
|
148
|
+
const { executionName, fileRelativeUrl, runtime } = paramsFromStep
|
|
149
|
+
const runtimeName = runtime.name
|
|
150
|
+
const runtimeVersion = runtime.version
|
|
151
|
+
|
|
71
152
|
const executionParams = {
|
|
72
153
|
// the params below can be overriden by executionDefaultParams
|
|
73
154
|
measurePerformance: false,
|
|
74
155
|
collectPerformance: false,
|
|
75
|
-
measureDuration: true,
|
|
76
156
|
captureConsole: true,
|
|
77
|
-
collectRuntimeName: true,
|
|
78
|
-
collectRuntimeVersion: true,
|
|
79
157
|
// stopAfterExecute: true to ensure runtime is stopped once executed
|
|
80
158
|
// because we have what we wants: execution is completed and
|
|
81
159
|
// we have associated coverage and capturedConsole
|
|
@@ -85,6 +163,7 @@ export const executeConcurrently = async (
|
|
|
85
163
|
stopAfterExecuteReason: "execution-done",
|
|
86
164
|
allocatedMs: defaultMsAllocatedPerExecution,
|
|
87
165
|
...paramsFromStep,
|
|
166
|
+
runtime,
|
|
88
167
|
// mirrorConsole: false because file will be executed in parallel
|
|
89
168
|
// so log would be a mess to read
|
|
90
169
|
mirrorConsole: false,
|
|
@@ -92,47 +171,69 @@ export const executeConcurrently = async (
|
|
|
92
171
|
|
|
93
172
|
const beforeExecutionInfo = {
|
|
94
173
|
fileRelativeUrl,
|
|
174
|
+
runtimeName,
|
|
175
|
+
runtimeVersion,
|
|
95
176
|
executionIndex,
|
|
96
177
|
executionParams,
|
|
97
178
|
}
|
|
98
179
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
180
|
+
let spinner
|
|
181
|
+
if (executionSpinner) {
|
|
182
|
+
spinner = startSpinner({
|
|
183
|
+
log: executionLog,
|
|
184
|
+
text: formatExecuting(beforeExecutionInfo, {
|
|
185
|
+
executionCount,
|
|
186
|
+
abortedCount,
|
|
187
|
+
timedoutCount,
|
|
188
|
+
erroredCount,
|
|
189
|
+
completedCount,
|
|
190
|
+
}),
|
|
191
|
+
})
|
|
106
192
|
}
|
|
107
|
-
|
|
108
193
|
beforeExecutionCallback(beforeExecutionInfo)
|
|
109
194
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
195
|
+
const filePath = urlToFileSystemPath(
|
|
196
|
+
`${projectDirectoryUrl}${fileRelativeUrl}`,
|
|
197
|
+
)
|
|
198
|
+
let executionResult
|
|
199
|
+
if (existsSync(filePath)) {
|
|
200
|
+
executionResult = await launchAndExecute({
|
|
201
|
+
signal: multipleExecutionsOperation.signal,
|
|
202
|
+
launchAndExecuteLogLevel,
|
|
116
203
|
|
|
117
|
-
|
|
118
|
-
collectCoverage: coverage,
|
|
119
|
-
runtimeParams: {
|
|
120
|
-
projectDirectoryUrl,
|
|
121
|
-
compileServerOrigin,
|
|
122
|
-
outDirectoryRelativeUrl,
|
|
204
|
+
...executionParams,
|
|
123
205
|
collectCoverage: coverage,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
206
|
+
coverageTempDirectoryUrl,
|
|
207
|
+
runtimeParams: {
|
|
208
|
+
projectDirectoryUrl,
|
|
209
|
+
compileServerOrigin,
|
|
210
|
+
outDirectoryRelativeUrl,
|
|
211
|
+
collectCoverage: coverage,
|
|
212
|
+
coverageIgnorePredicate,
|
|
213
|
+
coverageForceIstanbul,
|
|
214
|
+
...executionParams.runtimeParams,
|
|
215
|
+
},
|
|
216
|
+
executeParams: {
|
|
217
|
+
fileRelativeUrl,
|
|
218
|
+
...executionParams.executeParams,
|
|
219
|
+
},
|
|
220
|
+
coverageV8ConflictWarning,
|
|
221
|
+
})
|
|
222
|
+
} else {
|
|
223
|
+
executionResult = {
|
|
224
|
+
status: "errored",
|
|
225
|
+
error: new Error(
|
|
226
|
+
`No file at ${fileRelativeUrl} for execution "${executionName}"`,
|
|
227
|
+
),
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (fileRelativeUrl in report === false) {
|
|
231
|
+
report[fileRelativeUrl] = {}
|
|
232
|
+
}
|
|
233
|
+
report[fileRelativeUrl][executionName] = executionResult
|
|
134
234
|
const afterExecutionInfo = {
|
|
135
235
|
...beforeExecutionInfo,
|
|
236
|
+
endMs: Date.now(),
|
|
136
237
|
executionResult,
|
|
137
238
|
}
|
|
138
239
|
afterExecutionCallback(afterExecutionInfo)
|
|
@@ -147,8 +248,8 @@ export const executeConcurrently = async (
|
|
|
147
248
|
completedCount++
|
|
148
249
|
}
|
|
149
250
|
|
|
150
|
-
if (
|
|
151
|
-
let log =
|
|
251
|
+
if (executionLogsEnabled) {
|
|
252
|
+
let log = formatExecutionResult(afterExecutionInfo, {
|
|
152
253
|
completedExecutionLogAbbreviation,
|
|
153
254
|
executionCount,
|
|
154
255
|
abortedCount,
|
|
@@ -163,31 +264,21 @@ export const executeConcurrently = async (
|
|
|
163
264
|
wordWrap: false,
|
|
164
265
|
})
|
|
165
266
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
previousExecutionLog.write(log)
|
|
267
|
+
// replace spinner with this execution result
|
|
268
|
+
if (spinner) spinner.stop()
|
|
269
|
+
executionLog.write(log)
|
|
270
|
+
|
|
271
|
+
const canOverwriteLog = canOverwriteLogGetter({
|
|
272
|
+
completedExecutionLogMerging,
|
|
273
|
+
executionResult,
|
|
274
|
+
})
|
|
275
|
+
if (canOverwriteLog) {
|
|
276
|
+
// nothing to do, we reuse the current executionLog object
|
|
177
277
|
} else {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
previousExecutionLog = createLog()
|
|
182
|
-
previousExecutionLog.write(log)
|
|
278
|
+
executionLog.destroy()
|
|
279
|
+
executionLog = createLog({ newLine: "around" })
|
|
183
280
|
}
|
|
184
281
|
}
|
|
185
|
-
|
|
186
|
-
if (fileRelativeUrl in report === false) {
|
|
187
|
-
report[fileRelativeUrl] = {}
|
|
188
|
-
}
|
|
189
|
-
report[fileRelativeUrl][executionName] = executionResult
|
|
190
|
-
previousExecutionResult = executionResult
|
|
191
282
|
},
|
|
192
283
|
})
|
|
193
284
|
|
|
@@ -202,37 +293,40 @@ export const executeConcurrently = async (
|
|
|
202
293
|
executionsDone.length -
|
|
203
294
|
// we substract abortedCount because they are not pushed into executionsDone
|
|
204
295
|
summaryCounts.abortedCount,
|
|
205
|
-
|
|
296
|
+
duration: Date.now() - startMs,
|
|
206
297
|
}
|
|
207
298
|
if (logSummary) {
|
|
208
299
|
logger.info(createSummaryLog(summary))
|
|
209
300
|
}
|
|
210
301
|
|
|
211
|
-
|
|
212
|
-
// don't try to do the coverage stuff
|
|
213
|
-
return {
|
|
214
|
-
summary,
|
|
215
|
-
report,
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return {
|
|
302
|
+
return transformReturnValue({
|
|
220
303
|
summary,
|
|
221
304
|
report,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const canOverwriteLogGetter = ({
|
|
309
|
+
completedExecutionLogMerging,
|
|
310
|
+
executionResult,
|
|
311
|
+
}) => {
|
|
312
|
+
if (!completedExecutionLogMerging) {
|
|
313
|
+
return false
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (executionResult.status === "aborted") {
|
|
317
|
+
return true
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (executionResult.status !== "completed") {
|
|
321
|
+
return false
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const { consoleCalls = [] } = executionResult
|
|
325
|
+
if (consoleCalls.length > 0) {
|
|
326
|
+
return false
|
|
235
327
|
}
|
|
328
|
+
|
|
329
|
+
return true
|
|
236
330
|
}
|
|
237
331
|
|
|
238
332
|
const executeInParallel = async ({
|
|
@@ -240,6 +334,7 @@ const executeInParallel = async ({
|
|
|
240
334
|
executionSteps,
|
|
241
335
|
start,
|
|
242
336
|
maxExecutionsInParallel = 1,
|
|
337
|
+
cooldownBetweenExecutions,
|
|
243
338
|
}) => {
|
|
244
339
|
const executionResults = []
|
|
245
340
|
let progressionIndex = 0
|
|
@@ -275,6 +370,11 @@ const executeInParallel = async ({
|
|
|
275
370
|
if (!multipleExecutionsOperation.signal.aborted) {
|
|
276
371
|
executionResults[index] = output
|
|
277
372
|
}
|
|
373
|
+
if (cooldownBetweenExecutions) {
|
|
374
|
+
await new Promise((resolve) =>
|
|
375
|
+
setTimeout(resolve, cooldownBetweenExecutions),
|
|
376
|
+
)
|
|
377
|
+
}
|
|
278
378
|
}
|
|
279
379
|
|
|
280
380
|
await nextChunk()
|
|
@@ -282,22 +382,6 @@ const executeInParallel = async ({
|
|
|
282
382
|
return executionResults
|
|
283
383
|
}
|
|
284
384
|
|
|
285
|
-
const pathLeadsToFile = (path) => {
|
|
286
|
-
return new Promise((resolve, reject) => {
|
|
287
|
-
stat(path, (error, stats) => {
|
|
288
|
-
if (error) {
|
|
289
|
-
if (error.code === "ENOENT") {
|
|
290
|
-
resolve(false)
|
|
291
|
-
} else {
|
|
292
|
-
reject(error)
|
|
293
|
-
}
|
|
294
|
-
} else {
|
|
295
|
-
resolve(stats.isFile())
|
|
296
|
-
}
|
|
297
|
-
})
|
|
298
|
-
})
|
|
299
|
-
}
|
|
300
|
-
|
|
301
385
|
const reportToSummary = (report) => {
|
|
302
386
|
const fileNames = Object.keys(report)
|
|
303
387
|
|
|
@@ -25,16 +25,17 @@ export const executePlan = async (
|
|
|
25
25
|
|
|
26
26
|
defaultMsAllocatedPerExecution,
|
|
27
27
|
maxExecutionsInParallel,
|
|
28
|
+
cooldownBetweenExecutions,
|
|
28
29
|
completedExecutionLogMerging,
|
|
29
30
|
completedExecutionLogAbbreviation,
|
|
30
31
|
logSummary,
|
|
31
|
-
measureGlobalDuration,
|
|
32
32
|
|
|
33
33
|
coverage,
|
|
34
34
|
coverageConfig,
|
|
35
35
|
coverageIncludeMissing,
|
|
36
36
|
coverageForceIstanbul,
|
|
37
|
-
|
|
37
|
+
coverageV8ConflictWarning,
|
|
38
|
+
coverageTempDirectoryRelativeUrl,
|
|
38
39
|
|
|
39
40
|
compileServerProtocol,
|
|
40
41
|
compileServerPrivateKey,
|
|
@@ -81,7 +82,6 @@ export const executePlan = async (
|
|
|
81
82
|
SIGINT: true,
|
|
82
83
|
},
|
|
83
84
|
() => {
|
|
84
|
-
logger.info("Aborting execution (SIGINT)")
|
|
85
85
|
abort()
|
|
86
86
|
},
|
|
87
87
|
)
|
|
@@ -147,19 +147,22 @@ export const executePlan = async (
|
|
|
147
147
|
|
|
148
148
|
defaultMsAllocatedPerExecution,
|
|
149
149
|
maxExecutionsInParallel,
|
|
150
|
+
cooldownBetweenExecutions,
|
|
150
151
|
completedExecutionLogMerging,
|
|
151
152
|
completedExecutionLogAbbreviation,
|
|
152
153
|
logSummary,
|
|
153
|
-
measureGlobalDuration,
|
|
154
154
|
|
|
155
155
|
coverage,
|
|
156
156
|
coverageConfig,
|
|
157
157
|
coverageIncludeMissing,
|
|
158
158
|
coverageForceIstanbul,
|
|
159
|
-
|
|
159
|
+
coverageV8ConflictWarning,
|
|
160
|
+
coverageTempDirectoryRelativeUrl,
|
|
161
|
+
runtimeSupport,
|
|
160
162
|
})
|
|
161
163
|
|
|
162
164
|
return {
|
|
165
|
+
aborted: multipleExecutionsOperation.signal.aborted,
|
|
163
166
|
planSummary: result.summary,
|
|
164
167
|
planReport: result.report,
|
|
165
168
|
planCoverage: result.coverage,
|
|
@@ -4,8 +4,40 @@ import { msAsDuration } from "../logs/msAsDuration.js"
|
|
|
4
4
|
import { EXECUTION_COLORS } from "./execution_colors.js"
|
|
5
5
|
import { createSummaryDetails } from "./createSummaryLog.js"
|
|
6
6
|
|
|
7
|
-
export const
|
|
8
|
-
{ executionIndex
|
|
7
|
+
export const formatExecuting = (
|
|
8
|
+
{ executionIndex },
|
|
9
|
+
{ executionCount, abortedCount, timedoutCount, erroredCount, completedCount },
|
|
10
|
+
) => {
|
|
11
|
+
const executionNumber = executionIndex + 1
|
|
12
|
+
const description = ANSI.color(
|
|
13
|
+
`executing ${executionNumber} of ${executionCount}`,
|
|
14
|
+
EXECUTION_COLORS.executing,
|
|
15
|
+
)
|
|
16
|
+
const summary =
|
|
17
|
+
executionIndex === 0
|
|
18
|
+
? ""
|
|
19
|
+
: `(${createSummaryDetails({
|
|
20
|
+
executionCount: executionIndex,
|
|
21
|
+
abortedCount,
|
|
22
|
+
timedoutCount,
|
|
23
|
+
erroredCount,
|
|
24
|
+
completedCount,
|
|
25
|
+
})})`
|
|
26
|
+
|
|
27
|
+
return formatExecution({
|
|
28
|
+
label: `${description} ${summary}`,
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const formatExecutionResult = (
|
|
33
|
+
{
|
|
34
|
+
executionIndex,
|
|
35
|
+
fileRelativeUrl,
|
|
36
|
+
runtimeName,
|
|
37
|
+
runtimeVersion,
|
|
38
|
+
executionParams,
|
|
39
|
+
executionResult,
|
|
40
|
+
},
|
|
9
41
|
{
|
|
10
42
|
completedExecutionLogAbbreviation,
|
|
11
43
|
executionCount,
|
|
@@ -24,6 +56,7 @@ export const createExecutionResultLog = (
|
|
|
24
56
|
executionCount,
|
|
25
57
|
allocatedMs,
|
|
26
58
|
})
|
|
59
|
+
|
|
27
60
|
const summary = `(${createSummaryDetails({
|
|
28
61
|
executionCount: executionNumber,
|
|
29
62
|
abortedCount,
|
|
@@ -33,21 +66,22 @@ export const createExecutionResultLog = (
|
|
|
33
66
|
})})`
|
|
34
67
|
|
|
35
68
|
if (completedExecutionLogAbbreviation && status === "completed") {
|
|
36
|
-
return `
|
|
37
|
-
${description} ${summary}`
|
|
69
|
+
return `${description} ${summary}`
|
|
38
70
|
}
|
|
39
71
|
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
file:
|
|
47
|
-
runtime:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
72
|
+
const { consoleCalls = [], error, duration } = executionResult
|
|
73
|
+
const console = formatConsoleCalls(consoleCalls)
|
|
74
|
+
|
|
75
|
+
return formatExecution({
|
|
76
|
+
label: `${description} ${summary}`,
|
|
77
|
+
details: {
|
|
78
|
+
file: fileRelativeUrl,
|
|
79
|
+
runtime: `${runtimeName}/${runtimeVersion}`,
|
|
80
|
+
duration: msAsDuration(duration),
|
|
81
|
+
...(error ? { error: error.stack } : {}),
|
|
82
|
+
},
|
|
83
|
+
console,
|
|
84
|
+
})
|
|
51
85
|
}
|
|
52
86
|
|
|
53
87
|
const descriptionFormatters = {
|
|
@@ -83,38 +117,33 @@ const descriptionFormatters = {
|
|
|
83
117
|
},
|
|
84
118
|
}
|
|
85
119
|
|
|
86
|
-
const
|
|
87
|
-
if (!endMs) return ""
|
|
88
|
-
|
|
89
|
-
return `
|
|
90
|
-
duration: ${msAsDuration(endMs - startMs)}`
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const appendConsole = (consoleCalls) => {
|
|
94
|
-
if (!consoleCalls || consoleCalls.length === 0) return ""
|
|
95
|
-
|
|
120
|
+
const formatConsoleCalls = (consoleCalls) => {
|
|
96
121
|
const consoleOutput = consoleCalls.reduce((previous, { text }) => {
|
|
97
122
|
return `${previous}${text}`
|
|
98
123
|
}, "")
|
|
99
124
|
|
|
100
125
|
const consoleOutputTrimmed = consoleOutput.trim()
|
|
101
|
-
if (consoleOutputTrimmed === "")
|
|
126
|
+
if (consoleOutputTrimmed === "") {
|
|
127
|
+
return ""
|
|
128
|
+
}
|
|
102
129
|
|
|
103
|
-
return
|
|
104
|
-
${ANSI.color(`-------- console --------`, ANSI.GREY)}
|
|
130
|
+
return `${ANSI.color(`-------- console --------`, ANSI.GREY)}
|
|
105
131
|
${consoleOutputTrimmed}
|
|
106
132
|
${ANSI.color(`-------------------------`, ANSI.GREY)}`
|
|
107
133
|
}
|
|
108
134
|
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
const formatExecution = ({ label, details = {}, console }) => {
|
|
136
|
+
let message = ``
|
|
137
|
+
|
|
138
|
+
message += label
|
|
139
|
+
Object.keys(details).forEach((key) => {
|
|
140
|
+
message += `
|
|
141
|
+
${key}: ${details[key]}`
|
|
142
|
+
})
|
|
143
|
+
if (console) {
|
|
144
|
+
message += `
|
|
145
|
+
${console}`
|
|
112
146
|
}
|
|
113
147
|
|
|
114
|
-
return
|
|
115
|
-
error: ${error.stack}`
|
|
148
|
+
return message
|
|
116
149
|
}
|
|
117
|
-
|
|
118
|
-
// export const createShortExecutionResultLog = () => {
|
|
119
|
-
// return `Execution completed (2/9) - (all completed)`
|
|
120
|
-
// }
|