UNPKG

blanket

Version:
335 lines (293 loc) 15.6 kB
blanket.defaultReporter = function(coverage){ var cssSytle = "#blanket-main {margin:2px;background:#EEE;color:#333;clear:both;font-family:'Helvetica Neue Light', 'HelveticaNeue-Light', 'Helvetica Neue', Calibri, Helvetica, Arial, sans-serif; font-size:17px;} #blanket-main a {color:#333;text-decoration:none;} #blanket-main a:hover {text-decoration:underline;} .blanket {margin:0;padding:5px;clear:both;border-bottom: 1px solid #FFFFFF;} .bl-error {color:red;}.bl-success {color:#5E7D00;} .bl-file{width:auto;} .bl-cl{float:left;} .blanket div.rs {margin-left:50px; width:150px; float:right} .bl-nb {padding-right:10px;} #blanket-main a.bl-logo {color: #EB1764;cursor: pointer;font-weight: bold;text-decoration: none} .bl-source{ overflow-x:scroll; background-color: #FFFFFF; border: 1px solid #CBCBCB; color: #363636; margin: 25px 20px; width: 80%;} .bl-source div{white-space: pre;font-family: monospace;} .bl-source > div > span:first-child{background-color: #EAEAEA;color: #949494;display: inline-block;padding: 0 10px;text-align: center;width: 30px;} .bl-source .hit{background-color:#c3e6c7} .bl-source .miss{background-color:#e6c3c7} .bl-source span.branchWarning{color:#000;background-color:yellow;} .bl-source span.branchOkay{color:#000;background-color:transparent;}", successRate = 60, head = document.head, fileNumber = 0, body = document.body, headerContent, hasBranchTracking = Object.keys(coverage.files).some(function(elem){ return typeof coverage.files[elem].branchData !== 'undefined'; }), bodyContent = "<table id='blanket-main'><tr><th class='blanket bl-title'><th class='bl-cl bl-file'><a href='http://alex-seville.github.com/blanket/' target='_blank' class='bl-logo'>Blanket.js</a> results</th><th class='bl-cl rs'>Coverage (%)</th><th class='bl-cl rs'>Covered/Total Smts.</th>"+(hasBranchTracking ? "<th class='bl-cl rs'>Covered/Total Branches</th>":"")+"<th style='clear:both;'></th></tr></table>", fileTemplate = "<tr><td class='blanket {{statusclass}}'><td class='bl-cl bl-file'><span class='bl-nb'>{{fileNumber}}.</span><a href='javascript:blanket_toggleSource(\"file-{{fileNumber}}\")'>{{file}}</a></td><td class='bl-cl rs'>{{percentage}} %</td><td class='bl-cl rs'>{{numberCovered}}/{{totalSmts}}</td>"+( hasBranchTracking ? "<td class='bl-cl rs'>{{passedBranches}}/{{totalBranches}}</td>" : "" )+"<td id='file-{{fileNumber}}' class='bl-source' style='display:none;'>{{source}}</td><td style='clear:both;'></td></td></tr>"; grandTotalTemplate = "<tr><td class='blanket grand-total {{statusclass}}'><td class='bl-cl'>{{rowTitle}}</td><td class='bl-cl rs'>{{percentage}} %</td><td class='bl-cl rs'>{{numberCovered}}/{{totalSmts}}</td>"+( hasBranchTracking ? "<td class='bl-cl rs'>{{passedBranches}}/{{totalBranches}}</td>" : "" ) + "<td style='clear:both;'></td></td></tr>"; function blanket_toggleSource(id) { var element = document.getElementById(id); if(element.style.display === 'block') { element.style.display = 'none'; } else { element.style.display = 'block'; } } var script = document.createElement("script"); script.type = "text/javascript"; script.text = blanket_toggleSource.toString().replace('function ' + blanket_toggleSource.name, 'function blanket_toggleSource'); body.appendChild(script); var percentage = function(number, total) { return (Math.round(((number/total) * 100)*100)/100); }; var appendTag = function (type, el, str) { var dom = document.createElement(type); dom.innerHTML = str; el.appendChild(dom); }; function escapeInvalidXmlChars(str) { return str.replace(/\&/g, "&amp;") .replace(/</g, "&lt;") .replace(/\>/g, "&gt;") .replace(/\"/g, "&quot;") .replace(/\'/g, "&apos;") .replace(/`/g, "&grave;") .replace(/[$]/g, "&dollar;"); } function isBranchFollowed(data,bool){ var mode = bool ? 0 : 1; if (typeof data === 'undefined' || typeof data === null || typeof data[mode] === 'undefined'){ return false; } return data[mode].length > 0; } var branchStack = []; function branchReport(colsIndex,src,cols,offset,lineNum){ var newsrc=""; var postfix=""; if (branchStack.length > 0){ newsrc += "<span class='" + (isBranchFollowed(branchStack[0][1],branchStack[0][1].consequent === branchStack[0][0]) ? 'branchOkay' : 'branchWarning') + "'>"; if (branchStack[0][0].end.line === lineNum){ newsrc += escapeInvalidXmlChars(src.slice(0,branchStack[0][0].end.column)) + "</span>"; src = src.slice(branchStack[0][0].end.column); branchStack.shift(); if (branchStack.length > 0){ newsrc += "<span class='" + (isBranchFollowed(branchStack[0][1],false) ? 'branchOkay' : 'branchWarning') + "'>"; if (branchStack[0][0].end.line === lineNum){ newsrc += escapeInvalidXmlChars(src.slice(0,branchStack[0][0].end.column)) + "</span>"; src = src.slice(branchStack[0][0].end.column); branchStack.shift(); if (!cols){ return {src: newsrc + escapeInvalidXmlChars(src) ,cols:cols}; } } else if (!cols){ return {src: newsrc + escapeInvalidXmlChars(src) + "</span>",cols:cols}; } else{ postfix = "</span>"; } }else if (!cols){ return {src: newsrc + escapeInvalidXmlChars(src) ,cols:cols}; } }else if(!cols){ return {src: newsrc + escapeInvalidXmlChars(src) + "</span>",cols:cols}; }else{ postfix = "</span>"; } } var thisline = cols[colsIndex]; //consequent var cons = thisline.consequent; if (cons.start.line > lineNum){ branchStack.unshift([thisline.alternate,thisline]); branchStack.unshift([cons,thisline]); src = escapeInvalidXmlChars(src); }else{ var style = "<span class='" + (isBranchFollowed(thisline,true) ? 'branchOkay' : 'branchWarning') + "'>"; newsrc += escapeInvalidXmlChars(src.slice(0,cons.start.column-offset)) + style; if (cols.length > colsIndex+1 && cols[colsIndex+1].consequent.start.line === lineNum && cols[colsIndex+1].consequent.start.column-offset < cols[colsIndex].consequent.end.column-offset) { var res = branchReport(colsIndex+1,src.slice(cons.start.column-offset,cons.end.column-offset),cols,cons.start.column-offset,lineNum); newsrc += res.src; cols = res.cols; cols[colsIndex+1] = cols[colsIndex+2]; cols.length--; }else{ newsrc += escapeInvalidXmlChars(src.slice(cons.start.column-offset,cons.end.column-offset)); } newsrc += "</span>"; var alt = thisline.alternate; if (alt.start.line > lineNum){ newsrc += escapeInvalidXmlChars(src.slice(cons.end.column-offset)); branchStack.unshift([alt,thisline]); }else{ newsrc += escapeInvalidXmlChars(src.slice(cons.end.column-offset,alt.start.column-offset)); style = "<span class='" + (isBranchFollowed(thisline,false) ? 'branchOkay' : 'branchWarning') + "'>"; newsrc += style; if (cols.length > colsIndex+1 && cols[colsIndex+1].consequent.start.line === lineNum && cols[colsIndex+1].consequent.start.column-offset < cols[colsIndex].alternate.end.column-offset) { var res2 = branchReport(colsIndex+1,src.slice(alt.start.column-offset,alt.end.column-offset),cols,alt.start.column-offset,lineNum); newsrc += res2.src; cols = res2.cols; cols[colsIndex+1] = cols[colsIndex+2]; cols.length--; }else{ newsrc += escapeInvalidXmlChars(src.slice(alt.start.column-offset,alt.end.column-offset)); } newsrc += "</span>"; newsrc += escapeInvalidXmlChars(src.slice(alt.end.column-offset)); src = newsrc; } } return {src:src+postfix, cols:cols}; } var isUndefined = function(item){ return typeof item !== 'undefined'; }; var files = coverage.files; var totals = { totalSmts: 0, numberOfFilesCovered: 0, passedBranches: 0, totalBranches: 0, moduleTotalStatements : {}, moduleTotalCoveredStatements : {}, moduleTotalBranches : {}, moduleTotalCoveredBranches : {} }; // check if a data-cover-modulepattern was provided for per-module coverage reporting var modulePattern = _blanket.options("modulePattern"); var modulePatternRegex = ( modulePattern ? new RegExp(modulePattern) : null ); for(var file in files) { if (!files.hasOwnProperty(file)) { continue; } fileNumber++; var statsForFile = files[file], totalSmts = 0, numberOfFilesCovered = 0, code = [], i; var end = []; for(i = 0; i < statsForFile.source.length; i +=1){ var src = statsForFile.source[i]; if (branchStack.length > 0 || typeof statsForFile.branchData !== 'undefined') { if (typeof statsForFile.branchData[i+1] !== 'undefined') { var cols = statsForFile.branchData[i+1].filter(isUndefined); var colsIndex=0; src = branchReport(colsIndex,src,cols,0,i+1).src; }else if (branchStack.length){ src = branchReport(0,src,null,0,i+1).src; }else{ src = escapeInvalidXmlChars(src); } }else{ src = escapeInvalidXmlChars(src); } var lineClass=""; if(statsForFile[i+1]) { numberOfFilesCovered += 1; totalSmts += 1; lineClass = 'hit'; }else{ if(statsForFile[i+1] === 0){ totalSmts++; lineClass = 'miss'; } } code[i + 1] = "<div class='"+lineClass+"'><span class=''>"+(i + 1)+"</span>"+src+"</div>"; } totals.totalSmts += totalSmts; totals.numberOfFilesCovered += numberOfFilesCovered; var totalBranches=0; var passedBranches=0; if (typeof statsForFile.branchData !== 'undefined'){ for(var j=0;j<statsForFile.branchData.length;j++){ if (typeof statsForFile.branchData[j] !== 'undefined'){ for(var k=0;k<statsForFile.branchData[j].length;k++){ if (typeof statsForFile.branchData[j][k] !== 'undefined'){ totalBranches++; if (typeof statsForFile.branchData[j][k][0] !== 'undefined' && statsForFile.branchData[j][k][0].length > 0 && typeof statsForFile.branchData[j][k][1] !== 'undefined' && statsForFile.branchData[j][k][1].length > 0){ passedBranches++; } } } } } } totals.passedBranches += passedBranches; totals.totalBranches += totalBranches; // if "data-cover-modulepattern" was provided, // track totals per module name as well as globally if (modulePatternRegex) { var moduleName = file.match(modulePatternRegex)[1]; if(!totals.moduleTotalStatements.hasOwnProperty(moduleName)) { totals.moduleTotalStatements[moduleName] = 0; totals.moduleTotalCoveredStatements[moduleName] = 0; } totals.moduleTotalStatements[moduleName] += totalSmts; totals.moduleTotalCoveredStatements[moduleName] += numberOfFilesCovered; if(!totals.moduleTotalBranches.hasOwnProperty(moduleName)) { totals.moduleTotalBranches[moduleName] = 0; totals.moduleTotalCoveredBranches[moduleName] = 0; } totals.moduleTotalBranches[moduleName] += totalBranches; totals.moduleTotalCoveredBranches[moduleName] += passedBranches; } var result = percentage(numberOfFilesCovered, totalSmts); var output = fileTemplate.replace("{{file}}", file) .replace("{{percentage}}",result) .replace("{{numberCovered}}", numberOfFilesCovered) .replace(/\{\{fileNumber\}\}/g, fileNumber) .replace("{{totalSmts}}", totalSmts) .replace("{{totalBranches}}", totalBranches) .replace("{{passedBranches}}", passedBranches) .replace("{{source}}", code.join(" ")); if(result < successRate) { output = output.replace("{{statusclass}}", "bl-error"); } else { output = output.replace("{{statusclass}}", "bl-success"); } bodyContent += output; } // create temporary function for use by the global totals reporter, // as well as the per-module totals reporter var createAggregateTotal = function(numSt, numCov, numBranch, numCovBr, moduleName) { var totalPercent = percentage(numCov, numSt); var statusClass = totalPercent < successRate ? "bl-error" : "bl-success"; var rowTitle = ( moduleName ? "Total for module: " + moduleName : "Global total" ); var totalsOutput = grandTotalTemplate.replace("{{rowTitle}}", rowTitle) .replace("{{percentage}}", totalPercent) .replace("{{numberCovered}}", numCov) .replace("{{totalSmts}}", numSt) .replace("{{passedBranches}}", numCovBr) .replace("{{totalBranches}}", numBranch) .replace("{{statusclass}}", statusClass); bodyContent += totalsOutput; }; // if "data-cover-modulepattern" was provided, // output the per-module totals alongside the global totals if (modulePatternRegex) { for (var thisModuleName in totals.moduleTotalStatements) { if (totals.moduleTotalStatements.hasOwnProperty(thisModuleName)) { var moduleTotalSt = totals.moduleTotalStatements[thisModuleName]; var moduleTotalCovSt = totals.moduleTotalCoveredStatements[thisModuleName]; var moduleTotalBr = totals.moduleTotalBranches[thisModuleName]; var moduleTotalCovBr = totals.moduleTotalCoveredBranches[thisModuleName]; createAggregateTotal(moduleTotalSt, moduleTotalCovSt, moduleTotalBr, moduleTotalCovBr, thisModuleName); } } } createAggregateTotal(totals.totalSmts, totals.numberOfFilesCovered, totals.totalBranches, totals.passedBranches, null); bodyContent += "</div>"; //closing main appendTag('style', head, cssSytle); //appendStyle(body, headerContent); if (document.getElementById("blanket-main")){ document.getElementById("blanket-main").innerHTML= bodyContent.slice(23,-6); }else{ appendTag('div', body, bodyContent); } //appendHtml(body, '</div>'); };