incubed
Version:
Typescript-version of the incubed client
148 lines • 7.33 kB
JavaScript
;
/***********************************************************
* This file is part of the Slock.it IoT Layer. *
* The Slock.it IoT Layer contains: *
* - USN (Universal Sharing Network) *
* - INCUBED (Trustless INcentivized remote Node Network) *
************************************************************
* Copyright (C) 2016 - 2018 Slock.it GmbH *
* All Rights Reserved. *
************************************************************
* You may use, distribute and modify this code under the *
* terms of the license contract you have concluded with *
* Slock.it GmbH. *
* For information about liability, maintenance etc. also *
* refer to the contract concluded with Slock.it GmbH. *
************************************************************
* For more information, please refer to https://slock.it *
* For questions, please contact info@slock.it *
***********************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
const mocha = require("mocha");
// tslint:disable-next-line:no-submodule-imports
const mu = require("mocha/lib/utils");
const fs = require("fs");
const memoryLogger_1 = require("./memoryLogger");
function color(colorName, content) {
return `<span style="color:${colorName}">${content}</span>`;
}
/**
*
* reporter writing html including logs
*
* @export
* @class USNReporter
*/
class TestReporter extends mocha.reporters.Spec {
constructor(runner) {
super(runner);
this.root = 'test/report/';
this.results = [];
runner.on('pass', (test) => this.reportTest(test, null, false));
runner.on('fail', (test, error) => this.reportTest(test, error, false));
runner.on('pending', (test) => this.reportTest(test, null, true));
runner.on('end', () => this.createIndex());
runner.on('test', () => this.lastStart = Date.now());
if (!fs.existsSync(this.root))
fs.mkdirSync(this.root);
}
writeHtml(fileName, title, body) {
fs.writeFileSync(this.root + fileName, '<html><head><style>' +
'body, td { background-color: black; color:white; font-family: sans-serif; vertical-align:top; padding-right:10px;padding-bottom:10px }'
+ '</style><title>' + title + '</title></head><body>' + body + '</body></html>', 'utf-8');
}
createIndex() {
this.writeHtml('index.html', 'Test Result', '<h2>Test Results</h2>'
+ '<div style="padding-bottom:10px"><a style="color:yellow" href="coverage/index.html">Code Coverage</a></div>'
+ '<table border=0 cellspacing=0 cellpadding=0>'
+ this.results.map(r => '<tr><td colspan=2>' + r.title + '</td></tr>' + r.tests.map(t => `<tr><td> - </td><td><a style='color:${t.status === 'pass' ? 'green' : (t.status === 'fail' ? 'red' : 'white')}' href="${t.details}">${t.title}</a></td><td style='text-align:end'>${t.time} ms</td><td>${t.error || ''}</td></tr>`).join('')).join('')
+ '</table>');
}
createError(test) {
if (!test.err)
return { message: '', stack: '' };
let message = test.err.toString();
let stackString;
// <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
// check for the result of the stringifying.
if (message === '[object Error]')
message = test.err.message;
if (test.err.stack) {
const indexOfMessage = test.err.stack.indexOf(test.err.message);
stackString = (indexOfMessage === -1)
? test.err.stack
: test.err.stack.substr(test.err.message.length + indexOfMessage);
}
else if (test.err.sourceURL && test.err.line !== undefined) {
// Safari doesn't give you a stack. Let's at least provide a source line.
stackString = '\n(' + test.err.sourceURL + ':' + test.err.line + ')';
}
stackString = stackString || '';
return { message, stack: stackString, err: test.err };
}
reportTest(test, error, pending) {
const err = this.createError(test);
const logs = memoryLogger_1.getLogsAndClear();
const title = test.fullTitle();
const simpleTitle = test.title;
const parentTitle = test.parent.title;
const now = Date.now();
const fName = title.replace(/\W/g, '_') + '.html';
const eq = (error && error.expected !== undefined && '<span style="font-family:monospace; color:green">' + mu.stringify(error.expected)
+ '</span> != <br/><span style="font-family:monospace; color:red">' + mu.stringify(error.actual) + '</span>') || '';
let suite = this.results.find(_ => _.title === parentTitle);
if (!suite)
this.results.push(suite = { title: parentTitle, tests: [] });
this.createIndex();
const res = {
title: simpleTitle,
status: pending ? 'pending' : (error ? 'fail' : 'pass'),
time: now - this.lastStart,
error: error && err.message + '<br/>' + eq + ' <pre style="color:grey">npm test -- --grep \"' + simpleTitle + '\" </pre>',
details: fName
};
suite.tests.push(res);
setTimeout(() => {
const log = toHTML(logs);
this.writeHtml(fName, simpleTitle, '<h2>' + parentTitle + ' / ' + simpleTitle + '</h2>'
+ ' <ul><li>Time : ' + res.time + '</li>'
+ '<li>Result: ' + (pending ? color('gray', 'skipped') : (error ? color('red', 'failed') : color('green', 'passed'))) + '</li>'
+ (error ? '<li>Error: ' + err.message + '<br>' + eq + getFileContent(err.stack) + ' <pre>' + err.stack + '</pre></li>' : '')
+ '</ul>'
+ '<h3>Log:</h3>' + log);
}, 0);
}
}
function toHTML(logs) {
return '<div style="font-family: monospace;white-space:pre">' + logs.map((log, i) => {
let l = '<div style="color:';
if (log.level === 'info')
l += 'white';
if (log.level === 'error')
l += 'red';
if (log.level === 'tx')
l += 'green';
if (log.level === 'debug')
l += 'gray';
l += '">' + (i + 1) + ' | ' + log.level.toUpperCase() + ' ' + log.message;
if (log.data) {
l += log.data.map(d => '<div style="padding-left:30px;color:gray">' + JSON.stringify(d, null, 2) + '</div>').join('');
}
return l + '</div>';
}).join('') + '</div>';
}
function getFileContent(stack) {
const reg = /at.*?\((js\/test\/.*?\.js):(\d+)/;
const found = stack.match(reg);
if (!found)
return '';
const file = found[1];
const line = parseInt(found[2]);
let r = '<pre style="color:grey">';
const content = fs.readFileSync(file, 'utf-8').split('\n');
for (let i = Math.max(0, line - 4); i < Math.min(content.length - 1, line + 3); i++)
r += '' + (i + 1) + ' <span ' + (i === line - 1 ? ' style="color:red"' : '') + '>' + content[i] + '</span>\n';
return r + '</pre>';
}
module.exports = TestReporter;
//# sourceMappingURL=mochaReporter.js.map