Skip to content

Commit

Permalink
Add #1 and folder-summary.json output to text-folders report
Browse files Browse the repository at this point in the history
  • Loading branch information
moos committed Jul 8, 2020
1 parent 24ec482 commit fe96bc7
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 48 deletions.
21 changes: 21 additions & 0 deletions lib/assets/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ a:hover { text-decoration:underline; }
visibility:hidden;
}
.fl { float: left; }
.fr { float: right; }
@media only screen and (max-width:640px) {
.col3 { width:100%; max-width:100%; }
.hide-mobile { display:none!important; }
Expand Down Expand Up @@ -211,3 +212,23 @@ pre.prettyprint {
.footer, .push {
height: 48px;
}

#depthSlider {
width: 7em;
}

tr.recursive {
display: none;
}
body.normal tr.recursive {
display: none;
}
.recursive .recursive {
display: table-row;
}
body.recursive tr.shallow {
display: none !important;
}
.recursive_cb {
width: 50%;
}
6 changes: 5 additions & 1 deletion lib/assets/sorter.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,8 @@ var addSorting = (function () {
};
})();

window.addEventListener('load', addSorting);
if (window.addEventListener) {
window.addEventListener('load', addSorting);
} else {
window.attachEvent('onload', addSorting);
}
7 changes: 2 additions & 5 deletions lib/command/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ Command.mix(ReportCommand, {
formatOption('--include <glob>', 'The glob pattern to select one or more coverage files, defaults to **/coverage*.json'),
formatOption('--depth <depth>', 'depth to show for detail reports (0 unlimited)'),
formatOption('--match <string>', 'pattern to match path to show for detail reports'),
formatOption('--relative', 'Use relative path in lcov report (default: false)'),
formatOption('--verbose, -v', 'verbose mode')
].join('\n\n'));

