You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

142 lines
3.4 KiB

'use strict';
const EventEmitter = require('events');
const chalk = require('chalk');
const isObj = require('is-obj');
const flatten = require('arr-flatten');
const figures = require('figures');
const autoBind = require('auto-bind');
const prefixTitle = require('./prefix-title');
function sum(arr, key) {
let result = 0;
arr.forEach(item => {
result += item[key];
});
return result;
}
function normalizeError(err) {
if (!isObj(err)) {
err = {
message: err,
stack: err
};
}
return err;
}
class RunStatus extends EventEmitter {
constructor(opts) {
super();
opts = opts || {};
this.prefixTitles = opts.prefixTitles !== false;
this.hasExclusive = Boolean(opts.runOnlyExclusive);
this.base = opts.base || '';
this.rejectionCount = 0;
this.exceptionCount = 0;
this.passCount = 0;
this.knownFailureCount = 0;
this.skipCount = 0;
this.todoCount = 0;
this.failCount = 0;
this.fileCount = 0;
this.testCount = 0;
this.remainingCount = 0;
this.previousFailCount = 0;
this.knownFailures = [];
this.errors = [];
this.stats = [];
this.tests = [];
this.failFastEnabled = opts.failFast || false;
autoBind(this);
}
observeFork(emitter) {
emitter
.on('teardown', this.handleTeardown)
.on('stats', this.handleStats)
.on('test', this.handleTest)
.on('unhandledRejections', this.handleRejections)
.on('uncaughtException', this.handleExceptions)
.on('stdout', this.handleOutput.bind(this, 'stdout'))
.on('stderr', this.handleOutput.bind(this, 'stderr'));
}
handleRejections(data) {
this.rejectionCount += data.rejections.length;
data.rejections.forEach(err => {
err = normalizeError(err);
err.type = 'rejection';
err.file = data.file;
this.emit('error', err, this);
this.errors.push(err);
});
}
handleExceptions(data) {
this.exceptionCount++;
const err = normalizeError(data.exception);
err.type = 'exception';
err.file = data.file;
this.emit('error', err, this);
this.errors.push(err);
}
handleTeardown(data) {
this.emit('dependencies', data.file, data.dependencies, this);
}
handleStats(stats) {
this.emit('stats', stats, this);
if (stats.hasExclusive) {
this.hasExclusive = true;
}
this.testCount += stats.testCount;
}
handleTest(test) {
test.title = this.prefixTitle(test.file) + test.title;
if (test.error) {
if (test.error.name !== 'AssertionError') {
test.error.message = `Error: ${test.error.message}`;
}
this.errors.push(test);
}
if (test.failing && !test.error) {
this.knownFailures.push(test);
}
this.emit('test', test, this);
}
prefixTitle(file) {
if (!this.prefixTitles) {
return '';
}
const separator = ' ' + chalk.gray.dim(figures.pointerSmall) + ' ';
return prefixTitle(file, this.base, separator);
}
handleOutput(channel, data) {
this.emit(channel, data, this);
}
processResults(results) {
// Assemble stats from all tests
this.stats = results.map(result => result.stats);
this.tests = results.map(result => result.tests);
this.tests = flatten(this.tests);
this.passCount = sum(this.stats, 'passCount');
this.knownFailureCount = sum(this.stats, 'knownFailureCount');
this.skipCount = sum(this.stats, 'skipCount');
this.todoCount = sum(this.stats, 'todoCount');
this.failCount = sum(this.stats, 'failCount');
this.remainingCount = this.testCount - this.passCount - this.failCount - this.skipCount - this.todoCount - this.knownFailureCount;
}
}
module.exports = RunStatus;