@jsenv/core 33.0.1 → 34.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/js/autoreload.js +1 -4
- package/dist/js/supervisor.js +498 -290
- package/dist/jsenv.js +874 -347
- package/package.json +2 -3
- package/src/basic_fetch.js +23 -13
- package/src/build/start_build_server.js +3 -2
- package/src/dev/file_service.js +1 -1
- package/src/dev/start_dev_server.js +9 -6
- package/src/execute/execute.js +7 -18
- package/src/execute/runtimes/browsers/from_playwright.js +168 -32
- package/src/execute/runtimes/browsers/webkit.js +1 -1
- package/src/execute/web_server_param.js +68 -0
- package/src/kitchen/compat/features_compatibility.js +3 -0
- package/src/plugins/autoreload/client/reload.js +1 -4
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +30 -18
- package/src/plugins/plugins.js +1 -1
- package/src/plugins/ribbon/jsenv_plugin_ribbon.js +3 -2
- package/src/plugins/supervisor/client/supervisor.js +467 -287
- package/src/plugins/supervisor/html_supervisor_injection.js +281 -0
- package/src/plugins/supervisor/js_supervisor_injection.js +281 -0
- package/src/plugins/supervisor/jsenv_plugin_supervisor.js +48 -233
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +1 -1
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +5 -0
- package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +1 -1
- package/src/test/execute_steps.js +10 -18
- package/src/test/execute_test_plan.js +16 -61
- package/src/test/logs_file_execution.js +74 -28
- package/dist/js/script_type_module_supervisor.js +0 -109
- package/src/plugins/supervisor/client/script_type_module_supervisor.js +0 -98
|
@@ -1,68 +1,19 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Jsenv needs to wait for all js execution inside an HTML page before killing the browser.
|
|
3
|
-
* A naive approach would consider execution done when "load" event is dispatched on window but:
|
|
4
|
-
*
|
|
5
|
-
* scenario | covered by window "load"
|
|
6
|
-
* ------------------------------------------- | -------------------------
|
|
7
|
-
* js referenced by <script src> | yes
|
|
8
|
-
* js inlined into <script> | yes
|
|
9
|
-
* js referenced by <script type="module" src> | partially (not for import and top level await)
|
|
10
|
-
* js inlined into <script type="module"> | not at all
|
|
11
|
-
*
|
|
12
2
|
* This plugin provides a way for jsenv to know when js execution is done
|
|
13
|
-
* As a side effect this plugin enables ability to hot reload js inlined into <script hot-accept>
|
|
14
|
-
*
|
|
15
|
-
* <script src="file.js">
|
|
16
|
-
* becomes
|
|
17
|
-
* <script>
|
|
18
|
-
* window.__supervisor__.superviseScript({ src: 'file.js' })
|
|
19
|
-
* </script>
|
|
20
|
-
*
|
|
21
|
-
* <script>
|
|
22
|
-
* console.log(42)
|
|
23
|
-
* </script>
|
|
24
|
-
* becomes
|
|
25
|
-
* <script>
|
|
26
|
-
* window.__supervisor__.superviseScript({ src: 'main.html@L10-L13.js' })
|
|
27
|
-
* </script>
|
|
28
|
-
*
|
|
29
|
-
* <script type="module" src="module.js"></script>
|
|
30
|
-
* becomes
|
|
31
|
-
* <script type="module">
|
|
32
|
-
* import { superviseScriptTypeModule } from 'supervisor'
|
|
33
|
-
* superviseScriptTypeModule({ src: "module.js" })
|
|
34
|
-
* </script>
|
|
35
|
-
*
|
|
36
|
-
* <script type="module">
|
|
37
|
-
* console.log(42)
|
|
38
|
-
* </script>
|
|
39
|
-
* becomes
|
|
40
|
-
* <script type="module">
|
|
41
|
-
* import { superviseScriptTypeModule } from 'supervisor'
|
|
42
|
-
* superviseScriptTypeModule({ src: 'main.html@L10-L13.js' })
|
|
43
|
-
* </script>
|
|
44
3
|
*/
|
|
45
4
|
|
|
46
5
|
import { fileURLToPath } from "node:url"
|
|
47
|
-
import {
|
|
48
|
-
parseHtmlString,
|
|
49
|
-
stringifyHtmlAst,
|
|
50
|
-
visitHtmlNodes,
|
|
51
|
-
getHtmlNodeAttribute,
|
|
52
|
-
setHtmlNodeAttributes,
|
|
53
|
-
analyzeScriptNode,
|
|
54
|
-
injectScriptNodeAsEarlyAsPossible,
|
|
55
|
-
createHtmlNode,
|
|
56
|
-
getHtmlNodePosition,
|
|
57
|
-
getHtmlNodeText,
|
|
58
|
-
removeHtmlNodeText,
|
|
59
|
-
setHtmlNodeText,
|
|
60
|
-
} from "@jsenv/ast"
|
|
61
|
-
import { generateInlineContentUrl, stringifyUrlSite } from "@jsenv/urls"
|
|
62
6
|
import { getOriginalPosition } from "@jsenv/sourcemap"
|
|
7
|
+
import { stringifyUrlSite } from "@jsenv/urls"
|
|
63
8
|
|
|
9
|
+
import { injectSupervisorIntoHTML } from "./html_supervisor_injection.js"
|
|
64
10
|
import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
|
|
65
11
|
|
|
12
|
+
export const supervisorFileUrl = new URL(
|
|
13
|
+
"./client/supervisor.js",
|
|
14
|
+
import.meta.url,
|
|
15
|
+
).href
|
|
16
|
+
|
|
66
17
|
export const jsenvPluginSupervisor = ({
|
|
67
18
|
logs = false,
|
|
68
19
|
measurePerf = false,
|
|
@@ -70,13 +21,6 @@ export const jsenvPluginSupervisor = ({
|
|
|
70
21
|
openInEditor = true,
|
|
71
22
|
errorBaseUrl,
|
|
72
23
|
}) => {
|
|
73
|
-
const supervisorFileUrl = new URL("./client/supervisor.js", import.meta.url)
|
|
74
|
-
.href
|
|
75
|
-
const scriptTypeModuleSupervisorFileUrl = new URL(
|
|
76
|
-
"./client/script_type_module_supervisor.js",
|
|
77
|
-
import.meta.url,
|
|
78
|
-
).href
|
|
79
|
-
|
|
80
24
|
return {
|
|
81
25
|
name: "jsenv:supervisor",
|
|
82
26
|
appliesDuring: "dev",
|
|
@@ -216,184 +160,55 @@ export const jsenvPluginSupervisor = ({
|
|
|
216
160
|
},
|
|
217
161
|
transformUrlContent: {
|
|
218
162
|
html: ({ url, content }, context) => {
|
|
219
|
-
const htmlAst = parseHtmlString(content)
|
|
220
|
-
const scriptsToSupervise = []
|
|
221
|
-
|
|
222
|
-
const handleInlineScript = (node, htmlNodeText) => {
|
|
223
|
-
const { type, extension } = analyzeScriptNode(node)
|
|
224
|
-
const { line, column, lineEnd, columnEnd, isOriginal } =
|
|
225
|
-
getHtmlNodePosition(node, { preferOriginal: true })
|
|
226
|
-
let inlineScriptUrl = generateInlineContentUrl({
|
|
227
|
-
url,
|
|
228
|
-
extension: extension || ".js",
|
|
229
|
-
line,
|
|
230
|
-
column,
|
|
231
|
-
lineEnd,
|
|
232
|
-
columnEnd,
|
|
233
|
-
})
|
|
234
|
-
const [inlineScriptReference] = context.referenceUtils.foundInline({
|
|
235
|
-
type: "script",
|
|
236
|
-
subtype: "inline",
|
|
237
|
-
expectedType: type,
|
|
238
|
-
isOriginalPosition: isOriginal,
|
|
239
|
-
specifierLine: line - 1,
|
|
240
|
-
specifierColumn: column,
|
|
241
|
-
specifier: inlineScriptUrl,
|
|
242
|
-
contentType: "text/javascript",
|
|
243
|
-
content: htmlNodeText,
|
|
244
|
-
})
|
|
245
|
-
removeHtmlNodeText(node)
|
|
246
|
-
if (extension) {
|
|
247
|
-
setHtmlNodeAttributes(node, {
|
|
248
|
-
type: type === "js_module" ? "module" : undefined,
|
|
249
|
-
})
|
|
250
|
-
}
|
|
251
|
-
scriptsToSupervise.push({
|
|
252
|
-
node,
|
|
253
|
-
isInline: true,
|
|
254
|
-
type,
|
|
255
|
-
src: inlineScriptReference.generatedSpecifier,
|
|
256
|
-
})
|
|
257
|
-
}
|
|
258
|
-
const handleScriptWithSrc = (node, src) => {
|
|
259
|
-
const { type } = analyzeScriptNode(node)
|
|
260
|
-
const integrity = getHtmlNodeAttribute(node, "integrity")
|
|
261
|
-
const crossorigin =
|
|
262
|
-
getHtmlNodeAttribute(node, "crossorigin") !== undefined
|
|
263
|
-
const defer = getHtmlNodeAttribute(node, "defer") !== undefined
|
|
264
|
-
const async = getHtmlNodeAttribute(node, "async") !== undefined
|
|
265
|
-
scriptsToSupervise.push({
|
|
266
|
-
node,
|
|
267
|
-
type,
|
|
268
|
-
src,
|
|
269
|
-
defer,
|
|
270
|
-
async,
|
|
271
|
-
integrity,
|
|
272
|
-
crossorigin,
|
|
273
|
-
})
|
|
274
|
-
}
|
|
275
|
-
visitHtmlNodes(htmlAst, {
|
|
276
|
-
script: (node) => {
|
|
277
|
-
const { type } = analyzeScriptNode(node)
|
|
278
|
-
if (type !== "js_classic" && type !== "js_module") {
|
|
279
|
-
return
|
|
280
|
-
}
|
|
281
|
-
if (
|
|
282
|
-
getHtmlNodeAttribute(node, "jsenv-cooked-by") ||
|
|
283
|
-
getHtmlNodeAttribute(node, "jsenv-inlined-by") ||
|
|
284
|
-
getHtmlNodeAttribute(node, "jsenv-injected-by")
|
|
285
|
-
) {
|
|
286
|
-
return
|
|
287
|
-
}
|
|
288
|
-
const noSupervisor = getHtmlNodeAttribute(node, "no-supervisor")
|
|
289
|
-
if (noSupervisor !== undefined) {
|
|
290
|
-
return
|
|
291
|
-
}
|
|
292
|
-
const htmlNodeText = getHtmlNodeText(node)
|
|
293
|
-
if (htmlNodeText) {
|
|
294
|
-
handleInlineScript(node, htmlNodeText)
|
|
295
|
-
return
|
|
296
|
-
}
|
|
297
|
-
const src = getHtmlNodeAttribute(node, "src")
|
|
298
|
-
if (src) {
|
|
299
|
-
handleScriptWithSrc(node, src)
|
|
300
|
-
return
|
|
301
|
-
}
|
|
302
|
-
},
|
|
303
|
-
})
|
|
304
|
-
const [scriptTypeModuleSupervisorFileReference] =
|
|
305
|
-
context.referenceUtils.inject({
|
|
306
|
-
type: "js_import",
|
|
307
|
-
expectedType: "js_module",
|
|
308
|
-
specifier: scriptTypeModuleSupervisorFileUrl,
|
|
309
|
-
})
|
|
310
163
|
const [supervisorFileReference] = context.referenceUtils.inject({
|
|
311
164
|
type: "script",
|
|
312
165
|
expectedType: "js_classic",
|
|
313
166
|
specifier: supervisorFileUrl,
|
|
314
167
|
})
|
|
315
|
-
injectScriptNodeAsEarlyAsPossible(
|
|
316
|
-
htmlAst,
|
|
317
|
-
createHtmlNode({
|
|
318
|
-
tagName: "script",
|
|
319
|
-
textContent: `
|
|
320
|
-
window.__supervisor__.setup(${JSON.stringify(
|
|
321
|
-
{
|
|
322
|
-
rootDirectoryUrl: context.rootDirectoryUrl,
|
|
323
|
-
errorBaseUrl,
|
|
324
|
-
logs,
|
|
325
|
-
measurePerf,
|
|
326
|
-
errorOverlay,
|
|
327
|
-
openInEditor,
|
|
328
|
-
},
|
|
329
|
-
null,
|
|
330
|
-
" ",
|
|
331
|
-
)})
|
|
332
|
-
`,
|
|
333
|
-
}),
|
|
334
|
-
"jsenv:supervisor",
|
|
335
|
-
)
|
|
336
|
-
injectScriptNodeAsEarlyAsPossible(
|
|
337
|
-
htmlAst,
|
|
338
|
-
createHtmlNode({
|
|
339
|
-
tagName: "script",
|
|
340
|
-
src: supervisorFileReference.generatedSpecifier,
|
|
341
|
-
}),
|
|
342
|
-
"jsenv:supervisor",
|
|
343
|
-
)
|
|
344
168
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
} else {
|
|
387
|
-
setHtmlNodeAttributes(node, {
|
|
388
|
-
"jsenv-cooked-by": "jsenv:supervisor",
|
|
389
|
-
})
|
|
390
|
-
}
|
|
169
|
+
return injectSupervisorIntoHTML(
|
|
170
|
+
{
|
|
171
|
+
content,
|
|
172
|
+
url,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
supervisorScriptSrc: supervisorFileReference.generatedSpecifier,
|
|
176
|
+
supervisorOptions: {
|
|
177
|
+
errorBaseUrl,
|
|
178
|
+
logs,
|
|
179
|
+
measurePerf,
|
|
180
|
+
errorOverlay,
|
|
181
|
+
openInEditor,
|
|
182
|
+
},
|
|
183
|
+
webServer: {
|
|
184
|
+
rootDirectoryUrl: context.rootDirectoryUrl,
|
|
185
|
+
isJsenvDevServer: true,
|
|
186
|
+
},
|
|
187
|
+
inlineAsRemote: true,
|
|
188
|
+
generateInlineScriptSrc: ({
|
|
189
|
+
type,
|
|
190
|
+
textContent,
|
|
191
|
+
inlineScriptUrl,
|
|
192
|
+
isOriginal,
|
|
193
|
+
line,
|
|
194
|
+
column,
|
|
195
|
+
}) => {
|
|
196
|
+
const [inlineScriptReference] =
|
|
197
|
+
context.referenceUtils.foundInline({
|
|
198
|
+
type: "script",
|
|
199
|
+
subtype: "inline",
|
|
200
|
+
expectedType: type,
|
|
201
|
+
isOriginalPosition: isOriginal,
|
|
202
|
+
specifierLine: line - 1,
|
|
203
|
+
specifierColumn: column,
|
|
204
|
+
specifier: inlineScriptUrl,
|
|
205
|
+
contentType: "text/javascript",
|
|
206
|
+
content: textContent,
|
|
207
|
+
})
|
|
208
|
+
return inlineScriptReference.generatedSpecifier
|
|
209
|
+
},
|
|
391
210
|
},
|
|
392
211
|
)
|
|
393
|
-
const htmlModified = stringifyHtmlAst(htmlAst)
|
|
394
|
-
return {
|
|
395
|
-
content: htmlModified,
|
|
396
|
-
}
|
|
397
212
|
},
|
|
398
213
|
},
|
|
399
214
|
}
|
|
@@ -157,7 +157,7 @@ export const jsenvPluginAsJsClassicHtml = ({
|
|
|
157
157
|
break
|
|
158
158
|
}
|
|
159
159
|
} catch (e) {
|
|
160
|
-
if (context.dev) {
|
|
160
|
+
if (context.dev && e.code !== "PARSE_ERROR") {
|
|
161
161
|
needsSystemJs = true
|
|
162
162
|
// ignore cooking error, the browser will trigger it again on fetch
|
|
163
163
|
// + disable cache for this html file because when browser will reload
|
|
@@ -74,7 +74,7 @@ const babelPluginMetadataUsesTopLevelAwait = () => {
|
|
|
74
74
|
programPath.traverse({
|
|
75
75
|
AwaitExpression: (path) => {
|
|
76
76
|
const closestFunction = path.getFunctionParent()
|
|
77
|
-
if (!closestFunction) {
|
|
77
|
+
if (!closestFunction || closestFunction.type === "Program") {
|
|
78
78
|
usesTopLevelAwait = true
|
|
79
79
|
path.stop()
|
|
80
80
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs"
|
|
2
2
|
import { memoryUsage } from "node:process"
|
|
3
3
|
import { takeCoverage } from "node:v8"
|
|
4
|
-
import wrapAnsi from "wrap-ansi"
|
|
5
4
|
import stripAnsi from "strip-ansi"
|
|
6
5
|
|
|
7
6
|
import { urlToFileSystemPath } from "@jsenv/urls"
|
|
@@ -31,8 +30,7 @@ export const executeSteps = async (
|
|
|
31
30
|
completedExecutionLogMerging,
|
|
32
31
|
completedExecutionLogAbbreviation,
|
|
33
32
|
rootDirectoryUrl,
|
|
34
|
-
|
|
35
|
-
sourceDirectoryUrl,
|
|
33
|
+
webServer,
|
|
36
34
|
|
|
37
35
|
keepRunning,
|
|
38
36
|
defaultMsAllocatedPerExecution,
|
|
@@ -119,8 +117,7 @@ export const executeSteps = async (
|
|
|
119
117
|
|
|
120
118
|
let runtimeParams = {
|
|
121
119
|
rootDirectoryUrl,
|
|
122
|
-
|
|
123
|
-
sourceDirectoryUrl,
|
|
120
|
+
webServer,
|
|
124
121
|
|
|
125
122
|
coverageEnabled,
|
|
126
123
|
coverageConfig,
|
|
@@ -279,7 +276,7 @@ export const executeSteps = async (
|
|
|
279
276
|
global.gc()
|
|
280
277
|
}
|
|
281
278
|
if (executionLogsEnabled) {
|
|
282
|
-
|
|
279
|
+
const log = createExecutionLog(afterExecutionInfo, {
|
|
283
280
|
completedExecutionLogAbbreviation,
|
|
284
281
|
counters,
|
|
285
282
|
logRuntime,
|
|
@@ -293,16 +290,6 @@ export const executeSteps = async (
|
|
|
293
290
|
? { memoryHeap: memoryUsage().heapUsed }
|
|
294
291
|
: {}),
|
|
295
292
|
})
|
|
296
|
-
log = `${log}
|
|
297
|
-
|
|
298
|
-
`
|
|
299
|
-
const { columns = 80 } = process.stdout
|
|
300
|
-
log = wrapAnsi(log, columns, {
|
|
301
|
-
trim: false,
|
|
302
|
-
hard: true,
|
|
303
|
-
wordWrap: false,
|
|
304
|
-
})
|
|
305
|
-
|
|
306
293
|
// replace spinner with this execution result
|
|
307
294
|
if (spinner) spinner.stop()
|
|
308
295
|
executionLog.write(log)
|
|
@@ -319,11 +306,16 @@ export const executeSteps = async (
|
|
|
319
306
|
executionLog = createLog({ newLine: "" })
|
|
320
307
|
}
|
|
321
308
|
}
|
|
322
|
-
|
|
309
|
+
const isLastExecutionLog = executionIndex === executionSteps.length - 1
|
|
310
|
+
const cancelRemaining =
|
|
323
311
|
failFast &&
|
|
324
312
|
executionResult.status !== "completed" &&
|
|
325
313
|
counters.done < counters.total
|
|
326
|
-
) {
|
|
314
|
+
if (isLastExecutionLog) {
|
|
315
|
+
executionLog.write("\n")
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (cancelRemaining) {
|
|
327
319
|
logger.info(`"failFast" enabled -> cancel remaining executions`)
|
|
328
320
|
failFastAbortController.abort()
|
|
329
321
|
}
|
|
@@ -8,8 +8,7 @@ import {
|
|
|
8
8
|
} from "@jsenv/filesystem"
|
|
9
9
|
import { createLogger, createDetailedMessage } from "@jsenv/log"
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import { basicFetch } from "../basic_fetch.js"
|
|
11
|
+
import { assertAndNormalizeWebServer } from "../execute/web_server_param.js"
|
|
13
12
|
import { generateCoverageJsonFile } from "./coverage/coverage_reporter_json_file.js"
|
|
14
13
|
import { generateCoverageHtmlDirectory } from "./coverage/coverage_reporter_html_directory.js"
|
|
15
14
|
import { generateCoverageTextLog } from "./coverage/coverage_reporter_text_log.js"
|
|
@@ -20,7 +19,7 @@ import { executeSteps } from "./execute_steps.js"
|
|
|
20
19
|
* Execute a list of files and log how it goes.
|
|
21
20
|
* @param {Object} testPlanParameters
|
|
22
21
|
* @param {string|url} testPlanParameters.rootDirectoryUrl Directory containing test files;
|
|
23
|
-
* @param {
|
|
22
|
+
* @param {Object} [testPlanParameters.webServer] Web server info; required when executing test on browsers
|
|
24
23
|
* @param {Object} testPlanParameters.testPlan Object associating files with runtimes where they will be executed
|
|
25
24
|
* @param {boolean} [testPlanParameters.completedExecutionLogAbbreviation=false] Abbreviate completed execution information to shorten terminal output
|
|
26
25
|
* @param {boolean} [testPlanParameters.completedExecutionLogMerging=false] Merge completed execution logs to shorten terminal output
|
|
@@ -46,10 +45,9 @@ export const executeTestPlan = async ({
|
|
|
46
45
|
logFileRelativeUrl = ".jsenv/test_plan_debug.txt",
|
|
47
46
|
completedExecutionLogAbbreviation = false,
|
|
48
47
|
completedExecutionLogMerging = false,
|
|
49
|
-
rootDirectoryUrl,
|
|
50
|
-
devServerModuleUrl,
|
|
51
|
-
devServerOrigin,
|
|
52
48
|
|
|
49
|
+
rootDirectoryUrl,
|
|
50
|
+
webServer,
|
|
53
51
|
testPlan,
|
|
54
52
|
updateProcessExitCode = true,
|
|
55
53
|
maxExecutionsInParallel = 1,
|
|
@@ -66,7 +64,10 @@ export const executeTestPlan = async ({
|
|
|
66
64
|
|
|
67
65
|
coverageEnabled = process.argv.includes("--coverage"),
|
|
68
66
|
coverageConfig = {
|
|
69
|
-
"
|
|
67
|
+
"file:///**/.*": false,
|
|
68
|
+
"file:///**/.*/": false,
|
|
69
|
+
"file:///**/node_modules/": false,
|
|
70
|
+
"./**/src/": true,
|
|
70
71
|
"./**/tests/": false,
|
|
71
72
|
"./**/*.test.html": false,
|
|
72
73
|
"./**/*.test.js": false,
|
|
@@ -93,8 +94,6 @@ export const executeTestPlan = async ({
|
|
|
93
94
|
}) => {
|
|
94
95
|
let someNeedsServer = false
|
|
95
96
|
let someNodeRuntime = false
|
|
96
|
-
let stopDevServerNeeded = false
|
|
97
|
-
let sourceDirectoryUrl
|
|
98
97
|
const runtimes = {}
|
|
99
98
|
// param validation
|
|
100
99
|
{
|
|
@@ -134,44 +133,7 @@ export const executeTestPlan = async ({
|
|
|
134
133
|
})
|
|
135
134
|
|
|
136
135
|
if (someNeedsServer) {
|
|
137
|
-
|
|
138
|
-
throw new TypeError(
|
|
139
|
-
`devServerOrigin is required when running tests on browser(s)`,
|
|
140
|
-
)
|
|
141
|
-
}
|
|
142
|
-
let devServerStarted = await pingServer(devServerOrigin)
|
|
143
|
-
if (!devServerStarted) {
|
|
144
|
-
if (!devServerModuleUrl) {
|
|
145
|
-
throw new TypeError(
|
|
146
|
-
`devServerModuleUrl is required when dev server is not started in order to run tests on browser(s)`,
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
try {
|
|
150
|
-
process.env.IMPORTED_BY_TEST_PLAN = "1"
|
|
151
|
-
await import(devServerModuleUrl)
|
|
152
|
-
delete process.env.IMPORTED_BY_TEST_PLAN
|
|
153
|
-
} catch (e) {
|
|
154
|
-
if (e.code === "ERR_MODULE_NOT_FOUND") {
|
|
155
|
-
throw new Error(
|
|
156
|
-
`Cannot find file responsible to start dev server at "${devServerModuleUrl}"`,
|
|
157
|
-
)
|
|
158
|
-
}
|
|
159
|
-
throw e
|
|
160
|
-
}
|
|
161
|
-
devServerStarted = await pingServer(devServerOrigin)
|
|
162
|
-
if (!devServerStarted) {
|
|
163
|
-
throw new Error(
|
|
164
|
-
`dev server not started after importing "${devServerModuleUrl}", ensure this module file is starting a server at "${devServerOrigin}"`,
|
|
165
|
-
)
|
|
166
|
-
}
|
|
167
|
-
stopDevServerNeeded = true
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const devServerParams = await basicFetch(
|
|
171
|
-
`${devServerOrigin}/__server_params__.json`,
|
|
172
|
-
{ rejectUnauthorized: false },
|
|
173
|
-
)
|
|
174
|
-
sourceDirectoryUrl = devServerParams.sourceDirectoryUrl
|
|
136
|
+
await assertAndNormalizeWebServer(webServer)
|
|
175
137
|
}
|
|
176
138
|
|
|
177
139
|
if (coverageEnabled) {
|
|
@@ -287,7 +249,12 @@ export const executeTestPlan = async ({
|
|
|
287
249
|
}
|
|
288
250
|
}
|
|
289
251
|
|
|
290
|
-
testPlan = {
|
|
252
|
+
testPlan = {
|
|
253
|
+
"file:///**/node_modules/": null,
|
|
254
|
+
"**/*./": null,
|
|
255
|
+
...testPlan,
|
|
256
|
+
"**/.jsenv/": null,
|
|
257
|
+
}
|
|
291
258
|
logger.debug(`Generate executions`)
|
|
292
259
|
const executionSteps = await executionStepsFromTestPlan({
|
|
293
260
|
signal,
|
|
@@ -310,8 +277,7 @@ export const executeTestPlan = async ({
|
|
|
310
277
|
completedExecutionLogMerging,
|
|
311
278
|
completedExecutionLogAbbreviation,
|
|
312
279
|
rootDirectoryUrl,
|
|
313
|
-
|
|
314
|
-
sourceDirectoryUrl,
|
|
280
|
+
webServer,
|
|
315
281
|
|
|
316
282
|
maxExecutionsInParallel,
|
|
317
283
|
defaultMsAllocatedPerExecution,
|
|
@@ -328,17 +294,6 @@ export const executeTestPlan = async ({
|
|
|
328
294
|
coverageV8ConflictWarning,
|
|
329
295
|
coverageTempDirectoryUrl,
|
|
330
296
|
})
|
|
331
|
-
if (stopDevServerNeeded) {
|
|
332
|
-
// we are expecting ECONNRESET because server will be stopped by the request
|
|
333
|
-
basicFetch(`${devServerOrigin}/__stop__`, {
|
|
334
|
-
rejectUnauthorized: false,
|
|
335
|
-
}).catch((e) => {
|
|
336
|
-
if (e.code === "ECONNRESET") {
|
|
337
|
-
return
|
|
338
|
-
}
|
|
339
|
-
throw e
|
|
340
|
-
})
|
|
341
|
-
}
|
|
342
297
|
if (
|
|
343
298
|
updateProcessExitCode &&
|
|
344
299
|
result.planSummary.counters.total !== result.planSummary.counters.completed
|