Skip to content
This repository has been archived by the owner on Sep 21, 2022. It is now read-only.

Commit

Permalink
Enhanced html report
Browse files Browse the repository at this point in the history
As told in #6:

- suites are now collapsible;
- all but failed suites are collapsed by default;
- buttons to expand all, collapse all and expand only errors are added;
- stats of total numbers of tests run, failed, succeeded and skipped
  are shown at the top.
  • Loading branch information
Sergey Tatarintsev committed May 28, 2014
1 parent 6325db4 commit 14d6df1
Show file tree
Hide file tree
Showing 6 changed files with 317 additions and 90 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## Dev

* Enhanced html report:
- suites are now collapsible;
- all but failed suites are collapsed by default;
- buttons to expand all, collapse all and expand only errors are added;
- stats of total numbers of tests run, failed, succeeded and skipped
are shown at the top.

## 0.3.3 - 2014-05-19

* Allow to use multiple reporters in `test` command.
Expand Down
99 changes: 87 additions & 12 deletions lib/reporters/html/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,17 @@ var q = require('q'),

var REPORT_DIR = 'gemini-report',
REPORT_INDEX = path.join(REPORT_DIR, 'index.html'),
REPORT_ATTACHMENTS = path.join(REPORT_DIR, 'attach');
REPORT_ATTACHMENTS = path.join(REPORT_DIR, 'attach'),

REPORT_JS_NAME = 'report.js',
REPORT_CSS_NAME = 'report.css',
REPORT_TPL_SRC = path.join(__dirname, 'report.hbs'),
SUITE_TPL_SRC = path.join(__dirname, 'suite.hbs'),
REPORT_JS_SRC = path.join(__dirname, REPORT_JS_NAME),
REPORT_CSS_SRC = path.join(__dirname, REPORT_CSS_NAME),

REPORT_JS_DST = path.join(REPORT_DIR, REPORT_JS_NAME),
REPORT_CSS_DST = path.join(REPORT_DIR, REPORT_CSS_NAME);

