Browse Source

Merge pull request #363 from sindresorhus/reporters

Internal reporters
babel-plugin-for-integration-tests
Sindre Sorhus 9 years ago
parent
commit
94fbb1a384
  1. 78
      cli.js
  2. 114
      lib/logger.js
  3. 38
      lib/reporters/tap.js
  4. 109
      lib/reporters/verbose.js
  5. 10
      test/cli.js
  6. 261
      test/logger.js
  7. 45
      test/reporters/tap.js
  8. 243
      test/reporters/verbose.js

78
cli.js

@ -17,13 +17,15 @@ if (debug.enabled) {
require('time-require'); require('time-require');
} }
var updateNotifier = require('update-notifier');
var figures = require('figures');
var arrify = require('arrify'); var arrify = require('arrify');
var meow = require('meow'); var meow = require('meow');
var updateNotifier = require('update-notifier');
var chalk = require('chalk'); var chalk = require('chalk');
var Promise = require('bluebird'); var Promise = require('bluebird');
var log = require('./lib/logger'); var verboseReporter = require('./lib/reporters/verbose');
var tap = require('./lib/tap'); var tapReporter = require('./lib/reporters/tap');
var Logger = require('./lib/logger');
var Api = require('./api'); var Api = require('./api');
// Bluebird specific // Bluebird specific
@ -68,75 +70,37 @@ if (cli.flags.init) {
return; return;
} }
if (cli.flags.tap) {
console.log(tap.start());
} else {
log.write();
}
var api = new Api(cli.input, { var api = new Api(cli.input, {
failFast: cli.flags.failFast, failFast: cli.flags.failFast,
serial: cli.flags.serial, serial: cli.flags.serial,
require: arrify(cli.flags.require) require: arrify(cli.flags.require)
}); });
api.on('test', function (test) { var logger = new Logger();
if (cli.flags.tap) { logger.api = api;
console.log(tap.test(test));
return;
}
if (test.error) { if (cli.flags.tap) {
log.error(test.title, chalk.red(test.error.message)); logger.use(tapReporter());
} else { } else {
// don't log it if there's only one file and one anonymous test logger.use(verboseReporter());
if (api.fileCount === 1 && api.testCount === 1 && test.title === '[anonymous]') {
return;
} }
log.test(test); logger.start();
}
});
api.on('error', function (data) {
if (cli.flags.tap) {
console.log(tap.unhandledError(data));
return;
}
log.unhandledError(data.type, data.file, data); api.on('test', logger.test);
}); api.on('error', logger.unhandledError);
api.run() api.run()
.then(function () { .then(function () {
if (cli.flags.tap) { logger.finish();
console.log(tap.finish(api.passCount, api.failCount, api.rejectionCount, api.exceptionCount)); logger.exit(api.failCount > 0 || api.rejectionCount > 0 || api.exceptionCount > 0 ? 1 : 0);
})
.catch(function (err) {
if (err instanceof Error) {
console.log(' ' + chalk.red(figures.cross) + ' ' + err.message);
} else { } else {
log.write(); console.error(err.stack);
log.report(api.passCount, api.failCount, api.rejectionCount, api.exceptionCount);
log.write();
if (api.failCount > 0) {
log.errors(api.errors);
}
} }
process.stdout.write(''); logger.exit(1);
flushIoAndExit(api.failCount > 0 || api.rejectionCount > 0 || api.exceptionCount > 0 ? 1 : 0);
})
.catch(function (err) {
log.error(err.message);
flushIoAndExit(1);
}); });
function flushIoAndExit(code) {
// TODO: figure out why this needs to be here to
// correctly flush the output when multiple test files
process.stdout.write('');
process.stderr.write('');
// timeout required to correctly flush IO on Node.js 0.10 on Windows
setTimeout(function () {
process.exit(code);
}, process.env.AVA_APPVEYOR ? 500 : 0);
}

114
lib/logger.js

