Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80679 views
1
/*
2
Copyright (c) 2012, Yahoo! Inc. All rights reserved.
3
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
4
*/
5
6
var path = require('path'),
7
mkdirp = require('mkdirp'),
8
util = require('util'),
9
fs = require('fs'),
10
defaults = require('./common/defaults'),
11
Report = require('./index'),
12
TreeSummarizer = require('../util/tree-summarizer'),
13
utils = require('../object-utils'),
14
PCT_COLS = 10,
15
TAB_SIZE = 3,
16
DELIM = ' |',
17
COL_DELIM = '-|';
18
19
/**
20
* a `Report` implementation that produces text output in a detailed table.
21
*
22
* Usage
23
* -----
24
*
25
* var report = require('istanbul').Report.create('text');
26
*
27
* @class TextReport
28
* @extends Report
29
* @module report
30
* @constructor
31
* @param {Object} opts optional
32
* @param {String} [opts.dir] the directory in which to the text coverage report will be written, when writing to a file
33
* @param {String} [opts.file] the filename for the report. When omitted, the report is written to console
34
* @param {Number} [opts.maxCols] the max column width of the report. By default, the width of the report is adjusted based on the length of the paths
35
* to be reported.
36
*/
37
function TextReport(opts) {
38
Report.call(this);
39
opts = opts || {};
40
this.dir = opts.dir || process.cwd();
41
this.file = opts.file;
42
this.summary = opts.summary;
43
this.maxCols = opts.maxCols || 0;
44
this.watermarks = opts.watermarks || defaults.watermarks();
45
}
46
47
TextReport.TYPE = 'text';
48
util.inherits(TextReport, Report);
49
50
function padding(num, ch) {
51
var str = '',
52
i;
53
ch = ch || ' ';
54
for (i = 0; i < num; i += 1) {
55
str += ch;
56
}
57
return str;
58
}
59
60
function fill(str, width, right, tabs, clazz) {
61
tabs = tabs || 0;
62
str = String(str);
63
64
var leadingSpaces = tabs * TAB_SIZE,
65
remaining = width - leadingSpaces,
66
leader = padding(leadingSpaces),
67
fmtStr = '',
68
fillStr,
69
strlen = str.length;
70
71
if (remaining > 0) {
72
if (remaining >= strlen) {
73
fillStr = padding(remaining - strlen);
74
fmtStr = right ? fillStr + str : str + fillStr;
75
} else {
76
fmtStr = str.substring(strlen - remaining);
77
fmtStr = '... ' + fmtStr.substring(4);
78
}
79
}
80
81
fmtStr = defaults.colorize(fmtStr, clazz);
82
return leader + fmtStr;
83
}
84
85
function formatName(name, maxCols, level, clazz) {
86
return fill(name, maxCols, false, level, clazz);
87
}
88
89
function formatPct(pct, clazz) {
90
return fill(pct, PCT_COLS, true, 0, clazz);
91
}
92
93
function nodeName(node) {
94
return node.displayShortName() || 'All files';
95
}
96
97
98
function tableHeader(maxNameCols) {
99
var elements = [];
100
elements.push(formatName('File', maxNameCols, 0));
101
elements.push(formatPct('% Stmts'));
102
elements.push(formatPct('% Branches'));
103
elements.push(formatPct('% Funcs'));
104
elements.push(formatPct('% Lines'));
105
return elements.join(' |') + ' |';
106
}
107
108
function tableRow(node, maxNameCols, level, watermarks) {
109
var name = nodeName(node),
110
statements = node.metrics.statements.pct,
111
branches = node.metrics.branches.pct,
112
functions = node.metrics.functions.pct,
113
lines = node.metrics.lines.pct,
114
elements = [];
115
116
elements.push(formatName(name, maxNameCols, level, defaults.classFor('statements', node.metrics, watermarks)));
117
elements.push(formatPct(statements, defaults.classFor('statements', node.metrics, watermarks)));
118
elements.push(formatPct(branches, defaults.classFor('branches', node.metrics, watermarks)));
119
elements.push(formatPct(functions, defaults.classFor('functions', node.metrics, watermarks)));
120
elements.push(formatPct(lines, defaults.classFor('lines', node.metrics, watermarks)));
121
122
return elements.join(DELIM) + DELIM;
123
}
124
125
function findNameWidth(node, level, last) {
126
last = last || 0;
127
level = level || 0;
128
var idealWidth = TAB_SIZE * level + nodeName(node).length;
129
if (idealWidth > last) {
130
last = idealWidth;
131
}
132
node.children.forEach(function (child) {
133
last = findNameWidth(child, level + 1, last);
134
});
135
return last;
136
}
137
138
function makeLine(nameWidth) {
139
var name = padding(nameWidth, '-'),
140
pct = padding(PCT_COLS, '-'),
141
elements = [];
142
143
elements.push(name);
144
elements.push(pct);
145
elements.push(pct);
146
elements.push(pct);
147
elements.push(pct);
148
return elements.join(COL_DELIM) + COL_DELIM;
149
}
150
151
function walk(node, nameWidth, array, level, watermarks) {
152
var line;
153
if (level === 0) {
154
line = makeLine(nameWidth);
155
array.push(line);
156
array.push(tableHeader(nameWidth));
157
array.push(line);
158
} else {
159
array.push(tableRow(node, nameWidth, level, watermarks));
160
}
161
node.children.forEach(function (child) {
162
walk(child, nameWidth, array, level + 1, watermarks);
163
});
164
if (level === 0) {
165
array.push(line);
166
array.push(tableRow(node, nameWidth, level, watermarks));
167
array.push(line);
168
}
169
}
170
171
Report.mix(TextReport, {
172
synopsis: function () {
173
return 'text report that prints a coverage line for every file, typically to console';
174
},
175
getDefaultConfig: function () {
176
return { file: null, maxCols: 0 };
177
},
178
writeReport: function (collector /*, sync */) {
179
var summarizer = new TreeSummarizer(),
180
tree,
181
root,
182
nameWidth,
183
statsWidth = 4 * ( PCT_COLS + 2),
184
maxRemaining,
185
strings = [],
186
text;
187
188
collector.files().forEach(function (key) {
189
summarizer.addFileCoverageSummary(key, utils.summarizeFileCoverage(collector.fileCoverageFor(key)));
190
});
191
tree = summarizer.getTreeSummary();
192
root = tree.root;
193
nameWidth = findNameWidth(root);
194
if (this.maxCols > 0) {
195
maxRemaining = this.maxCols - statsWidth - 2;
196
if (nameWidth > maxRemaining) {
197
nameWidth = maxRemaining;
198
}
199
}
200
walk(root, nameWidth, strings, 0, this.watermarks);
201
text = strings.join('\n') + '\n';
202
if (this.file) {
203
mkdirp.sync(this.dir);
204
fs.writeFileSync(path.join(this.dir, this.file), text, 'utf8');
205
} else {
206
console.log(text);
207
}
208
this.emit('done');
209
}
210
});
211
212
module.exports = TextReport;
213
214