function suitePath(suite) {
var result = '';
Expand All @@ -31,9 +41,13 @@ function attachmentRelPath(suite, result, kind) {

Handlebars.registerHelper('status', function() {
if (this.skipped) {
return 'skip';
return 'section_status_skip';
}
return this.equal? 'success' : 'fail';
return isOK(this)? 'section_status_success' : 'section_status_fail';
});

Handlebars.registerHelper('has-fails', function() {
return this.failed > 0? 'summary__key_has-fails' : '';
});

Handlebars.registerHelper('image', function(kind) {
Expand All @@ -48,20 +62,64 @@ Handlebars.registerHelper('stacktrace', function() {
return error.stack || error.message || error;
});

Handlebars.registerHelper('collapse', function() {
return isOK(this) ? 'section_collapsed' : '';
});

function isOK(section) {
if ('equal' in section) {
return section.equal;
}

if ('skipped' in section) {
return true;
}

if ('error' in section) {
return false;
}

var result = true;
if (section.children) {
result = result && section.children.every(isOK);
}

if (section.states) {
result = result && section.states.every(isOK);
}

if (section.browsers) {
result = result && section.browsers.every(isOK);
}
return result;
}

module.exports = function htmlReporter(tester) {
var currentSuite,
attachmentsQueue;
attachmentsQueue,
failed,
passed,
skipped;

function createState(name) {
var state = {name: name, browsers: []};
var state = {
name: name,
browsers: []
};

currentSuite.states.push(state);
currentSuite.statesByName[name] = state;
return state;
}

tester.on('begin', function() {
currentSuite = {name: '',children: [], parent: null};
failed = passed = skipped = 0;
currentSuite = {
name: '',
children: [],
parent: null,
};

attachmentsQueue = fs.makeTree(REPORT_ATTACHMENTS);
});

Expand Down Expand Up @@ -102,8 +160,9 @@ module.exports = function htmlReporter(tester) {

state.browsers.push({
name: browserName,
skipped: true
skipped: true,
});
skipped++;
});

tester.on('endTest', function(result) {
Expand All @@ -112,12 +171,15 @@ module.exports = function htmlReporter(tester) {
name: result.browserName,
tested: true,
equal: result.equal,
currentPath: attachmentRelPath(currentSuite, result, 'current')
currentPath: attachmentRelPath(currentSuite, result, 'current'),
};

if (!result.equal) {
failed++;
reportData.referencePath = attachmentRelPath(currentSuite, result, 'ref');
reportData.diffPath = attachmentRelPath(currentSuite, result, 'diff');
} else {
passed++;
}

state.browsers.push(reportData);
Expand All @@ -143,23 +205,36 @@ module.exports = function htmlReporter(tester) {
name: error.browserName,
error: error
});
failed++;
});

tester.on('end', function () {
attachmentsQueue
.then(function() {
return fs.read(path.resolve(__dirname, 'suite.hbs'));
return fs.read(SUITE_TPL_SRC);
})
.then(function(suiteTpl) {
Handlebars.registerPartial('suite', suiteTpl);
return fs.read(path.resolve(__dirname, 'report.hbs'));
return fs.read(REPORT_TPL_SRC);
})
.then(function(tpl) {
var tplFunc = Handlebars.compile(tpl);
return tplFunc(currentSuite);
return tplFunc({
suites: currentSuite.children,
stats: {
total: failed + passed + skipped,
failed: failed,
passed: passed,
skipped: skipped
}
});
})
.then(function(index) {
return fs.write(REPORT_INDEX, index);
return q.all([
fs.write(REPORT_INDEX, index),
fs.copy(REPORT_JS_SRC, path.resolve(REPORT_JS_DST)),
fs.copy(REPORT_CSS_SRC, path.resolve(REPORT_CSS_DST))
]);
})
.fail(function(e) {
console.log(e.stack);
Expand Down
111 changes: 111 additions & 0 deletions lib/reporters/html/report.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
.report {
font: 14px Helvetica Neue, Arial, sans-serif;
}

.summary__key {
font-weight: bold;
display: inline;
}

.summary__key::after {
content: ':';
}

.summary__key_has-fails {
color: #c00;
}

.summary__value {
margin-left: 5px;
margin-right: 20px;
display: inline;
}

.button {
background: #fff;
border: 1px solid #ccc;
border-radius: 2px;
outline: 0;
}

.button:hover {
border-color: #555;
}

.button:active {
background: #eee;
}

.image-box {
padding: 5px;
background: #f6f5f3;
border: 1px solid #ccc;
}

.image-box__image {
padding: 0 5px;
display: inline-block;
vertical-align: top;
}

.section__title {
font-weight: bold;
cursor: pointer;

-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}

.section__title:before {
display: inline-block;
margin-right: 2px;
vertical-align: middle;
content: '\25bc';
color: black;
}

.section_status_success > .section__title {
color: #038035;
}

.section_status_fail > .section__title {
color: #c00;
}

.section_status_skip > .section__title {
color: #ccc;
}

.section__title:hover {
color: #2D3E50;
}

.section__body {
padding-left: 15px;
}

.section__body_guided {
border-left: 1px dotted #ccc;
}

.section_collapsed .section__body {
display: none;
}

.section_collapsed .section__title:before {
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
transform: rotate(-90deg);
}

.stacktrace {
background: #f6f5f3;
border: 1px solid #ccc;
padding: 5px;
font: 12px Consolas, Monaco, monospace;
}

61 changes: 20 additions & 41 deletions lib/reporters/html/report.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,27 @@
<html>
<head>
<title>Gemini report</title>
<style>
.suite {
padding-left: 30px;
}
.state {
padding-left: 30px;
}
.success::before {
content: '\2713 ';
color: green;
}
.fail {
color: red;
}
.fail:before {
content: '\2718 ';
color: red;
}
.skip {
color: gray;
}
.skip:before {
content: '- ';
color: gray;
}
.image-box {
display: inline-block;
padding: 5px;
}
</style>
<link rel="stylesheet" type="text/css" href="report.css">
</head>

<body>
<h1>Gemini report</h1>
{{> suite}}
<body class="report">
{{#with stats}}
<dl class="summary">
<dt class="summary__key">Total Tests</dt><dd class="summary__value">{{total}}</dd>
<dt class="summary__key">Passed</dt><dd class="summary__value">{{passed}}</dd>
<dt class="summary__key {{has-fails}}">Failed</dt><dd class="summary__value">{{failed}}</dd>
<dt class="summary__key">Skipped</dt><dd class="summary__value">{{skipped}}</dd>
</dl>
{{/with}}

<button id="expandAll" class="button">Expand all</button>
<button id="collapseAll" class="button">Collapse all</button>
<button id="expandErrors" class="button">Expand errors</button>

{{#each suites}}
{{> suite}}
{{/each}}

<script src="report.js"></script>
</body>
</html>
Loading

0 comments on commit 14d6df1

Please sign in to comment.