source: trip-planner-front/node_modules/karma-coverage/lib/reporter.js@ 76712b2

Last change on this file since 76712b2 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 8.7 KB
RevLine 
[6a3a178]1// Coverage Reporter
2// Part of this code is based on [1], which is licensed under the New BSD License.
3// For more information see the See the accompanying LICENSE-istanbul file for terms.
4//
5// [1]: https://github.com/gotwarlost/istanbul/blob/master/lib/command/check-coverage.js
6// =====================
7//
8// Generates the report
9
10// Dependencies
11// ------------
12
13var path = require('path')
14var istanbulLibCoverage = require('istanbul-lib-coverage')
15var istanbulLibReport = require('istanbul-lib-report')
16var minimatch = require('minimatch')
17
18var globalSourceMapStore = require('./source-map-store')
19var globalCoverageMap = require('./coverage-map')
20var reports = require('./report-creator')
21const hasOwnProperty = Object.prototype.hasOwnProperty
22
23// TODO(vojta): inject only what required (config.basePath, config.coverageReporter)
24var CoverageReporter = function (rootConfig, helper, logger, emitter) {
25 var log = logger.create('coverage')
26
27 // Instance variables
28 // ------------------
29
30 this.adapters = []
31
32 // Options
33 // -------
34
35 var config = rootConfig.coverageReporter || {}
36 var basePath = rootConfig.basePath
37 var reporters = config.reporters
38 var sourceMapStore = globalSourceMapStore.get(basePath)
39 var includeAllSources = config.includeAllSources === true
40
41 if (config.watermarks) {
42 config.watermarks = helper.merge({}, istanbulLibReport.getDefaultWatermarks(), config.watermarks)
43 }
44
45 if (!helper.isDefined(reporters)) {
46 reporters = [config]
47 }
48
49 var coverageMaps
50
51 function normalize (key) {
52 // Exclude keys will always be relative, but covObj keys can be absolute or relative
53 var excludeKey = path.isAbsolute(key) ? path.relative(basePath, key) : key
54 // Also normalize for files that start with `./`, etc.
55 excludeKey = path.normalize(excludeKey)
56
57 return excludeKey
58 }
59
60 function getTrackedFiles (coverageMap, patterns) {
61 var files = []
62
63 coverageMap.files().forEach(function (key) {
64 // Do any patterns match the resolved key
65 var found = patterns.some(function (pattern) {
66 return minimatch(normalize(key), pattern, { dot: true })
67 })
68
69 // if no patterns match, keep the key
70 if (!found) {
71 files.push(key)
72 }
73 })
74
75 return files
76 }
77
78 function overrideThresholds (key, overrides) {
79 var thresholds = {}
80
81 // First match wins
82 Object.keys(overrides).some(function (pattern) {
83 if (minimatch(normalize(key), pattern, { dot: true })) {
84 thresholds = overrides[pattern]
85 return true
86 }
87 })
88
89 return thresholds
90 }
91
92 function checkCoverage (browser, coverageMap) {
93 var defaultThresholds = {
94 global: {
95 statements: 0,
96 branches: 0,
97 lines: 0,
98 functions: 0,
99 excludes: []
100 },
101 each: {
102 statements: 0,
103 branches: 0,
104 lines: 0,
105 functions: 0,
106 excludes: [],
107 overrides: {}
108 }
109 }
110
111 var thresholds = helper.merge({}, defaultThresholds, config.check)
112
113 var globalTrackedFiles = getTrackedFiles(coverageMap, thresholds.global.excludes)
114 var eachTrackedFiles = getTrackedFiles(coverageMap, thresholds.each.excludes)
115 var globalResults = istanbulLibCoverage.createCoverageSummary()
116 var eachResults = {}
117 globalTrackedFiles.forEach(function (f) {
118 var fileCoverage = coverageMap.fileCoverageFor(f)
119 var summary = fileCoverage.toSummary()
120 globalResults.merge(summary)
121 })
122 eachTrackedFiles.forEach(function (f) {
123 var fileCoverage = coverageMap.fileCoverageFor(f)
124 var summary = fileCoverage.toSummary()
125 eachResults[f] = summary
126 })
127
128 var coverageFailed = false
129
130 function check (name, thresholds, actuals) {
131 var keys = [
132 'statements',
133 'branches',
134 'lines',
135 'functions'
136 ]
137
138 keys.forEach(function (key) {
139 var actual = actuals[key].pct
140 var actualUncovered = actuals[key].total - actuals[key].covered
141 var threshold = thresholds[key]
142
143 if (threshold < 0) {
144 if (threshold * -1 < actualUncovered) {
145 coverageFailed = true
146 log.error(browser.name + ': Uncovered count for ' + key + ' (' + actualUncovered +
147 ') exceeds ' + name + ' threshold (' + -1 * threshold + ')')
148 }
149 } else {
150 if (actual < threshold) {
151 coverageFailed = true
152 log.error(browser.name + ': Coverage for ' + key + ' (' + actual +
153 '%) does not meet ' + name + ' threshold (' + threshold + '%)')
154 }
155 }
156 })
157 }
158
159 check('global', thresholds.global, globalResults.toJSON())
160
161 eachTrackedFiles.forEach(function (key) {
162 var keyThreshold = helper.merge(thresholds.each, overrideThresholds(key, thresholds.each.overrides))
163 check('per-file' + ' (' + key + ') ', keyThreshold, eachResults[key].toJSON())
164 })
165
166 return coverageFailed
167 }
168
169 // Generate the output path from the `coverageReporter.dir` and
170 // `coverageReporter.subdir` options.
171 function generateOutputPath (basePath, browserName, dir = 'coverage', subdir) {
172 if (subdir && typeof subdir === 'function') {
173 subdir = subdir(browserName)
174 }
175 if (browserName) {
176 browserName = browserName.replace(':', '')
177 }
178
179 let outPutPath = path.join(dir, subdir || browserName)
180 outPutPath = path.resolve(basePath, outPutPath)
181
182 return helper.normalizeWinPath(outPutPath)
183 }
184
185 this.onRunStart = function (browsers) {
186 coverageMaps = Object.create(null)
187
188 // TODO(vojta): remove once we don't care about Karma 0.10
189 if (browsers) {
190 browsers.forEach(this.onBrowserStart.bind(this))
191 }
192 }
193
194 this.onBrowserStart = function (browser) {
195 var startingMap = {}
196 if (includeAllSources) {
197 startingMap = globalCoverageMap.get()
198 }
199
200 coverageMaps[browser.id] = istanbulLibCoverage.createCoverageMap(startingMap)
201 }
202
203 this.onBrowserComplete = function (browser, result) {
204 var coverageMap = coverageMaps[browser.id]
205
206 if (!coverageMap) return
207 if (!result || !result.coverage) return
208
209 coverageMap.merge(result.coverage)
210 }
211
212 this.onSpecComplete = function (browser, result) {
213 var coverageMap = coverageMaps[browser.id]
214
215 if (!coverageMap) return
216 if (!result.coverage) return
217
218 coverageMap.merge(result.coverage)
219 }
220
221 let checkedCoverage = {}
222 let promiseComplete = null
223
224 this.executeReport = async function (reporterConfig, browser) {
225 const results = { exitCode: 0 }
226 const coverageMap = coverageMaps[browser.id]
227 if (!coverageMap) {
228 return
229 }
230
231 const mainDir = reporterConfig.dir || config.dir
232 const subDir = reporterConfig.subdir || config.subdir
233 const outputPath = generateOutputPath(basePath, browser.name, mainDir, subDir)
234 const remappedCoverageMap = await sourceMapStore.transformCoverage(coverageMap)
235
236 const options = helper.merge(config, reporterConfig, {
237 dir: outputPath,
238 subdir: '',
239 browser: browser,
240 emitter: emitter,
241 coverageMap: remappedCoverageMap
242 })
243
244 // If config.check is defined, check coverage levels for each browser
245 if (hasOwnProperty.call(config, 'check') && !checkedCoverage[browser.id]) {
246 checkedCoverage[browser.id] = true
247 var coverageFailed = checkCoverage(browser, remappedCoverageMap)
248 if (coverageFailed && results) {
249 results.exitCode = 1
250 }
251 }
252
253 const context = istanbulLibReport.createContext(options)
254 const report = reports.create(reporterConfig.type || 'html', options)
255
256 // // If reporting to console or in-memory skip directory creation
257 const toDisk = !reporterConfig.type || !reporterConfig.type.match(/^(text|text-summary|in-memory)$/)
258
259 if (!toDisk && reporterConfig.file === undefined) {
260 report.execute(context)
261 return
262 }
263
264 helper.mkdirIfNotExists(outputPath, function () {
265 log.debug('Writing coverage to %s', outputPath)
266 report.execute(context)
267 })
268 return results
269 }
270
271 this.onRunComplete = function (browsers) {
272 checkedCoverage = {}
273 let results = { exitCode: 0 }
274
275 const promiseCollection = reporters.map(reporterConfig =>
276 Promise.all(browsers.map(async (browser) => {
277 const res = await this.executeReport(reporterConfig, browser)
278 if (res && res.exitCode === 1) {
279 results = res
280 }
281 })))
282 promiseComplete = Promise.all(promiseCollection).then(() => results)
283 return promiseComplete
284 }
285
286 this.onExit = async function (done) {
287 const results = await promiseComplete
288 if (results && results.exitCode === 1) {
289 done(results.exitCode)
290 return
291 }
292 if (typeof config._onExit === 'function') {
293 config._onExit(done)
294 } else {
295 done()
296 }
297 }
298}
299
300CoverageReporter.$inject = ['config', 'helper', 'logger', 'emitter']
301
302// PUBLISH
303module.exports = CoverageReporter
Note: See TracBrowser for help on using the repository browser.