@jsenv/core 23.3.0 → 23.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/readme.md +1 -1
- package/src/executeTestPlan.js +9 -8
- package/src/internal/browser-launcher/executeHtmlFile.js +20 -16
- package/src/internal/executing/coverage/babel_plugin_instrument.js +1 -0
- package/src/internal/executing/coverage/reportToCoverage.js +147 -120
- package/src/internal/executing/{coverage → coverage_empty}/createEmptyCoverage.js +0 -0
- package/src/internal/executing/coverage_empty/list_files_not_covered.js +20 -0
- package/src/internal/executing/{coverage → coverage_empty}/relativeUrlToEmptyCoverage.js +1 -1
- package/src/internal/executing/{coverage/generateCoverageHtmlDirectory.js → coverage_reporter/coverage_reporter_html_directory.js} +11 -4
- package/src/internal/executing/{coverage/generateCoverageJsonFile.js → coverage_reporter/coverage_reporter_json_file.js} +0 -0
- package/src/internal/executing/{coverage/generateCoverageTextLog.js → coverage_reporter/coverage_reporter_text_log.js} +4 -2
- package/src/internal/executing/{coverage → coverage_reporter}/istanbulCoverageMapFromCoverage.js +0 -0
- package/src/internal/executing/{coverage/normalizeIstanbulCoverage.js → coverage_utils/file_by_file_coverage.js} +9 -7
- package/src/internal/executing/coverage_utils/istanbul_coverage_composition.js +28 -0
- package/src/internal/executing/coverage_utils/v8_and_istanbul.js +38 -0
- package/src/internal/executing/coverage_utils/v8_coverage_composition.js +23 -0
- package/src/internal/executing/coverage_utils/v8_coverage_from_directory.js +59 -0
- package/src/internal/executing/coverage_utils/v8_coverage_to_istanbul.js +90 -0
- package/src/internal/executing/createSummaryLog.js +3 -1
- package/src/internal/executing/executeConcurrently.js +85 -27
- package/src/internal/executing/executePlan.js +5 -2
- package/src/internal/executing/launchAndExecute.js +47 -24
- package/src/launchBrowser.js +8 -8
- package/src/launchNode.js +5 -93
- package/src/internal/executing/coverage/composeIstanbulCoverages.js +0 -108
- package/src/internal/executing/coverage/composeV8Coverages.js +0 -20
- package/src/internal/executing/coverage/istanbulCoverageFromCoverages.js +0 -43
- package/src/internal/executing/coverage/istanbulCoverageFromV8Coverage.js +0 -79
- package/src/internal/executing/coverage/v8CoverageFromAllV8Coverages.js +0 -40
- package/src/internal/executing/coverage/v8CoverageFromNodeV8Directory.js +0 -67
package/package.json
CHANGED
package/readme.md
CHANGED
package/src/executeTestPlan.js
CHANGED
|
@@ -14,9 +14,9 @@ import {
|
|
|
14
14
|
} from "./internal/argUtils.js"
|
|
15
15
|
import { executePlan } from "./internal/executing/executePlan.js"
|
|
16
16
|
import { executionIsPassed } from "./internal/executing/executionIsPassed.js"
|
|
17
|
-
import { generateCoverageJsonFile } from "./internal/executing/
|
|
18
|
-
import { generateCoverageHtmlDirectory } from "./internal/executing/
|
|
19
|
-
import { generateCoverageTextLog } from "./internal/executing/
|
|
17
|
+
import { generateCoverageJsonFile } from "./internal/executing/coverage_reporter/coverage_reporter_json_file.js"
|
|
18
|
+
import { generateCoverageHtmlDirectory } from "./internal/executing/coverage_reporter/coverage_reporter_html_directory.js"
|
|
19
|
+
import { generateCoverageTextLog } from "./internal/executing/coverage_reporter/coverage_reporter_text_log.js"
|
|
20
20
|
import { jsenvCoverageConfig } from "./jsenvCoverageConfig.js"
|
|
21
21
|
|
|
22
22
|
export const executeTestPlan = async ({
|
|
@@ -44,18 +44,18 @@ export const executeTestPlan = async ({
|
|
|
44
44
|
|
|
45
45
|
coverage = process.argv.includes("--cover") ||
|
|
46
46
|
process.argv.includes("--coverage"),
|
|
47
|
+
coverageTempDirectoryRelativeUrl = "./coverage/tmp/",
|
|
47
48
|
coverageConfig = jsenvCoverageConfig,
|
|
48
49
|
coverageIncludeMissing = true,
|
|
49
50
|
coverageAndExecutionAllowed = false,
|
|
50
51
|
coverageForceIstanbul = false,
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
coverageV8ConflictWarning = true,
|
|
53
53
|
coverageTextLog = true,
|
|
54
54
|
coverageJsonFile = Boolean(process.env.CI),
|
|
55
55
|
coverageJsonFileLog = true,
|
|
56
56
|
coverageJsonFileRelativeUrl = "./coverage/coverage.json",
|
|
57
57
|
coverageHtmlDirectory = !process.env.CI,
|
|
58
|
-
coverageHtmlDirectoryRelativeUrl = "./coverage",
|
|
58
|
+
coverageHtmlDirectoryRelativeUrl = "./coverage/",
|
|
59
59
|
coverageHtmlDirectoryIndexLog = true,
|
|
60
60
|
// skip empty means empty files won't appear in the coverage reports (log and html)
|
|
61
61
|
coverageSkipEmpty = false,
|
|
@@ -153,7 +153,8 @@ export const executeTestPlan = async ({
|
|
|
153
153
|
coverageConfig,
|
|
154
154
|
coverageIncludeMissing,
|
|
155
155
|
coverageForceIstanbul,
|
|
156
|
-
|
|
156
|
+
coverageV8ConflictWarning,
|
|
157
|
+
coverageTempDirectoryRelativeUrl,
|
|
157
158
|
|
|
158
159
|
jsenvDirectoryClean,
|
|
159
160
|
compileServerProtocol,
|
|
@@ -173,7 +174,7 @@ export const executeTestPlan = async ({
|
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
const planCoverage = result.planCoverage
|
|
176
|
-
// planCoverage can be null when execution is
|
|
177
|
+
// planCoverage can be null when execution is aborted
|
|
177
178
|
if (planCoverage) {
|
|
178
179
|
const promises = []
|
|
179
180
|
// keep this one first because it does ensureEmptyDirectory
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
} from "@jsenv/filesystem"
|
|
7
7
|
|
|
8
8
|
import { jsenvCompileProxyHtmlFileInfo } from "@jsenv/core/src/internal/jsenvInternalFiles.js"
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { filterV8Coverage } from "@jsenv/core/src/internal/executing/coverage_utils/v8_coverage_from_directory.js"
|
|
10
|
+
import { composeTwoFileByFileIstanbulCoverages } from "@jsenv/core/src/internal/executing/coverage_utils/istanbul_coverage_composition.js"
|
|
11
11
|
import { evalSource } from "../runtime/createNodeRuntime/evalSource.js"
|
|
12
12
|
import { escapeRegexpSpecialCharacters } from "../escapeRegexpSpecialCharacters.js"
|
|
13
13
|
|
|
@@ -23,7 +23,7 @@ export const executeHtmlFile = async (
|
|
|
23
23
|
// measurePerformance,
|
|
24
24
|
collectPerformance,
|
|
25
25
|
collectCoverage,
|
|
26
|
-
|
|
26
|
+
coverageIgnorePredicate,
|
|
27
27
|
coverageForceIstanbul,
|
|
28
28
|
coveragePlaywrightAPIAvailable,
|
|
29
29
|
transformErrorHook,
|
|
@@ -76,7 +76,7 @@ export const executeHtmlFile = async (
|
|
|
76
76
|
fileRelativeUrl,
|
|
77
77
|
page,
|
|
78
78
|
collectCoverage,
|
|
79
|
-
|
|
79
|
+
coverageIgnorePredicate,
|
|
80
80
|
transformErrorHook,
|
|
81
81
|
})
|
|
82
82
|
} else {
|
|
@@ -149,7 +149,7 @@ const executeSource = async ({
|
|
|
149
149
|
fileRelativeUrl,
|
|
150
150
|
page,
|
|
151
151
|
collectCoverage,
|
|
152
|
-
|
|
152
|
+
coverageIgnorePredicate,
|
|
153
153
|
transformErrorHook,
|
|
154
154
|
}) => {
|
|
155
155
|
let transformResult = (result) => result
|
|
@@ -175,11 +175,12 @@ const executeSource = async ({
|
|
|
175
175
|
}
|
|
176
176
|
},
|
|
177
177
|
)
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
const coverage = filterV8Coverage(
|
|
179
|
+
{ result: v8CoveragesWithFsUrls },
|
|
180
|
+
{
|
|
181
|
+
coverageIgnorePredicate,
|
|
182
|
+
},
|
|
183
|
+
)
|
|
183
184
|
return {
|
|
184
185
|
...result,
|
|
185
186
|
coverage,
|
|
@@ -297,15 +298,18 @@ const executeCompiledVersion = async ({
|
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
const generateCoverageForPage = (fileExecutionResultMap) => {
|
|
300
|
-
|
|
301
|
+
let istanbulCoverageComposed = null
|
|
301
302
|
Object.keys(fileExecutionResultMap).forEach((fileRelativeUrl) => {
|
|
302
303
|
const istanbulCoverage = fileExecutionResultMap[fileRelativeUrl].coverage
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
304
|
+
istanbulCoverageComposed = istanbulCoverageComposed
|
|
305
|
+
? composeTwoFileByFileIstanbulCoverages(
|
|
306
|
+
istanbulCoverageComposed,
|
|
307
|
+
istanbulCoverage,
|
|
308
|
+
)
|
|
309
|
+
: istanbulCoverage
|
|
306
310
|
})
|
|
307
|
-
|
|
308
|
-
return
|
|
311
|
+
|
|
312
|
+
return istanbulCoverageComposed
|
|
309
313
|
}
|
|
310
314
|
|
|
311
315
|
const evalException = (
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { readFile } from "@jsenv/filesystem"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
visitNodeV8Directory,
|
|
5
|
+
filterV8Coverage,
|
|
6
|
+
} from "../coverage_utils/v8_coverage_from_directory.js"
|
|
7
|
+
import { composeTwoV8Coverages } from "../coverage_utils/v8_coverage_composition.js"
|
|
8
|
+
import { composeTwoFileByFileIstanbulCoverages } from "../coverage_utils/istanbul_coverage_composition.js"
|
|
9
|
+
import { v8CoverageToIstanbul } from "../coverage_utils/v8_coverage_to_istanbul.js"
|
|
10
|
+
import { composeV8AndIstanbul } from "../coverage_utils/v8_and_istanbul.js"
|
|
11
|
+
import { normalizeFileByFileCoveragePaths } from "../coverage_utils/file_by_file_coverage.js"
|
|
12
|
+
import { listRelativeFileUrlToCover } from "../coverage_empty/list_files_not_covered.js"
|
|
13
|
+
import { relativeUrlToEmptyCoverage } from "../coverage_empty/relativeUrlToEmptyCoverage.js"
|
|
6
14
|
|
|
7
15
|
export const reportToCoverage = async (
|
|
8
16
|
report,
|
|
@@ -13,134 +21,153 @@ export const reportToCoverage = async (
|
|
|
13
21
|
babelPluginMap,
|
|
14
22
|
coverageConfig,
|
|
15
23
|
coverageIncludeMissing,
|
|
16
|
-
|
|
24
|
+
coverageIgnorePredicate,
|
|
25
|
+
coverageForceIstanbul,
|
|
26
|
+
coverageV8ConflictWarning,
|
|
17
27
|
},
|
|
18
28
|
) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const istanbulCoverageFromExecution = await executionReportToCoverage(
|
|
22
|
-
report,
|
|
23
|
-
{
|
|
24
|
-
logger,
|
|
25
|
-
projectDirectoryUrl,
|
|
26
|
-
coverageV8MergeConflictIsExpected,
|
|
27
|
-
},
|
|
28
|
-
)
|
|
29
|
+
let v8Coverage
|
|
30
|
+
let fileByFileIstanbulCoverage
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
// collect v8 and istanbul coverage from executions
|
|
33
|
+
await Object.keys(report).reduce(async (previous, file) => {
|
|
34
|
+
await previous
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const executionResultForFile = report[file]
|
|
37
|
+
await Object.keys(executionResultForFile).reduce(
|
|
38
|
+
async (previous, executionName) => {
|
|
39
|
+
await previous
|
|
40
|
+
|
|
41
|
+
const executionResultForFileOnRuntime =
|
|
42
|
+
executionResultForFile[executionName]
|
|
43
|
+
const { status, coverageFileUrl } = executionResultForFileOnRuntime
|
|
44
|
+
if (!coverageFileUrl) {
|
|
45
|
+
// several reasons not to have coverage here:
|
|
46
|
+
// 1. the file we executed did not import an instrumented file.
|
|
47
|
+
// - a test file without import
|
|
48
|
+
// - a test file importing only file excluded from coverage
|
|
49
|
+
// - a coverDescription badly configured so that we don't realize
|
|
50
|
+
// a file should be covered
|
|
51
|
+
|
|
52
|
+
// 2. the file we wanted to executed timedout
|
|
53
|
+
// - infinite loop
|
|
54
|
+
// - too extensive operation
|
|
55
|
+
// - a badly configured or too low allocatedMs for that execution.
|
|
56
|
+
|
|
57
|
+
// 3. the file we wanted to execute contains syntax-error
|
|
58
|
+
|
|
59
|
+
// in any scenario we are fine because
|
|
60
|
+
// coverDescription will generate empty coverage for files
|
|
61
|
+
// that were suppose to be coverage but were not.
|
|
62
|
+
if (status === "completed") {
|
|
63
|
+
logger.debug(
|
|
64
|
+
`No execution.coverageFileUrl from execution named "${executionName}" of ${file}`,
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
return
|
|
68
|
+
}
|
|
39
69
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
70
|
+
const executionCoverage = await readFile(coverageFileUrl, {
|
|
71
|
+
as: "json",
|
|
72
|
+
})
|
|
73
|
+
if (isV8Coverage(executionCoverage)) {
|
|
74
|
+
v8Coverage = v8Coverage
|
|
75
|
+
? composeTwoV8Coverages(v8Coverage, executionCoverage)
|
|
76
|
+
: executionCoverage
|
|
77
|
+
} else {
|
|
78
|
+
fileByFileIstanbulCoverage = fileByFileIstanbulCoverage
|
|
79
|
+
? composeTwoFileByFileIstanbulCoverages(
|
|
80
|
+
fileByFileIstanbulCoverage,
|
|
81
|
+
executionCoverage,
|
|
82
|
+
)
|
|
83
|
+
: executionCoverage
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
Promise.resolve(),
|
|
45
87
|
)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
},
|
|
60
|
-
)
|
|
61
|
-
istanbulCoverageFromMissedFiles[relativeFileUrlMissingCoverage] =
|
|
62
|
-
emptyCoverage
|
|
63
|
-
return emptyCoverage
|
|
88
|
+
}, Promise.resolve())
|
|
89
|
+
|
|
90
|
+
if (!coverageForceIstanbul && process.env.NODE_V8_COVERAGE) {
|
|
91
|
+
await visitNodeV8Directory({
|
|
92
|
+
signal: multipleExecutionsOperation.signal,
|
|
93
|
+
NODE_V8_COVERAGE: process.env.NODE_V8_COVERAGE,
|
|
94
|
+
onV8Coverage: (nodeV8Coverage) => {
|
|
95
|
+
const nodeV8CoverageLight = filterV8Coverage(nodeV8Coverage, {
|
|
96
|
+
coverageIgnorePredicate,
|
|
97
|
+
})
|
|
98
|
+
v8Coverage = v8Coverage
|
|
99
|
+
? composeTwoV8Coverages(v8Coverage, nodeV8CoverageLight)
|
|
100
|
+
: nodeV8CoverageLight
|
|
64
101
|
},
|
|
65
|
-
)
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
...istanbulCoverageFromExecution, // already normalized
|
|
70
|
-
...normalizeIstanbulCoverage(
|
|
71
|
-
istanbulCoverageFromMissedFiles,
|
|
72
|
-
projectDirectoryUrl,
|
|
73
|
-
),
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const listRelativeFileUrlToCover = async ({
|
|
78
|
-
multipleExecutionsOperation,
|
|
79
|
-
projectDirectoryUrl,
|
|
80
|
-
coverageConfig,
|
|
81
|
-
}) => {
|
|
82
|
-
const structuredMetaMapForCoverage = {
|
|
83
|
-
cover: coverageConfig,
|
|
102
|
+
})
|
|
84
103
|
}
|
|
85
104
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
predicate: ({ cover }) => cover,
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
return matchingFileResultArray.map(({ relativeUrl }) => relativeUrl)
|
|
94
|
-
}
|
|
105
|
+
// try to merge v8 with istanbul, if any
|
|
106
|
+
let fileByFileCoverage
|
|
107
|
+
if (v8Coverage) {
|
|
108
|
+
let v8FileByFileCoverage = await v8CoverageToIstanbul(v8Coverage)
|
|
95
109
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
)
|
|
100
|
-
const coverages = []
|
|
110
|
+
v8FileByFileCoverage = normalizeFileByFileCoveragePaths(
|
|
111
|
+
v8FileByFileCoverage,
|
|
112
|
+
projectDirectoryUrl,
|
|
113
|
+
)
|
|
101
114
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (status === "completed") {
|
|
129
|
-
logger.warn(
|
|
130
|
-
`No execution.coverage from execution named "${executionName}" of ${file}`,
|
|
131
|
-
)
|
|
132
|
-
}
|
|
133
|
-
return
|
|
134
|
-
}
|
|
115
|
+
if (fileByFileIstanbulCoverage) {
|
|
116
|
+
fileByFileIstanbulCoverage = normalizeFileByFileCoveragePaths(
|
|
117
|
+
fileByFileIstanbulCoverage,
|
|
118
|
+
projectDirectoryUrl,
|
|
119
|
+
)
|
|
120
|
+
fileByFileCoverage = composeV8AndIstanbul(
|
|
121
|
+
v8FileByFileCoverage,
|
|
122
|
+
fileByFileIstanbulCoverage,
|
|
123
|
+
{ coverageV8ConflictWarning },
|
|
124
|
+
)
|
|
125
|
+
} else {
|
|
126
|
+
fileByFileCoverage = v8FileByFileCoverage
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// get istanbul only
|
|
130
|
+
else if (fileByFileIstanbulCoverage) {
|
|
131
|
+
fileByFileCoverage = normalizeFileByFileCoveragePaths(
|
|
132
|
+
fileByFileIstanbulCoverage,
|
|
133
|
+
projectDirectoryUrl,
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
// no coverage found in execution (or zero file where executed)
|
|
137
|
+
else {
|
|
138
|
+
fileByFileCoverage = {}
|
|
139
|
+
}
|
|
135
140
|
|
|
136
|
-
|
|
141
|
+
// now add coverage for file not covered
|
|
142
|
+
if (coverageIncludeMissing) {
|
|
143
|
+
const relativeUrlsToCover = await listRelativeFileUrlToCover({
|
|
144
|
+
multipleExecutionsOperation,
|
|
145
|
+
projectDirectoryUrl,
|
|
146
|
+
coverageConfig,
|
|
137
147
|
})
|
|
138
|
-
})
|
|
139
148
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
149
|
+
const relativeUrlsMissing = relativeUrlsToCover.filter(
|
|
150
|
+
(relativeUrlToCover) =>
|
|
151
|
+
Object.keys(fileByFileCoverage).every((key) => {
|
|
152
|
+
return key !== `./${relativeUrlToCover}`
|
|
153
|
+
}),
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
await relativeUrlsMissing.reduce(async (previous, relativeUrlMissing) => {
|
|
157
|
+
const emptyCoverage = await relativeUrlToEmptyCoverage(
|
|
158
|
+
relativeUrlMissing,
|
|
159
|
+
{
|
|
160
|
+
multipleExecutionsOperation,
|
|
161
|
+
projectDirectoryUrl,
|
|
162
|
+
babelPluginMap,
|
|
163
|
+
},
|
|
164
|
+
)
|
|
165
|
+
fileByFileCoverage[`./${relativeUrlMissing}`] = emptyCoverage
|
|
166
|
+
return emptyCoverage
|
|
167
|
+
}, Promise.resolve())
|
|
168
|
+
}
|
|
144
169
|
|
|
145
|
-
return
|
|
170
|
+
return fileByFileCoverage
|
|
146
171
|
}
|
|
172
|
+
|
|
173
|
+
const isV8Coverage = (coverage) => Boolean(coverage.result)
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { collectFiles } from "@jsenv/filesystem"
|
|
2
|
+
|
|
3
|
+
export const listRelativeFileUrlToCover = async ({
|
|
4
|
+
multipleExecutionsOperation,
|
|
5
|
+
projectDirectoryUrl,
|
|
6
|
+
coverageConfig,
|
|
7
|
+
}) => {
|
|
8
|
+
const structuredMetaMapForCoverage = {
|
|
9
|
+
cover: coverageConfig,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const matchingFileResultArray = await collectFiles({
|
|
13
|
+
signal: multipleExecutionsOperation.signal,
|
|
14
|
+
directoryUrl: projectDirectoryUrl,
|
|
15
|
+
structuredMetaMap: structuredMetaMapForCoverage,
|
|
16
|
+
predicate: ({ cover }) => cover,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
return matchingFileResultArray.map(({ relativeUrl }) => relativeUrl)
|
|
20
|
+
}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
babelPluginsFromBabelPluginMap,
|
|
5
5
|
getMinimalBabelPluginMap,
|
|
6
6
|
} from "@jsenv/core/src/internal/compiling/babel_plugins.js"
|
|
7
|
-
import { babelPluginInstrument } from "
|
|
7
|
+
import { babelPluginInstrument } from "../coverage/babel_plugin_instrument.js"
|
|
8
8
|
import { createEmptyCoverage } from "./createEmptyCoverage.js"
|
|
9
9
|
|
|
10
10
|
export const relativeUrlToEmptyCoverage = async (
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { readFileSync } from "fs"
|
|
1
|
+
import { readFileSync } from "node:fs"
|
|
2
2
|
import { resolveUrl, urlToFileSystemPath } from "@jsenv/filesystem"
|
|
3
3
|
|
|
4
4
|
import { require } from "../../require.js"
|
|
5
|
-
|
|
6
5
|
import { istanbulCoverageMapFromCoverage } from "./istanbulCoverageMapFromCoverage.js"
|
|
7
6
|
|
|
8
7
|
export const generateCoverageHtmlDirectory = async (
|
|
9
8
|
coverage,
|
|
10
|
-
{
|
|
9
|
+
{
|
|
10
|
+
projectDirectoryUrl,
|
|
11
|
+
coverageHtmlDirectoryRelativeUrl,
|
|
12
|
+
coverageSkipEmpty,
|
|
13
|
+
coverageSkipFull,
|
|
14
|
+
},
|
|
11
15
|
) => {
|
|
12
16
|
const libReport = require("istanbul-lib-report")
|
|
13
17
|
const reports = require("istanbul-reports")
|
|
@@ -16,7 +20,10 @@ export const generateCoverageHtmlDirectory = async (
|
|
|
16
20
|
dir: urlToFileSystemPath(projectDirectoryUrl),
|
|
17
21
|
coverageMap: istanbulCoverageMapFromCoverage(coverage),
|
|
18
22
|
sourceFinder: (path) => {
|
|
19
|
-
return readFileSync(
|
|
23
|
+
return readFileSync(
|
|
24
|
+
urlToFileSystemPath(resolveUrl(path, projectDirectoryUrl)),
|
|
25
|
+
"utf8",
|
|
26
|
+
)
|
|
20
27
|
},
|
|
21
28
|
})
|
|
22
29
|
|
|
File without changes
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { require } from "../../require.js"
|
|
2
|
-
|
|
3
2
|
import { istanbulCoverageMapFromCoverage } from "./istanbulCoverageMapFromCoverage.js"
|
|
4
3
|
|
|
5
|
-
export const generateCoverageTextLog = (
|
|
4
|
+
export const generateCoverageTextLog = (
|
|
5
|
+
coverage,
|
|
6
|
+
{ coverageSkipEmpty, coverageSkipFull },
|
|
7
|
+
) => {
|
|
6
8
|
const libReport = require("istanbul-lib-report")
|
|
7
9
|
const reports = require("istanbul-reports")
|
|
8
10
|
|
package/src/internal/executing/{coverage → coverage_reporter}/istanbulCoverageMapFromCoverage.js
RENAMED
|
File without changes
|
|
@@ -5,22 +5,24 @@ import {
|
|
|
5
5
|
resolveUrl,
|
|
6
6
|
} from "@jsenv/filesystem"
|
|
7
7
|
|
|
8
|
-
export const
|
|
9
|
-
|
|
8
|
+
export const normalizeFileByFileCoveragePaths = (
|
|
9
|
+
fileByFileCoverage,
|
|
10
|
+
projectDirectoryUrl,
|
|
11
|
+
) => {
|
|
12
|
+
const fileByFileNormalized = {}
|
|
10
13
|
|
|
11
|
-
Object.keys(
|
|
12
|
-
const fileCoverage =
|
|
14
|
+
Object.keys(fileByFileCoverage).forEach((key) => {
|
|
15
|
+
const fileCoverage = fileByFileCoverage[key]
|
|
13
16
|
const { path } = fileCoverage
|
|
14
17
|
const url = isFileSystemPath(path)
|
|
15
18
|
? fileSystemPathToUrl(path)
|
|
16
19
|
: resolveUrl(path, projectDirectoryUrl)
|
|
17
20
|
const relativeUrl = urlToRelativeUrl(url, projectDirectoryUrl)
|
|
18
|
-
|
|
19
|
-
istanbulCoverageNormalized[`./${relativeUrl}`] = {
|
|
21
|
+
fileByFileNormalized[`./${relativeUrl}`] = {
|
|
20
22
|
...fileCoverage,
|
|
21
23
|
path: `./${relativeUrl}`,
|
|
22
24
|
}
|
|
23
25
|
})
|
|
24
26
|
|
|
25
|
-
return
|
|
27
|
+
return fileByFileNormalized
|
|
26
28
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { require } from "../../require.js"
|
|
2
|
+
|
|
3
|
+
export const composeTwoFileByFileIstanbulCoverages = (
|
|
4
|
+
firstFileByFileIstanbulCoverage,
|
|
5
|
+
secondFileByFileIstanbulCoverage,
|
|
6
|
+
) => {
|
|
7
|
+
const fileByFileIstanbulCoverage = {}
|
|
8
|
+
Object.keys(firstFileByFileIstanbulCoverage).forEach((key) => {
|
|
9
|
+
fileByFileIstanbulCoverage[key] = firstFileByFileIstanbulCoverage[key]
|
|
10
|
+
})
|
|
11
|
+
Object.keys(secondFileByFileIstanbulCoverage).forEach((key) => {
|
|
12
|
+
const firstCoverage = firstFileByFileIstanbulCoverage[key]
|
|
13
|
+
const secondCoverage = secondFileByFileIstanbulCoverage[key]
|
|
14
|
+
fileByFileIstanbulCoverage[key] = firstCoverage
|
|
15
|
+
? merge(firstCoverage, secondCoverage)
|
|
16
|
+
: secondCoverage
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
return fileByFileIstanbulCoverage
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const merge = (firstIstanbulCoverage, secondIstanbulCoverage) => {
|
|
23
|
+
const { createFileCoverage } = require("istanbul-lib-coverage")
|
|
24
|
+
const istanbulFileCoverageObject = createFileCoverage(firstIstanbulCoverage)
|
|
25
|
+
istanbulFileCoverageObject.merge(secondIstanbulCoverage)
|
|
26
|
+
const istanbulCoverage = istanbulFileCoverageObject.toJSON()
|
|
27
|
+
return istanbulCoverage
|
|
28
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createDetailedMessage } from "@jsenv/logger"
|
|
2
|
+
|
|
3
|
+
export const composeV8AndIstanbul = (
|
|
4
|
+
v8FileByFileCoverage,
|
|
5
|
+
istanbulFileByFileCoverage,
|
|
6
|
+
{ coverageV8ConflictWarning },
|
|
7
|
+
) => {
|
|
8
|
+
const fileByFileCoverage = {}
|
|
9
|
+
const v8Files = Object.keys(v8FileByFileCoverage)
|
|
10
|
+
const istanbulFiles = Object.keys(istanbulFileByFileCoverage)
|
|
11
|
+
|
|
12
|
+
v8Files.forEach((key) => {
|
|
13
|
+
fileByFileCoverage[key] = v8FileByFileCoverage[key]
|
|
14
|
+
})
|
|
15
|
+
istanbulFiles.forEach((key) => {
|
|
16
|
+
const v8Coverage = v8FileByFileCoverage[key]
|
|
17
|
+
if (v8Coverage) {
|
|
18
|
+
if (coverageV8ConflictWarning) {
|
|
19
|
+
console.warn(
|
|
20
|
+
createDetailedMessage(
|
|
21
|
+
`Coverage conflict on "${key}", found two coverage that cannot be merged together: v8 and istanbul. The istanbul coverage will be ignored.`,
|
|
22
|
+
{
|
|
23
|
+
"details": `This happens when a file is executed on a runtime using v8 coverage (node or chromium) and on runtime using istanbul coverage (firefox or webkit)`,
|
|
24
|
+
"suggestion":
|
|
25
|
+
"You can disable this warning with coverageV8ConflictWarning: false",
|
|
26
|
+
"suggestion 2": `You can force usage of istanbul to prevent this conflict with coverageForceIstanbul: true`,
|
|
27
|
+
},
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
fileByFileCoverage[key] = v8Coverage
|
|
32
|
+
} else {
|
|
33
|
+
fileByFileCoverage[key] = istanbulFileByFileCoverage[key]
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
return fileByFileCoverage
|
|
38
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { require } from "@jsenv/core/src/internal/require.js"
|
|
2
|
+
|
|
3
|
+
export const composeTwoV8Coverages = (firstV8Coverage, secondV8Coverage) => {
|
|
4
|
+
if (secondV8Coverage.result.length === 0) {
|
|
5
|
+
return firstV8Coverage
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const { mergeProcessCovs } = require("@c88/v8-coverage")
|
|
9
|
+
// "mergeProcessCovs" do not preserves source-map-cache during the merge
|
|
10
|
+
// so we store sourcemap cache now
|
|
11
|
+
const sourceMapCache = {}
|
|
12
|
+
const visit = (coverageReport) => {
|
|
13
|
+
if (coverageReport["source-map-cache"]) {
|
|
14
|
+
Object.assign(sourceMapCache, coverageReport["source-map-cache"])
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
visit(firstV8Coverage)
|
|
18
|
+
visit(secondV8Coverage)
|
|
19
|
+
const v8Coverage = mergeProcessCovs([firstV8Coverage, secondV8Coverage])
|
|
20
|
+
v8Coverage["source-map-cache"] = sourceMapCache
|
|
21
|
+
|
|
22
|
+
return v8Coverage
|
|
23
|
+
}
|