Expand All @@ -73,8 +72,7 @@ Command.mix(ReportCommand, {
include: String,
verbose: Boolean,
depth: Number,
match: String,
relative: Boolean
match: String
},
opts = nopt(template, { v : '--verbose' }, args, 0),
includePattern = opts.include || '**/coverage*.json',
Expand All @@ -85,8 +83,7 @@ Command.mix(ReportCommand, {
reporting: {
dir: opts.dir,
depth: opts.depth,
match: opts.match,
relative: opts.relative
match: opts.match
}
}),
formats = opts.argv.remain,
Expand Down
5 changes: 2 additions & 3 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ function defaultConfig(includeBackCompatAttrs) {
reports: [ 'lcov' ],
dir: './coverage',
depth: 0,
match: '',
relative: false
match: ''
},
hooks: {
'hook-run-in-context': false,
Expand Down Expand Up @@ -264,7 +263,7 @@ function ReportingOptions(config) {
* @method reportConfig
* @return {Object} detailed report configuration per report format.
*/
addMethods(ReportingOptions, 'print', 'reports', 'dir', 'reportConfig','depth', 'match', 'relative');
addMethods(ReportingOptions, 'print', 'reports', 'dir', 'reportConfig','depth', 'match');

function isInvalidMark(v, key) {
var prefix = 'Watermark for [' + key + '] :';
Expand Down
86 changes: 61 additions & 25 deletions lib/report/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ var handlebars = require('handlebars').create(),
'<td class="text"><pre class="prettyprint lang-js">{{#show_code structured}}{{/show_code}}</pre></td>',
'</tr>\n'
].join('')),
summaryTableHeader = [
summaryTableHeader = handlebars.compile([
'<div class="pad1">',
'<table class="coverage-summary">',
'<thead>',
'<tr>',
' <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>',
' <th data-col="file" data-fmt="html" data-html="true" class="file">{{#show_recursive isRoot}}{{/show_recursive}}File</th>',
' <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>',
' <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>',
' <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>',
Expand All @@ -43,9 +43,9 @@ var handlebars = require('handlebars').create(),
'</tr>',
'</thead>',
'<tbody>'
].join('\n'),
].join('\n')),
summaryLineTemplate = handlebars.compile([
'<tr>',
'<tr class="depth-{{depth}} {{recursive}}">',
'<td class="file {{reportClasses.statements}}" data-value="{{file}}"><a href="{{output}}">{{file}}</a></td>',
'<td data-value="{{metrics.statements.pct}}" class="pic {{reportClasses.statements}}"><div class="chart">{{#show_picture}}{{metrics.statements.pct}}{{/show_picture}}</div></td>',
'<td data-value="{{metrics.statements.pct}}" class="pct {{reportClasses.statements}}">{{metrics.statements.pct}}%</td>',
Expand All @@ -69,7 +69,8 @@ var handlebars = require('handlebars').create(),
RE_GT = />/g,
RE_AMP = /&/g,
RE_lt = /\u0001/g,
RE_gt = /\u0002/g;
RE_gt = /\u0002/g,
SEP = path.sep || '/';

handlebars.registerHelper('show_picture', function (opts) {
var num = Number(opts.fn(this)),
Expand Down Expand Up @@ -326,6 +327,30 @@ function isEmptySourceStore(sourceStore) {
return cache && !Object.keys(cache).length;
}

handlebars.registerHelper('show_recursive', function(isRoot){
if (!isRoot) { return '';}
return '<div class="fr recursive_cb" title="show recursive folder totals">' +
'<input type="checkbox" id="recursive" onclick="onRecursiveChange(null, event)" onchange="onRecursiveChange(this.checked, event)" />' +
'<label for="recursive" class="quiet" onclick="onRecursiveChange(null, event)">recursive totals</label>' +
'</div>';
});

handlebars.registerHelper('depth_styles', function () {
var maxDepth = 10,
lazyLoop = Array(maxDepth + 1).join().split(','),
depth = 0,
getStyle = function (ignore, index) {
if (!index) { return ''; }
var val = depth && index > depth ? 'none' : 'table-row;';
return '.depth-' + index + '{display:' + val + '} ';
},
getAtStyle = function (ignore, index) {
depth = index;
return lazyLoop.map(getStyle).join('.at-depth-' + depth + ' ');
};
return '<style type="text/css">' + lazyLoop.map(getAtStyle).join('\n') + '</style>';
});

/**
* a `Report` implementation that produces HTML coverage reports.
*
Expand Down Expand Up @@ -438,46 +463,57 @@ Report.mix(HtmlReport, {
writer.write(footerTemplate(templateData));
},

writeIndexPage: function (writer, node) {
writeIndexPage: function (writer, node, isRoot) {
var linkMapper = this.opts.linkMapper,
templateData = this.opts.templateData,
children = Array.prototype.slice.apply(node.children),
watermarks = this.opts.watermarks;
watermarks = this.opts.watermarks,
maxDepth = 0,
_writeRow = function (child, metrics, recursive) {
var reportClasses = {
statements: getReportClass(metrics.statements, watermarks.statements),
lines: getReportClass(metrics.lines, watermarks.lines),
functions: getReportClass(metrics.functions, watermarks.functions),
branches: getReportClass(metrics.branches, watermarks.branches)
},
data = {
metrics: metrics,
reportClasses: reportClasses,
file: cleanPath(child.displayShortName()),
output: linkMapper.fromParent(child),
depth: isRoot ? child.name.split(SEP).length - 1 : 0,
recursive: recursive ? 'recursive' : 'shallow'
};
if (data.depth > maxDepth) { maxDepth = data.depth; }
writer.write(summaryLineTemplate(data) + '\n');
};

children.sort(function (a, b) {
return a.name < b.name ? -1 : 1;
});
templateData.isRoot = isRoot;

this.fillTemplate(node, templateData);
writer.write(headerTemplate(templateData));
writer.write(summaryTableHeader);
writer.write(summaryTableHeader(templateData));
children.forEach(function (child) {
var metrics = child.metrics,
reportClasses = {
statements: getReportClass(metrics.statements, watermarks.statements),
lines: getReportClass(metrics.lines, watermarks.lines),
functions: getReportClass(metrics.functions, watermarks.functions),
branches: getReportClass(metrics.branches, watermarks.branches)
},
data = {
metrics: metrics,
reportClasses: reportClasses,
file: cleanPath(child.displayShortName()),
output: linkMapper.fromParent(child)
};
writer.write(summaryLineTemplate(data) + '\n');
_writeRow(child, child.metrics, false);
if (isRoot) { // write recursive metrics
_writeRow(child, child.recursiveMetrics, true);
}
});
templateData.maxDepth = maxDepth;
writer.write(summaryTableFooter);
writer.write(footerTemplate(templateData));
},

writeFiles: function (writer, node, dir, collector) {
writeFiles: function (writer, node, dir, collector, isRoot) {
var that = this,
indexFile = path.resolve(dir, 'index.html'),
childFile;
if (this.opts.verbose) { console.error('Writing ' + indexFile); }
writer.writeFile(indexFile, function (contentWriter) {
that.writeIndexPage(contentWriter, node);
that.writeIndexPage(contentWriter, node, isRoot);
});
node.children.forEach(function (child) {
if (child.kind === 'dir') {
Expand Down Expand Up @@ -563,7 +599,7 @@ Report.mix(HtmlReport, {
});
writer.on('done', function () { that.emit('done'); });
//console.log(JSON.stringify(tree.root, undefined, 4));
this.writeFiles(writer, tree.root, dir, collector);
this.writeFiles(writer, tree.root, dir, collector, true);
writer.done();
}
});
Expand Down
2 changes: 1 addition & 1 deletion lib/report/lcov.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function LcovReport(opts) {
htmlDir = path.resolve(baseDir, 'lcov-report');

mkdirp.sync(baseDir);
this.lcov = new LcovOnlyReport({ dir: baseDir, watermarks: opts.watermarks, relative: opts.relative});
this.lcov = new LcovOnlyReport({ dir: baseDir, watermarks: opts.watermarks });
this.html = new HtmlReport({ dir: htmlDir, watermarks: opts.watermarks, sourceStore: opts.sourceStore});
}

Expand Down
4 changes: 1 addition & 3 deletions lib/report/lcovonly.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ var path = require('path'),
* @constructor
* @param {Object} opts optional
* @param {String} [opts.dir] the directory in which to the `lcov.info` file. Defaults to `process.cwd()`
* @param {Boolean} [opts.relative] If true paths reported will be relative to `process.cwd()`. Defaults to `false`
*/
function LcovOnlyReport(opts) {
this.opts = opts || {};
this.opts.dir = this.opts.dir || process.cwd();
this.opts.relative = this.opts.relative || false;
this.opts.file = this.opts.file || this.getDefaultConfig().file;
this.opts.writer = this.opts.writer || null;
}
Expand All @@ -51,7 +49,7 @@ Report.mix(LcovOnlyReport, {
summary = utils.summarizeFileCoverage(fc);

writer.println('TN:'); //no test name
writer.println('SF:' + (this.opts.relative ? path.relative(process.cwd(), fc.path) : fc.path));
writer.println('SF:' + fc.path);

Object.keys(functions).forEach(function (key) {
var meta = functionMap[key];
Expand Down
10 changes: 7 additions & 3 deletions lib/report/templates/foot.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
{{#if prettify}}
<script src="{{prettify.js}}"></script>
<script>
var maxDepth = {{maxDepth}};
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
if (typeof prettyPrint === 'function') {
prettyPrint();
}

var slider = document.querySelector('#depthSlider');
if (slider) { slider.max = slider.value = maxDepth; }
};
</script>
{{/if}}
Expand Down
37 changes: 36 additions & 1 deletion lib/report/templates/head.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,45 @@
background-image: url({{sorter.image}});
}
</style>
{{#if isRoot}}
<script>
function onDepthChange(value){
document.body.className = document.body.className.replace(/\s*at-depth-\d+/,'') + ' at-depth-' + value;
}
function onRecursiveChange(checked, event){
var ie8 = /MSIE 8/.test(navigator.userAgent);
if (checked === null && !ie8) { // prevent sorter clicks
if(event.stopPropagation) {
event.stopPropagation();
} else {
event.returnValue = false;
}
return false;
}
if (ie8) event.srcElement.blur();
toggleClass(document.body, 'normal');
toggleClass(document.body, 'recursive');
}
function toggleClass(el, name) {
if (el.className.indexOf(name) > -1) {
el.className = el.className.replace(name, '');
} else {
el.className += ' ' + name;
}
}
</script>
{{#depth_styles}}{{/depth_styles}}
{{/if}}
</head>
<body>
<body class="normal">
<div class='wrapper'>
<div class='pad1'>
{{#if isRoot}}
<div class='fr space-right2'>
<label for="depthSlider" class="quiet">show depth</label>
<input type="range" id="depthSlider" min="1" max="10" oninput="onDepthChange(value)" onchange="onDepthChange(value)"/>
</div>
{{/if}}
<h1>
{{{pathHtml}}}
</h1>
Expand Down
20 changes: 16 additions & 4 deletions lib/report/text-folders.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/

var
var path = require('path'),
util = require('util'),
fs = require('fs'),
mkdirp = require('mkdirp'),
TextReport = require('./text');

/**
Expand All @@ -21,8 +23,9 @@ var
* @param {Object} opts - see TextReport
*/
function TextFolderReport(opts) {
TextReport.call(this);
this.opts = opts || {};
TextReport.call(this, opts);
this.opts.rawMetrics = {};
this.opts.file = 'folder-summary.json';
}

TextFolderReport.TYPE = 'text-folders';
Expand All @@ -33,7 +36,16 @@ TextReport.super_.mix(TextFolderReport, {
node_type: 'dir',

synopsis: function () {
return 'text report that prints a coverage line for every /folder/, typically to console';
return 'text report that prints a coverage line for every /folder/, to console and as JSON file';
},

writeReport: function () {
TextFolderReport.super_.prototype.writeReport.apply(this, arguments);

if (this.opts.file) {
mkdirp.sync(this.dir);
fs.writeFileSync(path.join(this.dir, this.opts.file), JSON.stringify(this.opts.rawMetrics), 'utf8');
}
}
});

Expand Down
Loading

0 comments on commit fe96bc7

Please sign in to comment.