From 1c1742e4e6fdc65b494537ac46b38d0355f958af Mon Sep 17 00:00:00 2001 From: Vladimir Alaev Date: Tue, 21 Oct 2014 17:44:32 +0400 Subject: [PATCH] Add sorting feature to the coverage index; Colorize index items depending on the coverage level --- .gitignore | 2 +- .jscsrc | 3 +- .jshintignore | 3 +- lib/coverage-index.hbs | 24 ---- lib/coverage.css | 60 ---------- lib/coverage/coverage-index.hbs | 44 ++++++++ lib/coverage/coverage.css | 143 ++++++++++++++++++++++++ lib/{ => coverage}/coverage.hbs | 0 lib/{coverage.js => coverage/index.js} | 13 ++- lib/coverage/tinytable.sorter.js | 146 +++++++++++++++++++++++++ 10 files changed, 349 insertions(+), 89 deletions(-) delete mode 100644 lib/coverage-index.hbs delete mode 100644 lib/coverage.css create mode 100644 lib/coverage/coverage-index.hbs create mode 100644 lib/coverage/coverage.css rename lib/{ => coverage}/coverage.hbs (100%) rename lib/{coverage.js => coverage/index.js} (97%) create mode 100755 lib/coverage/tinytable.sorter.js diff --git a/.gitignore b/.gitignore index c24621a4b..cb2afbc89 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,4 @@ build .grunt node_modules -coverage +/coverage diff --git a/.jscsrc b/.jscsrc index d40b16c7a..096c0f66e 100644 --- a/.jscsrc +++ b/.jscsrc @@ -1,7 +1,8 @@ { "excludeFiles": [ "node_modules", - "coverage" + "/coverage", + "lib/coverage/tinytable.sorter.js" ], "requireCurlyBraces": [ "if", diff --git a/.jshintignore b/.jshintignore index ba2a97b57..58ba66cc3 100644 --- a/.jshintignore +++ b/.jshintignore @@ -1,2 +1,3 @@ node_modules -coverage +/coverage +lib/coverage/tinytable.sorter.js diff --git a/lib/coverage-index.hbs b/lib/coverage-index.hbs deleted file mode 100644 index 966ddd8b2..000000000 --- a/lib/coverage-index.hbs +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - -
-

Gemini tests CSS coverage report

-

Summary: {{percent}}% ({{covered}}/{{total}})

- -
- - diff --git a/lib/coverage.css b/lib/coverage.css deleted file mode 100644 index 76233f6ac..000000000 --- a/lib/coverage.css +++ /dev/null @@ -1,60 +0,0 @@ -body { - background-color: #eee; - margin: 0px; - padding: 0px; -} - -body, pre { - font: 13px arial; -} - -pre { - margin: 0px; - padding-left: 10px; -} - -a, a:visited { - color: #00d; - text-decoration: none; -} - -.covered { - background-color: #abf7ad; -} - -.none { - background-color: #ffb3b3; -} - -.partial { - background-color: #fffcb3; -} - -.report { - margin: 10px; -} - -.report-list { - list-style-type: none; - margin: 0px; - padding: 0px; -} - -.report-list__item { - background-color: #eee; - padding: 3px; -} - -.report-list__item:nth-child(odd) { - background-color: #fff; -} - -.link-index { - display: block; - background-color: #ddd; - padding: 6px; -} - -.content { - padding-top: 10px; -} diff --git a/lib/coverage/coverage-index.hbs b/lib/coverage/coverage-index.hbs new file mode 100644 index 000000000..dd1b497c1 --- /dev/null +++ b/lib/coverage/coverage-index.hbs @@ -0,0 +1,44 @@ + + + + + + + + +
+

Gemini tests CSS coverage report

+

Summary: {{percent}}% ({{covered}}/{{total}})

+ + + + + + + + + + {{#each reports}} + + + + + + + {{/each}} + +
FileCoverage, %Rules CoveredRules Total
{{source}}
{{stat.percent}}
 
{{stat.covered}}{{stat.total}}
+
+ + + diff --git a/lib/coverage/coverage.css b/lib/coverage/coverage.css new file mode 100644 index 000000000..57dd6e989 --- /dev/null +++ b/lib/coverage/coverage.css @@ -0,0 +1,143 @@ +body { + background-color: #eee; + margin: 0px; + padding: 0px; +} + +body, pre { + font: 13px arial; +} + +pre { + margin: 0px; + padding-left: 10px; +} + +.covered { + background-color: #abf7ad; +} + +.none { + background-color: #ffb3b3; +} + +.partial { + background-color: #fffcb3; +} + +.report { + margin: 10px; +} + +.report-list { + width: 100%; + margin: 0px; + padding: 0px; + border: solid 1px #999; + border-right: none; + border-bottom: none; + border-spacing: 0px; +} + +.report-list td, .report-list th { + border: solid 1px #999; + border-left: none; + border-top: none; + padding: 3px; +} + +.report-list td:nth-child(3), .report-list td:nth-child(4) { + text-align: right; +} + +.report-list th { + cursor: pointer; +} +.report-list th:nth-child(2), .report-list th:nth-child(3), .report-list th:nth-child(4) { + width: 9em; +} + +.report-list__item { + background-color: #eee; + padding: 3px; +} + +.report-list__header { + background-color: #ccc; + padding: 3px; + + -user-select: none; + -moz-user-select: none; + -webkit-user-select: none; +} + +.report-list__row { + background-color: #bbb; +} + +.report-list__row_odd { + background-color: white; +} + +.report-list__item:nth-child(odd) { + background-color: #fff; +} + +.link-index { + display: block; + background-color: #ddd; + padding: 6px; +} + +.report-link, .report-link:visited { + color: #333; + text-decoration: none; +} + +.content { + padding-top: 10px; +} + +.report-list__row_level_bad { + background: #ffb3b3; +} + +.report-list__row_level_good { + background: #fffcb3; +} + +.report-list__row_level_perfect { + background: #abf7ad; +} + +.report-list__header__cell_asc:before, .report-list__header__cell_desc:before { + display: inline-block; + margin-left: -1em; + vertical-align: top; + content: '\25bc'; + color: black; +} + +.report-list__header__cell_desc:before { + content: '\25b2'; +} + +.gauge { + position: relative; + background: #999999; + width: 100%; +} + +.gauge__text { + position: absolute; + color: #eee; + width: 100%; + text-align: center; + z-index: 1; +} + +.gauge__fill { + background: #000; + opacity: 0.3; + position: relative; +} diff --git a/lib/coverage.hbs b/lib/coverage/coverage.hbs similarity index 100% rename from lib/coverage.hbs rename to lib/coverage/coverage.hbs diff --git a/lib/coverage.js b/lib/coverage/index.js similarity index 97% rename from lib/coverage.js rename to lib/coverage/index.js index b3ca2068a..41af237b9 100644 --- a/lib/coverage.js +++ b/lib/coverage/index.js @@ -285,12 +285,20 @@ module.exports = inherit({ } } + var percent = Math.round(coveredCount / data.length * 100); stat = { total: data.length, covered: coveredCount, - percent: Math.round(coveredCount / data.length * 100) + percent: percent, + level: 'bad' }; + if (percent === 100) { + stat.level = 'perfect'; + } else if (percent >= 50) { + stat.level = 'good'; + } + return hb.compile(opts.tmpl)({ content: lines.join('\n'), source: path.relative(path.dirname(dest), file), @@ -387,7 +395,8 @@ function writeStatsJson(stats, covDir) { function copyResources(covDir) { var res = [ - 'coverage.css' + 'coverage.css', + 'tinytable.sorter.js' ]; return q.all(res.map(function(r) { diff --git a/lib/coverage/tinytable.sorter.js b/lib/coverage/tinytable.sorter.js new file mode 100755 index 000000000..98b89c15f --- /dev/null +++ b/lib/coverage/tinytable.sorter.js @@ -0,0 +1,146 @@ +// Based on the source from http://www.scriptiny.com/2009/03/table-sorter/ +var TINY = {}; + +function T$(i) { + return document.getElementById(i); +} +function T$$(e, p) { + return p.getElementsByTagName(e); +} + +TINY.table = function() { + function sorter(n) { + this.n = n; + this.pagesize = 20; + this.paginate = 0; + } + + sorter.prototype.init = function(e, f) { + var t = ge(e), i = 0; + this.e = e; + this.l = t.r.length; + t.a = []; + t.h = T$$('thead', T$(e))[0].rows[0]; + t.w = t.h.cells.length; + for (i; i < t.w; i++) { + var c = t.h.cells[i]; + if (c.className != 'nosort') { + c.className = this.head; + c.onclick = new Function(this.n + '.wk(this.cellIndex)'); + } + } + for (i = 0; i < this.l; i++) { + t.a[i] = {}; + } + if (f != null) { + var a = new Function(this.n + '.wk(' + f + ')'); + a(); + } + if (this.paginate) { + this.g = 1; + this.pages(); + } + }; + sorter.prototype.wk = function(y) { + var t = ge(this.e), x = t.h.cells[y], i = 0; + for (i; i < this.l; i++) { + t.a[i].o = i; + var v = t.r[i].cells[y]; + t.r[i].style.display = ''; + while (v.hasChildNodes()) { + v = v.firstChild; + } + t.a[i].v = v.nodeValue? v.nodeValue : ''; + } + for (i = 0; i < t.w; i++) { + var c = t.h.cells[i]; + if (c.className != 'nosort') { + c.className = this.head; + } + } + if (t.p == y) { + t.a.reverse(); + var sort = t.d? this.asc : this.desc; + this.asc && x.classList.remove(this.asc); + this.desc && x.classList.remove(this.desc); + sort && x.classList.add(sort); + t.d = t.d? 0 : 1; + } + else { + t.p = y; + t.a.sort(cp); + t.d = 0; + this.asc && x.classList.add(this.asc); + } + var n = document.createElement('tbody'); + for (i = 0; i < this.l; i++) { + var r = t.r[t.a[i].o].cloneNode(true); + n.appendChild(r); + var cl = i % 2 == 0? this.even : this.odd; + this.even && r.classList.remove(this.even); + this.odd && r.classList.remove(this.odd); + cl && r.classList.add(cl); + var cells = T$$('td', r); + for (var z = 0; z < t.w; z++) { + cl = y == z? i % 2 == 0? this.evensel : this.oddsel : ''; + this.evensel && cells[z].classList.remove(this.evensel); + this.oddsel && cells[z].classList.remove(this.oddsel); + cl && cells[z].classList.add(cl); + } + } + t.replaceChild(n, t.b); + if (this.paginate) { + this.size(this.pagesize); + } + }; + sorter.prototype.page = function(s) { + var t = ge(this.e), i = 0, l = s + parseInt(this.pagesize); + if (this.currentid && this.limitid) { + T$(this.currentid).innerHTML = this.g; + } + for (i; i < this.l; i++) { + t.r[i].style.display = i >= s && i < l? '' : 'none'; + } + }; + sorter.prototype.move = function(d, m) { + var s = d == 1? (m? this.d : this.g + 1) : (m? 1 : this.g - 1); + if (s <= this.d && s > 0) { + this.g = s; + this.page((s - 1) * this.pagesize); + } + }; + sorter.prototype.size = function(s) { + this.pagesize = s; + this.g = 1; + this.pages(); + this.page(0); + if (this.currentid && this.limitid) { + T$(this.limitid).innerHTML = this.d; + } + }; + sorter.prototype.pages = function() { + this.d = Math.ceil(this.l / this.pagesize); + }; + function ge(e) { + var t = T$(e); + t.b = T$$('tbody', t)[0]; + t.r = t.b.rows; + return t; + }; + function cp(f, c) { + var g, h; + f = g = f.v.toLowerCase(), c = h = c.v.toLowerCase(); + var i = parseFloat(f.replace(/(\$|\,)/g, '')), n = parseFloat(c.replace(/(\$|\,)/g, '')); + if (!isNaN(i) && !isNaN(n)) { + return i - n; + } + if (f < c) { + return -1; + } + if (f > c) { + return 1; + } + return 0; + }; + return {sorter: sorter}; +}();