1 var path = require('path');
2 var fs = require('fs');
3 var util = require('util');
4 var istanbul = require('istanbul');
5 var dateformat = require('dateformat');
6 var globalSourceCache = require('./sourceCache');
9 var Store = istanbul.Store;
11 var SourceCacheStore = function(opts) {
12 Store.call(this, opts);
14 this.sourceCache = opts.sourceCache;
16 SourceCacheStore.TYPE = 'sourceCacheLookup';
17 util.inherits(SourceCacheStore, Store);
19 Store.mix(SourceCacheStore, {
21 throw 'not implemented';
24 return this.sourceCache[key];
26 hasKey : function(key) {
27 return this.sourceCache.hasOwnProperty(key);
29 set : function(key, contents) {
30 throw 'not applicable';
35 // TODO(vojta): inject only what required (config.basePath, config.coverageReporter)
36 var CoverageReporter = function(rootConfig, helper, logger) {
37 var log = logger.create('coverage');
38 var config = rootConfig.coverageReporter || {};
39 var basePath = rootConfig.basePath;
40 var reporters = config.reporters;
41 var sourceCache = globalSourceCache.getByBasePath(basePath);
43 if (!helper.isDefined(reporters)) {
49 var pendingFileWritings = 0;
50 var fileWritingFinished = function() {};
53 if (!--pendingFileWritings) {
55 Object.keys(collectors).forEach(function(key) {
56 collectors[key].dispose();
58 fileWritingFinished();
63 * Generate the output directory from the `coverageReporter.dir` and
64 * `coverageReporter.subdir` options.
66 * @param {String} browserName - The browser name
67 * @param {String} dir - The given option
68 * @param {String|Function} subdir - The given option
70 * @return {String} - The output directory
72 function generateOutputDir(browserName, dir, subdir) {
73 dir = dir || 'coverage';
74 subdir = subdir || browserName;
76 if (typeof subdir === 'function') {
77 subdir = subdir(browserName);
80 return path.join(dir, subdir);
83 this.onRunStart = function(browsers) {
84 collectors = Object.create(null);
86 // TODO(vojta): remove once we don't care about Karma 0.10
88 browsers.forEach(function(browser) {
89 collectors[browser.id] = new istanbul.Collector();
94 this.onBrowserStart = function(browser) {
95 collectors[browser.id] = new istanbul.Collector();
98 this.onBrowserComplete = function(browser, result) {
99 var collector = collectors[browser.id];
105 if (result && result.coverage) {
106 collector.add(result.coverage);
110 this.onSpecComplete = function(browser, result) {
111 if (result.coverage) {
112 collectors[browser.id].add(result.coverage);
116 this.onRunComplete = function(browsers) {
117 reporters.forEach(function(reporterConfig) {
118 browsers.forEach(function(browser) {
120 var collector = collectors[browser.id];
122 pendingFileWritings++;
124 var outputDir = helper.normalizeWinPath(path.resolve(basePath, generateOutputDir(browser.name,
125 reporterConfig.dir || config.dir,
126 reporterConfig.subdir || config.subdir)));
128 helper.mkdirIfNotExists(outputDir, function() {
129 log.debug('Writing coverage to %s', outputDir);
130 var options = helper.merge({}, reporterConfig, {
132 sourceStore : new SourceCacheStore({
133 sourceCache: sourceCache
136 var reporter = istanbul.Report.create(reporterConfig.type || 'html', options);
138 reporter.writeReport(collector, true);
150 this.onExit = function(done) {
151 if (pendingFileWritings) {
152 fileWritingFinished = done;
159 CoverageReporter.$inject = ['config', 'helper', 'logger'];
162 module.exports = CoverageReporter;