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 | };
|
---|