@jsenv/core 34.2.2 → 35.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/README.md +1 -1
- package/dist/html/explorer.html +5 -4
- package/dist/{jsenv.js → jsenv_core.js} +840 -3914
- package/package.json +7 -21
- package/src/build/build.js +34 -16
- package/src/build/version_mappings_injection.js +20 -27
- package/src/dev/file_service.js +9 -9
- package/src/dev/start_dev_server.js +3 -3
- package/src/dev/user_agent.js +1 -1
- package/src/kitchen/kitchen.js +5 -3
- package/src/main.js +0 -23
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +2 -2
- package/src/plugins/importmap/jsenv_plugin_importmap.js +6 -2
- package/src/plugins/{inline/jsenv_plugin_html_inline_content.js → inline_content_analysis/jsenv_plugin_html_inline_content_analysis.js} +12 -6
- package/src/plugins/{inline/jsenv_plugin_inline.js → inline_content_analysis/jsenv_plugin_inline_content_analysis.js} +8 -10
- package/src/plugins/{inline/jsenv_plugin_js_inline_content.js → inline_content_analysis/jsenv_plugin_js_inline_content_analysis.js} +4 -2
- package/src/plugins/inlining/jsenv_plugin_inlining.js +22 -0
- package/src/plugins/{inline/jsenv_plugin_inline_query_param.js → inlining/jsenv_plugin_inlining_as_data_url.js} +16 -9
- package/src/plugins/inlining/jsenv_plugin_inlining_into_html.js +149 -0
- package/src/plugins/plugins.js +5 -2
- package/src/plugins/ribbon/jsenv_plugin_ribbon.js +11 -10
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +2 -2
- package/src/plugins/supervisor/html_supervisor_injection.js +23 -25
- package/src/plugins/supervisor/jsenv_plugin_supervisor.js +1 -1
- package/src/plugins/transpilation/babel/require_babel_plugin.js +1 -1
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +20 -5
- package/src/plugins/transpilation/js_module_fallback/convert_js_module_to_js_classic.js +1 -1
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js +2 -2
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js +3 -3
- package/src/plugins/url_analysis/html/html_urls.js +1 -1
- package/dist/controllable_child_process.mjs +0 -129
- package/dist/controllable_worker_thread.mjs +0 -91
- package/dist/js/execute_using_dynamic_import.js +0 -850
- package/dist/js/v8_coverage.js +0 -508
- package/src/execute/execute.js +0 -109
- package/src/execute/run.js +0 -161
- package/src/execute/runtimes/browsers/chromium.js +0 -10
- package/src/execute/runtimes/browsers/firefox.js +0 -9
- package/src/execute/runtimes/browsers/from_playwright.js +0 -574
- package/src/execute/runtimes/browsers/middleware_istanbul.js +0 -65
- package/src/execute/runtimes/browsers/middleware_js_supervisor.js +0 -100
- package/src/execute/runtimes/browsers/webkit.js +0 -26
- package/src/execute/runtimes/node/child_exec_options.js +0 -166
- package/src/execute/runtimes/node/controllable_child_process.mjs +0 -135
- package/src/execute/runtimes/node/controllable_worker_thread.mjs +0 -103
- package/src/execute/runtimes/node/exec_options.js +0 -44
- package/src/execute/runtimes/node/execute_using_dynamic_import.js +0 -55
- package/src/execute/runtimes/node/exit_codes.js +0 -9
- package/src/execute/runtimes/node/kill_process_tree.js +0 -76
- package/src/execute/runtimes/node/node_child_process.js +0 -348
- package/src/execute/runtimes/node/node_execution_performance.js +0 -67
- package/src/execute/runtimes/node/node_worker_thread.js +0 -282
- package/src/execute/runtimes/node/profiler_v8_coverage.js +0 -56
- package/src/execute/runtimes/readme.md +0 -13
- package/src/execute/web_server_param.js +0 -74
- package/src/test/coverage/babel_plugin_instrument.js +0 -48
- package/src/test/coverage/coverage_reporter_html_directory.js +0 -32
- package/src/test/coverage/coverage_reporter_json_file.js +0 -17
- package/src/test/coverage/coverage_reporter_text_log.js +0 -19
- package/src/test/coverage/empty_coverage_factory.js +0 -52
- package/src/test/coverage/file_by_file_coverage.js +0 -25
- package/src/test/coverage/istanbul_coverage_composition.js +0 -28
- package/src/test/coverage/istanbul_coverage_map_from_coverage.js +0 -16
- package/src/test/coverage/list_files_not_covered.js +0 -15
- package/src/test/coverage/missing_coverage.js +0 -41
- package/src/test/coverage/report_to_coverage.js +0 -198
- package/src/test/coverage/v8_and_istanbul.js +0 -37
- package/src/test/coverage/v8_coverage.js +0 -26
- package/src/test/coverage/v8_coverage_composition.js +0 -24
- package/src/test/coverage/v8_coverage_node_directory.js +0 -85
- package/src/test/coverage/v8_coverage_to_istanbul.js +0 -99
- package/src/test/execute_steps.js +0 -425
- package/src/test/execute_test_plan.js +0 -372
- package/src/test/execution_colors.js +0 -10
- package/src/test/execution_steps.js +0 -65
- package/src/test/gc.js +0 -9
- package/src/test/logs_file_execution.js +0 -427
- package/src/test/logs_file_execution.test.mjs +0 -41
- package/src/test/readme.md +0 -3
- /package/src/{basic_fetch.js → helpers/basic_fetch.js} +0 -0
- /package/src/{lookup_package_directory.js → helpers/lookup_package_directory.js} +0 -0
- /package/src/{ping_server.js → helpers/ping_server.js} +0 -0
- /package/src/{require_from_jsenv.js → helpers/require_from_jsenv.js} +0 -0
- /package/src/{watch_source_files.js → helpers/watch_source_files.js} +0 -0
- /package/src/{web_url_converter.js → helpers/web_url_converter.js} +0 -0
- /package/src/plugins/{inline → inline_content_analysis}/client/inline_content.js +0 -0
- /package/src/plugins/{inline → inline_content_analysis}/jsenv_plugin_data_urls.js +0 -0
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs"
|
|
2
|
-
import { URL_META } from "@jsenv/url-meta"
|
|
3
|
-
import { urlToFileSystemPath, urlToRelativeUrl } from "@jsenv/urls"
|
|
4
|
-
import {
|
|
5
|
-
ensureEmptyDirectory,
|
|
6
|
-
assertAndNormalizeDirectoryUrl,
|
|
7
|
-
assertAndNormalizeFileUrl,
|
|
8
|
-
} from "@jsenv/filesystem"
|
|
9
|
-
import { createLogger, createDetailedMessage } from "@jsenv/log"
|
|
10
|
-
|
|
11
|
-
import { assertAndNormalizeWebServer } from "../execute/web_server_param.js"
|
|
12
|
-
import { generateCoverageJsonFile } from "./coverage/coverage_reporter_json_file.js"
|
|
13
|
-
import { generateCoverageHtmlDirectory } from "./coverage/coverage_reporter_html_directory.js"
|
|
14
|
-
import { generateCoverageTextLog } from "./coverage/coverage_reporter_text_log.js"
|
|
15
|
-
import { executionStepsFromTestPlan } from "./execution_steps.js"
|
|
16
|
-
import { executeSteps } from "./execute_steps.js"
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Execute a list of files and log how it goes.
|
|
20
|
-
* @param {Object} testPlanParameters
|
|
21
|
-
* @param {string|url} testPlanParameters.rootDirectoryUrl Directory containing test files;
|
|
22
|
-
* @param {Object} [testPlanParameters.webServer] Web server info; required when executing test on browsers
|
|
23
|
-
* @param {Object} testPlanParameters.testPlan Object associating files with runtimes where they will be executed
|
|
24
|
-
* @param {boolean} [testPlanParameters.completedExecutionLogAbbreviation=false] Abbreviate completed execution information to shorten terminal output
|
|
25
|
-
* @param {boolean} [testPlanParameters.completedExecutionLogMerging=false] Merge completed execution logs to shorten terminal output
|
|
26
|
-
* @param {number} [testPlanParameters.maxExecutionsInParallel=1] Maximum amount of execution in parallel
|
|
27
|
-
* @param {number} [testPlanParameters.defaultMsAllocatedPerExecution=30000] Milliseconds after which execution is aborted and considered as failed by timeout
|
|
28
|
-
* @param {boolean} [testPlanParameters.failFast=false] Fails immediatly when a test execution fails
|
|
29
|
-
* @param {number} [testPlanParameters.cooldownBetweenExecutions=0] Millisecond to wait between each execution
|
|
30
|
-
* @param {boolean} [testPlanParameters.logMemoryHeapUsage=false] Add memory heap usage during logs
|
|
31
|
-
* @param {boolean} [testPlanParameters.coverageEnabled=false] Controls if coverage is collected during files executions
|
|
32
|
-
* @param {boolean} [testPlanParameters.coverageV8ConflictWarning=true] Warn when coverage from 2 executions cannot be merged
|
|
33
|
-
* @return {Object} An object containing the result of all file executions
|
|
34
|
-
*/
|
|
35
|
-
export const executeTestPlan = async ({
|
|
36
|
-
signal = new AbortController().signal,
|
|
37
|
-
handleSIGINT = true,
|
|
38
|
-
logLevel = "info",
|
|
39
|
-
logRefresh = true,
|
|
40
|
-
logRuntime = true,
|
|
41
|
-
logEachDuration = true,
|
|
42
|
-
logSummary = true,
|
|
43
|
-
logTimeUsage = false,
|
|
44
|
-
logMemoryHeapUsage = false,
|
|
45
|
-
logFileRelativeUrl = ".jsenv/test_plan_debug.txt",
|
|
46
|
-
completedExecutionLogAbbreviation = false,
|
|
47
|
-
completedExecutionLogMerging = false,
|
|
48
|
-
|
|
49
|
-
rootDirectoryUrl,
|
|
50
|
-
webServer,
|
|
51
|
-
testPlan,
|
|
52
|
-
updateProcessExitCode = true,
|
|
53
|
-
maxExecutionsInParallel = 1,
|
|
54
|
-
defaultMsAllocatedPerExecution = 30_000,
|
|
55
|
-
failFast = false,
|
|
56
|
-
// keepRunning: false to ensure runtime is stopped once executed
|
|
57
|
-
// because we have what we wants: execution is completed and
|
|
58
|
-
// we have associated coverage and console output
|
|
59
|
-
// passsing true means all node process and browsers launched stays opened
|
|
60
|
-
// (can eventually be used for debug)
|
|
61
|
-
keepRunning = false,
|
|
62
|
-
cooldownBetweenExecutions = 0,
|
|
63
|
-
gcBetweenExecutions = logMemoryHeapUsage,
|
|
64
|
-
|
|
65
|
-
coverageEnabled = process.argv.includes("--coverage"),
|
|
66
|
-
coverageConfig = {
|
|
67
|
-
"file:///**/node_modules/": false,
|
|
68
|
-
"./**/.*": false,
|
|
69
|
-
"./**/.*/": false,
|
|
70
|
-
"./**/src/**/*.js": true,
|
|
71
|
-
"./**/src/**/*.ts": true,
|
|
72
|
-
"./**/src/**/*.jsx": true,
|
|
73
|
-
"./**/src/**/*.tsx": true,
|
|
74
|
-
"./**/tests/": false,
|
|
75
|
-
"./**/*.test.html": false,
|
|
76
|
-
"./**/*.test.js": false,
|
|
77
|
-
"./**/*.test.mjs": false,
|
|
78
|
-
},
|
|
79
|
-
coverageIncludeMissing = true,
|
|
80
|
-
coverageAndExecutionAllowed = false,
|
|
81
|
-
coverageMethodForNodeJs = process.env.NODE_V8_COVERAGE
|
|
82
|
-
? "NODE_V8_COVERAGE"
|
|
83
|
-
: "Profiler",
|
|
84
|
-
// - When chromium only -> coverage generated by v8
|
|
85
|
-
// - When chromium + node -> coverage generated by v8 are merged
|
|
86
|
-
// - When firefox only -> coverage generated by babel+istanbul
|
|
87
|
-
// - When chromium + firefox
|
|
88
|
-
// -> by default only coverage from chromium is used
|
|
89
|
-
// and a warning is logged according to coverageV8ConflictWarning
|
|
90
|
-
// -> to collect coverage from both browsers, pass coverageMethodForBrowsers: "istanbul"
|
|
91
|
-
coverageMethodForBrowsers, // undefined | "playwright" | "istanbul"
|
|
92
|
-
coverageV8ConflictWarning = true,
|
|
93
|
-
coverageTempDirectoryUrl,
|
|
94
|
-
// skip empty means empty files won't appear in the coverage reports (json and html)
|
|
95
|
-
coverageReportSkipEmpty = false,
|
|
96
|
-
// skip full means file with 100% coverage won't appear in coverage reports (json and html)
|
|
97
|
-
coverageReportSkipFull = false,
|
|
98
|
-
coverageReportTextLog = true,
|
|
99
|
-
coverageReportJson = process.env.CI,
|
|
100
|
-
coverageReportJsonFileUrl,
|
|
101
|
-
coverageReportHtml = !process.env.CI,
|
|
102
|
-
coverageReportHtmlDirectoryUrl,
|
|
103
|
-
...rest
|
|
104
|
-
}) => {
|
|
105
|
-
let someNeedsServer = false
|
|
106
|
-
let someHasCoverageV8 = false
|
|
107
|
-
let someNodeRuntime = false
|
|
108
|
-
const runtimes = {}
|
|
109
|
-
// param validation
|
|
110
|
-
{
|
|
111
|
-
const unexpectedParamNames = Object.keys(rest)
|
|
112
|
-
if (unexpectedParamNames.length > 0) {
|
|
113
|
-
throw new TypeError(
|
|
114
|
-
`${unexpectedParamNames.join(",")}: there is no such param`,
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
118
|
-
rootDirectoryUrl,
|
|
119
|
-
"rootDirectoryUrl",
|
|
120
|
-
)
|
|
121
|
-
if (!existsSync(new URL(rootDirectoryUrl))) {
|
|
122
|
-
throw new Error(`ENOENT on rootDirectoryUrl at ${rootDirectoryUrl}`)
|
|
123
|
-
}
|
|
124
|
-
if (typeof testPlan !== "object") {
|
|
125
|
-
throw new Error(`testPlan must be an object, got ${testPlan}`)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
Object.keys(testPlan).forEach((filePattern) => {
|
|
129
|
-
const filePlan = testPlan[filePattern]
|
|
130
|
-
if (!filePlan) return
|
|
131
|
-
Object.keys(filePlan).forEach((executionName) => {
|
|
132
|
-
const executionConfig = filePlan[executionName]
|
|
133
|
-
const { runtime } = executionConfig
|
|
134
|
-
if (runtime) {
|
|
135
|
-
runtimes[runtime.name] = runtime.version
|
|
136
|
-
if (runtime.type === "browser") {
|
|
137
|
-
if (runtime.capabilities && runtime.capabilities.coverageV8) {
|
|
138
|
-
someHasCoverageV8 = true
|
|
139
|
-
}
|
|
140
|
-
someNeedsServer = true
|
|
141
|
-
}
|
|
142
|
-
if (runtime.type === "node") {
|
|
143
|
-
someNodeRuntime = true
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
if (someNeedsServer) {
|
|
150
|
-
await assertAndNormalizeWebServer(webServer)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (coverageEnabled) {
|
|
154
|
-
if (coverageMethodForBrowsers === undefined) {
|
|
155
|
-
coverageMethodForBrowsers = someHasCoverageV8
|
|
156
|
-
? "playwright"
|
|
157
|
-
: "istanbul"
|
|
158
|
-
}
|
|
159
|
-
if (typeof coverageConfig !== "object") {
|
|
160
|
-
throw new TypeError(
|
|
161
|
-
`coverageConfig must be an object, got ${coverageConfig}`,
|
|
162
|
-
)
|
|
163
|
-
}
|
|
164
|
-
if (!coverageAndExecutionAllowed) {
|
|
165
|
-
const associationsForExecute = URL_META.resolveAssociations(
|
|
166
|
-
{ execute: testPlan },
|
|
167
|
-
"file:///",
|
|
168
|
-
)
|
|
169
|
-
const associationsForCover = URL_META.resolveAssociations(
|
|
170
|
-
{ cover: coverageConfig },
|
|
171
|
-
"file:///",
|
|
172
|
-
)
|
|
173
|
-
const patternsMatchingCoverAndExecute = Object.keys(
|
|
174
|
-
associationsForExecute.execute,
|
|
175
|
-
).filter((testPlanPattern) => {
|
|
176
|
-
const { cover } = URL_META.applyAssociations({
|
|
177
|
-
url: testPlanPattern,
|
|
178
|
-
associations: associationsForCover,
|
|
179
|
-
})
|
|
180
|
-
return cover
|
|
181
|
-
})
|
|
182
|
-
if (patternsMatchingCoverAndExecute.length) {
|
|
183
|
-
// It would be strange, for a given file to be both covered and executed
|
|
184
|
-
throw new Error(
|
|
185
|
-
createDetailedMessage(
|
|
186
|
-
`some file will be both covered and executed`,
|
|
187
|
-
{
|
|
188
|
-
patterns: patternsMatchingCoverAndExecute,
|
|
189
|
-
},
|
|
190
|
-
),
|
|
191
|
-
)
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (coverageTempDirectoryUrl === undefined) {
|
|
196
|
-
coverageTempDirectoryUrl = new URL("./.coverage/tmp/", rootDirectoryUrl)
|
|
197
|
-
} else {
|
|
198
|
-
coverageTempDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
199
|
-
coverageTempDirectoryUrl,
|
|
200
|
-
"coverageTempDirectoryUrl",
|
|
201
|
-
)
|
|
202
|
-
}
|
|
203
|
-
if (coverageReportJson) {
|
|
204
|
-
if (coverageReportJsonFileUrl === undefined) {
|
|
205
|
-
coverageReportJsonFileUrl = new URL(
|
|
206
|
-
"./.coverage/coverage.json",
|
|
207
|
-
rootDirectoryUrl,
|
|
208
|
-
)
|
|
209
|
-
} else {
|
|
210
|
-
coverageReportJsonFileUrl = assertAndNormalizeFileUrl(
|
|
211
|
-
coverageReportJsonFileUrl,
|
|
212
|
-
"coverageReportJsonFileUrl",
|
|
213
|
-
)
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
if (coverageReportHtml) {
|
|
217
|
-
if (coverageReportHtmlDirectoryUrl === undefined) {
|
|
218
|
-
coverageReportHtmlDirectoryUrl = new URL(
|
|
219
|
-
"./.coverage/",
|
|
220
|
-
rootDirectoryUrl,
|
|
221
|
-
)
|
|
222
|
-
} else {
|
|
223
|
-
coverageReportHtmlDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
224
|
-
coverageReportHtmlDirectoryUrl,
|
|
225
|
-
"coverageReportHtmlDirectoryUrl",
|
|
226
|
-
)
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const logger = createLogger({ logLevel })
|
|
233
|
-
logger.debug(
|
|
234
|
-
createDetailedMessage(`Prepare executing plan`, {
|
|
235
|
-
runtimes: JSON.stringify(runtimes, null, " "),
|
|
236
|
-
}),
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
// param normalization
|
|
240
|
-
{
|
|
241
|
-
if (coverageEnabled) {
|
|
242
|
-
if (Object.keys(coverageConfig).length === 0) {
|
|
243
|
-
logger.warn(
|
|
244
|
-
`coverageConfig is an empty object. Nothing will be instrumented for coverage so your coverage will be empty`,
|
|
245
|
-
)
|
|
246
|
-
}
|
|
247
|
-
if (
|
|
248
|
-
someNodeRuntime &&
|
|
249
|
-
coverageEnabled &&
|
|
250
|
-
coverageMethodForNodeJs === "NODE_V8_COVERAGE"
|
|
251
|
-
) {
|
|
252
|
-
if (process.env.NODE_V8_COVERAGE) {
|
|
253
|
-
// when runned multiple times, we don't want to keep previous files in this directory
|
|
254
|
-
await ensureEmptyDirectory(process.env.NODE_V8_COVERAGE)
|
|
255
|
-
} else {
|
|
256
|
-
coverageMethodForNodeJs = "Profiler"
|
|
257
|
-
logger.warn(
|
|
258
|
-
createDetailedMessage(
|
|
259
|
-
`process.env.NODE_V8_COVERAGE is required to generate coverage for Node.js subprocesses`,
|
|
260
|
-
{
|
|
261
|
-
"suggestion": `set process.env.NODE_V8_COVERAGE`,
|
|
262
|
-
"suggestion 2": `use coverageMethodForNodeJs: "Profiler". But it means coverage for child_process and worker_thread cannot be collected`,
|
|
263
|
-
},
|
|
264
|
-
),
|
|
265
|
-
)
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
testPlan = {
|
|
272
|
-
"file:///**/node_modules/": null,
|
|
273
|
-
"**/*./": null,
|
|
274
|
-
...testPlan,
|
|
275
|
-
"**/.jsenv/": null,
|
|
276
|
-
}
|
|
277
|
-
logger.debug(`Generate executions`)
|
|
278
|
-
const executionSteps = await executionStepsFromTestPlan({
|
|
279
|
-
signal,
|
|
280
|
-
testPlan,
|
|
281
|
-
rootDirectoryUrl,
|
|
282
|
-
})
|
|
283
|
-
logger.debug(`${executionSteps.length} executions planned`)
|
|
284
|
-
|
|
285
|
-
const result = await executeSteps(executionSteps, {
|
|
286
|
-
signal,
|
|
287
|
-
handleSIGINT,
|
|
288
|
-
logger,
|
|
289
|
-
logRefresh,
|
|
290
|
-
logSummary,
|
|
291
|
-
logRuntime,
|
|
292
|
-
logEachDuration,
|
|
293
|
-
logTimeUsage,
|
|
294
|
-
logMemoryHeapUsage,
|
|
295
|
-
logFileRelativeUrl,
|
|
296
|
-
completedExecutionLogMerging,
|
|
297
|
-
completedExecutionLogAbbreviation,
|
|
298
|
-
rootDirectoryUrl,
|
|
299
|
-
webServer,
|
|
300
|
-
|
|
301
|
-
maxExecutionsInParallel,
|
|
302
|
-
defaultMsAllocatedPerExecution,
|
|
303
|
-
failFast,
|
|
304
|
-
keepRunning,
|
|
305
|
-
cooldownBetweenExecutions,
|
|
306
|
-
gcBetweenExecutions,
|
|
307
|
-
|
|
308
|
-
coverageEnabled,
|
|
309
|
-
coverageConfig,
|
|
310
|
-
coverageIncludeMissing,
|
|
311
|
-
coverageMethodForBrowsers,
|
|
312
|
-
coverageMethodForNodeJs,
|
|
313
|
-
coverageV8ConflictWarning,
|
|
314
|
-
coverageTempDirectoryUrl,
|
|
315
|
-
})
|
|
316
|
-
if (
|
|
317
|
-
updateProcessExitCode &&
|
|
318
|
-
result.planSummary.counters.total !== result.planSummary.counters.completed
|
|
319
|
-
) {
|
|
320
|
-
process.exitCode = 1
|
|
321
|
-
}
|
|
322
|
-
const planCoverage = result.planCoverage
|
|
323
|
-
// planCoverage can be null when execution is aborted
|
|
324
|
-
if (planCoverage) {
|
|
325
|
-
const promises = []
|
|
326
|
-
// keep this one first because it does ensureEmptyDirectory
|
|
327
|
-
// and in case coverage json file gets written in the same directory
|
|
328
|
-
// it must be done before
|
|
329
|
-
if (coverageEnabled && coverageReportHtml) {
|
|
330
|
-
await ensureEmptyDirectory(coverageReportHtmlDirectoryUrl)
|
|
331
|
-
const htmlCoverageDirectoryIndexFileUrl = `${coverageReportHtmlDirectoryUrl}index.html`
|
|
332
|
-
logger.info(
|
|
333
|
-
`-> ${urlToFileSystemPath(htmlCoverageDirectoryIndexFileUrl)}`,
|
|
334
|
-
)
|
|
335
|
-
promises.push(
|
|
336
|
-
generateCoverageHtmlDirectory(planCoverage, {
|
|
337
|
-
rootDirectoryUrl,
|
|
338
|
-
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(
|
|
339
|
-
coverageReportHtmlDirectoryUrl,
|
|
340
|
-
rootDirectoryUrl,
|
|
341
|
-
),
|
|
342
|
-
coverageReportSkipEmpty,
|
|
343
|
-
coverageReportSkipFull,
|
|
344
|
-
}),
|
|
345
|
-
)
|
|
346
|
-
}
|
|
347
|
-
if (coverageEnabled && coverageReportJson) {
|
|
348
|
-
promises.push(
|
|
349
|
-
generateCoverageJsonFile({
|
|
350
|
-
coverage: result.planCoverage,
|
|
351
|
-
coverageJsonFileUrl: coverageReportJsonFileUrl,
|
|
352
|
-
logger,
|
|
353
|
-
}),
|
|
354
|
-
)
|
|
355
|
-
}
|
|
356
|
-
if (coverageEnabled && coverageReportTextLog) {
|
|
357
|
-
promises.push(
|
|
358
|
-
generateCoverageTextLog(result.planCoverage, {
|
|
359
|
-
coverageReportSkipEmpty,
|
|
360
|
-
coverageReportSkipFull,
|
|
361
|
-
}),
|
|
362
|
-
)
|
|
363
|
-
}
|
|
364
|
-
await Promise.all(promises)
|
|
365
|
-
}
|
|
366
|
-
return {
|
|
367
|
-
testPlanAborted: result.aborted,
|
|
368
|
-
testPlanSummary: result.planSummary,
|
|
369
|
-
testPlanReport: result.planReport,
|
|
370
|
-
testPlanCoverage: planCoverage,
|
|
371
|
-
}
|
|
372
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { Abort } from "@jsenv/abort"
|
|
2
|
-
import { collectFiles } from "@jsenv/filesystem"
|
|
3
|
-
import { createDetailedMessage } from "@jsenv/log"
|
|
4
|
-
|
|
5
|
-
export const executionStepsFromTestPlan = async ({
|
|
6
|
-
signal,
|
|
7
|
-
rootDirectoryUrl,
|
|
8
|
-
testPlan,
|
|
9
|
-
}) => {
|
|
10
|
-
try {
|
|
11
|
-
const fileResultArray = await collectFiles({
|
|
12
|
-
signal,
|
|
13
|
-
directoryUrl: rootDirectoryUrl,
|
|
14
|
-
associations: { testPlan },
|
|
15
|
-
predicate: ({ testPlan }) => testPlan,
|
|
16
|
-
})
|
|
17
|
-
const executionSteps = []
|
|
18
|
-
fileResultArray.forEach(({ relativeUrl, meta }) => {
|
|
19
|
-
const fileExecutionSteps = generateFileExecutionSteps({
|
|
20
|
-
fileRelativeUrl: relativeUrl,
|
|
21
|
-
filePlan: meta.testPlan,
|
|
22
|
-
})
|
|
23
|
-
executionSteps.push(...fileExecutionSteps)
|
|
24
|
-
})
|
|
25
|
-
return executionSteps
|
|
26
|
-
} catch (e) {
|
|
27
|
-
if (Abort.isAbortError(e)) {
|
|
28
|
-
return {
|
|
29
|
-
aborted: true,
|
|
30
|
-
planSummary: {},
|
|
31
|
-
planReport: {},
|
|
32
|
-
planCoverage: null,
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
throw e
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const generateFileExecutionSteps = ({ fileRelativeUrl, filePlan }) => {
|
|
40
|
-
const fileExecutionSteps = []
|
|
41
|
-
Object.keys(filePlan).forEach((executionName) => {
|
|
42
|
-
const stepConfig = filePlan[executionName]
|
|
43
|
-
if (stepConfig === null || stepConfig === undefined) {
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
if (typeof stepConfig !== "object") {
|
|
47
|
-
throw new TypeError(
|
|
48
|
-
createDetailedMessage(
|
|
49
|
-
`found unexpected value in plan, they must be object`,
|
|
50
|
-
{
|
|
51
|
-
["file relative path"]: fileRelativeUrl,
|
|
52
|
-
["execution name"]: executionName,
|
|
53
|
-
["value"]: stepConfig,
|
|
54
|
-
},
|
|
55
|
-
),
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
fileExecutionSteps.push({
|
|
59
|
-
executionName,
|
|
60
|
-
fileRelativeUrl,
|
|
61
|
-
...stepConfig,
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
return fileExecutionSteps
|
|
65
|
-
}
|