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

Commit

Permalink
feat(html-reporter): add ability to copy suite name and open suite urls
Browse files Browse the repository at this point in the history
  • Loading branch information
sipayRT committed Nov 10, 2016
1 parent 74168cd commit 6219b74
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 22 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ node_modules
/coverage
lib/coverage/tinytable.sorter.js
lib/browser/client-scripts/gemini.calibrate.min.js
/lib/reporters/html/static/report.min.js
/_book
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ build
node_modules
/coverage
/lib/browser/client-scripts/gemini.calibrate.min.js
/lib/reporters/html/static/report.min.js
/_book
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ test/
coverage/
CONTRIBUTING.md
/lib/browser/client-scripts/gemini.calibrate.js
/lib/reporters/html/static/report.js
/_book
/book.json
/.bookignore
2 changes: 1 addition & 1 deletion lib/reporters/html/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function makeDirFor(destPath) {

function prepareViewData(runner) {
return new Promise((resolve) => {
var model = new ViewModel();
var model = new ViewModel(runner.config);

runner.on(Events.SKIP_STATE, model.addSkipped.bind(model));

Expand Down
41 changes: 41 additions & 0 deletions lib/reporters/html/static/report.css
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,39 @@
display: none;
}

.section__icon {
display: inline-block;
width: 19px;
height: 19px;
vertical-align: top;
padding: 0 3px;
border: none;
opacity: 0.5;
cursor: pointer;
}

.section__icon:hover {
opacity: 1;
}

.section__icon:before {
display: block;
width: 100%;
height: 100%;
content: '';
background-repeat: no-repeat;
background-size: 100%;
background-position: center;
}

.section__icon_view-local:before {
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgLTAuNzA5IC0zMi4wODEgMTQxLjczMiAxNDEuNzMyIiBoZWlnaHQ9IjE0MS43MzJweCIgaWQ9IkxpdmVsbG9fMSIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSItMC43MDkgLTMyLjA4MSAxNDEuNzMyIDE0MS43MzIiIHdpZHRoPSIxNDEuNzMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJMaXZlbGxvXzgwIj48cGF0aCBkPSJNODkuNjY4LDM4Ljc4NmMwLTEwLjc3My04LjczMS0xOS41MTItMTkuNTEtMTkuNTEyUzUwLjY0NiwyOC4wMSw1MC42NDYsMzguNzg2YzAsMTAuNzc0LDguNzMyLDE5LjUxMSwxOS41MTIsMTkuNTExICAgQzgwLjkzNCw1OC4yOTcsODkuNjY4LDQ5LjU2MSw4OS42NjgsMzguNzg2IE0xMjguMzUyLDM4LjcyN2MtMTMuMzE1LDE3LjU5OS0zNC40MjYsMjguOTcyLTU4LjE5MywyOC45NzIgICBjLTIzLjc3LDAtNDQuODc5LTExLjM3My01OC4xOTQtMjguOTcyQzI1LjI3OSwyMS4xMjksNDYuMzg5LDkuNzU2LDcwLjE1OCw5Ljc1NkM5My45MjcsOS43NTYsMTE1LjAzNiwyMS4xMjksMTI4LjM1MiwzOC43MjcgICAgTTE0MC4zMTQsMzguNzZDMTI1LjY2NiwxNS40NzgsOTkuNzI1LDAsNzAuMTU4LDBTMTQuNjQ4LDE1LjQ3OCwwLDM4Ljc2YzE0LjY0OCwyMy4zMTIsNDAuNTkxLDM4LjgxLDcwLjE1OCwzOC44MSAgIFMxMjUuNjY2LDYyLjA3MiwxNDAuMzE0LDM4Ljc2Ii8+PC9nPjxnIGlkPSJMaXZlbGxvXzFfMV8iLz48L3N2Zz4=);
}

.section__icon_copy-to-clipboard:before {
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUxMiA1MTIiIGhlaWdodD0iNTEycHgiIGlkPSJMYXllcl8xIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB3aWR0aD0iNTEycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxwYXRoIGQ9Ik00NjguNDkzLDEwMS42MzdMMzcxLjk1NSw1LjA5OEgxNTkuNTd2NzcuMjMxSDQzLjcyNHY0MjQuNzY5aDMwOC45MjN2LTc3LjIzMWgxMTUuODQ2VjEwMS42Mzd6ICAgTTM3MS45NTUsMzIuNDAxbDY5LjIzNiw2OS4yMzVoLTY5LjIzNlYzMi40MDF6IE02My4wMzEsNDg3Ljc5VjEwMS42MzdoMTczLjc2OXY5Ni41MzhoOTYuNTM4VjQ4Ny43OUg2My4wMzF6IE0yNTYuMTA4LDEwOS42MzIgIGw2OS4yMzYsNjkuMjM1aC02OS4yMzZWMTA5LjYzMnogTTM1Mi42NDcsNDEwLjU2VjE3OC44NjdsLTk2LjUzOC05Ni41MzhoLTc3LjIzMVYyNC40MDZoMTczLjc2OXY5Ni41MzhoOTYuNTM4VjQxMC41NkgzNTIuNjQ3eiIgZmlsbD0iIzM3NDA0RCIvPjwvc3ZnPg==);
}

.section_collapsed .section__title:before,
.meta-info_collapsed .meta-info__switcher:before {
-webkit-transform: rotate(-90deg);
Expand Down Expand Up @@ -246,3 +279,11 @@ a:active {
.meta-info_collapsed .meta-info__content {
display: none;
}

.text-input {
outline: 0;
line-height: 14px;
padding: 2px 5px;
border: 1px solid #ccc;
border-radius: 2px;
}
73 changes: 68 additions & 5 deletions lib/reporters/html/static/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,28 @@
'use strict';

var forEach = Array.prototype.forEach,
filter = Array.prototype.filter;
filter = Array.prototype.filter,
sections = document.querySelectorAll('.section'),
url = require('url'),
Clipboard = require('clipboard');

function expandAll() {
loadLazyImages(document, '.section_collapsed img');
forEach.call(document.querySelectorAll('.section'), function(section) {
forEach.call(sections, function(section) {
section.classList.remove('section_collapsed');
});
}

function collapseAll() {
forEach.call(document.querySelectorAll('.section'), function(section) {
forEach.call(sections, function(section) {
section.classList.add('section_collapsed');
});
}

function expandErrors() {
loadLazyImages(document, '.section_status_fail > .section__body > .image-box img');
loadLazyImages(document, '.section_status_warning > .section__body > .image-box img');
forEach.call(document.querySelectorAll('.section'), function(section) {
forEach.call(sections, function(section) {
if (section.classList.contains('section_status_fail') ||
section.classList.contains('section_status_warning')) {
section.classList.remove('section_collapsed');
Expand All @@ -33,7 +36,7 @@

function expandRetries() {
loadLazyImages(document, '.has-retries > .section__body > .image-box img');
forEach.call(document.querySelectorAll('.section'), function(section) {
forEach.call(sections, function(section) {
if (section.classList.contains('has-retries')) {
section.classList.remove('section_collapsed');
} else {
Expand Down Expand Up @@ -125,6 +128,57 @@
document.getElementById('skippedList').classList.toggle('collapsed');
}

function handleHostChange() {
var textInput = document.getElementById('viewHostInput');
var viewButtons = document.querySelectorAll('.section__icon_view-local');

textInput.addEventListener('change', function() {
setViewLinkHost(textInput.value);
// will save host to local storage
if (window.localStorage) {
window.localStorage.setItem('_gemini-replace-host', textInput.value);
}
});

// read saved host from local storage
if (window.localStorage) {
var host = window.localStorage.getItem('_gemini-replace-host');
if (host) {
setViewLinkHost(host);
textInput.value = host;
}
}

function setViewLinkHost(host) {
viewButtons.forEach(function(item) {
var href = item.dataset.suiteViewLink,
parsedHost;

if (host) {
parsedHost = url.parse(host, false, true);
// extending current url from entered host
href = url.format(Object.assign(
url.parse(href),
{
host: parsedHost.slashes ? parsedHost.host : host,
protocol: parsedHost.slashes ? parsedHost.protocol : null,
hostname: null,
port: null
}
));
}
item.setAttribute('href', href);
});
}
}

function handleClipboard() {
forEach.call(document.querySelectorAll('.section__icon_copy-to-clipboard'), function(clipboard) {
/* eslint-disable no-new */
new Clipboard(clipboard);
});
}

document.addEventListener('DOMContentLoaded', function() {
document.getElementById('expandAll').addEventListener('click', expandAll);
document.getElementById('collapseAll').addEventListener('click', collapseAll);
Expand All @@ -140,7 +194,16 @@
section.classList.toggle('section_collapsed');
});
});

// turning off event bubbling when click button
forEach.call(document.querySelectorAll('.button'), function(button) {
button.addEventListener('click', function(e) {
e.stopPropagation();
});
});
});

handleClipboard();
handleHostChange();
expandErrors();
}());
3 changes: 2 additions & 1 deletion lib/reporters/html/templates/report.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<button id="showSkipped" class="button">Show skipped</button>
<button id="showRetries" class="button">Expand retries</button>
<button id="showOnlyDiff" class="button">Show only diff</button>
<input id="viewHostInput" class="text-input" size="40" placeholder="change original host for view in browser"/>

<div id="skippedList" class="skipped__list collapsed">
{{#if skips}}
Expand All @@ -36,6 +37,6 @@
{{> suite}}
{{/each}}

<script src="report.js"></script>
<script src="report.min.js"></script>
</body>
</html>
21 changes: 19 additions & 2 deletions lib/reporters/html/templates/suite.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
<div class="section {{collapse}} {{section-status}} {{has-retries}}">
<div class="section__title">{{name}}</div>
<div class="section__title">
{{name}}
{{#if suitePath}}
<button
class="button section__icon section__icon_copy-to-clipboard"
title="copy to clipboard"
data-clipboard-text="{{suitePath}}">
</button>
{{/if}}
</div>
<div class="section__body section__body_guided">
{{#each browsers}}
<div class="section section_collapsed {{section-status}} {{has-retries}}">
Expand All @@ -12,7 +21,15 @@
{{/unless}}
{{/if}}
{{#unless result.skipped}}
<div class="section__title">{{name}}</div>
<div class="section__title">
{{name}}
<a
class="button section__icon section__icon_view-local"
data-suite-view-link="{{result.suiteUrl}}" href="{{result.suiteUrl}}"
title="view in browser"
target="_blank">
</a>
</div>
<div class="section__body">
<div class="image-box {{image-box-status}}">
<div class="cswitcher">
Expand Down
23 changes: 18 additions & 5 deletions lib/reporters/html/view-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ const TestCounter = require('../../test-counter');
const NO_STATE = 'NO_STATE';

module.exports = class ViewModel {
constructor() {
constructor(config) {
this._tree = {name: 'root'};
this._skips = [];
this._counter = new TestCounter();
this._config = config;
}

/**
Expand Down Expand Up @@ -109,15 +110,19 @@ module.exports = class ViewModel {
}

_addTestResult(result, props) {
const metaInfo = result.suite ? result.suite.metaInfo : {};
const browserId = result.browserId;
const rootUrl = this._getRootUrlforBrowser(browserId);
const suite = result.suite;
const metaInfo = suite ? suite.metaInfo : {};
metaInfo.sessionId = result.sessionId || 'unknown session id';

const testResult = _.assign({
name: result.browserId,
suiteUrl: rootUrl + suite.url,
name: browserId,
metaInfo: JSON.stringify(metaInfo, null, 4) || 'Meta info is not available'
}, props);
const node = findOrCreate(this._tree, result.suite.path.concat(result.state ? result.state.name : NO_STATE));

const node = findOrCreate(this._tree, suite.path.concat(result.state ? result.state.name : NO_STATE));
node.browsers = Array.isArray(node.browsers) ? node.browsers : [];

const existing = _.findIndex(node.browsers, {name: testResult.name});
Expand All @@ -137,6 +142,10 @@ module.exports = class ViewModel {
stateInBrowser.result = testResult;
}

_getRootUrlforBrowser(browserId) {
return this._config.forBrowser(browserId).rootUrl;
}

static hasFails(node) {
return walk(node, ViewModel.hasFails, node.result && (node.result.error || node.result.fail));
}
Expand Down Expand Up @@ -170,6 +179,7 @@ function findOrCreate(node, statePath) {
node.children = Array.isArray(node.children) ? node.children : [];

const pathPart = statePath.shift();
node.suitePath = node.suitePath || [];

if (pathPart === NO_STATE) {
return node;
Expand All @@ -178,7 +188,10 @@ function findOrCreate(node, statePath) {
let child = _.find(node.children, {name: pathPart});

if (!child) {
child = {name: pathPart};
child = {
name: pathPart,
suitePath: node.suitePath.concat(pathPart)
};
node.children.push(child);
}

Expand Down
12 changes: 5 additions & 7 deletions lib/reporters/html/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,10 @@ module.exports = {
*/
save: function(html) {
return fs.mkdirsAsync(REPORT_DIR)
.then(function() {
return Promise.all([
fs.writeFileAsync(makeOutFilePath('index.html'), html, 'utf8'),
copyToReportDir('report.js'),
copyToReportDir('report.css')
]);
});
.then(() => Promise.all([
fs.writeFileAsync(makeOutFilePath('index.html'), html, 'utf8'),
copyToReportDir('report.min.js'),
copyToReportDir('report.css')
]));
}
};
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"bluebird-q": "^2.1.1",
"browserify": "^13.0.0",
"chalk": "^1.1.3",
"clipboard": "^1.5.15",
"commander": "^2.8.1",
"css": "^2.1.0",
"debug": "^2.2.0",
Expand Down Expand Up @@ -62,7 +63,9 @@
},
"scripts": {
"test-unit": "istanbul test _mocha -- --recursive test/unit",
"prepublish": "uglifyjs ./lib/browser/client-scripts/gemini.calibrate.js -m > ./lib/browser/client-scripts/gemini.calibrate.min.js --support-ie8",
"prepublish": "npm run prepare-calibrate-script && npm run prepare-report-script",
"prepare-calibrate-script": "uglifyjs ./lib/browser/client-scripts/gemini.calibrate.js -m > ./lib/browser/client-scripts/gemini.calibrate.min.js --support-ie8",
"prepare-report-script": "browserify ./lib/reporters/html/static/report.js | uglifyjs -o ./lib/reporters/html/static/report.min.js",
"postpublish": "npm run publish-site",
"test-func": "istanbul test _mocha test/functional",
"test-browser": "istanbul test _mocha test/browser",
Expand Down
6 changes: 6 additions & 0 deletions test/unit/reporters/html/html.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('HTML Reporter', () => {
path: ['suite/path-default'],
metaInfo: {sessionId: 'sessionId-default'}
},
saveDiffTo: sandbox.stub(),
currentPath: 'current/path-default',
referencePath: 'reference/path-default',
equal: false
Expand All @@ -38,6 +39,11 @@ describe('HTML Reporter', () => {
sandbox.stub(fs, 'mkdirsAsync').returns(Promise.resolve());

emitter = new QEmitter();
emitter.config = {
forBrowser: sinon.stub().returns({
rootUrl: 'browser/root/url'
})
};

// calling constructor for its side effect
new HtmlReporter(emitter); // eslint-disable-line no-new
Expand Down

0 comments on commit 6219b74

Please sign in to comment.