@jsenv/core 30.4.1 → 31.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.
- package/dist/babel_helpers/applyDecs2203R/applyDecs2203R.js +355 -388
- package/dist/babel_helpers/applyDecs2301/applyDecs2301.js +575 -0
- package/dist/js/s.js.map +12 -11
- package/dist/js/supervisor.js +1 -1
- package/dist/js/v8_coverage.js +29 -22
- package/dist/js/ws.js +30 -26
- package/dist/main.js +268 -165
- package/package.json +17 -16
- package/src/build/build.js +26 -3
- package/src/build/start_build_server.js +2 -6
- package/src/dev/start_dev_server.js +28 -15
- package/src/execute/execute.js +1 -1
- package/src/execute/run.js +2 -2
- package/src/execute/runtimes/browsers/from_playwright.js +5 -5
- package/src/execute/runtimes/node/node_child_process.js +6 -6
- package/src/execute/runtimes/node/node_worker_thread.js +6 -6
- package/src/plugins/supervisor/client/supervisor.js +1 -1
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_library.js +1 -4
- package/src/test/execute_plan.js +4 -4
- package/src/test/execute_test_plan.js +57 -39
- package/src/test/execution_colors.js +1 -1
- package/src/test/logs_file_execution.js +7 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "31.0.0",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -67,47 +67,48 @@
|
|
|
67
67
|
"@c88/v8-coverage": "0.1.1",
|
|
68
68
|
"@financial-times/polyfill-useragent-normaliser": "1.10.2",
|
|
69
69
|
"@jsenv/abort": "4.2.4",
|
|
70
|
-
"@jsenv/ast": "3.0.
|
|
71
|
-
"@jsenv/babel-plugins": "1.1.
|
|
72
|
-
"@jsenv/
|
|
73
|
-
"@jsenv/filesystem": "4.1.9",
|
|
70
|
+
"@jsenv/ast": "3.0.3",
|
|
71
|
+
"@jsenv/babel-plugins": "1.1.5",
|
|
72
|
+
"@jsenv/filesystem": "4.2.0",
|
|
74
73
|
"@jsenv/importmap": "1.2.1",
|
|
75
74
|
"@jsenv/integrity": "0.0.1",
|
|
76
|
-
"@jsenv/log": "3.3.
|
|
75
|
+
"@jsenv/log": "3.3.4",
|
|
77
76
|
"@jsenv/node-esm-resolution": "1.0.1",
|
|
78
|
-
"@jsenv/
|
|
79
|
-
"@jsenv/
|
|
77
|
+
"@jsenv/plugin-bundling": "2.0.0",
|
|
78
|
+
"@jsenv/server": "15.0.0",
|
|
79
|
+
"@jsenv/sourcemap": "1.0.9",
|
|
80
80
|
"@jsenv/uneval": "1.6.0",
|
|
81
|
-
"@jsenv/url-meta": "7.0
|
|
81
|
+
"@jsenv/url-meta": "7.1.0",
|
|
82
82
|
"@jsenv/urls": "1.2.8",
|
|
83
83
|
"@jsenv/utils": "2.0.1",
|
|
84
|
-
"@paralleldrive/cuid2": "2.0
|
|
84
|
+
"@paralleldrive/cuid2": "2.2.0",
|
|
85
85
|
"construct-style-sheets-polyfill": "3.1.0",
|
|
86
86
|
"istanbul-lib-coverage": "3.2.0",
|
|
87
87
|
"istanbul-lib-instrument": "5.2.1",
|
|
88
88
|
"istanbul-lib-report": "3.0.0",
|
|
89
89
|
"istanbul-reports": "3.1.5",
|
|
90
90
|
"launch-editor": "2.6.0",
|
|
91
|
-
"lightningcss": "1.
|
|
91
|
+
"lightningcss": "1.19.0",
|
|
92
92
|
"pidtree": "0.6.0",
|
|
93
93
|
"string-width": "5.1.2",
|
|
94
94
|
"strip-ansi": "7.0.1",
|
|
95
|
-
"v8-to-istanbul": "9.0
|
|
95
|
+
"v8-to-istanbul": "9.1.0",
|
|
96
|
+
"webidl2": "24.2.2",
|
|
96
97
|
"wrap-ansi": "8.1.0"
|
|
97
98
|
},
|
|
98
99
|
"devDependencies": {
|
|
99
|
-
"@babel/eslint-parser": "7.
|
|
100
|
+
"@babel/eslint-parser": "7.21.3",
|
|
100
101
|
"@babel/plugin-syntax-import-assertions": "7.20.0",
|
|
101
102
|
"@jsenv/assert": "./packages/assert/",
|
|
102
103
|
"@jsenv/eslint-config": "./packages/eslint-config/",
|
|
103
104
|
"@jsenv/file-size-impact": "14.0.0",
|
|
104
105
|
"@jsenv/https-local": "3.0.6",
|
|
105
106
|
"@jsenv/package-workspace": "0.5.1",
|
|
106
|
-
"@jsenv/
|
|
107
|
+
"@jsenv/performance-impact": "4.1.0",
|
|
107
108
|
"@jsenv/plugin-globals": "./packages/jsenv-plugin-globals/",
|
|
109
|
+
"@jsenv/plugin-minification": "./packages/jsenv-plugin-minification/",
|
|
108
110
|
"@jsenv/plugin-placeholders": "./packages/jsenv-plugin-placeholders/",
|
|
109
|
-
"
|
|
110
|
-
"eslint": "8.35.0",
|
|
111
|
+
"eslint": "8.36.0",
|
|
111
112
|
"eslint-plugin-html": "7.1.0",
|
|
112
113
|
"eslint-plugin-import": "2.27.5",
|
|
113
114
|
"eslint-plugin-react": "7.32.2",
|
package/src/build/build.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
urlToRelativeUrl,
|
|
29
29
|
} from "@jsenv/urls"
|
|
30
30
|
import {
|
|
31
|
-
|
|
31
|
+
validateDirectoryUrl,
|
|
32
32
|
ensureEmptyDirectory,
|
|
33
33
|
writeFileSync,
|
|
34
34
|
registerDirectoryLifecycle,
|
|
@@ -155,7 +155,32 @@ export const build = async ({
|
|
|
155
155
|
writeGeneratedFiles = false,
|
|
156
156
|
assetManifest = versioningMethod === "filename",
|
|
157
157
|
assetManifestFileRelativeUrl = "asset-manifest.json",
|
|
158
|
+
...rest
|
|
158
159
|
}) => {
|
|
160
|
+
// param validation
|
|
161
|
+
{
|
|
162
|
+
const unexpectedParamNames = Object.keys(rest)
|
|
163
|
+
if (unexpectedParamNames.length > 0) {
|
|
164
|
+
throw new TypeError(
|
|
165
|
+
`${unexpectedParamNames.join(",")}: there is no such param`,
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
const rootDirectoryUrlValidation = validateDirectoryUrl(rootDirectoryUrl)
|
|
169
|
+
if (!rootDirectoryUrlValidation.valid) {
|
|
170
|
+
throw new TypeError(
|
|
171
|
+
`rootDirectoryUrl ${rootDirectoryUrlValidation.message}, got ${rootDirectoryUrl}`,
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
rootDirectoryUrl = rootDirectoryUrlValidation.value
|
|
175
|
+
const buildDirectoryUrlValidation = validateDirectoryUrl(buildDirectoryUrl)
|
|
176
|
+
if (!buildDirectoryUrlValidation.valid) {
|
|
177
|
+
throw new TypeError(
|
|
178
|
+
`buildDirectoryUrl ${buildDirectoryUrlValidation.message}, got ${buildDirectoryUrlValidation}`,
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
buildDirectoryUrl = buildDirectoryUrlValidation.value
|
|
182
|
+
}
|
|
183
|
+
|
|
159
184
|
const operation = Abort.startOperation()
|
|
160
185
|
operation.addAbortSignal(signal)
|
|
161
186
|
if (handleSIGINT) {
|
|
@@ -169,8 +194,6 @@ export const build = async ({
|
|
|
169
194
|
})
|
|
170
195
|
}
|
|
171
196
|
|
|
172
|
-
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
173
|
-
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl)
|
|
174
197
|
assertEntryPoints({ entryPoints })
|
|
175
198
|
if (!["filename", "search_param"].includes(versioningMethod)) {
|
|
176
199
|
throw new Error(
|
|
@@ -44,10 +44,8 @@ export const startBuildServer = async ({
|
|
|
44
44
|
handleSIGINT = true,
|
|
45
45
|
logLevel,
|
|
46
46
|
serverLogLevel = "warn",
|
|
47
|
-
|
|
47
|
+
https,
|
|
48
48
|
http2,
|
|
49
|
-
certificate,
|
|
50
|
-
privateKey,
|
|
51
49
|
acceptAnyIp,
|
|
52
50
|
hostname,
|
|
53
51
|
port = 9779,
|
|
@@ -169,10 +167,8 @@ export const startBuildServer = async ({
|
|
|
169
167
|
logLevel: serverLogLevel,
|
|
170
168
|
startLog: false,
|
|
171
169
|
|
|
172
|
-
|
|
170
|
+
https,
|
|
173
171
|
http2,
|
|
174
|
-
certificate,
|
|
175
|
-
privateKey,
|
|
176
172
|
acceptAnyIp,
|
|
177
173
|
hostname,
|
|
178
174
|
port,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parentPort } from "node:worker_threads"
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
validateDirectoryUrl,
|
|
4
4
|
registerDirectoryLifecycle,
|
|
5
5
|
} from "@jsenv/filesystem"
|
|
6
6
|
import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
|
|
@@ -32,12 +32,10 @@ export const startDevServer = async ({
|
|
|
32
32
|
handleSIGINT = true,
|
|
33
33
|
logLevel = "info",
|
|
34
34
|
serverLogLevel = "warn",
|
|
35
|
-
|
|
35
|
+
https,
|
|
36
36
|
// it's better to use http1 by default because it allows to get statusText in devtools
|
|
37
37
|
// which gives valuable information when there is errors
|
|
38
38
|
http2 = false,
|
|
39
|
-
certificate,
|
|
40
|
-
privateKey,
|
|
41
39
|
hostname,
|
|
42
40
|
port = 3456,
|
|
43
41
|
acceptAnyIp,
|
|
@@ -82,9 +80,26 @@ export const startDevServer = async ({
|
|
|
82
80
|
// no real need to write files during github workflow
|
|
83
81
|
// and mitigates https://github.com/actions/runner-images/issues/3885
|
|
84
82
|
writeGeneratedFiles = !process.env.CI,
|
|
83
|
+
...rest
|
|
85
84
|
}) => {
|
|
85
|
+
// params type checking
|
|
86
|
+
{
|
|
87
|
+
const unexpectedParamNames = Object.keys(rest)
|
|
88
|
+
if (unexpectedParamNames.length > 0) {
|
|
89
|
+
throw new TypeError(
|
|
90
|
+
`${unexpectedParamNames.join(",")}: there is no such param`,
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
const rootDirectoryUrlValidation = validateDirectoryUrl(rootDirectoryUrl)
|
|
94
|
+
if (!rootDirectoryUrlValidation.valid) {
|
|
95
|
+
throw new TypeError(
|
|
96
|
+
`rootDirectoryUrl ${rootDirectoryUrlValidation.message}, got ${rootDirectoryUrl}`,
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
rootDirectoryUrl = rootDirectoryUrlValidation.value
|
|
100
|
+
}
|
|
101
|
+
|
|
86
102
|
const logger = createLogger({ logLevel })
|
|
87
|
-
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
88
103
|
const operation = Abort.startOperation()
|
|
89
104
|
operation.addAbortSignal(signal)
|
|
90
105
|
if (handleSIGINT) {
|
|
@@ -167,10 +182,8 @@ export const startDevServer = async ({
|
|
|
167
182
|
logLevel: serverLogLevel,
|
|
168
183
|
startLog: false,
|
|
169
184
|
|
|
170
|
-
|
|
185
|
+
https,
|
|
171
186
|
http2,
|
|
172
|
-
certificate,
|
|
173
|
-
privateKey,
|
|
174
187
|
acceptAnyIp,
|
|
175
188
|
hostname,
|
|
176
189
|
port,
|
|
@@ -265,13 +278,13 @@ export const startDevServer = async ({
|
|
|
265
278
|
sendErrorDetails: true,
|
|
266
279
|
}),
|
|
267
280
|
],
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
281
|
+
})
|
|
282
|
+
server.stoppedPromise.then((reason) => {
|
|
283
|
+
onStop()
|
|
284
|
+
serverStopCallbacks.forEach((serverStopCallback) => {
|
|
285
|
+
serverStopCallback(reason)
|
|
286
|
+
})
|
|
287
|
+
serverStopCallbacks.length = 0
|
|
275
288
|
})
|
|
276
289
|
startDevServerTask.done()
|
|
277
290
|
if (hostname) {
|
package/src/execute/execute.js
CHANGED
package/src/execute/run.js
CHANGED
|
@@ -119,7 +119,7 @@ export const run = async ({
|
|
|
119
119
|
cb(runResult)
|
|
120
120
|
} catch (e) {
|
|
121
121
|
cb({
|
|
122
|
-
status: "
|
|
122
|
+
status: "failed",
|
|
123
123
|
errors: [e],
|
|
124
124
|
})
|
|
125
125
|
}
|
|
@@ -147,7 +147,7 @@ export const run = async ({
|
|
|
147
147
|
result.status = "aborted"
|
|
148
148
|
}
|
|
149
149
|
} else {
|
|
150
|
-
result.status = "
|
|
150
|
+
result.status = "failed"
|
|
151
151
|
result.errors.push(e)
|
|
152
152
|
}
|
|
153
153
|
} finally {
|
|
@@ -331,12 +331,12 @@ export const createRuntimeFromPlaywright = ({
|
|
|
331
331
|
}
|
|
332
332
|
if (winner.name === "error") {
|
|
333
333
|
let error = winner.data
|
|
334
|
-
result.status = "
|
|
334
|
+
result.status = "failed"
|
|
335
335
|
result.errors.push(error)
|
|
336
336
|
return
|
|
337
337
|
}
|
|
338
338
|
if (winner.name === "closed") {
|
|
339
|
-
result.status = "
|
|
339
|
+
result.status = "failed"
|
|
340
340
|
result.errors.push(
|
|
341
341
|
isBrowserDedicatedToExecution
|
|
342
342
|
? new Error(`browser disconnected during execution`)
|
|
@@ -350,8 +350,8 @@ export const createRuntimeFromPlaywright = ({
|
|
|
350
350
|
result.namespace = executionResults
|
|
351
351
|
Object.keys(executionResults).forEach((key) => {
|
|
352
352
|
const executionResult = executionResults[key]
|
|
353
|
-
if (executionResult.status === "
|
|
354
|
-
result.status = "
|
|
353
|
+
if (executionResult.status === "failed") {
|
|
354
|
+
result.status = "failed"
|
|
355
355
|
result.errors.push({
|
|
356
356
|
...executionResult.exception,
|
|
357
357
|
stack: executionResult.exception.text,
|
|
@@ -370,7 +370,7 @@ export const createRuntimeFromPlaywright = ({
|
|
|
370
370
|
await callback()
|
|
371
371
|
}, Promise.resolve())
|
|
372
372
|
} catch (e) {
|
|
373
|
-
result.status = "
|
|
373
|
+
result.status = "failed"
|
|
374
374
|
result.errors = [e]
|
|
375
375
|
}
|
|
376
376
|
if (keepRunning) {
|
|
@@ -219,7 +219,7 @@ nodeChildProcess.run = async ({
|
|
|
219
219
|
if (winner.name === "error") {
|
|
220
220
|
const error = winner.data
|
|
221
221
|
removeOutputListener()
|
|
222
|
-
result.status = "
|
|
222
|
+
result.status = "failed"
|
|
223
223
|
result.errors.push(error)
|
|
224
224
|
return
|
|
225
225
|
}
|
|
@@ -227,7 +227,7 @@ nodeChildProcess.run = async ({
|
|
|
227
227
|
const { code } = winner.data
|
|
228
228
|
await cleanup("process exit")
|
|
229
229
|
if (code === 12) {
|
|
230
|
-
result.status = "
|
|
230
|
+
result.status = "failed"
|
|
231
231
|
result.errors.push(
|
|
232
232
|
new Error(
|
|
233
233
|
`node process exited with 12 (the forked child process wanted to use a non-available port for debug)`,
|
|
@@ -242,13 +242,13 @@ nodeChildProcess.run = async ({
|
|
|
242
242
|
code === EXIT_CODES.SIGTERM ||
|
|
243
243
|
code === EXIT_CODES.SIGABORT
|
|
244
244
|
) {
|
|
245
|
-
result.status = "
|
|
245
|
+
result.status = "failed"
|
|
246
246
|
result.errors.push(new Error(`node process exited during execution`))
|
|
247
247
|
return
|
|
248
248
|
}
|
|
249
249
|
// process.exit(1) in child process or process.exitCode = 1 + process.exit()
|
|
250
250
|
// means there was an error even if we don't know exactly what.
|
|
251
|
-
result.status = "
|
|
251
|
+
result.status = "failed"
|
|
252
252
|
result.errors.push(
|
|
253
253
|
new Error(`node process exited with code ${code} during execution`),
|
|
254
254
|
)
|
|
@@ -256,7 +256,7 @@ nodeChildProcess.run = async ({
|
|
|
256
256
|
}
|
|
257
257
|
const { status, value } = winner.data
|
|
258
258
|
if (status === "action-failed") {
|
|
259
|
-
result.status = "
|
|
259
|
+
result.status = "failed"
|
|
260
260
|
result.errors.push(value)
|
|
261
261
|
return
|
|
262
262
|
}
|
|
@@ -270,7 +270,7 @@ nodeChildProcess.run = async ({
|
|
|
270
270
|
try {
|
|
271
271
|
await writeResult()
|
|
272
272
|
} catch (e) {
|
|
273
|
-
result.status = "
|
|
273
|
+
result.status = "failed"
|
|
274
274
|
result.errors.push(e)
|
|
275
275
|
}
|
|
276
276
|
if (keepRunning) {
|
|
@@ -171,7 +171,7 @@ nodeWorkerThread.run = async ({
|
|
|
171
171
|
if (winner.name === "error") {
|
|
172
172
|
const error = winner.data
|
|
173
173
|
removeOutputListener()
|
|
174
|
-
result.status = "
|
|
174
|
+
result.status = "failed"
|
|
175
175
|
result.errors.push(error)
|
|
176
176
|
return
|
|
177
177
|
}
|
|
@@ -179,7 +179,7 @@ nodeWorkerThread.run = async ({
|
|
|
179
179
|
const { code } = winner.data
|
|
180
180
|
await cleanup("process exit")
|
|
181
181
|
if (code === 12) {
|
|
182
|
-
result.status = "
|
|
182
|
+
result.status = "failed"
|
|
183
183
|
result.errors.push(
|
|
184
184
|
new Error(
|
|
185
185
|
`node process exited with 12 (the forked child process wanted to use a non-available port for debug)`,
|
|
@@ -194,7 +194,7 @@ nodeWorkerThread.run = async ({
|
|
|
194
194
|
code === EXIT_CODES.SIGTERM ||
|
|
195
195
|
code === EXIT_CODES.SIGABORT
|
|
196
196
|
) {
|
|
197
|
-
result.status = "
|
|
197
|
+
result.status = "failed"
|
|
198
198
|
result.errors.push(
|
|
199
199
|
new Error(`node worker thread exited during execution`),
|
|
200
200
|
)
|
|
@@ -202,7 +202,7 @@ nodeWorkerThread.run = async ({
|
|
|
202
202
|
}
|
|
203
203
|
// process.exit(1) in child process or process.exitCode = 1 + process.exit()
|
|
204
204
|
// means there was an error even if we don't know exactly what.
|
|
205
|
-
result.status = "
|
|
205
|
+
result.status = "failed"
|
|
206
206
|
result.errors.push(
|
|
207
207
|
new Error(
|
|
208
208
|
`node worker thread exited with code ${code} during execution`,
|
|
@@ -211,7 +211,7 @@ nodeWorkerThread.run = async ({
|
|
|
211
211
|
}
|
|
212
212
|
const { status, value } = winner.data
|
|
213
213
|
if (status === "action-failed") {
|
|
214
|
-
result.status = "
|
|
214
|
+
result.status = "failed"
|
|
215
215
|
result.errors.push(value)
|
|
216
216
|
return
|
|
217
217
|
}
|
|
@@ -225,7 +225,7 @@ nodeWorkerThread.run = async ({
|
|
|
225
225
|
try {
|
|
226
226
|
await writeResult()
|
|
227
227
|
} catch (e) {
|
|
228
|
-
result.status = "
|
|
228
|
+
result.status = "failed"
|
|
229
229
|
result.errors.push(e)
|
|
230
230
|
}
|
|
231
231
|
|
|
@@ -814,7 +814,7 @@ window.__supervisor__ = (() => {
|
|
|
814
814
|
}
|
|
815
815
|
|
|
816
816
|
const onError = (e) => {
|
|
817
|
-
executionResult.status = "
|
|
817
|
+
executionResult.status = "failed"
|
|
818
818
|
const exception = supervisor.createException({ reason: e })
|
|
819
819
|
if (exception.needsReport) {
|
|
820
820
|
supervisor.reportException(exception)
|
|
@@ -51,10 +51,7 @@ export const jsenvPluginAsJsClassicLibrary = ({
|
|
|
51
51
|
...context,
|
|
52
52
|
buildDirectoryUrl: context.outDirectoryUrl,
|
|
53
53
|
},
|
|
54
|
-
|
|
55
|
-
babelHelpersChunk: false,
|
|
56
|
-
preserveDynamicImport: true,
|
|
57
|
-
},
|
|
54
|
+
preserveDynamicImport: true,
|
|
58
55
|
})
|
|
59
56
|
const jsModuleBundledUrlInfo = bundleUrlInfos[jsModuleUrlInfo.url]
|
|
60
57
|
if (context.dev) {
|
package/src/test/execute_plan.js
CHANGED
|
@@ -225,7 +225,7 @@ export const executePlan = async (
|
|
|
225
225
|
total: executionSteps.length,
|
|
226
226
|
aborted: 0,
|
|
227
227
|
timedout: 0,
|
|
228
|
-
|
|
228
|
+
failed: 0,
|
|
229
229
|
completed: 0,
|
|
230
230
|
done: 0,
|
|
231
231
|
}
|
|
@@ -306,7 +306,7 @@ export const executePlan = async (
|
|
|
306
306
|
})
|
|
307
307
|
} else {
|
|
308
308
|
executionResult = {
|
|
309
|
-
status: "
|
|
309
|
+
status: "failed",
|
|
310
310
|
errors: [
|
|
311
311
|
new Error(
|
|
312
312
|
`No file at ${fileRelativeUrl} for execution "${executionName}"`,
|
|
@@ -336,8 +336,8 @@ export const executePlan = async (
|
|
|
336
336
|
counters.aborted++
|
|
337
337
|
} else if (executionResult.status === "timedout") {
|
|
338
338
|
counters.timedout++
|
|
339
|
-
} else if (executionResult.status === "
|
|
340
|
-
counters.
|
|
339
|
+
} else if (executionResult.status === "failed") {
|
|
340
|
+
counters.failed++
|
|
341
341
|
} else if (executionResult.status === "completed") {
|
|
342
342
|
counters.completed++
|
|
343
343
|
}
|
|
@@ -5,10 +5,7 @@ import {
|
|
|
5
5
|
urlIsInsideOf,
|
|
6
6
|
urlToRelativeUrl,
|
|
7
7
|
} from "@jsenv/urls"
|
|
8
|
-
import {
|
|
9
|
-
ensureEmptyDirectory,
|
|
10
|
-
assertAndNormalizeDirectoryUrl,
|
|
11
|
-
} from "@jsenv/filesystem"
|
|
8
|
+
import { ensureEmptyDirectory, validateDirectoryUrl } from "@jsenv/filesystem"
|
|
12
9
|
import { createLogger, createDetailedMessage } from "@jsenv/log"
|
|
13
10
|
|
|
14
11
|
import { generateCoverageJsonFile } from "./coverage/coverage_reporter_json_file.js"
|
|
@@ -82,51 +79,72 @@ export const executeTestPlan = async ({
|
|
|
82
79
|
coverageReportTextLog = true,
|
|
83
80
|
coverageReportJsonFile = process.env.CI ? null : "./.coverage/coverage.json",
|
|
84
81
|
coverageReportHtmlDirectory = process.env.CI ? "./.coverage/" : null,
|
|
82
|
+
...rest
|
|
85
83
|
}) => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
if (coverageEnabled) {
|
|
92
|
-
if (typeof coverageConfig !== "object") {
|
|
84
|
+
// param validation
|
|
85
|
+
{
|
|
86
|
+
const unexpectedParamNames = Object.keys(rest)
|
|
87
|
+
if (unexpectedParamNames.length > 0) {
|
|
93
88
|
throw new TypeError(
|
|
94
|
-
|
|
89
|
+
`${unexpectedParamNames.join(",")}: there is no such param`,
|
|
95
90
|
)
|
|
96
91
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
const rootDirectoryUrlValidation = validateDirectoryUrl(rootDirectoryUrl)
|
|
93
|
+
if (!rootDirectoryUrlValidation.valid) {
|
|
94
|
+
throw new TypeError(
|
|
95
|
+
`rootDirectoryUrl ${rootDirectoryUrlValidation.message}, got ${rootDirectoryUrl}`,
|
|
100
96
|
)
|
|
101
97
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
)
|
|
111
|
-
const patternsMatchingCoverAndExecute = Object.keys(
|
|
112
|
-
associationsForExecute.execute,
|
|
113
|
-
).filter((testPlanPattern) => {
|
|
114
|
-
const { cover } = URL_META.applyAssociations({
|
|
115
|
-
url: testPlanPattern,
|
|
116
|
-
associations: associationsForCover,
|
|
117
|
-
})
|
|
118
|
-
return cover
|
|
119
|
-
})
|
|
120
|
-
if (patternsMatchingCoverAndExecute.length) {
|
|
121
|
-
// It would be strange, for a given file to be both covered and executed
|
|
122
|
-
throw new Error(
|
|
123
|
-
createDetailedMessage(`some file will be both covered and executed`, {
|
|
124
|
-
patterns: patternsMatchingCoverAndExecute,
|
|
125
|
-
}),
|
|
98
|
+
rootDirectoryUrl = rootDirectoryUrlValidation.value
|
|
99
|
+
if (typeof testPlan !== "object") {
|
|
100
|
+
throw new Error(`testPlan must be an object, got ${testPlan}`)
|
|
101
|
+
}
|
|
102
|
+
if (coverageEnabled) {
|
|
103
|
+
if (typeof coverageConfig !== "object") {
|
|
104
|
+
throw new TypeError(
|
|
105
|
+
`coverageConfig must be an object, got ${coverageConfig}`,
|
|
126
106
|
)
|
|
127
107
|
}
|
|
108
|
+
if (!coverageAndExecutionAllowed) {
|
|
109
|
+
const associationsForExecute = URL_META.resolveAssociations(
|
|
110
|
+
{ execute: testPlan },
|
|
111
|
+
"file:///",
|
|
112
|
+
)
|
|
113
|
+
const associationsForCover = URL_META.resolveAssociations(
|
|
114
|
+
{ cover: coverageConfig },
|
|
115
|
+
"file:///",
|
|
116
|
+
)
|
|
117
|
+
const patternsMatchingCoverAndExecute = Object.keys(
|
|
118
|
+
associationsForExecute.execute,
|
|
119
|
+
).filter((testPlanPattern) => {
|
|
120
|
+
const { cover } = URL_META.applyAssociations({
|
|
121
|
+
url: testPlanPattern,
|
|
122
|
+
associations: associationsForCover,
|
|
123
|
+
})
|
|
124
|
+
return cover
|
|
125
|
+
})
|
|
126
|
+
if (patternsMatchingCoverAndExecute.length) {
|
|
127
|
+
// It would be strange, for a given file to be both covered and executed
|
|
128
|
+
throw new Error(
|
|
129
|
+
createDetailedMessage(
|
|
130
|
+
`some file will be both covered and executed`,
|
|
131
|
+
{
|
|
132
|
+
patterns: patternsMatchingCoverAndExecute,
|
|
133
|
+
},
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
128
138
|
}
|
|
129
139
|
}
|
|
140
|
+
|
|
141
|
+
const logger = createLogger({ logLevel })
|
|
142
|
+
if (Object.keys(coverageConfig).length === 0) {
|
|
143
|
+
logger.warn(
|
|
144
|
+
`coverageConfig is an empty object. Nothing will be instrumented for coverage so your coverage will be empty`,
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
130
148
|
const result = await executePlan(testPlan, {
|
|
131
149
|
signal,
|
|
132
150
|
handleSIGINT,
|
|
@@ -147,8 +147,8 @@ const createStatusSummary = ({ counters }) => {
|
|
|
147
147
|
if (counters.timedout === counters.total) {
|
|
148
148
|
return `all ${ANSI.color(`timed out`, EXECUTION_COLORS.timedout)}`
|
|
149
149
|
}
|
|
150
|
-
if (counters.
|
|
151
|
-
return `all ${ANSI.color(`
|
|
150
|
+
if (counters.failed === counters.total) {
|
|
151
|
+
return `all ${ANSI.color(`failed`, EXECUTION_COLORS.failed)}`
|
|
152
152
|
}
|
|
153
153
|
if (counters.completed === counters.total) {
|
|
154
154
|
return `all ${ANSI.color(`completed`, EXECUTION_COLORS.completed)}`
|
|
@@ -171,9 +171,9 @@ const createMixedDetails = ({ counters }) => {
|
|
|
171
171
|
)}`,
|
|
172
172
|
)
|
|
173
173
|
}
|
|
174
|
-
if (counters.
|
|
174
|
+
if (counters.failed) {
|
|
175
175
|
parts.push(
|
|
176
|
-
`${counters.
|
|
176
|
+
`${counters.failed} ${ANSI.color(`failed`, EXECUTION_COLORS.failed)}`,
|
|
177
177
|
)
|
|
178
178
|
}
|
|
179
179
|
if (counters.completed) {
|
|
@@ -221,10 +221,10 @@ const descriptionFormatters = {
|
|
|
221
221
|
EXECUTION_COLORS.timedout,
|
|
222
222
|
)
|
|
223
223
|
},
|
|
224
|
-
|
|
224
|
+
efailedrrored: ({ index, total }) => {
|
|
225
225
|
return ANSI.color(
|
|
226
|
-
`${UNICODE.FAILURE_RAW} execution ${index + 1} of ${total}
|
|
227
|
-
EXECUTION_COLORS.
|
|
226
|
+
`${UNICODE.FAILURE_RAW} execution ${index + 1} of ${total} failed`,
|
|
227
|
+
EXECUTION_COLORS.failed,
|
|
228
228
|
)
|
|
229
229
|
},
|
|
230
230
|
completed: ({ index, total }) => {
|