Coverage (%)
Covered/Total Smts.
"+(hasBranchTracking ? "
Covered/Total Branches
":"")+"
",
+ fileTemplate = "
{{percentage}} %
{{numberCovered}}/{{totalSmts}}
"+( hasBranchTracking ? "
{{passedBranches}}/{{totalBranches}}
" : "" )+"
{{source}}
";
+ grandTotalTemplate = "
{{rowTitle}}
{{percentage}} %
{{numberCovered}}/{{totalSmts}}
"+( hasBranchTracking ? "
{{passedBranches}}/{{totalBranches}}
" : "" ) + "
";
+
+ 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);*/
+ (1,eval)(blanket_toggleSource.toString().replace('function ' + blanket_toggleSource.name, 'function blanket_toggleSource'));
+
+ 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, "&")
+ .replace(//g, ">")
+ .replace(/\"/g, """)
+ .replace(/\'/g, "'");
+ }
+
+ 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 += "
";
+ if (branchStack[0][0].end.line === lineNum){
+ newsrc += escapeInvalidXmlChars(src.slice(0,branchStack[0][0].end.column)) + "";
+ src = src.slice(branchStack[0][0].end.column);
+ branchStack.shift();
+ if (branchStack.length > 0){
+ newsrc += "
";
+ if (branchStack[0][0].end.line === lineNum){
+ newsrc += escapeInvalidXmlChars(src.slice(0,branchStack[0][0].end.column)) + "";
+ 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) + "",cols:cols};
+ }
+ else{
+ postfix = "";
+ }
+ }else if (!cols){
+ return {src: newsrc + escapeInvalidXmlChars(src) ,cols:cols};
+ }
+ }else if(!cols){
+ return {src: newsrc + escapeInvalidXmlChars(src) + "",cols:cols};
+ }else{
+ postfix = "";
+ }
+ }
+ 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 = "
";
+ 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 += "";
+
+ 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 = "
";
+ 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 += "";
+ 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] = "
"+(i + 1)+""+src+"
";
+ }
+ totals.totalSmts += totalSmts;
+ totals.numberOfFilesCovered += numberOfFilesCovered;
+ var totalBranches=0;
+ var passedBranches=0;
+ if (typeof statsForFile.branchData !== 'undefined'){
+ for(var j=0;j
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 += " "; //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);
+ }
+
+ fileNumber = 0;
+ for(var file in files) {
+ if (!files.hasOwnProperty(file)) {
+ continue;
+ }
+
+ fileNumber++;
+ var _ = function() {
+ var localFN = fileNumber;
+ $("#blanket-link-file-" + fileNumber).click(function() {
+ blanket_toggleSource("file-" + localFN);
+ });
+ }();
+ }
+
+ //appendHtml(body, '');
+};
+
+(function(){
+ var newOptions={};
+ //http://stackoverflow.com/a/2954896
+ var toArray =Array.prototype.slice;
+ var scripts = toArray.call(document.scripts);
+ toArray.call(scripts[scripts.length - 1].attributes)
+ .forEach(function(es){
+ if(es.nodeName === "data-cover-only"){
+ newOptions.filter = es.nodeValue;
+ }
+ if(es.nodeName === "data-cover-never"){
+ newOptions.antifilter = es.nodeValue;
+ }
+ if(es.nodeName === "data-cover-reporter"){
+ newOptions.reporter = es.nodeValue;
+ }
+ if (es.nodeName === "data-cover-adapter"){
+ newOptions.adapter = es.nodeValue;
+ }
+ if (es.nodeName === "data-cover-loader"){
+ newOptions.loader = es.nodeValue;
+ }
+ if (es.nodeName === "data-cover-timeout"){
+ newOptions.timeout = es.nodeValue;
+ }
+ if (es.nodeName === "data-cover-modulepattern") {
+ newOptions.modulePattern = es.nodeValue;
+ }
+ if (es.nodeName === "data-cover-reporter-options"){
+ try{
+ newOptions.reporter_options = JSON.parse(es.nodeValue);
+ }catch(e){
+ if (blanket.options("debug")){
+ throw new Error("Invalid reporter options. Must be a valid stringified JSON object.");
+ }
+ }
+ }
+ if (es.nodeName === "data-cover-testReadyCallback"){
+ newOptions.testReadyCallback = es.nodeValue;
+ }
+ if (es.nodeName === "data-cover-customVariable"){
+ newOptions.customVariable = es.nodeValue;
+ }
+ if (es.nodeName === "data-cover-flags"){
+ var flags = " "+es.nodeValue+" ";
+ if (flags.indexOf(" ignoreError ") > -1){
+ newOptions.ignoreScriptError = true;
+ }
+ if (flags.indexOf(" autoStart ") > -1){
+ newOptions.autoStart = true;
+ }
+ if (flags.indexOf(" ignoreCors ") > -1){
+ newOptions.ignoreCors = true;
+ }
+ if (flags.indexOf(" branchTracking ") > -1){
+ newOptions.branchTracking = true;
+ }
+ if (flags.indexOf(" sourceURL ") > -1){
+ newOptions.sourceURL = true;
+ }
+ if (flags.indexOf(" debug ") > -1){
+ newOptions.debug = true;
+ }
+ if (flags.indexOf(" engineOnly ") > -1){
+ newOptions.engineOnly = true;
+ }
+ if (flags.indexOf(" commonJS ") > -1){
+ newOptions.commonJS = true;
+ }
+ if (flags.indexOf(" instrumentCache ") > -1){
+ newOptions.instrumentCache = true;
+ }
+ }
+ });
+ blanket.options(newOptions);
+
+ if (typeof requirejs !== 'undefined'){
+ blanket.options("existingRequireJS",true);
+ }
+ /* setup requirejs loader, if needed */
+
+ if (blanket.options("commonJS")){
+ blanket._commonjs = {};
+ }
+})();
+(function(_blanket){
+_blanket.extend({
+ utils: {
+ normalizeBackslashes: function(str) {
+ return str.replace(/\\/g, '/');
+ },
+ matchPatternAttribute: function(filename,pattern){
+ if (typeof pattern === 'string'){
+ if (pattern.indexOf("[") === 0){
+ //treat as array
+ var pattenArr = pattern.slice(1,pattern.length-1).split(",");
+ return pattenArr.some(function(elem){
+ return _blanket.utils.matchPatternAttribute(filename,_blanket.utils.normalizeBackslashes(elem.slice(1,-1)));
+ //return filename.indexOf(_blanket.utils.normalizeBackslashes(elem.slice(1,-1))) > -1;
+ });
+ }else if ( pattern.indexOf("//") === 0){
+ var ex = pattern.slice(2,pattern.lastIndexOf('/'));
+ var mods = pattern.slice(pattern.lastIndexOf('/')+1);
+ var regex = new RegExp(ex,mods);
+ return regex.test(filename);
+ }else if (pattern.indexOf("#") === 0){
+ return window[pattern.slice(1)].call(window,filename);
+ }else{
+ return filename.indexOf(_blanket.utils.normalizeBackslashes(pattern)) > -1;
+ }
+ }else if ( pattern instanceof Array ){
+ return pattern.some(function(elem){
+ return _blanket.utils.matchPatternAttribute(filename,elem);
+ });
+ }else if (pattern instanceof RegExp){
+ return pattern.test(filename);
+ }else if (typeof pattern === "function"){
+ return pattern.call(window,filename);
+ }
+ },
+ blanketEval: function(data){
+ _blanket._addScript(data);
+ },
+ collectPageScripts: function(){
+ var toArray = Array.prototype.slice;
+ var scripts = toArray.call(document.scripts);
+ var selectedScripts=[],scriptNames=[];
+ var filter = _blanket.options("filter");
+ if(filter != null){
+ //global filter in place, data-cover-only
+ var antimatch = _blanket.options("antifilter");
+ selectedScripts = toArray.call(document.scripts)
+ .filter(function(s){
+ return toArray.call(s.attributes).filter(function(sn){
+ return sn.nodeName === "src" && _blanket.utils.matchPatternAttribute(sn.nodeValue,filter) &&
+ (typeof antimatch === "undefined" || !_blanket.utils.matchPatternAttribute(sn.nodeValue,antimatch));
+ }).length === 1;
+ });
+ }else{
+ selectedScripts = toArray.call(document.querySelectorAll("script[data-cover]"));
+ }
+ scriptNames = selectedScripts.map(function(s){
+ return _blanket.utils.qualifyURL(
+ toArray.call(s.attributes).filter(
+ function(sn){
+ return sn.nodeName === "src";
+ })[0].nodeValue);
+ });
+ if (!filter){
+ _blanket.options("filter","['"+scriptNames.join("','")+"']");
+ }
+ return scriptNames;
+ },
+ loadAll: function(nextScript,cb,preprocessor){
+ /**
+ * load dependencies
+ * @param {nextScript} factory for priority level
+ * @param {cb} the done callback
+ */
+ var currScript=nextScript();
+ var isLoaded = _blanket.utils.scriptIsLoaded(
+ currScript,
+ _blanket.utils.ifOrdered,
+ nextScript,
+ cb
+ );
+
+ if (!(_blanket.utils.cache[currScript] && _blanket.utils.cache[currScript].loaded)){
+ var attach = function(){
+ if (_blanket.options("debug")) {console.log("BLANKET-Mark script:"+currScript+", as loaded and move to next script.");}
+ isLoaded();
+ };
+ var whenDone = function(result){
+ if (_blanket.options("debug")) {console.log("BLANKET-File loading finished");}
+ if (typeof result !== 'undefined'){
+ if (_blanket.options("debug")) {console.log("BLANKET-Add file to DOM.");}
+ _blanket._addScript(result);
+ }
+ attach();
+ };
+
+ _blanket.utils.attachScript(
+ {
+ url: currScript
+ },
+ function (content){
+ _blanket.utils.processFile(
+ content,
+ currScript,
+ whenDone,
+ whenDone
+ );
+ }
+ );
+ }else{
+ isLoaded();
+ }
+ },
+ attachScript: function(options,cb){
+ var timeout = _blanket.options("timeout") || 3000;
+ setTimeout(function(){
+ if (!_blanket.utils.cache[options.url].loaded){
+ throw new Error("error loading source script");
+ }
+ },timeout);
+ _blanket.utils.getFile(
+ options.url,
+ cb,
+ function(){ throw new Error("error loading source script");}
+ );
+ },
+ ifOrdered: function(nextScript,cb){
+ /**
+ * ordered loading callback
+ * @param {nextScript} factory for priority level
+ * @param {cb} the done callback
+ */
+ var currScript = nextScript(true);
+ if (currScript){
+ _blanket.utils.loadAll(nextScript,cb);
+ }else{
+ cb(new Error("Error in loading chain."));
+ }
+ },
+ scriptIsLoaded: function(url,orderedCb,nextScript,cb){
+ /**
+ * returns a callback that checks a loading list to see if a script is loaded.
+ * @param {orderedCb} callback if ordered loading is being done
+ * @param {nextScript} factory for next priority level
+ * @param {cb} the done callback
+ */
+ if (_blanket.options("debug")) {console.log("BLANKET-Returning function");}
+ return function(){
+ if (_blanket.options("debug")) {console.log("BLANKET-Marking file as loaded: "+url);}
+
+ _blanket.utils.cache[url].loaded=true;
+
+ if (_blanket.utils.allLoaded()){
+ if (_blanket.options("debug")) {console.log("BLANKET-All files loaded");}
+ cb();
+ }else if (orderedCb){
+ //if it's ordered we need to
+ //traverse down to the next
+ //priority level
+ if (_blanket.options("debug")) {console.log("BLANKET-Load next file.");}
+ orderedCb(nextScript,cb);
+ }
+ };
+ },
+ cache: {},
+ allLoaded: function (){
+ /**
+ * check if depdencies are loaded in cache
+ */
+ var cached = Object.keys(_blanket.utils.cache);
+ for (var i=0;i