195 lines
6.3 KiB
JavaScript
195 lines
6.3 KiB
JavaScript
|
JSCovFileReporter = Backbone.View.extend({
|
||
|
initialize: function () {
|
||
|
_.bindAll(this);
|
||
|
this.open = '<tr class="{class}"><td class="line">{line_number}</td><td class="hits">{count}</td><td class="source">';
|
||
|
this.close = '</td></tr>';
|
||
|
|
||
|
this.coverObject = this.options.coverObject;
|
||
|
|
||
|
this.error = 0;
|
||
|
this.pass = 0;
|
||
|
this.total = 0;
|
||
|
},
|
||
|
|
||
|
// substitute credits: MooTools
|
||
|
substitute: function(string, object){
|
||
|
return string.replace(/\\?\{([^{}]+)\}/g, function(match, name){
|
||
|
if (match.charAt(0) == '\\') return match.slice(1);
|
||
|
return (object[name] !== null) ? object[name] : '';
|
||
|
});
|
||
|
},
|
||
|
|
||
|
generateClose: function(count){
|
||
|
return this.substitute(this.close, {
|
||
|
count: count
|
||
|
});
|
||
|
},
|
||
|
|
||
|
generateOpen: function(hit_count, line_number){
|
||
|
return this.substitute(this.open, {
|
||
|
'count': hit_count,
|
||
|
'line_number': line_number,
|
||
|
'class': hit_count ? 'hit' : 'miss'
|
||
|
});
|
||
|
},
|
||
|
|
||
|
report: function () {
|
||
|
var thisview = this;
|
||
|
var i, l, k;
|
||
|
|
||
|
var code = this.coverObject.__code;
|
||
|
|
||
|
// generate array of all tokens
|
||
|
var codez = [];
|
||
|
for (i = 0, l = code.length; i < l; i++){
|
||
|
codez.push({
|
||
|
pos: i,
|
||
|
value: code.slice(i, i + 1)
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// CoverObject has keys like "12:200" which means from char 12 to 200
|
||
|
// This orders all first gaps in a list of dictionaries to ease drawing table lines
|
||
|
var gaps = Object.keys(this.coverObject);
|
||
|
gaps = _.without(gaps, '__code');
|
||
|
var first_gaps = _.map(gaps, function ( gap ) {
|
||
|
return {
|
||
|
gap: parseInt(gap.split(':')[0], 10),
|
||
|
hit_count: thisview.coverObject[gap]
|
||
|
};
|
||
|
}).sort(function (a, b) {
|
||
|
if (a['gap'] > b['gap']) return 1;
|
||
|
if (b['gap'] > a['gap']) return -1;
|
||
|
return 0;
|
||
|
});
|
||
|
|
||
|
var second_gaps = _.map(gaps, function ( gap ) {
|
||
|
return {
|
||
|
gap: parseInt(gap.split(':')[1], 10),
|
||
|
hit_count: thisview.coverObject[gap]
|
||
|
};
|
||
|
}).sort(function (a, b) {
|
||
|
if (a['gap'] > b['gap']) return 1;
|
||
|
if (b['gap'] > a['gap']) return -1;
|
||
|
return 0;
|
||
|
});
|
||
|
|
||
|
|
||
|
// If it doesn't start from 0 it's because there are comments in the beginning
|
||
|
// We add a initial gap with one hit
|
||
|
if (first_gaps[0] !== 0) {
|
||
|
first_gaps.splice(0, 0, {gap: 0, hit_count: 1});
|
||
|
}
|
||
|
|
||
|
var result = '';
|
||
|
var number_trailing_whitespaces = 0;
|
||
|
var trailing_whitespaces = '';
|
||
|
|
||
|
|
||
|
// We will go from one gap to the next wrapping them in table lines
|
||
|
for (i=0, l = first_gaps.length; i < l; i++){
|
||
|
|
||
|
var hit_count = first_gaps[i]['hit_count'];
|
||
|
|
||
|
this.total++;
|
||
|
if (hit_count) this.pass++;
|
||
|
else this.error++;
|
||
|
|
||
|
var limit = null;
|
||
|
if (i+1 >= l) {
|
||
|
limit = codez.length;
|
||
|
}
|
||
|
else {
|
||
|
limit = first_gaps[i+1]['gap'];
|
||
|
}
|
||
|
|
||
|
// Table line opening
|
||
|
result += this.generateOpen(hit_count, this.total);
|
||
|
|
||
|
// Add trailing white space if it existed from previous line without carriage returns
|
||
|
if (number_trailing_whitespaces > 0 ) {
|
||
|
result += trailing_whitespaces.replace(/(\r\n|\n|\r)/gm,"");
|
||
|
}
|
||
|
|
||
|
// Add lines of code without initial white spaces, and replacing conflictive chars
|
||
|
result += _.map(codez.slice(first_gaps[i]['gap'], limit), function (loc) {
|
||
|
return loc['value'];
|
||
|
}).join('').trimLeft().replace(/</g, '<').replace(/>/g, '>');
|
||
|
|
||
|
// Count trailing white spaces for future line, then remove them
|
||
|
var matches = result.match(/(\s+)$/);
|
||
|
result = result.trimRight();
|
||
|
|
||
|
if (matches !== null) {
|
||
|
number_trailing_whitespaces = matches[0].length;
|
||
|
trailing_whitespaces = matches[0];
|
||
|
}
|
||
|
else {
|
||
|
number_trailing_whitespaces = 0;
|
||
|
}
|
||
|
|
||
|
// Generate table line closing
|
||
|
result += this.generateClose(hit_count);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
JSCovReporter = Backbone.View.extend({
|
||
|
initialize: function () {
|
||
|
this.coverObject = this.options.coverObject;
|
||
|
|
||
|
// Generate the report
|
||
|
this.report();
|
||
|
|
||
|
// Activate reporter.js scrolling UX
|
||
|
onload();
|
||
|
},
|
||
|
|
||
|
report: function () {
|
||
|
var result = '';
|
||
|
var index = '';
|
||
|
|
||
|
for (var file in this.coverObject) {
|
||
|
var fileReporter = new JSCovFileReporter({ coverObject: this.coverObject[file] });
|
||
|
|
||
|
var fileReport = fileReporter.report();
|
||
|
var percentage = Math.round(fileReporter.pass / fileReporter.total * 100);
|
||
|
|
||
|
this.error += fileReporter.error;
|
||
|
this.pass += fileReporter.pass;
|
||
|
this.total += fileReporter.total;
|
||
|
|
||
|
var type_coverage = "high";
|
||
|
if (percentage < 75 && percentage >= 50) {
|
||
|
type_coverage = 'medium';
|
||
|
}
|
||
|
else if (percentage < 50 && percentage >= 25) {
|
||
|
type_coverage = 'low';
|
||
|
}
|
||
|
else if (percentage < 25) {
|
||
|
type_coverage = 'terrible';
|
||
|
}
|
||
|
|
||
|
// Title
|
||
|
result += '<h2 id="' + file + '" class="file-title">' + file + '</h2>';
|
||
|
// Stats
|
||
|
result += '<div class="stats ' + type_coverage + '"><div class="percentage">'+ percentage + '%</div>';
|
||
|
result += '<div class="sloc">' + fileReporter.total + '</div><div class="hits">' + fileReporter.pass + '</div>';
|
||
|
result += '<div class="misses">' + fileReporter.error + '</div></div>';
|
||
|
// Report
|
||
|
result += '<div class="file-report">';
|
||
|
result += '<table id="source"><tbody>' + fileReport + '</tbody></table>';
|
||
|
result += '</div>';
|
||
|
|
||
|
// Menu index
|
||
|
index += '<li><span class="cov ' + type_coverage + '">' + percentage + '</span><a href="#' + file+ '">' + file + '</a></li>';
|
||
|
}
|
||
|
|
||
|
$('#coverage').html(result);
|
||
|
$('#menu').html('<ul id="toc">' + index + '</ul>');
|
||
|
}
|
||
|
});
|