@ -1,98 +1,66 @@
'use strict'; 'use strict';
var prettyMs = require('pretty-ms');
var figures = require('figures');
var Squeak = require('squeak');
var chalk = require('chalk');
var plur = require('plur');
var log = new Squeak({separator: ' '});
var x = module.exports;
function beautifyStack(stack) { function Logger() {
var re = /(?:^(?! {4}at\b).{6})|(?:\((?:[A-Z]:)?(?:[\\\/](?:(?!node_modules[\\\/]ava[\\\/])[^:\\\/])+)+:\d+:\d+\))/; if (!(this instanceof Logger)) {
var found = false; return new Logger();
return stack.split('\n').filter(function (line) {
var relevant = re.test(line);
found = found || relevant;
return !found || relevant;
}).join('\n');
} }
x._beautifyStack = beautifyStack; Object.keys(Logger.prototype).forEach(function (key) {
this[key] = this[key].bind(this);
log.type('success', { }, this);
color: 'green', }
prefix: figures.tick
});
log.type('error', {
color: 'red',
prefix: figures.cross
});
x.write = log.write.bind(log); module.exports = Logger;
x.writelpad = log.writelpad.bind(log);
x.success = log.success.bind(log);
x.error = log.error.bind(log);
x.test = function (props) { Logger.prototype.use = function (reporter) {
if (props.err) { this.reporter = reporter;
log.error(props.title, chalk.red(props.err.message)); this.reporter.api = this.api;
return; };
}
if (props.skip) { Logger.prototype.start = function () {
log.write(' ' + chalk.cyan('- ' + props.title)); if (!this.reporter.start) {
return; return;
} }
// display duration only over a threshold this.write(this.reporter.start());
var threshold = 100;
var dur = props.duration > threshold ? chalk.gray.dim(' (' + prettyMs(props.duration) + ')') : '';
log.success(props.title + dur);
}; };
x.errors = function (tests) { Logger.prototype.test = function (test) {
var i = 0; this.write(this.reporter.test(test));
};
tests.forEach(function (test) { Logger.prototype.unhandledError = function (err) {
i++; if (!this.reporter.unhandledError) {
return;
}
log.writelpad(chalk.red(i + '.', test.title)); this.write(this.reporter.unhandledError(err));
log.writelpad(chalk.red(beautifyStack(test.error.stack)));
log.write();
});
}; };
x.report = function (passed, failed, unhandled, uncaught) { Logger.prototype.finish = function () {
if (failed > 0) { if (!this.reporter.finish) {
log.writelpad(chalk.red(failed, plur('test', failed), 'failed')); return;
} else {
log.writelpad(chalk.green(passed, plur('test', passed), 'passed'));
} }
if (unhandled > 0) { this.write(this.reporter.finish());
log.writelpad(chalk.red(unhandled, 'unhandled', plur('rejection', unhandled))); };
}
if (uncaught > 0) { Logger.prototype.write = function (str) {
log.writelpad(chalk.red(uncaught, 'uncaught', plur('exception', uncaught))); if (typeof str === 'undefined') {
return;
} }
};
var types = { this.reporter.write(str);
rejection: 'Unhandled Rejection',
exception: 'Uncaught Exception'
}; };
x.unhandledError = function (type, file, error) { Logger.prototype.exit = function (code) {
log.write(chalk.red(types[type] + ':', file)); // TODO: figure out why this needs to be here to
// correctly flush the output when multiple test files
if (error.stack) { process.stdout.write('');
log.writelpad(chalk.red(beautifyStack(error.stack))); process.stderr.write('');
} else {
log.writelpad(chalk.red(JSON.stringify(error)));
}
log.write(); // timeout required to correctly flush IO on Node.js 0.10 on Windows
setTimeout(function () {
process.exit(code);
}, process.env.AVA_APPVEYOR ? 500 : 0);
}; };

38
lib/tap.js → lib/reporters/tap.js

