coverage-map.js
1 /* 2 Copyright 2012-2015, Yahoo Inc. 3 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. 4 */ 5 'use strict'; 6 7 const { FileCoverage } = require('./file-coverage'); 8 const { CoverageSummary } = require('./coverage-summary'); 9 10 function maybeConstruct(obj, klass) { 11 if (obj instanceof klass) { 12 return obj; 13 } 14 15 return new klass(obj); 16 } 17 18 function loadMap(source) { 19 const data = Object.create(null); 20 if (!source) { 21 return data; 22 } 23 24 Object.entries(source).forEach(([k, cov]) => { 25 data[k] = maybeConstruct(cov, FileCoverage); 26 }); 27 28 return data; 29 } 30 31 /** CoverageMap is a map of `FileCoverage` objects keyed by file paths. */ 32 class CoverageMap { 33 /** 34 * @constructor 35 * @param {Object} [obj=undefined] obj A coverage map from which to initialize this 36 * map's contents. This can be the raw global coverage object. 37 */ 38 constructor(obj) { 39 if (obj instanceof CoverageMap) { 40 this.data = obj.data; 41 } else { 42 this.data = loadMap(obj); 43 } 44 } 45 46 /** 47 * merges a second coverage map into this one 48 * @param {CoverageMap} obj - a CoverageMap or its raw data. Coverage is merged 49 * correctly for the same files and additional file coverage keys are created 50 * as needed. 51 */ 52 merge(obj) { 53 const other = maybeConstruct(obj, CoverageMap); 54 Object.values(other.data).forEach(fc => { 55 this.addFileCoverage(fc); 56 }); 57 } 58 59 /** 60 * filter the coveragemap based on the callback provided 61 * @param {Function (filename)} callback - Returns true if the path 62 * should be included in the coveragemap. False if it should be 63 * removed. 64 */ 65 filter(callback) { 66 Object.keys(this.data).forEach(k => { 67 if (!callback(k)) { 68 delete this.data[k]; 69 } 70 }); 71 } 72 73 /** 74 * returns a JSON-serializable POJO for this coverage map 75 * @returns {Object} 76 */ 77 toJSON() { 78 return this.data; 79 } 80 81 /** 82 * returns an array for file paths for which this map has coverage 83 * @returns {Array{string}} - array of files 84 */ 85 files() { 86 return Object.keys(this.data); 87 } 88 89 /** 90 * returns the file coverage for the specified file. 91 * @param {String} file 92 * @returns {FileCoverage} 93 */ 94 fileCoverageFor(file) { 95 const fc = this.data[file]; 96 if (!fc) { 97 throw new Error(`No file coverage available for: ${file}`); 98 } 99 return fc; 100 } 101 102 /** 103 * adds a file coverage object to this map. If the path for the object, 104 * already exists in the map, it is merged with the existing coverage 105 * otherwise a new key is added to the map. 106 * @param {FileCoverage} fc the file coverage to add 107 */ 108 addFileCoverage(fc) { 109 const cov = new FileCoverage(fc); 110 const { path } = cov; 111 if (this.data[path]) { 112 this.data[path].merge(cov); 113 } else { 114 this.data[path] = cov; 115 } 116 } 117 118 /** 119 * returns the coverage summary for all the file coverage objects in this map. 120 * @returns {CoverageSummary} 121 */ 122 getCoverageSummary() { 123 const ret = new CoverageSummary(); 124 Object.values(this.data).forEach(fc => { 125 ret.merge(fc.toSummary()); 126 }); 127 128 return ret; 129 } 130 } 131 132 module.exports = { 133 CoverageMap 134 };