ava 0.16.0 → 0.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.js +297 -265
- package/cli.js +15 -179
- package/index.js +5 -98
- package/index.js.flow +201 -0
- package/lib/assert.js +87 -53
- package/lib/ava-error.js +4 -8
- package/lib/ava-files.js +282 -0
- package/lib/babel-config.js +35 -73
- package/lib/beautify-stack.js +17 -16
- package/lib/caching-precompiler.js +72 -87
- package/lib/cli.js +181 -0
- package/lib/code-excerpt.js +57 -0
- package/lib/colors.js +6 -2
- package/lib/concurrent.js +62 -75
- package/lib/enhance-assert.js +57 -49
- package/lib/extract-stack.js +10 -0
- package/lib/fork.js +67 -68
- package/lib/format-assert-error.js +72 -0
- package/lib/globals.js +3 -8
- package/lib/hook.js +15 -20
- package/lib/logger.js +59 -82
- package/lib/main.js +90 -0
- package/lib/prefix-title.js +21 -0
- package/lib/process-adapter.js +108 -0
- package/lib/reporters/mini.js +260 -257
- package/lib/reporters/tap.js +80 -85
- package/lib/reporters/verbose.js +142 -115
- package/lib/run-status.js +110 -152
- package/lib/runner.js +125 -137
- package/lib/sequence.js +68 -84
- package/lib/serialize-error.js +68 -4
- package/lib/snapshot-state.js +30 -0
- package/lib/test-collection.js +144 -156
- package/lib/test-worker.js +45 -95
- package/lib/test.js +289 -318
- package/lib/throws-helper.js +9 -9
- package/lib/validate-test.js +48 -0
- package/lib/watcher.js +258 -297
- package/package.json +63 -53
- package/profile.js +68 -55
- package/readme.md +215 -101
- package/types/generated.d.ts +848 -228
- package/types/make.js +54 -23
- package/lib/send.js +0 -16
package/lib/run-status.js
CHANGED
|
@@ -1,56 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function RunStatus(opts) {
|
|
11
|
-
if (!(this instanceof RunStatus)) {
|
|
12
|
-
throw new TypeError('Class constructor RunStatus cannot be invoked without \'new\'');
|
|
13
|
-
}
|
|
14
|
-
EventEmitter.call(this);
|
|
15
|
-
|
|
16
|
-
opts = opts || {};
|
|
17
|
-
this.prefixTitles = opts.prefixTitles !== false;
|
|
18
|
-
this.hasExclusive = Boolean(opts.runOnlyExclusive);
|
|
19
|
-
this.base = opts.base || '';
|
|
20
|
-
|
|
21
|
-
this.rejectionCount = 0;
|
|
22
|
-
this.exceptionCount = 0;
|
|
23
|
-
this.passCount = 0;
|
|
24
|
-
this.knownFailureCount = 0;
|
|
25
|
-
this.skipCount = 0;
|
|
26
|
-
this.todoCount = 0;
|
|
27
|
-
this.failCount = 0;
|
|
28
|
-
this.fileCount = 0;
|
|
29
|
-
this.testCount = 0;
|
|
30
|
-
this.previousFailCount = 0;
|
|
31
|
-
this.knownFailures = [];
|
|
32
|
-
this.errors = [];
|
|
33
|
-
this.stats = [];
|
|
34
|
-
this.tests = [];
|
|
35
|
-
|
|
36
|
-
Object.keys(RunStatus.prototype).forEach(function (key) {
|
|
37
|
-
this[key] = this[key].bind(this);
|
|
38
|
-
}, this);
|
|
39
|
-
}
|
|
2
|
+
const EventEmitter = require('events');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const isObj = require('is-obj');
|
|
5
|
+
const flatten = require('arr-flatten');
|
|
6
|
+
const figures = require('figures');
|
|
7
|
+
const autoBind = require('auto-bind');
|
|
8
|
+
const prefixTitle = require('./prefix-title');
|
|
40
9
|
|
|
41
|
-
|
|
42
|
-
|
|
10
|
+
function sum(arr, key) {
|
|
11
|
+
let result = 0;
|
|
43
12
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.on('uncaughtException', this.handleExceptions)
|
|
51
|
-
.on('stdout', this.handleOutput.bind(this, 'stdout'))
|
|
52
|
-
.on('stderr', this.handleOutput.bind(this, 'stderr'));
|
|
53
|
-
};
|
|
13
|
+
arr.forEach(item => {
|
|
14
|
+
result += item[key];
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
54
19
|
|
|
55
20
|
function normalizeError(err) {
|
|
56
21
|
if (!isObj(err)) {
|
|
@@ -63,122 +28,115 @@ function normalizeError(err) {
|
|
|
63
28
|
return err;
|
|
64
29
|
}
|
|
65
30
|
|
|
66
|
-
RunStatus
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
31
|
+
class RunStatus extends EventEmitter {
|
|
32
|
+
constructor(opts) {
|
|
33
|
+
super();
|
|
34
|
+
|
|
35
|
+
opts = opts || {};
|
|
36
|
+
this.prefixTitles = opts.prefixTitles !== false;
|
|
37
|
+
this.hasExclusive = Boolean(opts.runOnlyExclusive);
|
|
38
|
+
this.base = opts.base || '';
|
|
39
|
+
this.rejectionCount = 0;
|
|
40
|
+
this.exceptionCount = 0;
|
|
41
|
+
this.passCount = 0;
|
|
42
|
+
this.knownFailureCount = 0;
|
|
43
|
+
this.skipCount = 0;
|
|
44
|
+
this.todoCount = 0;
|
|
45
|
+
this.failCount = 0;
|
|
46
|
+
this.fileCount = 0;
|
|
47
|
+
this.testCount = 0;
|
|
48
|
+
this.remainingCount = 0;
|
|
49
|
+
this.previousFailCount = 0;
|
|
50
|
+
this.knownFailures = [];
|
|
51
|
+
this.errors = [];
|
|
52
|
+
this.stats = [];
|
|
53
|
+
this.tests = [];
|
|
54
|
+
this.failFastEnabled = opts.failFast || false;
|
|
55
|
+
|
|
56
|
+
autoBind(this);
|
|
57
|
+
}
|
|
58
|
+
observeFork(emitter) {
|
|
59
|
+
emitter
|
|
60
|
+
.on('teardown', this.handleTeardown)
|
|
61
|
+
.on('stats', this.handleStats)
|
|
62
|
+
.on('test', this.handleTest)
|
|
63
|
+
.on('unhandledRejections', this.handleRejections)
|
|
64
|
+
.on('uncaughtException', this.handleExceptions)
|
|
65
|
+
.on('stdout', this.handleOutput.bind(this, 'stdout'))
|
|
66
|
+
.on('stderr', this.handleOutput.bind(this, 'stderr'));
|
|
67
|
+
}
|
|
68
|
+
handleRejections(data) {
|
|
69
|
+
this.rejectionCount += data.rejections.length;
|
|
70
|
+
|
|
71
|
+
data.rejections.forEach(err => {
|
|
72
|
+
err = normalizeError(err);
|
|
73
|
+
err.type = 'rejection';
|
|
74
|
+
err.file = data.file;
|
|
75
|
+
this.emit('error', err, this);
|
|
76
|
+
this.errors.push(err);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
handleExceptions(data) {
|
|
80
|
+
this.exceptionCount++;
|
|
81
|
+
const err = normalizeError(data.exception);
|
|
82
|
+
err.type = 'exception';
|
|
72
83
|
err.file = data.file;
|
|
73
84
|
this.emit('error', err, this);
|
|
74
85
|
this.errors.push(err);
|
|
75
|
-
}, this);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
RunStatus.prototype.handleExceptions = function (data) {
|
|
79
|
-
this.exceptionCount++;
|
|
80
|
-
var err = normalizeError(data.exception);
|
|
81
|
-
err.type = 'exception';
|
|
82
|
-
err.file = data.file;
|
|
83
|
-
this.emit('error', err, this);
|
|
84
|
-
this.errors.push(err);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
RunStatus.prototype.handleTeardown = function (data) {
|
|
88
|
-
this.emit('dependencies', data.file, data.dependencies, this);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
RunStatus.prototype.handleStats = function (stats) {
|
|
92
|
-
this.emit('stats', stats, this);
|
|
93
|
-
|
|
94
|
-
if (this.hasExclusive && !stats.hasExclusive) {
|
|
95
|
-
return;
|
|
96
86
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.hasExclusive = true;
|
|
100
|
-
this.testCount = 0;
|
|
87
|
+
handleTeardown(data) {
|
|
88
|
+
this.emit('dependencies', data.file, data.dependencies, this);
|
|
101
89
|
}
|
|
90
|
+
handleStats(stats) {
|
|
91
|
+
this.emit('stats', stats, this);
|
|
102
92
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
RunStatus.prototype.handleTest = function (test) {
|
|
107
|
-
test.title = this.prefixTitle(test.file) + test.title;
|
|
108
|
-
|
|
109
|
-
if (test.error) {
|
|
110
|
-
if (test.error.name !== 'AssertionError') {
|
|
111
|
-
test.error.message = 'failed with "' + test.error.message + '"';
|
|
93
|
+
if (stats.hasExclusive) {
|
|
94
|
+
this.hasExclusive = true;
|
|
112
95
|
}
|
|
113
96
|
|
|
114
|
-
this.
|
|
97
|
+
this.testCount += stats.testCount;
|
|
115
98
|
}
|
|
99
|
+
handleTest(test) {
|
|
100
|
+
test.title = this.prefixTitle(test.file) + test.title;
|
|
116
101
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
102
|
+
if (test.error) {
|
|
103
|
+
if (test.error.name !== 'AssertionError') {
|
|
104
|
+
test.error.message = `Error: ${test.error.message}`;
|
|
105
|
+
}
|
|
120
106
|
|
|
121
|
-
|
|
122
|
-
}
|
|
107
|
+
this.errors.push(test);
|
|
108
|
+
}
|
|
123
109
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
110
|
+
if (test.failing && !test.error) {
|
|
111
|
+
this.knownFailures.push(test);
|
|
112
|
+
}
|
|
128
113
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
var prefix = path.relative('.', file)
|
|
132
|
-
.replace(this.base, function (match, offset) {
|
|
133
|
-
// only replace this.base if it is found at the start of the path
|
|
134
|
-
return offset === 0 ? '' : match;
|
|
135
|
-
})
|
|
136
|
-
.replace(/\.spec/, '')
|
|
137
|
-
.replace(/\.test/, '')
|
|
138
|
-
.replace(/test\-/g, '')
|
|
139
|
-
.replace(/\.js$/, '')
|
|
140
|
-
.split(path.sep)
|
|
141
|
-
.filter(function (p) {
|
|
142
|
-
return p !== '__tests__';
|
|
143
|
-
})
|
|
144
|
-
.join(separator);
|
|
145
|
-
|
|
146
|
-
if (prefix.length > 0) {
|
|
147
|
-
prefix += separator;
|
|
114
|
+
this.emit('test', test, this);
|
|
148
115
|
}
|
|
116
|
+
prefixTitle(file) {
|
|
117
|
+
if (!this.prefixTitles) {
|
|
118
|
+
return '';
|
|
119
|
+
}
|
|
149
120
|
|
|
150
|
-
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
RunStatus.prototype.handleOutput = function (channel, data) {
|
|
154
|
-
this.emit(channel, data, this);
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
RunStatus.prototype.processResults = function (results) {
|
|
158
|
-
// assemble stats from all tests
|
|
159
|
-
this.stats = results.map(function (result) {
|
|
160
|
-
return result.stats;
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
this.tests = results.map(function (result) {
|
|
164
|
-
return result.tests;
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
this.tests = flatten(this.tests);
|
|
168
|
-
|
|
169
|
-
this.passCount = sum(this.stats, 'passCount');
|
|
170
|
-
this.knownFailureCount = sum(this.stats, 'knownFailureCount');
|
|
171
|
-
this.skipCount = sum(this.stats, 'skipCount');
|
|
172
|
-
this.todoCount = sum(this.stats, 'todoCount');
|
|
173
|
-
this.failCount = sum(this.stats, 'failCount');
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
function sum(arr, key) {
|
|
177
|
-
var result = 0;
|
|
178
|
-
|
|
179
|
-
arr.forEach(function (item) {
|
|
180
|
-
result += item[key];
|
|
181
|
-
});
|
|
121
|
+
const separator = ' ' + chalk.gray.dim(figures.pointerSmall) + ' ';
|
|
182
122
|
|
|
183
|
-
|
|
123
|
+
return prefixTitle(file, this.base, separator);
|
|
124
|
+
}
|
|
125
|
+
handleOutput(channel, data) {
|
|
126
|
+
this.emit(channel, data, this);
|
|
127
|
+
}
|
|
128
|
+
processResults(results) {
|
|
129
|
+
// Assemble stats from all tests
|
|
130
|
+
this.stats = results.map(result => result.stats);
|
|
131
|
+
this.tests = results.map(result => result.tests);
|
|
132
|
+
this.tests = flatten(this.tests);
|
|
133
|
+
this.passCount = sum(this.stats, 'passCount');
|
|
134
|
+
this.knownFailureCount = sum(this.stats, 'knownFailureCount');
|
|
135
|
+
this.skipCount = sum(this.stats, 'skipCount');
|
|
136
|
+
this.todoCount = sum(this.stats, 'todoCount');
|
|
137
|
+
this.failCount = sum(this.stats, 'failCount');
|
|
138
|
+
this.remainingCount = this.testCount - this.passCount - this.failCount - this.skipCount - this.todoCount - this.knownFailureCount;
|
|
139
|
+
}
|
|
184
140
|
}
|
|
141
|
+
|
|
142
|
+
module.exports = RunStatus;
|
package/lib/runner.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
const EventEmitter = require('events');
|
|
3
|
+
const Promise = require('bluebird');
|
|
4
|
+
const optionChain = require('option-chain');
|
|
5
|
+
const matcher = require('matcher');
|
|
6
|
+
const TestCollection = require('./test-collection');
|
|
7
|
+
const validateTest = require('./validate-test');
|
|
8
8
|
|
|
9
9
|
function noop() {}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const chainableMethods = {
|
|
12
12
|
defaults: {
|
|
13
13
|
type: 'test',
|
|
14
14
|
serial: false,
|
|
@@ -35,32 +35,129 @@ var chainableMethods = {
|
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
function wrapFunction(fn, args) {
|
|
39
|
+
return function (t) {
|
|
40
|
+
return fn.apply(this, [t].concat(args));
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class Runner extends EventEmitter {
|
|
45
|
+
constructor(options) {
|
|
46
|
+
super();
|
|
47
|
+
|
|
48
|
+
options = options || {};
|
|
49
|
+
|
|
50
|
+
this.results = [];
|
|
51
|
+
this.tests = new TestCollection();
|
|
52
|
+
this.hasStarted = false;
|
|
53
|
+
this._bail = options.bail;
|
|
54
|
+
this._serial = options.serial;
|
|
55
|
+
this._match = options.match || [];
|
|
56
|
+
this._addTestResult = this._addTestResult.bind(this);
|
|
57
|
+
this._buildStats = this._buildStats.bind(this);
|
|
41
58
|
}
|
|
59
|
+
_addTest(title, opts, fn, args) {
|
|
60
|
+
if (args) {
|
|
61
|
+
if (fn.title) {
|
|
62
|
+
title = fn.title.apply(fn, [title || ''].concat(args));
|
|
63
|
+
}
|
|
42
64
|
|
|
43
|
-
|
|
65
|
+
fn = wrapFunction(fn, args);
|
|
66
|
+
}
|
|
44
67
|
|
|
45
|
-
|
|
68
|
+
if (opts.type === 'test' && this._match.length > 0) {
|
|
69
|
+
opts.exclusive = title !== null && matcher([title], this._match).length === 1;
|
|
70
|
+
}
|
|
46
71
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this._serial = options.serial;
|
|
52
|
-
this._match = options.match || [];
|
|
53
|
-
this._addTestResult = this._addTestResult.bind(this);
|
|
54
|
-
this._buildStats = this._buildStats.bind(this);
|
|
55
|
-
}
|
|
72
|
+
const validationError = validateTest(title, fn, opts);
|
|
73
|
+
if (validationError !== null) {
|
|
74
|
+
throw new TypeError(validationError);
|
|
75
|
+
}
|
|
56
76
|
|
|
57
|
-
|
|
58
|
-
|
|
77
|
+
if (opts.todo) {
|
|
78
|
+
fn = noop;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.tests.add({
|
|
82
|
+
metadata: opts,
|
|
83
|
+
fn,
|
|
84
|
+
title
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
_addTestResult(result) {
|
|
88
|
+
const test = result.result;
|
|
89
|
+
const props = {
|
|
90
|
+
duration: test.duration,
|
|
91
|
+
title: test.title,
|
|
92
|
+
error: result.reason,
|
|
93
|
+
type: test.metadata.type,
|
|
94
|
+
skip: test.metadata.skipped,
|
|
95
|
+
todo: test.metadata.todo,
|
|
96
|
+
failing: test.metadata.failing
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
this.results.push(result);
|
|
100
|
+
this.emit('test', props);
|
|
101
|
+
}
|
|
102
|
+
_buildStats() {
|
|
103
|
+
const stats = {
|
|
104
|
+
testCount: 0,
|
|
105
|
+
skipCount: 0,
|
|
106
|
+
todoCount: 0
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
this.results
|
|
110
|
+
.map(result => {
|
|
111
|
+
return result.result;
|
|
112
|
+
})
|
|
113
|
+
.filter(test => {
|
|
114
|
+
return test.metadata.type === 'test';
|
|
115
|
+
})
|
|
116
|
+
.forEach(test => {
|
|
117
|
+
stats.testCount++;
|
|
118
|
+
|
|
119
|
+
if (test.metadata.skipped) {
|
|
120
|
+
stats.skipCount++;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (test.metadata.todo) {
|
|
124
|
+
stats.todoCount++;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
stats.failCount = this.results
|
|
129
|
+
.filter(result => {
|
|
130
|
+
return result.passed === false;
|
|
131
|
+
})
|
|
132
|
+
.length;
|
|
133
|
+
|
|
134
|
+
stats.knownFailureCount = this.results
|
|
135
|
+
.filter(result => {
|
|
136
|
+
return result.passed === true && result.result.metadata.failing;
|
|
137
|
+
})
|
|
138
|
+
.length;
|
|
139
|
+
|
|
140
|
+
stats.passCount = stats.testCount - stats.failCount - stats.skipCount - stats.todoCount;
|
|
141
|
+
|
|
142
|
+
return stats;
|
|
143
|
+
}
|
|
144
|
+
run(options) {
|
|
145
|
+
if (options.runOnlyExclusive && !this.tests.hasExclusive) {
|
|
146
|
+
return Promise.resolve(null);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.tests.on('test', this._addTestResult);
|
|
150
|
+
|
|
151
|
+
this.hasStarted = true;
|
|
152
|
+
|
|
153
|
+
return Promise.resolve(this.tests.build(this._bail).run()).then(this._buildStats);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
59
156
|
|
|
60
157
|
optionChain(chainableMethods, function (opts, args) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
158
|
+
let title;
|
|
159
|
+
let fn;
|
|
160
|
+
let macroArgIndex;
|
|
64
161
|
|
|
65
162
|
if (this.hasStarted) {
|
|
66
163
|
throw new Error('All tests and hooks must be declared synchronously in your ' +
|
|
@@ -96,115 +193,6 @@ optionChain(chainableMethods, function (opts, args) {
|
|
|
96
193
|
}
|
|
97
194
|
}, Runner.prototype);
|
|
98
195
|
|
|
99
|
-
function wrapFunction(fn, args) {
|
|
100
|
-
return function (t) {
|
|
101
|
-
return fn.apply(this, [t].concat(args));
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
Runner.prototype._addTest = function (title, opts, fn, args) {
|
|
106
|
-
if (args) {
|
|
107
|
-
if (fn.title) {
|
|
108
|
-
title = fn.title.apply(fn, [title || ''].concat(args));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
fn = wrapFunction(fn, args);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (opts.type === 'test' && this._match.length > 0) {
|
|
115
|
-
opts.exclusive = title !== null && matcher([title], this._match).length === 1;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (opts.todo) {
|
|
119
|
-
if (typeof fn === 'function') {
|
|
120
|
-
throw new TypeError('`todo` tests are not allowed to have an implementation. Use `test.skip()` for tests with an implementation.');
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
fn = noop;
|
|
124
|
-
|
|
125
|
-
if (typeof title !== 'string') {
|
|
126
|
-
throw new TypeError('`todo` tests require a title');
|
|
127
|
-
}
|
|
128
|
-
} else if (typeof fn !== 'function') {
|
|
129
|
-
throw new TypeError('Expected an implementation. Use `test.todo()` for tests without an implementation.');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
this.tests.add({
|
|
133
|
-
metadata: opts,
|
|
134
|
-
fn: fn,
|
|
135
|
-
title: title
|
|
136
|
-
});
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
Runner.prototype._addTestResult = function (result) {
|
|
140
|
-
var test = result.result;
|
|
141
|
-
var props = {
|
|
142
|
-
duration: test.duration,
|
|
143
|
-
title: test.title,
|
|
144
|
-
error: result.reason,
|
|
145
|
-
type: test.metadata.type,
|
|
146
|
-
skip: test.metadata.skipped,
|
|
147
|
-
todo: test.metadata.todo,
|
|
148
|
-
failing: test.metadata.failing
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
this.results.push(result);
|
|
152
|
-
this.emit('test', props);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
Runner.prototype._buildStats = function () {
|
|
156
|
-
var stats = {
|
|
157
|
-
testCount: 0,
|
|
158
|
-
skipCount: 0,
|
|
159
|
-
todoCount: 0
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
this.results
|
|
163
|
-
.map(function (result) {
|
|
164
|
-
return result.result;
|
|
165
|
-
})
|
|
166
|
-
.filter(function (test) {
|
|
167
|
-
return test.metadata.type === 'test';
|
|
168
|
-
})
|
|
169
|
-
.forEach(function (test) {
|
|
170
|
-
stats.testCount++;
|
|
171
|
-
|
|
172
|
-
if (test.metadata.skipped) {
|
|
173
|
-
stats.skipCount++;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (test.metadata.todo) {
|
|
177
|
-
stats.todoCount++;
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
stats.failCount = this.results
|
|
182
|
-
.filter(function (result) {
|
|
183
|
-
return result.passed === false;
|
|
184
|
-
})
|
|
185
|
-
.length;
|
|
186
|
-
|
|
187
|
-
stats.knownFailureCount = this.results
|
|
188
|
-
.filter(function (result) {
|
|
189
|
-
return result.passed === true && result.result.metadata.failing;
|
|
190
|
-
})
|
|
191
|
-
.length;
|
|
192
|
-
|
|
193
|
-
stats.passCount = stats.testCount - stats.failCount - stats.skipCount - stats.todoCount;
|
|
194
|
-
|
|
195
|
-
return stats;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
Runner.prototype.run = function (options) {
|
|
199
|
-
if (options.runOnlyExclusive && !this.tests.hasExclusive) {
|
|
200
|
-
return Promise.resolve(null);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
this.tests.on('test', this._addTestResult);
|
|
204
|
-
|
|
205
|
-
this.hasStarted = true;
|
|
206
|
-
|
|
207
|
-
return Promise.resolve(this.tests.build(this._bail).run()).then(this._buildStats);
|
|
208
|
-
};
|
|
209
|
-
|
|
210
196
|
Runner._chainableMethods = chainableMethods.chainableMethods;
|
|
197
|
+
|
|
198
|
+
module.exports = Runner;
|