@ -10,19 +10,27 @@ function getSourceFromStack(stack, index) {
.replace(/^\s+at /, ''); .replace(/^\s+at /, '');
} }
exports.start = function () { function TapReporter() {
if (!(this instanceof TapReporter)) {
return new TapReporter();
}
this.i = 0;
}
module.exports = TapReporter;
TapReporter.prototype.start = function () {
return 'TAP version 13'; return 'TAP version 13';
}; };
var i = 0; TapReporter.prototype.test = function (test) {
exports.test = function (test) {
var output; var output;
if (test.error) { if (test.error) {
output = [ output = [
'# ' + test.title, '# ' + test.title,
format('not ok %d - %s', ++i, test.error.message), format('not ok %d - %s', ++this.i, test.error.message),
' ---', ' ---',
' operator: ' + test.error.operator, ' operator: ' + test.error.operator,
' expected: ' + test.error.expected, ' expected: ' + test.error.expected,
@ -33,17 +41,17 @@ exports.test = function (test) {
} else { } else {
output = [ output = [
'# ' + test.title, '# ' + test.title,
format('ok %d - %s', ++i, test.title) format('ok %d - %s', ++this.i, test.title)
]; ];
} }
return output.join('\n'); return output.join('\n');
}; };
exports.unhandledError = function (err) { TapReporter.prototype.unhandledError = function (err) {
var output = [ var output = [
'# ' + err.message, '# ' + err.message,
format('not ok %d - %s', ++i, err.message), format('not ok %d - %s', ++this.i, err.message),
' ---', ' ---',
' name: ' + err.name, ' name: ' + err.name,
' at: ' + getSourceFromStack(err.stack, 1), ' at: ' + getSourceFromStack(err.stack, 1),
@ -53,15 +61,19 @@ exports.unhandledError = function (err) {
return output.join('\n'); return output.join('\n');
}; };
exports.finish = function (passCount, failCount, rejectionCount, exceptionCount) { TapReporter.prototype.finish = function () {
var output = [ var output = [
'', '',
'1..' + (passCount + failCount), '1..' + (this.api.passCount + this.api.failCount),
'# tests ' + (passCount + failCount), '# tests ' + (this.api.passCount + this.api.failCount),
'# pass ' + passCount, '# pass ' + this.api.passCount,
'# fail ' + (failCount + rejectionCount + exceptionCount), '# fail ' + (this.api.failCount + this.api.rejectionCount + this.api.exceptionCount),
'' ''
]; ];
return output.join('\n'); return output.join('\n');
}; };
TapReporter.prototype.write = function (str) {
console.log(str);
};

109
lib/reporters/verbose.js

@ -0,0 +1,109 @@
'use strict';
var prettyMs = require('pretty-ms');
var figures = require('figures');
var chalk = require('chalk');
var plur = require('plur');
function beautifyStack(stack) {
var re = /(?:^(?! {4}at\b).{6})|(?:\((?:[A-Z]:)?(?:[\\\/](?:(?!node_modules[\\\/]ava[\\\/])[^:\\\/])+)+:\d+:\d+\))/;
var found = false;
return stack.split('\n').filter(function (line) {
var relevant = re.test(line);
found = found || relevant;
return !found || relevant;
}).join('\n');
}
function VerboseReporter() {
if (!(this instanceof VerboseReporter)) {
return new VerboseReporter();
}
}
module.exports = VerboseReporter;
module.exports._beautifyStack = beautifyStack;
VerboseReporter.prototype.start = function () {
return '';
};
VerboseReporter.prototype.test = function (test) {
if (test.error) {
return ' ' + chalk.red(figures.cross) + ' ' + test.title + ' ' + chalk.red(test.error.message);
}
if (test.skip) {
return ' ' + chalk.cyan('- ' + test.title);
}
if (this.api.fileCount === 1 && this.api.testCount === 1 && test.title === '[anonymous]') {
return null;
}
// display duration only over a threshold
var threshold = 100;
var duration = test.duration > threshold ? chalk.gray.dim(' (' + prettyMs(test.duration) + ')') : '';
return ' ' + chalk.green(figures.tick) + ' ' + test.title + duration;
};
VerboseReporter.prototype.unhandledError = function (err) {
var types = {
rejection: 'Unhandled Rejection',
exception: 'Uncaught Exception'
};
var output = chalk.red(types[err.type] + ':', err.file) + '\n';
if (err.stack) {
output += ' ' + chalk.red(beautifyStack(err.stack)) + '\n';
} else {
output += ' ' + chalk.red(JSON.stringify(err)) + '\n';
}
output += '\n';
return output;
};
VerboseReporter.prototype.finish = function () {
var output = '\n';
if (this.api.failCount > 0) {
output += ' ' + chalk.red(this.api.failCount, plur('test', this.api.failCount), 'failed') + '\n';
} else {
output += ' ' + chalk.green(this.api.passCount, plur('test', this.api.passCount), 'passed') + '\n';
}
if (this.api.rejectionCount > 0) {
output += ' ' + chalk.red(this.api.rejectionCount, 'unhandled', plur('rejection', this.api.rejectionCount)) + '\n';
}
if (this.api.exceptionCount > 0) {
output += ' ' + chalk.red(this.api.exceptionCount, 'uncaught', plur('exception', this.api.exceptionCount)) + '\n';
}
if (this.api.failCount > 0) {
output += '\n';
var i = 0;
this.api.tests.forEach(function (test) {
if (!test.error.message) {
return;
}
i++;
output += ' ' + chalk.red(i + '.', test.title) + '\n';
output += ' ' + chalk.red(beautifyStack(test.error.stack)) + '\n';
});
}
return output;
};
VerboseReporter.prototype.write = function (str) {
console.error(str);
};

10
test/cli.js

@ -19,16 +19,6 @@ function execCli(args, cb) {
}, cb); }, cb);
} }
test('don\'t display test title if there is only one anonymous test', function (t) {
t.plan(2);
execCli(['fixture/es2015.js'], function (err, stdout, stderr) {
t.ifError(err);
t.is(stderr.trim(), '1 test passed');
t.end();
});
});
test('throwing a named function will report the to the console', function (t) { test('throwing a named function will report the to the console', function (t) {
execCli('fixture/throw-named-function.js', function (err, stdout, stderr) { execCli('fixture/throw-named-function.js', function (err, stdout, stderr) {
t.ok(err); t.ok(err);

261
test/logger.js

@ -1,261 +0,0 @@
'use strict';
var test = require('tap').test;
var logger = require('../lib/logger');
var figures = require('figures');
var hookStd = require('hook-std');
test('beautify stack - removes uninteresting lines', function (t) {
try {
fooFunc();
} catch (err) {
var stack = logger._beautifyStack(err.stack);
t.match(stack, /fooFunc/);
t.match(stack, /barFunc/);
t.match(err.stack, /Module._compile/);
t.notMatch(stack, /Module\._compile/);
t.end();
}
});
test('logger.write', function (t) {
t.plan(1);
var unhook = hookStd.stderr({silent: true}, function (output) {
unhook();
t.is(output.toString(), 'Test');
t.end();
});
logger.write('Test');
});
test('logger.writelpad', function (t) {
t.plan(1);
var unhook = hookStd.stderr({silent: true}, function (output) {
unhook();
t.is(output.toString(), ' Test');
t.end();
});
logger.writelpad('Test');
});
test('logger.success', function (t) {
t.plan(1);
var unhook = hookStd.stderr({silent: true}, function (output) {
unhook();
t.is(output.toString(), ' ' + figures.tick + ' Test');
t.end();
});
logger.success('Test');
});
test('logger.error', function (t) {
t.plan(1);
var unhook = hookStd.stderr({silent: true}, function (output) {
unhook();
t.is(output.toString(), ' ' + figures.cross + ' Test');
t.end();
});
logger.error('Test');
});
test('logger.test with passing test and duration less than threshold', function (t) {
t.plan(1);
var passingTest = {
title: 'Passed',
duration: 90
};
var unhook = hookStd.stderr({silent: true}, function (output) {
unhook();
t.is(output.toString(), ' ' + figures.tick + ' Passed');
t.end();
});
logger.test(passingTest);
});
test('logger.test with passing test and duration greater than threshold', function (t) {
t.plan(1);
var passingTest = {
title: 'Passed',
duration: 150
};
var unhook = hookStd.stderr({silent: true}, function (output) {
unhook();
t.is(output.toString(), ' ' + figures.tick + ' Passed (150ms)');
t.end();
});
logger.test(passingTest);
});
test('logger.test with failing test', function (t) {
t.plan(1);
var passingTest = {
title: 'Failed',
err: {
message: 'Assertion failed'
}
};
var unhook = hookStd.stderr({silent: true}, function (output) {
unhook();
t.is(output.toString(), ' ' + figures.cross + ' Failed Assertion failed');
t.end();
});
logger.test(passingTest);
});
test('logger.test with skipped test', function (t) {
t.plan(1);
var skippedTest = {
title: 'Skipped',
skipped: true
};
var unhook = hookStd.stderr({silent: true}, function (output) {
unhook();
t.is(output.toString(), ' ' + figures.tick + ' Skipped');
t.end();
});
logger.test(skippedTest);
});
test('logger.errors', function (t) {
t.plan(1);
var lines = [];
var failedTest = {
title: 'Failed',
error: {
stack: 'Unexpected token'
}
};
hookStd.stderr({silent: true}, function (output) {
onLine(lines, output);
});
logger.errors([failedTest]);
t.is(lines.join(''), '1. Failed\nUnexpected token\n');
});
test('logger.report', function (t) {
t.plan(1);
var lines = [];
hookStd.stderr({silent: true}, function (output) {
onLine(lines, output);
});
logger.report(1, 2, 1, 2);
t.is(lines.join(''), '2 tests failed\n1 unhandled rejection\n2 uncaught exceptions\n');
});
test('logger.unhandledError with exception with stack', function (t) {
t.plan(3);
var lines = [];
hookStd.stderr({silent: true}, function (output) {
onLine(lines, output);
});
logger.unhandledError('exception', 'test.js', new Error('Unexpected token'));
t.is(lines[0], 'Uncaught Exception: test.js\n');
t.match(lines[1], /Error: Unexpected token\n/);
t.match(lines[1], /at Test.test/);
});
test('logger.unhandledError with exception without stack', function (t) {
t.plan(2);
var lines = [];
var error = {
message: 'Unexpected token'
};
hookStd.stderr({silent: true}, function (output) {
onLine(lines, output);
});
logger.unhandledError('exception', 'test.js', error);
t.is(lines[0], 'Uncaught Exception: test.js\n');
t.is(lines[1], '{"message":"Unexpected token"}\n');
});
test('logger.unhandledError rejection with stack', function (t) {
t.plan(3);
var lines = [];
hookStd.stderr({silent: true}, function (output) {
onLine(lines, output);
});
logger.unhandledError('rejection', 'test.js', new Error('I have been rejected'));
t.is(lines[0], 'Unhandled Rejection: test.js\n');
t.match(lines[1], /Error: I have been rejected\n/);
t.match(lines[1], /at Test.test/);
});
test('logger.unhandledError rejection without stack', function (t) {
t.plan(2);
var lines = [];
var error = {
message: 'I have been rejected'
};
hookStd.stderr({silent: true}, function (output) {
onLine(lines, output);
});
logger.unhandledError('rejection', 'test.js', error);
t.is(lines[0], 'Unhandled Rejection: test.js\n');
t.is(lines[1], '{"message":"I have been rejected"}\n');
});
function fooFunc() {
barFunc();
}
function barFunc() {
throw new Error();
}
function onLine(lines, line) {
var trimmed = line.trim();
if (trimmed.length) {
lines.push(line.trim() + '\n');
}
}

45
test/tap.js → test/reporters/tap.js

@ -1,14 +1,18 @@
'use strict'; 'use strict';
var test = require('tap').test; var test = require('tap').test;
var tap = require('../lib/tap'); var tapReporter = require('../../lib/reporters/tap');
test('start', function (t) { test('start', function (t) {
t.is(tap.start(), 'TAP version 13'); var reporter = tapReporter();
t.is(reporter.start(), 'TAP version 13');
t.end(); t.end();
}); });
test('passing test', function (t) { test('passing test', function (t) {
var actualOutput = tap.test({ var reporter = tapReporter();
var actualOutput = reporter.test({
title: 'passing' title: 'passing'
}); });
@ -22,7 +26,9 @@ test('passing test', function (t) {
}); });
test('failing test', function (t) { test('failing test', function (t) {
var actualOutput = tap.test({ var reporter = tapReporter();
var actualOutput = reporter.test({
title: 'failing', title: 'failing',
error: { error: {
message: 'false == true', message: 'false == true',
@ -35,7 +41,7 @@ test('failing test', function (t) {
var expectedOutput = [ var expectedOutput = [
'# failing', '# failing',
'not ok 2 - false == true', 'not ok 1 - false == true',
' ---', ' ---',
' operator: ==', ' operator: ==',
' expected: true', ' expected: true',
@ -49,7 +55,9 @@ test('failing test', function (t) {
}); });
test('unhandled error', function (t) { test('unhandled error', function (t) {
var actualOutput = tap.unhandledError({ var reporter = tapReporter();
var actualOutput = reporter.unhandledError({
message: 'unhandled', message: 'unhandled',
name: 'TypeError', name: 'TypeError',
stack: ['', ' at Test.fn (test.js:1:2)'].join('\n') stack: ['', ' at Test.fn (test.js:1:2)'].join('\n')
@ -57,7 +65,7 @@ test('unhandled error', function (t) {
var expectedOutput = [ var expectedOutput = [
'# unhandled', '# unhandled',
'not ok 3 - unhandled', 'not ok 1 - unhandled',
' ---', ' ---',
' name: TypeError', ' name: TypeError',
' at: Test.fn (test.js:1:2)', ' at: Test.fn (test.js:1:2)',
@ -69,18 +77,23 @@ test('unhandled error', function (t) {
}); });
test('results', function (t) { test('results', function (t) {
var passCount = 1; var reporter = tapReporter();
var failCount = 2; var api = {
var rejectionCount = 3; passCount: 1,
var exceptionCount = 4; failCount: 2,
rejectionCount: 3,
exceptionCount: 4
};
reporter.api = api;
var actualOutput = tap.finish(passCount, failCount, rejectionCount, exceptionCount); var actualOutput = reporter.finish();
var expectedOutput = [ var expectedOutput = [
'', '',
'1..' + (passCount + failCount), '1..' + (api.passCount + api.failCount),
'# tests ' + (passCount + failCount), '# tests ' + (api.passCount + api.failCount),
'# pass ' + passCount, '# pass ' + api.passCount,
'# fail ' + (failCount + rejectionCount + exceptionCount), '# fail ' + (api.failCount + api.rejectionCount + api.exceptionCount),
'' ''
].join('\n'); ].join('\n');

243
test/reporters/verbose.js

@ -0,0 +1,243 @@
'use strict';
var figures = require('figures');
var chalk = require('chalk');
var test = require('tap').test;
var verboseReporter = require('../../lib/reporters/verbose');
function createReporter() {
var reporter = verboseReporter();
reporter.api = {
fileCount: 1,
testCount: 1
};
return reporter;
}
test('beautify stack - removes uninteresting lines', function (t) {
try {
fooFunc();
} catch (err) {
var stack = verboseReporter._beautifyStack(err.stack);
t.match(stack, /fooFunc/);
t.match(stack, /barFunc/);
t.match(err.stack, /Module._compile/);
t.notMatch(stack, /Module\._compile/);
t.end();
}
});
test('start', function (t) {
var reporter = createReporter();
t.is(reporter.start(), '');
t.end();
});
test('passing test and duration less than threshold', function (t) {
var reporter = createReporter();
var actualOutput = reporter.test({
title: 'passed',
duration: 90
});
var expectedOutput = ' ' + chalk.green(figures.tick) + ' passed';
t.is(actualOutput, expectedOutput);
t.end();
});
test('passing test and duration greater than threshold', function (t) {
var reporter = createReporter();
var actualOutput = reporter.test({
title: 'passed',
duration: 150
});
var expectedOutput = ' ' + chalk.green(figures.tick) + ' passed' + chalk.grey.dim(' (150ms)');
t.is(actualOutput, expectedOutput);
t.end();
});
test('don\'t display test title if there is only one anonymous test', function (t) {
var reporter = createReporter();
var output = reporter.test({
title: '[anonymous]'
});
t.is(output, undefined);
t.end();
});
test('failing test', function (t) {
var reporter = createReporter();
var actualOutput = reporter.test({
title: 'failed',
err: {
message: 'assertion failed'
}
});
var expectedOutput = ' ' + chalk.red(figures.cross) + ' failed ' + chalk.red('assertion failed');
t.is(actualOutput, expectedOutput);
t.end();
});
test('skipped test', function (t) {
var reporter = createReporter();
var actualOutput = reporter.test({
title: 'skipped',
skip: true
});
var expectedOutput = ' ' + chalk.cyan('- skipped');
t.is(actualOutput, expectedOutput);
t.end();
});
test('uncaught exception', function (t) {
var reporter = createReporter();
var output = reporter.unhandledError({
type: 'exception',
file: 'test.js',
stack: new Error('Unexpected token').stack
}).split('\n');
t.is(output[0], chalk.red('Uncaught Exception: test.js'));
t.match(output[1], /Error: Unexpected token/);
t.match(output[2], /at Test\.test/);
t.end();
});
test('unhandled rejection', function (t) {
var reporter = createReporter();
var output = reporter.unhandledError({
type: 'rejection',
file: 'test.js',
stack: new Error('Unexpected token').stack
}).split('\n');
t.is(output[0], chalk.red('Unhandled Rejection: test.js'));
t.match(output[1], /Error: Unexpected token/);
t.match(output[2], /at Test\.test/);
t.end();
});
test('unhandled error without stack', function (t) {
var reporter = createReporter();
var err = {
type: 'exception',
file: 'test.js',
message: 'test'
};
var output = reporter.unhandledError(err).split('\n');
t.is(output[0], chalk.red('Uncaught Exception: test.js'));
t.is(output[1], ' ' + chalk.red(JSON.stringify(err)));
t.end();
});
test('results with passing tests', function (t) {
var reporter = createReporter();
reporter.api.passCount = 1;
var actualOutput = reporter.finish();
var expectedOutput = [
'',
' ' + chalk.green('1 test passed'),
''
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
});
test('results with passing tests and rejections', function (t) {
var reporter = createReporter();
reporter.api.passCount = 1;
reporter.api.rejectionCount = 1;
var actualOutput = reporter.finish();
var expectedOutput = [
'',
' ' + chalk.green('1 test passed'),
' ' + chalk.red('1 unhandled rejection'),
''
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
});
test('results with passing tests and exceptions', function (t) {
var reporter = createReporter();
reporter.api.passCount = 1;
reporter.api.exceptionCount = 1;
var actualOutput = reporter.finish();
var expectedOutput = [
'',
' ' + chalk.green('1 test passed'),
' ' + chalk.red('1 uncaught exception'),
''
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
});
test('results with passing tests, rejections and exceptions', function (t) {
var reporter = createReporter();
reporter.api.passCount = 1;
reporter.api.exceptionCount = 1;
reporter.api.rejectionCount = 1;
var actualOutput = reporter.finish();
var expectedOutput = [
'',
' ' + chalk.green('1 test passed'),
' ' + chalk.red('1 unhandled rejection'),
' ' + chalk.red('1 uncaught exception'),
''
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
});
test('results with errors', function (t) {
var reporter = createReporter();
reporter.api.failCount = 1;
reporter.api.tests = [{
title: 'fail',
error: new Error('error message')
}];
var output = reporter.finish().split('\n');
t.is(output[1], ' ' + chalk.red('1 test failed'));
t.is(output[3], ' ' + chalk.red('1. fail'));
t.match(output[4], /Error: error message/);
t.match(output[5], /Test\.test/);
t.end();
});
function fooFunc() {
barFunc();
}
function barFunc() {
throw new Error();
}
Loading…
Cancel
Save