@jsenv/core 32.2.3 → 33.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/jsenv.js +134 -125
- package/package.json +5 -5
- package/src/basic_fetch.js +2 -1
- package/src/dev/file_service.js +0 -1
- package/src/execute/execute.js +2 -0
- package/src/execute/runtimes/browsers/from_playwright.js +17 -6
- package/src/kitchen/kitchen.js +0 -1
- package/src/test/{execute_plan.js → execute_steps.js} +5 -34
- package/src/test/execute_test_plan.js +45 -46
- package/src/test/execution_steps.js +32 -18
- package/src/watch_source_files.js +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ It has naturally evolved to cover the core needs of a JavaScript project: develo
|
|
|
7
7
|
- :sparkles: Same tooling for dev, tests and build.
|
|
8
8
|
- :exploding_head: Can execute tests on Chrome, Firefox, Safari and Node.js.
|
|
9
9
|
|
|
10
|
-
[Documentation](https://github.com/jsenv/jsenv-core/wiki)
|
|
10
|
+
[Documentation](https://github.com/jsenv/jsenv-core/wiki/A\)-Getting-started)
|
|
11
11
|
|
|
12
12
|
# Installation
|
|
13
13
|
|
package/dist/jsenv.js
CHANGED
|
@@ -540,7 +540,7 @@ const moveUrl = ({
|
|
|
540
540
|
url,
|
|
541
541
|
from,
|
|
542
542
|
to,
|
|
543
|
-
|
|
543
|
+
preferRelative
|
|
544
544
|
}) => {
|
|
545
545
|
let relativeUrl = urlToRelativeUrl(url, from);
|
|
546
546
|
if (relativeUrl.slice(0, 2) === "//") {
|
|
@@ -548,10 +548,10 @@ const moveUrl = ({
|
|
|
548
548
|
relativeUrl = new URL(relativeUrl, url).href;
|
|
549
549
|
}
|
|
550
550
|
const absoluteUrl = new URL(relativeUrl, to).href;
|
|
551
|
-
if (
|
|
552
|
-
return absoluteUrl;
|
|
551
|
+
if (preferRelative) {
|
|
552
|
+
return urlToRelativeUrl(absoluteUrl, to);
|
|
553
553
|
}
|
|
554
|
-
return
|
|
554
|
+
return absoluteUrl;
|
|
555
555
|
};
|
|
556
556
|
|
|
557
557
|
const urlIsInsideOf = (url, otherUrl) => {
|
|
@@ -7106,7 +7106,8 @@ const watchSourceFiles = (sourceDirectoryUrl, callback, {
|
|
|
7106
7106
|
// by default watch everything inside the source directory
|
|
7107
7107
|
// line below is commented until @jsenv/url-meta fixes the fact that is matches
|
|
7108
7108
|
// any file with an extension
|
|
7109
|
-
|
|
7109
|
+
"**/.*": false,
|
|
7110
|
+
// file starting with a dot -> do not watch
|
|
7110
7111
|
"**/.*/": false,
|
|
7111
7112
|
// directory starting with a dot -> do not watch
|
|
7112
7113
|
"**/node_modules/": false,
|
|
@@ -9588,8 +9589,7 @@ const determineFileUrlForOutDirectory = ({
|
|
|
9588
9589
|
return moveUrl({
|
|
9589
9590
|
url,
|
|
9590
9591
|
from: context.rootDirectoryUrl,
|
|
9591
|
-
to: context.outDirectoryUrl
|
|
9592
|
-
preferAbsolute: true
|
|
9592
|
+
to: context.outDirectoryUrl
|
|
9593
9593
|
});
|
|
9594
9594
|
};
|
|
9595
9595
|
|
|
@@ -22748,8 +22748,7 @@ const inferParentFromRequest = (request, sourceDirectoryUrl) => {
|
|
|
22748
22748
|
return moveUrl({
|
|
22749
22749
|
url: referer,
|
|
22750
22750
|
from: `${request.origin}/`,
|
|
22751
|
-
to: sourceDirectoryUrl
|
|
22752
|
-
preferAbsolute: true
|
|
22751
|
+
to: sourceDirectoryUrl
|
|
22753
22752
|
});
|
|
22754
22753
|
};
|
|
22755
22754
|
|
|
@@ -23018,6 +23017,7 @@ const pingServer = async url => {
|
|
|
23018
23017
|
};
|
|
23019
23018
|
|
|
23020
23019
|
const basicFetch = async (url, {
|
|
23020
|
+
rejectUnauthorized = true,
|
|
23021
23021
|
method = "GET",
|
|
23022
23022
|
headers = {}
|
|
23023
23023
|
} = {}) => {
|
|
@@ -23033,6 +23033,7 @@ const basicFetch = async (url, {
|
|
|
23033
23033
|
const urlObject = new URL(url);
|
|
23034
23034
|
return new Promise((resolve, reject) => {
|
|
23035
23035
|
const req = request({
|
|
23036
|
+
rejectUnauthorized,
|
|
23036
23037
|
hostname: urlObject.hostname,
|
|
23037
23038
|
port: urlObject.port,
|
|
23038
23039
|
path: urlObject.pathname,
|
|
@@ -23122,6 +23123,72 @@ const generateCoverageTextLog = (coverage, {
|
|
|
23122
23123
|
report.execute(context);
|
|
23123
23124
|
};
|
|
23124
23125
|
|
|
23126
|
+
const executionStepsFromTestPlan = async ({
|
|
23127
|
+
signal,
|
|
23128
|
+
rootDirectoryUrl,
|
|
23129
|
+
testPlan
|
|
23130
|
+
}) => {
|
|
23131
|
+
try {
|
|
23132
|
+
const fileResultArray = await collectFiles({
|
|
23133
|
+
signal,
|
|
23134
|
+
directoryUrl: rootDirectoryUrl,
|
|
23135
|
+
associations: {
|
|
23136
|
+
testPlan
|
|
23137
|
+
},
|
|
23138
|
+
predicate: ({
|
|
23139
|
+
testPlan
|
|
23140
|
+
}) => testPlan
|
|
23141
|
+
});
|
|
23142
|
+
const executionSteps = [];
|
|
23143
|
+
fileResultArray.forEach(({
|
|
23144
|
+
relativeUrl,
|
|
23145
|
+
meta
|
|
23146
|
+
}) => {
|
|
23147
|
+
const fileExecutionSteps = generateFileExecutionSteps({
|
|
23148
|
+
fileRelativeUrl: relativeUrl,
|
|
23149
|
+
filePlan: meta.testPlan
|
|
23150
|
+
});
|
|
23151
|
+
executionSteps.push(...fileExecutionSteps);
|
|
23152
|
+
});
|
|
23153
|
+
return executionSteps;
|
|
23154
|
+
} catch (e) {
|
|
23155
|
+
if (Abort.isAbortError(e)) {
|
|
23156
|
+
return {
|
|
23157
|
+
aborted: true,
|
|
23158
|
+
planSummary: {},
|
|
23159
|
+
planReport: {},
|
|
23160
|
+
planCoverage: null
|
|
23161
|
+
};
|
|
23162
|
+
}
|
|
23163
|
+
throw e;
|
|
23164
|
+
}
|
|
23165
|
+
};
|
|
23166
|
+
const generateFileExecutionSteps = ({
|
|
23167
|
+
fileRelativeUrl,
|
|
23168
|
+
filePlan
|
|
23169
|
+
}) => {
|
|
23170
|
+
const fileExecutionSteps = [];
|
|
23171
|
+
Object.keys(filePlan).forEach(executionName => {
|
|
23172
|
+
const stepConfig = filePlan[executionName];
|
|
23173
|
+
if (stepConfig === null || stepConfig === undefined) {
|
|
23174
|
+
return;
|
|
23175
|
+
}
|
|
23176
|
+
if (typeof stepConfig !== "object") {
|
|
23177
|
+
throw new TypeError(createDetailedMessage$1(`found unexpected value in plan, they must be object`, {
|
|
23178
|
+
["file relative path"]: fileRelativeUrl,
|
|
23179
|
+
["execution name"]: executionName,
|
|
23180
|
+
["value"]: stepConfig
|
|
23181
|
+
}));
|
|
23182
|
+
}
|
|
23183
|
+
fileExecutionSteps.push({
|
|
23184
|
+
executionName,
|
|
23185
|
+
fileRelativeUrl,
|
|
23186
|
+
...stepConfig
|
|
23187
|
+
});
|
|
23188
|
+
});
|
|
23189
|
+
return fileExecutionSteps;
|
|
23190
|
+
};
|
|
23191
|
+
|
|
23125
23192
|
const readNodeV8CoverageDirectory = async ({
|
|
23126
23193
|
logger,
|
|
23127
23194
|
signal,
|
|
@@ -23779,59 +23846,6 @@ const ensureGlobalGc = () => {
|
|
|
23779
23846
|
}
|
|
23780
23847
|
};
|
|
23781
23848
|
|
|
23782
|
-
const generateExecutionSteps = async (plan, {
|
|
23783
|
-
signal,
|
|
23784
|
-
rootDirectoryUrl
|
|
23785
|
-
}) => {
|
|
23786
|
-
const fileResultArray = await collectFiles({
|
|
23787
|
-
signal,
|
|
23788
|
-
directoryUrl: rootDirectoryUrl,
|
|
23789
|
-
associations: {
|
|
23790
|
-
filePlan: plan
|
|
23791
|
-
},
|
|
23792
|
-
predicate: ({
|
|
23793
|
-
filePlan
|
|
23794
|
-
}) => filePlan
|
|
23795
|
-
});
|
|
23796
|
-
const executionSteps = [];
|
|
23797
|
-
fileResultArray.forEach(({
|
|
23798
|
-
relativeUrl,
|
|
23799
|
-
meta
|
|
23800
|
-
}) => {
|
|
23801
|
-
const fileExecutionSteps = generateFileExecutionSteps({
|
|
23802
|
-
fileRelativeUrl: relativeUrl,
|
|
23803
|
-
filePlan: meta.filePlan
|
|
23804
|
-
});
|
|
23805
|
-
executionSteps.push(...fileExecutionSteps);
|
|
23806
|
-
});
|
|
23807
|
-
return executionSteps;
|
|
23808
|
-
};
|
|
23809
|
-
const generateFileExecutionSteps = ({
|
|
23810
|
-
fileRelativeUrl,
|
|
23811
|
-
filePlan
|
|
23812
|
-
}) => {
|
|
23813
|
-
const fileExecutionSteps = [];
|
|
23814
|
-
Object.keys(filePlan).forEach(executionName => {
|
|
23815
|
-
const stepConfig = filePlan[executionName];
|
|
23816
|
-
if (stepConfig === null || stepConfig === undefined) {
|
|
23817
|
-
return;
|
|
23818
|
-
}
|
|
23819
|
-
if (typeof stepConfig !== "object") {
|
|
23820
|
-
throw new TypeError(createDetailedMessage$1(`found unexpected value in plan, they must be object`, {
|
|
23821
|
-
["file relative path"]: fileRelativeUrl,
|
|
23822
|
-
["execution name"]: executionName,
|
|
23823
|
-
["value"]: stepConfig
|
|
23824
|
-
}));
|
|
23825
|
-
}
|
|
23826
|
-
fileExecutionSteps.push({
|
|
23827
|
-
executionName,
|
|
23828
|
-
fileRelativeUrl,
|
|
23829
|
-
...stepConfig
|
|
23830
|
-
});
|
|
23831
|
-
});
|
|
23832
|
-
return fileExecutionSteps;
|
|
23833
|
-
};
|
|
23834
|
-
|
|
23835
23849
|
const EXECUTION_COLORS = {
|
|
23836
23850
|
executing: ANSI.BLUE,
|
|
23837
23851
|
aborted: ANSI.MAGENTA,
|
|
@@ -24172,7 +24186,7 @@ ${key}: ${details[key]}`;
|
|
|
24172
24186
|
return message;
|
|
24173
24187
|
};
|
|
24174
24188
|
|
|
24175
|
-
const
|
|
24189
|
+
const executeSteps = async (executionSteps, {
|
|
24176
24190
|
signal,
|
|
24177
24191
|
handleSIGINT,
|
|
24178
24192
|
logger,
|
|
@@ -24187,6 +24201,7 @@ const executePlan = async (plan, {
|
|
|
24187
24201
|
completedExecutionLogAbbreviation,
|
|
24188
24202
|
rootDirectoryUrl,
|
|
24189
24203
|
devServerOrigin,
|
|
24204
|
+
sourceDirectoryUrl,
|
|
24190
24205
|
keepRunning,
|
|
24191
24206
|
defaultMsAllocatedPerExecution,
|
|
24192
24207
|
maxExecutionsInParallel,
|
|
@@ -24266,19 +24281,13 @@ const executePlan = async (plan, {
|
|
|
24266
24281
|
let runtimeParams = {
|
|
24267
24282
|
rootDirectoryUrl,
|
|
24268
24283
|
devServerOrigin,
|
|
24284
|
+
sourceDirectoryUrl,
|
|
24269
24285
|
coverageEnabled,
|
|
24270
24286
|
coverageConfig,
|
|
24271
24287
|
coverageMethodForBrowsers,
|
|
24272
24288
|
coverageMethodForNodeJs,
|
|
24273
24289
|
stopAfterAllSignal
|
|
24274
24290
|
};
|
|
24275
|
-
logger.debug(`Generate executions`);
|
|
24276
|
-
const executionSteps = await getExecutionAsSteps({
|
|
24277
|
-
plan,
|
|
24278
|
-
multipleExecutionsOperation,
|
|
24279
|
-
rootDirectoryUrl
|
|
24280
|
-
});
|
|
24281
|
-
logger.debug(`${executionSteps.length} executions planned`);
|
|
24282
24291
|
if (completedExecutionLogMerging && !process.stdout.isTTY) {
|
|
24283
24292
|
completedExecutionLogMerging = false;
|
|
24284
24293
|
logger.debug(`Force completedExecutionLogMerging to false because process.stdout.isTTY is false`);
|
|
@@ -24495,29 +24504,6 @@ const executePlan = async (plan, {
|
|
|
24495
24504
|
await multipleExecutionsOperation.end();
|
|
24496
24505
|
}
|
|
24497
24506
|
};
|
|
24498
|
-
const getExecutionAsSteps = async ({
|
|
24499
|
-
plan,
|
|
24500
|
-
multipleExecutionsOperation,
|
|
24501
|
-
rootDirectoryUrl
|
|
24502
|
-
}) => {
|
|
24503
|
-
try {
|
|
24504
|
-
const executionSteps = await generateExecutionSteps(plan, {
|
|
24505
|
-
signal: multipleExecutionsOperation.signal,
|
|
24506
|
-
rootDirectoryUrl
|
|
24507
|
-
});
|
|
24508
|
-
return executionSteps;
|
|
24509
|
-
} catch (e) {
|
|
24510
|
-
if (Abort.isAbortError(e)) {
|
|
24511
|
-
return {
|
|
24512
|
-
aborted: true,
|
|
24513
|
-
planSummary: {},
|
|
24514
|
-
planReport: {},
|
|
24515
|
-
planCoverage: null
|
|
24516
|
-
};
|
|
24517
|
-
}
|
|
24518
|
-
throw e;
|
|
24519
|
-
}
|
|
24520
|
-
};
|
|
24521
24507
|
const canOverwriteLogGetter = ({
|
|
24522
24508
|
completedExecutionLogMerging,
|
|
24523
24509
|
executionResult
|
|
@@ -24584,9 +24570,9 @@ const executeInParallel = async ({
|
|
|
24584
24570
|
/**
|
|
24585
24571
|
* Execute a list of files and log how it goes.
|
|
24586
24572
|
* @param {Object} testPlanParameters
|
|
24587
|
-
* @param {string|url} testPlanParameters.
|
|
24573
|
+
* @param {string|url} testPlanParameters.rootDirectoryUrl Directory containing test files;
|
|
24588
24574
|
* @param {string|url} [testPlanParameters.devServerOrigin=undefined] Jsenv dev server origin; required when executing test on browsers
|
|
24589
|
-
* @param {Object} testPlanParameters.testPlan Object associating
|
|
24575
|
+
* @param {Object} testPlanParameters.testPlan Object associating files with runtimes where they will be executed
|
|
24590
24576
|
* @param {boolean} [testPlanParameters.completedExecutionLogAbbreviation=false] Abbreviate completed execution information to shorten terminal output
|
|
24591
24577
|
* @param {boolean} [testPlanParameters.completedExecutionLogMerging=false] Merge completed execution logs to shorten terminal output
|
|
24592
24578
|
* @param {number} [testPlanParameters.maxExecutionsInParallel=1] Maximum amount of execution in parallel
|
|
@@ -24611,7 +24597,7 @@ const executeTestPlan = async ({
|
|
|
24611
24597
|
logFileRelativeUrl = ".jsenv/test_plan_debug.txt",
|
|
24612
24598
|
completedExecutionLogAbbreviation = false,
|
|
24613
24599
|
completedExecutionLogMerging = false,
|
|
24614
|
-
|
|
24600
|
+
rootDirectoryUrl,
|
|
24615
24601
|
devServerModuleUrl,
|
|
24616
24602
|
devServerOrigin,
|
|
24617
24603
|
testPlan,
|
|
@@ -24629,7 +24615,14 @@ const executeTestPlan = async ({
|
|
|
24629
24615
|
gcBetweenExecutions = logMemoryHeapUsage,
|
|
24630
24616
|
coverageEnabled = process.argv.includes("--coverage"),
|
|
24631
24617
|
coverageConfig = {
|
|
24632
|
-
"
|
|
24618
|
+
"**/*": true,
|
|
24619
|
+
"**/.*": false,
|
|
24620
|
+
"**/.*/": false,
|
|
24621
|
+
"**/node_modules/": false,
|
|
24622
|
+
"**/tests/": false,
|
|
24623
|
+
"**/*.test.html": false,
|
|
24624
|
+
"**/*.test.js": false,
|
|
24625
|
+
"**/*.test.mjs": false
|
|
24633
24626
|
},
|
|
24634
24627
|
coverageIncludeMissing = true,
|
|
24635
24628
|
coverageAndExecutionAllowed = false,
|
|
@@ -24638,7 +24631,6 @@ const executeTestPlan = async ({
|
|
|
24638
24631
|
// "istanbul" also accepted
|
|
24639
24632
|
coverageV8ConflictWarning = true,
|
|
24640
24633
|
coverageTempDirectoryUrl,
|
|
24641
|
-
coverageReportRootDirectoryUrl,
|
|
24642
24634
|
// skip empty means empty files won't appear in the coverage reports (json and html)
|
|
24643
24635
|
coverageReportSkipEmpty = false,
|
|
24644
24636
|
// skip full means file with 100% coverage won't appear in coverage reports (json and html)
|
|
@@ -24653,6 +24645,7 @@ const executeTestPlan = async ({
|
|
|
24653
24645
|
let someNeedsServer = false;
|
|
24654
24646
|
let someNodeRuntime = false;
|
|
24655
24647
|
let stopDevServerNeeded = false;
|
|
24648
|
+
let sourceDirectoryUrl;
|
|
24656
24649
|
const runtimes = {};
|
|
24657
24650
|
// param validation
|
|
24658
24651
|
{
|
|
@@ -24660,9 +24653,9 @@ const executeTestPlan = async ({
|
|
|
24660
24653
|
if (unexpectedParamNames.length > 0) {
|
|
24661
24654
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
24662
24655
|
}
|
|
24663
|
-
|
|
24664
|
-
if (!existsSync(new URL(
|
|
24665
|
-
throw new Error(`ENOENT on
|
|
24656
|
+
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl, "rootDirectoryUrl");
|
|
24657
|
+
if (!existsSync(new URL(rootDirectoryUrl))) {
|
|
24658
|
+
throw new Error(`ENOENT on rootDirectoryUrl at ${rootDirectoryUrl}`);
|
|
24666
24659
|
}
|
|
24667
24660
|
if (typeof testPlan !== "object") {
|
|
24668
24661
|
throw new Error(`testPlan must be an object, got ${testPlan}`);
|
|
@@ -24711,12 +24704,10 @@ const executeTestPlan = async ({
|
|
|
24711
24704
|
}
|
|
24712
24705
|
stopDevServerNeeded = true;
|
|
24713
24706
|
}
|
|
24714
|
-
const {
|
|
24715
|
-
|
|
24716
|
-
}
|
|
24717
|
-
|
|
24718
|
-
throw new Error(`testDirectoryUrl must be inside sourceDirectoryUrl when running tests on browser(s)`);
|
|
24719
|
-
}
|
|
24707
|
+
const devServerParams = await basicFetch(`${devServerOrigin}/__server_params__.json`, {
|
|
24708
|
+
rejectUnauthorized: false
|
|
24709
|
+
});
|
|
24710
|
+
sourceDirectoryUrl = devServerParams.sourceDirectoryUrl;
|
|
24720
24711
|
}
|
|
24721
24712
|
if (coverageEnabled) {
|
|
24722
24713
|
if (typeof coverageConfig !== "object") {
|
|
@@ -24745,26 +24736,21 @@ const executeTestPlan = async ({
|
|
|
24745
24736
|
}));
|
|
24746
24737
|
}
|
|
24747
24738
|
}
|
|
24748
|
-
if (coverageReportRootDirectoryUrl === undefined) {
|
|
24749
|
-
coverageReportRootDirectoryUrl = lookupPackageDirectory(testDirectoryUrl);
|
|
24750
|
-
} else {
|
|
24751
|
-
coverageReportRootDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageReportRootDirectoryUrl, "coverageReportRootDirectoryUrl");
|
|
24752
|
-
}
|
|
24753
24739
|
if (coverageTempDirectoryUrl === undefined) {
|
|
24754
|
-
coverageTempDirectoryUrl = new URL("./.coverage/tmp/",
|
|
24740
|
+
coverageTempDirectoryUrl = new URL("./.coverage/tmp/", rootDirectoryUrl);
|
|
24755
24741
|
} else {
|
|
24756
24742
|
coverageTempDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageTempDirectoryUrl, "coverageTempDirectoryUrl");
|
|
24757
24743
|
}
|
|
24758
24744
|
if (coverageReportJson) {
|
|
24759
24745
|
if (coverageReportJsonFileUrl === undefined) {
|
|
24760
|
-
coverageReportJsonFileUrl = new URL("./.coverage/coverage.json",
|
|
24746
|
+
coverageReportJsonFileUrl = new URL("./.coverage/coverage.json", rootDirectoryUrl);
|
|
24761
24747
|
} else {
|
|
24762
24748
|
coverageReportJsonFileUrl = assertAndNormalizeFileUrl(coverageReportJsonFileUrl, "coverageReportJsonFileUrl");
|
|
24763
24749
|
}
|
|
24764
24750
|
}
|
|
24765
24751
|
if (coverageReportHtml) {
|
|
24766
24752
|
if (coverageReportHtmlDirectoryUrl === undefined) {
|
|
24767
|
-
coverageReportHtmlDirectoryUrl = new URL("./.coverage/",
|
|
24753
|
+
coverageReportHtmlDirectoryUrl = new URL("./.coverage/", rootDirectoryUrl);
|
|
24768
24754
|
} else {
|
|
24769
24755
|
coverageReportHtmlDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageReportHtmlDirectoryUrl, "coverageReportHtmlDirectoryUrl");
|
|
24770
24756
|
}
|
|
@@ -24802,7 +24788,14 @@ const executeTestPlan = async ({
|
|
|
24802
24788
|
...testPlan,
|
|
24803
24789
|
"**/.jsenv/": null
|
|
24804
24790
|
};
|
|
24805
|
-
|
|
24791
|
+
logger.debug(`Generate executions`);
|
|
24792
|
+
const executionSteps = await executionStepsFromTestPlan({
|
|
24793
|
+
signal,
|
|
24794
|
+
testPlan,
|
|
24795
|
+
rootDirectoryUrl
|
|
24796
|
+
});
|
|
24797
|
+
logger.debug(`${executionSteps.length} executions planned`);
|
|
24798
|
+
const result = await executeSteps(executionSteps, {
|
|
24806
24799
|
signal,
|
|
24807
24800
|
handleSIGINT,
|
|
24808
24801
|
logger,
|
|
@@ -24815,8 +24808,9 @@ const executeTestPlan = async ({
|
|
|
24815
24808
|
logFileRelativeUrl,
|
|
24816
24809
|
completedExecutionLogMerging,
|
|
24817
24810
|
completedExecutionLogAbbreviation,
|
|
24818
|
-
rootDirectoryUrl
|
|
24811
|
+
rootDirectoryUrl,
|
|
24819
24812
|
devServerOrigin,
|
|
24813
|
+
sourceDirectoryUrl,
|
|
24820
24814
|
maxExecutionsInParallel,
|
|
24821
24815
|
defaultMsAllocatedPerExecution,
|
|
24822
24816
|
failFast,
|
|
@@ -24833,7 +24827,9 @@ const executeTestPlan = async ({
|
|
|
24833
24827
|
});
|
|
24834
24828
|
if (stopDevServerNeeded) {
|
|
24835
24829
|
// we are expecting ECONNRESET because server will be stopped by the request
|
|
24836
|
-
basicFetch(`${devServerOrigin}/__stop__
|
|
24830
|
+
basicFetch(`${devServerOrigin}/__stop__`, {
|
|
24831
|
+
rejectUnauthorized: false
|
|
24832
|
+
}).catch(e => {
|
|
24837
24833
|
if (e.code === "ECONNRESET") {
|
|
24838
24834
|
return;
|
|
24839
24835
|
}
|
|
@@ -24855,8 +24851,8 @@ const executeTestPlan = async ({
|
|
|
24855
24851
|
const htmlCoverageDirectoryIndexFileUrl = `${coverageReportHtmlDirectoryUrl}index.html`;
|
|
24856
24852
|
logger.info(`-> ${urlToFileSystemPath(htmlCoverageDirectoryIndexFileUrl)}`);
|
|
24857
24853
|
promises.push(generateCoverageHtmlDirectory(planCoverage, {
|
|
24858
|
-
rootDirectoryUrl
|
|
24859
|
-
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(coverageReportHtmlDirectoryUrl,
|
|
24854
|
+
rootDirectoryUrl,
|
|
24855
|
+
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(coverageReportHtmlDirectoryUrl, rootDirectoryUrl),
|
|
24860
24856
|
coverageReportSkipEmpty,
|
|
24861
24857
|
coverageReportSkipFull
|
|
24862
24858
|
}));
|
|
@@ -24904,6 +24900,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
24904
24900
|
rootDirectoryUrl,
|
|
24905
24901
|
fileRelativeUrl,
|
|
24906
24902
|
devServerOrigin,
|
|
24903
|
+
sourceDirectoryUrl,
|
|
24907
24904
|
// measurePerformance,
|
|
24908
24905
|
collectPerformance,
|
|
24909
24906
|
coverageEnabled = false,
|
|
@@ -25010,8 +25007,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
25010
25007
|
const fsUrl = moveUrl({
|
|
25011
25008
|
url: v8CoveragesWithWebUrl.url,
|
|
25012
25009
|
from: `${devServerOrigin}/`,
|
|
25013
|
-
to:
|
|
25014
|
-
preferAbsolute: true
|
|
25010
|
+
to: sourceDirectoryUrl
|
|
25015
25011
|
});
|
|
25016
25012
|
return {
|
|
25017
25013
|
...v8CoveragesWithWebUrl,
|
|
@@ -25073,8 +25069,19 @@ const createRuntimeFromPlaywright = ({
|
|
|
25073
25069
|
result.performance = performance;
|
|
25074
25070
|
});
|
|
25075
25071
|
}
|
|
25076
|
-
const
|
|
25077
|
-
|
|
25072
|
+
const fileUrl = new URL(fileRelativeUrl, rootDirectoryUrl).href;
|
|
25073
|
+
if (!urlIsInsideOf(fileUrl, sourceDirectoryUrl)) {
|
|
25074
|
+
throw new Error(`Cannot execute file that is outside source directory
|
|
25075
|
+
--- file ---
|
|
25076
|
+
${fileUrl}
|
|
25077
|
+
--- source directory ---
|
|
25078
|
+
${sourceDirectoryUrl}`);
|
|
25079
|
+
}
|
|
25080
|
+
const fileDevServerUrl = moveUrl({
|
|
25081
|
+
url: fileUrl,
|
|
25082
|
+
from: sourceDirectoryUrl,
|
|
25083
|
+
to: `${devServerOrigin}/`
|
|
25084
|
+
});
|
|
25078
25085
|
// https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-console
|
|
25079
25086
|
const removeConsoleListener = registerEvent({
|
|
25080
25087
|
object: page,
|
|
@@ -25157,7 +25164,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
25157
25164
|
},
|
|
25158
25165
|
response: async cb => {
|
|
25159
25166
|
try {
|
|
25160
|
-
await page.goto(
|
|
25167
|
+
await page.goto(fileDevServerUrl, {
|
|
25161
25168
|
timeout: 0
|
|
25162
25169
|
});
|
|
25163
25170
|
const returnValue = await page.evaluate( /* eslint-disable no-undef */
|
|
@@ -26399,6 +26406,7 @@ const execute = async ({
|
|
|
26399
26406
|
handleSIGINT = true,
|
|
26400
26407
|
logLevel,
|
|
26401
26408
|
rootDirectoryUrl,
|
|
26409
|
+
sourceDirectoryUrl = rootDirectoryUrl,
|
|
26402
26410
|
devServerOrigin,
|
|
26403
26411
|
fileRelativeUrl,
|
|
26404
26412
|
allocatedMs,
|
|
@@ -26428,6 +26436,7 @@ const execute = async ({
|
|
|
26428
26436
|
let resultTransformer = result => result;
|
|
26429
26437
|
runtimeParams = {
|
|
26430
26438
|
rootDirectoryUrl,
|
|
26439
|
+
sourceDirectoryUrl,
|
|
26431
26440
|
devServerOrigin,
|
|
26432
26441
|
fileRelativeUrl,
|
|
26433
26442
|
...runtimeParams
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "33.0.0",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -69,17 +69,17 @@
|
|
|
69
69
|
"@jsenv/abort": "4.2.4",
|
|
70
70
|
"@jsenv/ast": "3.0.3",
|
|
71
71
|
"@jsenv/babel-plugins": "1.1.5",
|
|
72
|
-
"@jsenv/filesystem": "4.2.
|
|
72
|
+
"@jsenv/filesystem": "4.2.3",
|
|
73
73
|
"@jsenv/importmap": "1.2.1",
|
|
74
74
|
"@jsenv/integrity": "0.0.1",
|
|
75
75
|
"@jsenv/log": "3.3.4",
|
|
76
76
|
"@jsenv/node-esm-resolution": "1.0.1",
|
|
77
|
-
"@jsenv/plugin-bundling": "2.1.
|
|
77
|
+
"@jsenv/plugin-bundling": "2.1.3",
|
|
78
78
|
"@jsenv/server": "15.0.2",
|
|
79
|
-
"@jsenv/sourcemap": "1.0.
|
|
79
|
+
"@jsenv/sourcemap": "1.0.10",
|
|
80
80
|
"@jsenv/uneval": "1.6.0",
|
|
81
81
|
"@jsenv/url-meta": "8.1.0",
|
|
82
|
-
"@jsenv/urls": "
|
|
82
|
+
"@jsenv/urls": "2.0.0",
|
|
83
83
|
"@jsenv/utils": "2.0.1",
|
|
84
84
|
"@paralleldrive/cuid2": "2.2.0",
|
|
85
85
|
"construct-style-sheets-polyfill": "3.1.0",
|
package/src/basic_fetch.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const basicFetch = async (
|
|
2
2
|
url,
|
|
3
|
-
{ method = "GET", headers = {} } = {},
|
|
3
|
+
{ rejectUnauthorized = true, method = "GET", headers = {} } = {},
|
|
4
4
|
) => {
|
|
5
5
|
let requestModule
|
|
6
6
|
if (url.startsWith("http:")) {
|
|
@@ -14,6 +14,7 @@ export const basicFetch = async (
|
|
|
14
14
|
|
|
15
15
|
return new Promise((resolve, reject) => {
|
|
16
16
|
const req = request({
|
|
17
|
+
rejectUnauthorized,
|
|
17
18
|
hostname: urlObject.hostname,
|
|
18
19
|
port: urlObject.port,
|
|
19
20
|
path: urlObject.pathname,
|
package/src/dev/file_service.js
CHANGED
package/src/execute/execute.js
CHANGED
|
@@ -22,6 +22,7 @@ export const execute = async ({
|
|
|
22
22
|
handleSIGINT = true,
|
|
23
23
|
logLevel,
|
|
24
24
|
rootDirectoryUrl,
|
|
25
|
+
sourceDirectoryUrl = rootDirectoryUrl,
|
|
25
26
|
devServerOrigin,
|
|
26
27
|
|
|
27
28
|
fileRelativeUrl,
|
|
@@ -59,6 +60,7 @@ export const execute = async ({
|
|
|
59
60
|
let resultTransformer = (result) => result
|
|
60
61
|
runtimeParams = {
|
|
61
62
|
rootDirectoryUrl,
|
|
63
|
+
sourceDirectoryUrl,
|
|
62
64
|
devServerOrigin,
|
|
63
65
|
fileRelativeUrl,
|
|
64
66
|
...runtimeParams,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
raceProcessTeardownEvents,
|
|
8
8
|
raceCallbacks,
|
|
9
9
|
} from "@jsenv/abort"
|
|
10
|
-
import { moveUrl } from "@jsenv/urls"
|
|
10
|
+
import { moveUrl, urlIsInsideOf } from "@jsenv/urls"
|
|
11
11
|
import { memoize } from "@jsenv/utils/src/memoize/memoize.js"
|
|
12
12
|
|
|
13
13
|
import { filterV8Coverage } from "@jsenv/core/src/test/coverage/v8_coverage.js"
|
|
@@ -33,6 +33,7 @@ export const createRuntimeFromPlaywright = ({
|
|
|
33
33
|
rootDirectoryUrl,
|
|
34
34
|
fileRelativeUrl,
|
|
35
35
|
devServerOrigin,
|
|
36
|
+
sourceDirectoryUrl,
|
|
36
37
|
|
|
37
38
|
// measurePerformance,
|
|
38
39
|
collectPerformance,
|
|
@@ -145,8 +146,7 @@ export const createRuntimeFromPlaywright = ({
|
|
|
145
146
|
const fsUrl = moveUrl({
|
|
146
147
|
url: v8CoveragesWithWebUrl.url,
|
|
147
148
|
from: `${devServerOrigin}/`,
|
|
148
|
-
to:
|
|
149
|
-
preferAbsolute: true,
|
|
149
|
+
to: sourceDirectoryUrl,
|
|
150
150
|
})
|
|
151
151
|
return {
|
|
152
152
|
...v8CoveragesWithWebUrl,
|
|
@@ -218,8 +218,19 @@ export const createRuntimeFromPlaywright = ({
|
|
|
218
218
|
})
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
const
|
|
222
|
-
|
|
221
|
+
const fileUrl = new URL(fileRelativeUrl, rootDirectoryUrl).href
|
|
222
|
+
if (!urlIsInsideOf(fileUrl, sourceDirectoryUrl)) {
|
|
223
|
+
throw new Error(`Cannot execute file that is outside source directory
|
|
224
|
+
--- file ---
|
|
225
|
+
${fileUrl}
|
|
226
|
+
--- source directory ---
|
|
227
|
+
${sourceDirectoryUrl}`)
|
|
228
|
+
}
|
|
229
|
+
const fileDevServerUrl = moveUrl({
|
|
230
|
+
url: fileUrl,
|
|
231
|
+
from: sourceDirectoryUrl,
|
|
232
|
+
to: `${devServerOrigin}/`,
|
|
233
|
+
})
|
|
223
234
|
// https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-console
|
|
224
235
|
const removeConsoleListener = registerEvent({
|
|
225
236
|
object: page,
|
|
@@ -301,7 +312,7 @@ export const createRuntimeFromPlaywright = ({
|
|
|
301
312
|
},
|
|
302
313
|
response: async (cb) => {
|
|
303
314
|
try {
|
|
304
|
-
await page.goto(
|
|
315
|
+
await page.goto(fileDevServerUrl, { timeout: 0 })
|
|
305
316
|
const returnValue = await page.evaluate(
|
|
306
317
|
/* eslint-disable no-undef */
|
|
307
318
|
/* istanbul ignore next */
|
package/src/kitchen/kitchen.js
CHANGED
|
@@ -13,11 +13,10 @@ import { reportToCoverage } from "./coverage/report_to_coverage.js"
|
|
|
13
13
|
import { run } from "@jsenv/core/src/execute/run.js"
|
|
14
14
|
|
|
15
15
|
import { ensureGlobalGc } from "./gc.js"
|
|
16
|
-
import { generateExecutionSteps } from "./execution_steps.js"
|
|
17
16
|
import { createExecutionLog, createSummaryLog } from "./logs_file_execution.js"
|
|
18
17
|
|
|
19
|
-
export const
|
|
20
|
-
|
|
18
|
+
export const executeSteps = async (
|
|
19
|
+
executionSteps,
|
|
21
20
|
{
|
|
22
21
|
signal,
|
|
23
22
|
handleSIGINT,
|
|
@@ -33,6 +32,7 @@ export const executePlan = async (
|
|
|
33
32
|
completedExecutionLogAbbreviation,
|
|
34
33
|
rootDirectoryUrl,
|
|
35
34
|
devServerOrigin,
|
|
35
|
+
sourceDirectoryUrl,
|
|
36
36
|
|
|
37
37
|
keepRunning,
|
|
38
38
|
defaultMsAllocatedPerExecution,
|
|
@@ -120,6 +120,8 @@ export const executePlan = async (
|
|
|
120
120
|
let runtimeParams = {
|
|
121
121
|
rootDirectoryUrl,
|
|
122
122
|
devServerOrigin,
|
|
123
|
+
sourceDirectoryUrl,
|
|
124
|
+
|
|
123
125
|
coverageEnabled,
|
|
124
126
|
coverageConfig,
|
|
125
127
|
coverageMethodForBrowsers,
|
|
@@ -127,13 +129,6 @@ export const executePlan = async (
|
|
|
127
129
|
stopAfterAllSignal,
|
|
128
130
|
}
|
|
129
131
|
|
|
130
|
-
logger.debug(`Generate executions`)
|
|
131
|
-
const executionSteps = await getExecutionAsSteps({
|
|
132
|
-
plan,
|
|
133
|
-
multipleExecutionsOperation,
|
|
134
|
-
rootDirectoryUrl,
|
|
135
|
-
})
|
|
136
|
-
logger.debug(`${executionSteps.length} executions planned`)
|
|
137
132
|
if (completedExecutionLogMerging && !process.stdout.isTTY) {
|
|
138
133
|
completedExecutionLogMerging = false
|
|
139
134
|
logger.debug(
|
|
@@ -368,30 +363,6 @@ export const executePlan = async (
|
|
|
368
363
|
}
|
|
369
364
|
}
|
|
370
365
|
|
|
371
|
-
const getExecutionAsSteps = async ({
|
|
372
|
-
plan,
|
|
373
|
-
multipleExecutionsOperation,
|
|
374
|
-
rootDirectoryUrl,
|
|
375
|
-
}) => {
|
|
376
|
-
try {
|
|
377
|
-
const executionSteps = await generateExecutionSteps(plan, {
|
|
378
|
-
signal: multipleExecutionsOperation.signal,
|
|
379
|
-
rootDirectoryUrl,
|
|
380
|
-
})
|
|
381
|
-
return executionSteps
|
|
382
|
-
} catch (e) {
|
|
383
|
-
if (Abort.isAbortError(e)) {
|
|
384
|
-
return {
|
|
385
|
-
aborted: true,
|
|
386
|
-
planSummary: {},
|
|
387
|
-
planReport: {},
|
|
388
|
-
planCoverage: null,
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
throw e
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
366
|
const canOverwriteLogGetter = ({
|
|
396
367
|
completedExecutionLogMerging,
|
|
397
368
|
executionResult,
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs"
|
|
2
2
|
import { URL_META } from "@jsenv/url-meta"
|
|
3
|
-
import {
|
|
4
|
-
urlToFileSystemPath,
|
|
5
|
-
urlToRelativeUrl,
|
|
6
|
-
urlIsInsideOf,
|
|
7
|
-
} from "@jsenv/urls"
|
|
3
|
+
import { urlToFileSystemPath, urlToRelativeUrl } from "@jsenv/urls"
|
|
8
4
|
import {
|
|
9
5
|
ensureEmptyDirectory,
|
|
10
6
|
assertAndNormalizeDirectoryUrl,
|
|
@@ -12,20 +8,20 @@ import {
|
|
|
12
8
|
} from "@jsenv/filesystem"
|
|
13
9
|
import { createLogger, createDetailedMessage } from "@jsenv/log"
|
|
14
10
|
|
|
15
|
-
import { lookupPackageDirectory } from "../lookup_package_directory.js"
|
|
16
11
|
import { pingServer } from "../ping_server.js"
|
|
17
12
|
import { basicFetch } from "../basic_fetch.js"
|
|
18
13
|
import { generateCoverageJsonFile } from "./coverage/coverage_reporter_json_file.js"
|
|
19
14
|
import { generateCoverageHtmlDirectory } from "./coverage/coverage_reporter_html_directory.js"
|
|
20
15
|
import { generateCoverageTextLog } from "./coverage/coverage_reporter_text_log.js"
|
|
21
|
-
import {
|
|
16
|
+
import { executionStepsFromTestPlan } from "./execution_steps.js"
|
|
17
|
+
import { executeSteps } from "./execute_steps.js"
|
|
22
18
|
|
|
23
19
|
/**
|
|
24
20
|
* Execute a list of files and log how it goes.
|
|
25
21
|
* @param {Object} testPlanParameters
|
|
26
|
-
* @param {string|url} testPlanParameters.
|
|
22
|
+
* @param {string|url} testPlanParameters.rootDirectoryUrl Directory containing test files;
|
|
27
23
|
* @param {string|url} [testPlanParameters.devServerOrigin=undefined] Jsenv dev server origin; required when executing test on browsers
|
|
28
|
-
* @param {Object} testPlanParameters.testPlan Object associating
|
|
24
|
+
* @param {Object} testPlanParameters.testPlan Object associating files with runtimes where they will be executed
|
|
29
25
|
* @param {boolean} [testPlanParameters.completedExecutionLogAbbreviation=false] Abbreviate completed execution information to shorten terminal output
|
|
30
26
|
* @param {boolean} [testPlanParameters.completedExecutionLogMerging=false] Merge completed execution logs to shorten terminal output
|
|
31
27
|
* @param {number} [testPlanParameters.maxExecutionsInParallel=1] Maximum amount of execution in parallel
|
|
@@ -50,7 +46,7 @@ export const executeTestPlan = async ({
|
|
|
50
46
|
logFileRelativeUrl = ".jsenv/test_plan_debug.txt",
|
|
51
47
|
completedExecutionLogAbbreviation = false,
|
|
52
48
|
completedExecutionLogMerging = false,
|
|
53
|
-
|
|
49
|
+
rootDirectoryUrl,
|
|
54
50
|
devServerModuleUrl,
|
|
55
51
|
devServerOrigin,
|
|
56
52
|
|
|
@@ -69,7 +65,16 @@ export const executeTestPlan = async ({
|
|
|
69
65
|
gcBetweenExecutions = logMemoryHeapUsage,
|
|
70
66
|
|
|
71
67
|
coverageEnabled = process.argv.includes("--coverage"),
|
|
72
|
-
coverageConfig = {
|
|
68
|
+
coverageConfig = {
|
|
69
|
+
"**/*": true,
|
|
70
|
+
"**/.*": false,
|
|
71
|
+
"**/.*/": false,
|
|
72
|
+
"**/node_modules/": false,
|
|
73
|
+
"**/tests/": false,
|
|
74
|
+
"**/*.test.html": false,
|
|
75
|
+
"**/*.test.js": false,
|
|
76
|
+
"**/*.test.mjs": false,
|
|
77
|
+
},
|
|
73
78
|
coverageIncludeMissing = true,
|
|
74
79
|
coverageAndExecutionAllowed = false,
|
|
75
80
|
coverageMethodForNodeJs = process.env.NODE_V8_COVERAGE
|
|
@@ -78,7 +83,6 @@ export const executeTestPlan = async ({
|
|
|
78
83
|
coverageMethodForBrowsers = "playwright_api", // "istanbul" also accepted
|
|
79
84
|
coverageV8ConflictWarning = true,
|
|
80
85
|
coverageTempDirectoryUrl,
|
|
81
|
-
coverageReportRootDirectoryUrl,
|
|
82
86
|
// skip empty means empty files won't appear in the coverage reports (json and html)
|
|
83
87
|
coverageReportSkipEmpty = false,
|
|
84
88
|
// skip full means file with 100% coverage won't appear in coverage reports (json and html)
|
|
@@ -93,6 +97,7 @@ export const executeTestPlan = async ({
|
|
|
93
97
|
let someNeedsServer = false
|
|
94
98
|
let someNodeRuntime = false
|
|
95
99
|
let stopDevServerNeeded = false
|
|
100
|
+
let sourceDirectoryUrl
|
|
96
101
|
const runtimes = {}
|
|
97
102
|
// param validation
|
|
98
103
|
{
|
|
@@ -102,12 +107,12 @@ export const executeTestPlan = async ({
|
|
|
102
107
|
`${unexpectedParamNames.join(",")}: there is no such param`,
|
|
103
108
|
)
|
|
104
109
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"
|
|
110
|
+
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
111
|
+
rootDirectoryUrl,
|
|
112
|
+
"rootDirectoryUrl",
|
|
108
113
|
)
|
|
109
|
-
if (!existsSync(new URL(
|
|
110
|
-
throw new Error(`ENOENT on
|
|
114
|
+
if (!existsSync(new URL(rootDirectoryUrl))) {
|
|
115
|
+
throw new Error(`ENOENT on rootDirectoryUrl at ${rootDirectoryUrl}`)
|
|
111
116
|
}
|
|
112
117
|
if (typeof testPlan !== "object") {
|
|
113
118
|
throw new Error(`testPlan must be an object, got ${testPlan}`)
|
|
@@ -164,17 +169,12 @@ export const executeTestPlan = async ({
|
|
|
164
169
|
}
|
|
165
170
|
stopDevServerNeeded = true
|
|
166
171
|
}
|
|
167
|
-
|
|
172
|
+
|
|
173
|
+
const devServerParams = await basicFetch(
|
|
168
174
|
`${devServerOrigin}/__server_params__.json`,
|
|
175
|
+
{ rejectUnauthorized: false },
|
|
169
176
|
)
|
|
170
|
-
|
|
171
|
-
testDirectoryUrl !== sourceDirectoryUrl &&
|
|
172
|
-
!urlIsInsideOf(testDirectoryUrl, sourceDirectoryUrl)
|
|
173
|
-
) {
|
|
174
|
-
throw new Error(
|
|
175
|
-
`testDirectoryUrl must be inside sourceDirectoryUrl when running tests on browser(s)`,
|
|
176
|
-
)
|
|
177
|
-
}
|
|
177
|
+
sourceDirectoryUrl = devServerParams.sourceDirectoryUrl
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
if (coverageEnabled) {
|
|
@@ -213,20 +213,9 @@ export const executeTestPlan = async ({
|
|
|
213
213
|
)
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
|
-
|
|
217
|
-
coverageReportRootDirectoryUrl =
|
|
218
|
-
lookupPackageDirectory(testDirectoryUrl)
|
|
219
|
-
} else {
|
|
220
|
-
coverageReportRootDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
221
|
-
coverageReportRootDirectoryUrl,
|
|
222
|
-
"coverageReportRootDirectoryUrl",
|
|
223
|
-
)
|
|
224
|
-
}
|
|
216
|
+
|
|
225
217
|
if (coverageTempDirectoryUrl === undefined) {
|
|
226
|
-
coverageTempDirectoryUrl = new URL(
|
|
227
|
-
"./.coverage/tmp/",
|
|
228
|
-
coverageReportRootDirectoryUrl,
|
|
229
|
-
)
|
|
218
|
+
coverageTempDirectoryUrl = new URL("./.coverage/tmp/", rootDirectoryUrl)
|
|
230
219
|
} else {
|
|
231
220
|
coverageTempDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
232
221
|
coverageTempDirectoryUrl,
|
|
@@ -237,7 +226,7 @@ export const executeTestPlan = async ({
|
|
|
237
226
|
if (coverageReportJsonFileUrl === undefined) {
|
|
238
227
|
coverageReportJsonFileUrl = new URL(
|
|
239
228
|
"./.coverage/coverage.json",
|
|
240
|
-
|
|
229
|
+
rootDirectoryUrl,
|
|
241
230
|
)
|
|
242
231
|
} else {
|
|
243
232
|
coverageReportJsonFileUrl = assertAndNormalizeFileUrl(
|
|
@@ -250,7 +239,7 @@ export const executeTestPlan = async ({
|
|
|
250
239
|
if (coverageReportHtmlDirectoryUrl === undefined) {
|
|
251
240
|
coverageReportHtmlDirectoryUrl = new URL(
|
|
252
241
|
"./.coverage/",
|
|
253
|
-
|
|
242
|
+
rootDirectoryUrl,
|
|
254
243
|
)
|
|
255
244
|
} else {
|
|
256
245
|
coverageReportHtmlDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
@@ -302,8 +291,15 @@ export const executeTestPlan = async ({
|
|
|
302
291
|
}
|
|
303
292
|
|
|
304
293
|
testPlan = { ...testPlan, "**/.jsenv/": null }
|
|
294
|
+
logger.debug(`Generate executions`)
|
|
295
|
+
const executionSteps = await executionStepsFromTestPlan({
|
|
296
|
+
signal,
|
|
297
|
+
testPlan,
|
|
298
|
+
rootDirectoryUrl,
|
|
299
|
+
})
|
|
300
|
+
logger.debug(`${executionSteps.length} executions planned`)
|
|
305
301
|
|
|
306
|
-
const result = await
|
|
302
|
+
const result = await executeSteps(executionSteps, {
|
|
307
303
|
signal,
|
|
308
304
|
handleSIGINT,
|
|
309
305
|
logger,
|
|
@@ -316,8 +312,9 @@ export const executeTestPlan = async ({
|
|
|
316
312
|
logFileRelativeUrl,
|
|
317
313
|
completedExecutionLogMerging,
|
|
318
314
|
completedExecutionLogAbbreviation,
|
|
319
|
-
rootDirectoryUrl
|
|
315
|
+
rootDirectoryUrl,
|
|
320
316
|
devServerOrigin,
|
|
317
|
+
sourceDirectoryUrl,
|
|
321
318
|
|
|
322
319
|
maxExecutionsInParallel,
|
|
323
320
|
defaultMsAllocatedPerExecution,
|
|
@@ -336,7 +333,9 @@ export const executeTestPlan = async ({
|
|
|
336
333
|
})
|
|
337
334
|
if (stopDevServerNeeded) {
|
|
338
335
|
// we are expecting ECONNRESET because server will be stopped by the request
|
|
339
|
-
basicFetch(`${devServerOrigin}/__stop__
|
|
336
|
+
basicFetch(`${devServerOrigin}/__stop__`, {
|
|
337
|
+
rejectUnauthorized: false,
|
|
338
|
+
}).catch((e) => {
|
|
340
339
|
if (e.code === "ECONNRESET") {
|
|
341
340
|
return
|
|
342
341
|
}
|
|
@@ -364,10 +363,10 @@ export const executeTestPlan = async ({
|
|
|
364
363
|
)
|
|
365
364
|
promises.push(
|
|
366
365
|
generateCoverageHtmlDirectory(planCoverage, {
|
|
367
|
-
rootDirectoryUrl
|
|
366
|
+
rootDirectoryUrl,
|
|
368
367
|
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(
|
|
369
368
|
coverageReportHtmlDirectoryUrl,
|
|
370
|
-
|
|
369
|
+
rootDirectoryUrl,
|
|
371
370
|
),
|
|
372
371
|
coverageReportSkipEmpty,
|
|
373
372
|
coverageReportSkipFull,
|
|
@@ -1,25 +1,39 @@
|
|
|
1
|
+
import { Abort } from "@jsenv/abort"
|
|
1
2
|
import { collectFiles } from "@jsenv/filesystem"
|
|
2
3
|
import { createDetailedMessage } from "@jsenv/log"
|
|
3
4
|
|
|
4
|
-
export const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
fileResultArray.forEach(({ relativeUrl, meta }) => {
|
|
16
|
-
const fileExecutionSteps = generateFileExecutionSteps({
|
|
17
|
-
fileRelativeUrl: relativeUrl,
|
|
18
|
-
filePlan: meta.filePlan,
|
|
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,
|
|
19
16
|
})
|
|
20
|
-
executionSteps
|
|
21
|
-
|
|
22
|
-
|
|
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
|
+
}
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
export const generateFileExecutionSteps = ({ fileRelativeUrl, filePlan }) => {
|
|
@@ -15,7 +15,7 @@ export const watchSourceFiles = (
|
|
|
15
15
|
"**/*": true, // by default watch everything inside the source directory
|
|
16
16
|
// line below is commented until @jsenv/url-meta fixes the fact that is matches
|
|
17
17
|
// any file with an extension
|
|
18
|
-
|
|
18
|
+
"**/.*": false, // file starting with a dot -> do not watch
|
|
19
19
|
"**/.*/": false, // directory starting with a dot -> do not watch
|
|
20
20
|
"**/node_modules/": false, // node_modules directory -> do not watch
|
|
21
21
|
...sourceFileConfig,
|