ava 0.15.0 → 0.17.0
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 +243 -187
- package/cli.js +12 -187
- package/index.js +5 -98
- package/index.js.flow +218 -0
- package/lib/assert.js +11 -6
- package/lib/babel-config.js +152 -0
- package/lib/beautify-stack.js +23 -0
- package/lib/caching-precompiler.js +24 -115
- package/lib/cli.js +172 -0
- package/lib/colors.js +2 -0
- package/lib/concurrent.js +2 -3
- package/lib/enhance-assert.js +15 -6
- package/lib/fork.js +23 -15
- package/lib/logger.js +4 -5
- package/lib/main.js +89 -0
- package/lib/prefix-title.js +25 -0
- package/lib/process-adapter.js +107 -0
- package/lib/reporters/mini.js +32 -27
- package/lib/run-status.js +5 -36
- package/lib/runner.js +10 -0
- package/lib/sequence.js +2 -4
- package/lib/test-worker.js +13 -75
- package/lib/test.js +18 -5
- package/lib/throws-helper.js +6 -4
- package/lib/watcher.js +10 -18
- package/package.json +48 -29
- package/profile.js +15 -10
- package/readme.md +72 -43
- package/types/generated.d.ts +1667 -0
- package/types/make.js +166 -0
- package/index.d.ts +0 -206
- package/lib/ava-files.js +0 -262
- package/lib/send.js +0 -16
package/lib/fork.js
CHANGED
|
@@ -6,7 +6,6 @@ var objectAssign = require('object-assign');
|
|
|
6
6
|
var Promise = require('bluebird');
|
|
7
7
|
var debug = require('debug')('ava');
|
|
8
8
|
var AvaError = require('./ava-error');
|
|
9
|
-
var doSend = require('./send');
|
|
10
9
|
|
|
11
10
|
if (fs.realpathSync(__filename) !== __filename) {
|
|
12
11
|
console.warn(
|
|
@@ -31,7 +30,11 @@ if (env.NODE_PATH) {
|
|
|
31
30
|
.join(path.delimiter);
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
// In case the test file imports a different AVA install, the presence of this variable allows it to require this one
|
|
34
|
+
// instead.
|
|
35
|
+
env.AVA_PATH = path.resolve(__dirname, '..');
|
|
36
|
+
|
|
37
|
+
module.exports = function (file, opts, execArgv) {
|
|
35
38
|
opts = objectAssign({
|
|
36
39
|
file: file,
|
|
37
40
|
baseDir: process.cwd(),
|
|
@@ -42,20 +45,25 @@ module.exports = function (file, opts) {
|
|
|
42
45
|
}, opts);
|
|
43
46
|
|
|
44
47
|
var ps = childProcess.fork(path.join(__dirname, 'test-worker.js'), [JSON.stringify(opts)], {
|
|
45
|
-
cwd:
|
|
48
|
+
cwd: opts.pkgDir,
|
|
46
49
|
silent: true,
|
|
47
|
-
env: env
|
|
50
|
+
env: env,
|
|
51
|
+
execArgv: execArgv || process.execArgv
|
|
48
52
|
});
|
|
49
53
|
|
|
50
54
|
var relFile = path.relative('.', file);
|
|
51
55
|
|
|
52
56
|
var exiting = false;
|
|
53
|
-
var send = function (
|
|
57
|
+
var send = function (name, data) {
|
|
54
58
|
if (!exiting) {
|
|
55
59
|
// This seems to trigger a Node bug which kills the AVA master process, at
|
|
56
60
|
// least while running AVA's tests. See
|
|
57
61
|
// <https://github.com/novemberborn/_ava-tap-crash> for more details.
|
|
58
|
-
|
|
62
|
+
ps.send({
|
|
63
|
+
name: 'ava-' + name,
|
|
64
|
+
data: data,
|
|
65
|
+
ava: true
|
|
66
|
+
});
|
|
59
67
|
}
|
|
60
68
|
};
|
|
61
69
|
|
|
@@ -71,7 +79,7 @@ module.exports = function (file, opts) {
|
|
|
71
79
|
return;
|
|
72
80
|
}
|
|
73
81
|
|
|
74
|
-
event.name = event.name.replace(/^ava
|
|
82
|
+
event.name = event.name.replace(/^ava-/, '');
|
|
75
83
|
event.data.file = relFile;
|
|
76
84
|
|
|
77
85
|
debug('ipc %s:\n%o', event.name, event.data);
|
|
@@ -86,7 +94,7 @@ module.exports = function (file, opts) {
|
|
|
86
94
|
ps.on('results', function (data) {
|
|
87
95
|
results = data;
|
|
88
96
|
data.tests = testResults;
|
|
89
|
-
send(
|
|
97
|
+
send('teardown');
|
|
90
98
|
});
|
|
91
99
|
|
|
92
100
|
ps.on('exit', function (code, signal) {
|
|
@@ -106,7 +114,7 @@ module.exports = function (file, opts) {
|
|
|
106
114
|
});
|
|
107
115
|
|
|
108
116
|
ps.on('no-tests', function (data) {
|
|
109
|
-
send(
|
|
117
|
+
send('teardown');
|
|
110
118
|
|
|
111
119
|
var message = 'No tests found in ' + relFile;
|
|
112
120
|
|
|
@@ -120,13 +128,13 @@ module.exports = function (file, opts) {
|
|
|
120
128
|
|
|
121
129
|
// teardown finished, now exit
|
|
122
130
|
ps.on('teardown', function () {
|
|
123
|
-
send(
|
|
131
|
+
send('exit');
|
|
124
132
|
exiting = true;
|
|
125
133
|
});
|
|
126
134
|
|
|
127
135
|
// uncaught exception in fork, need to exit
|
|
128
136
|
ps.on('uncaughtException', function () {
|
|
129
|
-
send(
|
|
137
|
+
send('teardown');
|
|
130
138
|
});
|
|
131
139
|
|
|
132
140
|
ps.stdout.on('data', function (data) {
|
|
@@ -144,13 +152,13 @@ module.exports = function (file, opts) {
|
|
|
144
152
|
};
|
|
145
153
|
|
|
146
154
|
promise.send = function (name, data) {
|
|
147
|
-
send(
|
|
155
|
+
send(name, data);
|
|
148
156
|
|
|
149
157
|
return promise;
|
|
150
158
|
};
|
|
151
159
|
|
|
152
160
|
promise.exit = function () {
|
|
153
|
-
send(
|
|
161
|
+
send('init-exit');
|
|
154
162
|
|
|
155
163
|
return promise;
|
|
156
164
|
};
|
|
@@ -164,12 +172,12 @@ module.exports = function (file, opts) {
|
|
|
164
172
|
|
|
165
173
|
promise.run = function (options) {
|
|
166
174
|
if (isReady) {
|
|
167
|
-
send(
|
|
175
|
+
send('run', options);
|
|
168
176
|
return promise;
|
|
169
177
|
}
|
|
170
178
|
|
|
171
179
|
ps.on('stats', function () {
|
|
172
|
-
send(
|
|
180
|
+
send('run', options);
|
|
173
181
|
});
|
|
174
182
|
|
|
175
183
|
return promise;
|
package/lib/logger.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
var autoBind = require('auto-bind');
|
|
2
3
|
|
|
3
4
|
function Logger(reporter) {
|
|
4
5
|
if (!(this instanceof Logger)) {
|
|
5
6
|
throw new TypeError('Class constructor Logger cannot be invoked without \'new\'');
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
Object.keys(Logger.prototype).forEach(function (key) {
|
|
9
|
-
this[key] = this[key].bind(this);
|
|
10
|
-
}, this);
|
|
11
|
-
|
|
12
9
|
this.reporter = reporter;
|
|
10
|
+
|
|
11
|
+
autoBind(this);
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
module.exports = Logger;
|
|
@@ -99,6 +98,6 @@ Logger.prototype.exit = function (code) {
|
|
|
99
98
|
|
|
100
99
|
// timeout required to correctly flush IO on Node.js 0.10 on Windows
|
|
101
100
|
setTimeout(function () {
|
|
102
|
-
process.exit(code); // eslint-disable-line
|
|
101
|
+
process.exit(code); // eslint-disable-line unicorn/no-process-exit
|
|
103
102
|
}, process.env.AVA_APPVEYOR ? 500 : 0);
|
|
104
103
|
};
|
package/lib/main.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var process = require('./process-adapter');
|
|
4
|
+
var serializeError = require('./serialize-error');
|
|
5
|
+
var globals = require('./globals');
|
|
6
|
+
var Runner = require('./runner');
|
|
7
|
+
var send = process.send;
|
|
8
|
+
|
|
9
|
+
var opts = globals.options;
|
|
10
|
+
var runner = new Runner({
|
|
11
|
+
serial: opts.serial,
|
|
12
|
+
bail: opts.failFast,
|
|
13
|
+
match: opts.match
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// note that test files have require('ava')
|
|
17
|
+
require('./test-worker').avaRequired = true;
|
|
18
|
+
|
|
19
|
+
// if fail-fast is enabled, use this variable to detect
|
|
20
|
+
// that no more tests should be logged
|
|
21
|
+
var isFailed = false;
|
|
22
|
+
|
|
23
|
+
Error.stackTraceLimit = Infinity;
|
|
24
|
+
|
|
25
|
+
function test(props) {
|
|
26
|
+
if (isFailed) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var hasError = typeof props.error !== 'undefined';
|
|
31
|
+
|
|
32
|
+
// don't display anything if it's a passed hook
|
|
33
|
+
if (!hasError && props.type !== 'test') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (hasError) {
|
|
38
|
+
props.error = serializeError(props.error);
|
|
39
|
+
} else {
|
|
40
|
+
props.error = null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
send('test', props);
|
|
44
|
+
|
|
45
|
+
if (hasError && opts.failFast) {
|
|
46
|
+
isFailed = true;
|
|
47
|
+
exit();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function exit() {
|
|
52
|
+
var stats = runner._buildStats();
|
|
53
|
+
|
|
54
|
+
send('results', {
|
|
55
|
+
stats: stats
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
globals.setImmediate(function () {
|
|
60
|
+
var hasExclusive = runner.tests.hasExclusive;
|
|
61
|
+
var numberOfTests = runner.tests.tests.concurrent.length + runner.tests.tests.serial.length;
|
|
62
|
+
|
|
63
|
+
if (numberOfTests === 0) {
|
|
64
|
+
send('no-tests', {avaRequired: true});
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
send('stats', {
|
|
69
|
+
testCount: numberOfTests,
|
|
70
|
+
hasExclusive: hasExclusive
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
runner.on('test', test);
|
|
74
|
+
|
|
75
|
+
process.on('ava-run', function (options) {
|
|
76
|
+
runner.run(options).then(exit);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
process.on('ava-init-exit', function () {
|
|
80
|
+
exit();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
module.exports = runner.test;
|
|
85
|
+
|
|
86
|
+
// TypeScript imports the `default` property for
|
|
87
|
+
// an ES2015 default import (`import test from 'ava'`)
|
|
88
|
+
// See: https://github.com/Microsoft/TypeScript/issues/2242#issuecomment-83694181
|
|
89
|
+
module.exports.default = runner.test;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var path = require('path');
|
|
3
|
+
|
|
4
|
+
module.exports = function (file, base, separator) {
|
|
5
|
+
var prefix = file
|
|
6
|
+
.replace(base, function (match, offset) {
|
|
7
|
+
// only replace this.base if it is found at the start of the path
|
|
8
|
+
return offset === 0 ? '' : match;
|
|
9
|
+
})
|
|
10
|
+
.replace(/\.spec/, '')
|
|
11
|
+
.replace(/\.test/, '')
|
|
12
|
+
.replace(/test-/g, '')
|
|
13
|
+
.replace(/\.js$/, '')
|
|
14
|
+
.split(path.sep)
|
|
15
|
+
.filter(function (p) {
|
|
16
|
+
return p !== '__tests__';
|
|
17
|
+
})
|
|
18
|
+
.join(separator);
|
|
19
|
+
|
|
20
|
+
if (prefix.length > 0) {
|
|
21
|
+
prefix += separator;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return prefix;
|
|
25
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var fs = require('fs');
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var chalk = require('chalk');
|
|
5
|
+
var sourceMapSupport = require('source-map-support');
|
|
6
|
+
var installPrecompiler = require('require-precompiled');
|
|
7
|
+
|
|
8
|
+
var debug = require('debug')('ava');
|
|
9
|
+
|
|
10
|
+
// check if the test is being run without AVA cli
|
|
11
|
+
var isForked = typeof process.send === 'function';
|
|
12
|
+
|
|
13
|
+
if (!isForked) {
|
|
14
|
+
var fp = path.relative('.', process.argv[1]);
|
|
15
|
+
|
|
16
|
+
console.log();
|
|
17
|
+
console.error('Test files must be run with the AVA CLI:\n\n ' + chalk.grey.dim('$') + ' ' + chalk.cyan('ava ' + fp) + '\n');
|
|
18
|
+
|
|
19
|
+
process.exit(1); // eslint-disable-line unicorn/no-process-exit
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
exports.send = function (name, data) {
|
|
23
|
+
process.send({
|
|
24
|
+
name: 'ava-' + name,
|
|
25
|
+
data: data,
|
|
26
|
+
ava: true
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
exports.on = process.on.bind(process);
|
|
31
|
+
exports.emit = process.emit.bind(process);
|
|
32
|
+
exports.exit = process.exit.bind(process);
|
|
33
|
+
exports.env = process.env;
|
|
34
|
+
|
|
35
|
+
var opts = exports.opts = JSON.parse(process.argv[2]);
|
|
36
|
+
|
|
37
|
+
// Fake TTY support
|
|
38
|
+
if (opts.tty) {
|
|
39
|
+
process.stdout.isTTY = true;
|
|
40
|
+
process.stdout.columns = opts.tty.columns || 80;
|
|
41
|
+
process.stdout.rows = opts.tty.rows;
|
|
42
|
+
|
|
43
|
+
var tty = require('tty');
|
|
44
|
+
var isatty = tty.isatty;
|
|
45
|
+
|
|
46
|
+
tty.isatty = function (fd) {
|
|
47
|
+
if (fd === 1 || fd === process.stdout) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return isatty(fd);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (debug.enabled) {
|
|
56
|
+
// Forward the `time-require` `--sorted` flag.
|
|
57
|
+
// Intended for internal optimization tests only.
|
|
58
|
+
if (opts._sorted) {
|
|
59
|
+
process.argv.push('--sorted');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
require('time-require'); // eslint-disable-line import/no-unassigned-import
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var sourceMapCache = Object.create(null);
|
|
66
|
+
var cacheDir = opts.cacheDir;
|
|
67
|
+
|
|
68
|
+
exports.installSourceMapSupport = function () {
|
|
69
|
+
sourceMapSupport.install({
|
|
70
|
+
environment: 'node',
|
|
71
|
+
handleUncaughtExceptions: false,
|
|
72
|
+
retrieveSourceMap: function (source) {
|
|
73
|
+
if (sourceMapCache[source]) {
|
|
74
|
+
return {
|
|
75
|
+
url: source,
|
|
76
|
+
map: fs.readFileSync(sourceMapCache[source], 'utf8')
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
exports.installPrecompilerHook = function () {
|
|
84
|
+
installPrecompiler(function (filename) {
|
|
85
|
+
var precompiled = opts.precompiled[filename];
|
|
86
|
+
|
|
87
|
+
if (precompiled) {
|
|
88
|
+
sourceMapCache[filename] = path.join(cacheDir, precompiled + '.js.map');
|
|
89
|
+
return fs.readFileSync(path.join(cacheDir, precompiled + '.js'), 'utf8');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return null;
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
exports.installDependencyTracking = function (dependencies, testPath) {
|
|
97
|
+
Object.keys(require.extensions).forEach(function (ext) {
|
|
98
|
+
var wrappedHandler = require.extensions[ext];
|
|
99
|
+
require.extensions[ext] = function (module, filename) {
|
|
100
|
+
if (filename !== testPath) {
|
|
101
|
+
dependencies.push(filename);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
wrappedHandler(module, filename);
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
};
|
package/lib/reporters/mini.js
CHANGED
|
@@ -123,11 +123,11 @@ MiniReporter.prototype.unhandledError = function (err) {
|
|
|
123
123
|
|
|
124
124
|
MiniReporter.prototype.reportCounts = function (time) {
|
|
125
125
|
var lines = [
|
|
126
|
-
this.passCount > 0 ? '\n
|
|
127
|
-
this.knownFailureCount > 0 ? '\n
|
|
128
|
-
this.failCount > 0 ? '\n
|
|
129
|
-
this.skipCount > 0 ? '\n
|
|
130
|
-
this.todoCount > 0 ? '\n
|
|
126
|
+
this.passCount > 0 ? '\n ' + colors.pass(this.passCount, 'passed') : '',
|
|
127
|
+
this.knownFailureCount > 0 ? '\n ' + colors.error(this.knownFailureCount, plur('known failure', this.knownFailureCount)) : '',
|
|
128
|
+
this.failCount > 0 ? '\n ' + colors.error(this.failCount, 'failed') : '',
|
|
129
|
+
this.skipCount > 0 ? '\n ' + colors.skip(this.skipCount, 'skipped') : '',
|
|
130
|
+
this.todoCount > 0 ? '\n ' + colors.todo(this.todoCount, 'todo') : ''
|
|
131
131
|
].filter(Boolean);
|
|
132
132
|
|
|
133
133
|
if (time && lines.length > 0) {
|
|
@@ -148,26 +148,22 @@ MiniReporter.prototype.finish = function (runStatus) {
|
|
|
148
148
|
var status = this.reportCounts(time);
|
|
149
149
|
|
|
150
150
|
if (this.rejectionCount > 0) {
|
|
151
|
-
status += '\n
|
|
151
|
+
status += '\n ' + colors.error(this.rejectionCount, plur('rejection', this.rejectionCount));
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
if (this.exceptionCount > 0) {
|
|
155
|
-
status += '\n
|
|
155
|
+
status += '\n ' + colors.error(this.exceptionCount, plur('exception', this.exceptionCount));
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
if (runStatus.previousFailCount > 0) {
|
|
159
|
-
status += '\n
|
|
159
|
+
status += '\n ' + colors.error(runStatus.previousFailCount, 'previous', plur('failure', runStatus.previousFailCount), 'in test files that were not rerun');
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
var i = 0;
|
|
163
|
-
|
|
164
162
|
if (this.knownFailureCount > 0) {
|
|
165
163
|
runStatus.knownFailures.forEach(function (test) {
|
|
166
|
-
i++;
|
|
167
|
-
|
|
168
164
|
var title = test.title;
|
|
169
165
|
|
|
170
|
-
status += '\n\n
|
|
166
|
+
status += '\n\n ' + colors.title(title);
|
|
171
167
|
// TODO output description with link
|
|
172
168
|
// status += colors.stack(description);
|
|
173
169
|
});
|
|
@@ -179,19 +175,26 @@ MiniReporter.prototype.finish = function (runStatus) {
|
|
|
179
175
|
return;
|
|
180
176
|
}
|
|
181
177
|
|
|
182
|
-
i++;
|
|
183
|
-
|
|
184
178
|
var title = test.error ? test.title : 'Unhandled Error';
|
|
185
179
|
var description;
|
|
180
|
+
var errorTitle = ' ' + test.error.message + '\n';
|
|
181
|
+
var isPowerAssert = test.error.message.split('\n').length > 1;
|
|
186
182
|
|
|
187
183
|
if (test.error) {
|
|
188
|
-
description =
|
|
184
|
+
description = stripFirstLine(test.error.stack).trimRight();
|
|
189
185
|
} else {
|
|
190
186
|
description = JSON.stringify(test);
|
|
191
187
|
}
|
|
192
188
|
|
|
193
|
-
|
|
194
|
-
|
|
189
|
+
if (isPowerAssert) {
|
|
190
|
+
description = stripFirstLine(description).replace(/ {3}/g, ' ');
|
|
191
|
+
} else {
|
|
192
|
+
description.replace(/ {3}/g, ' ');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
status += '\n\n ' + colors.title(title) + '\n';
|
|
196
|
+
status += colors.stack(errorTitle);
|
|
197
|
+
status += colors.errorStack(description);
|
|
195
198
|
});
|
|
196
199
|
}
|
|
197
200
|
|
|
@@ -201,21 +204,23 @@ MiniReporter.prototype.finish = function (runStatus) {
|
|
|
201
204
|
return;
|
|
202
205
|
}
|
|
203
206
|
|
|
204
|
-
i++;
|
|
205
|
-
|
|
206
207
|
if (err.type === 'exception' && err.name === 'AvaError') {
|
|
207
|
-
status += '\n\n
|
|
208
|
+
status += '\n\n ' + colors.error(cross + ' ' + err.message);
|
|
208
209
|
} else {
|
|
209
210
|
var title = err.type === 'rejection' ? 'Unhandled Rejection' : 'Uncaught Exception';
|
|
210
211
|
var description = err.stack ? err.stack.trimRight() : JSON.stringify(err);
|
|
212
|
+
description = description.split('\n');
|
|
213
|
+
var errorTitle = description[0];
|
|
214
|
+
var errorStack = description.slice(1).join('\n');
|
|
211
215
|
|
|
212
|
-
status += '\n\n
|
|
213
|
-
status += '
|
|
216
|
+
status += '\n\n ' + colors.title(title) + '\n';
|
|
217
|
+
status += ' ' + colors.stack(errorTitle) + '\n';
|
|
218
|
+
status += colors.errorStack(errorStack);
|
|
214
219
|
}
|
|
215
220
|
});
|
|
216
221
|
}
|
|
217
222
|
|
|
218
|
-
return status + '\n';
|
|
223
|
+
return status + '\n\n';
|
|
219
224
|
};
|
|
220
225
|
|
|
221
226
|
MiniReporter.prototype.section = function () {
|
|
@@ -247,7 +252,7 @@ MiniReporter.prototype._update = function (data) {
|
|
|
247
252
|
lastLine = lastLine.substring(lastLine.length - (lastLine.length % columns));
|
|
248
253
|
|
|
249
254
|
// Don't delete the last log line if it's completely empty.
|
|
250
|
-
if (lastLine.length) {
|
|
255
|
+
if (lastLine.length > 0) {
|
|
251
256
|
ct++;
|
|
252
257
|
}
|
|
253
258
|
|
|
@@ -257,7 +262,7 @@ MiniReporter.prototype._update = function (data) {
|
|
|
257
262
|
// Rewrite the last log line.
|
|
258
263
|
str += lastLine;
|
|
259
264
|
|
|
260
|
-
if (str.length) {
|
|
265
|
+
if (str.length > 0) {
|
|
261
266
|
this.stream.write(str);
|
|
262
267
|
}
|
|
263
268
|
|
|
@@ -269,7 +274,7 @@ MiniReporter.prototype._update = function (data) {
|
|
|
269
274
|
|
|
270
275
|
var currentStatus = this.currentStatus;
|
|
271
276
|
|
|
272
|
-
if (currentStatus.length) {
|
|
277
|
+
if (currentStatus.length > 0) {
|
|
273
278
|
lastLine = this.lastLineTracker.lastLine();
|
|
274
279
|
// We need a newline at the end of the last log line, before the status message.
|
|
275
280
|
// However, if the last log line is the exact width of the terminal a newline is implied,
|
package/lib/run-status.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
var EventEmitter = require('events').EventEmitter;
|
|
3
|
-
var path = require('path');
|
|
4
3
|
var util = require('util');
|
|
5
4
|
var chalk = require('chalk');
|
|
6
5
|
var isObj = require('is-obj');
|
|
7
6
|
var flatten = require('arr-flatten');
|
|
8
7
|
var figures = require('figures');
|
|
9
|
-
var
|
|
8
|
+
var autoBind = require('auto-bind');
|
|
9
|
+
var prefixTitle = require('./prefix-title');
|
|
10
10
|
|
|
11
11
|
function RunStatus(opts) {
|
|
12
12
|
if (!(this instanceof RunStatus)) {
|
|
@@ -34,9 +34,7 @@ function RunStatus(opts) {
|
|
|
34
34
|
this.stats = [];
|
|
35
35
|
this.tests = [];
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
this[key] = this[key].bind(this);
|
|
39
|
-
}, this);
|
|
37
|
+
autoBind(this);
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
util.inherits(RunStatus, EventEmitter);
|
|
@@ -108,18 +106,8 @@ RunStatus.prototype.handleTest = function (test) {
|
|
|
108
106
|
test.title = this.prefixTitle(test.file) + test.title;
|
|
109
107
|
|
|
110
108
|
if (test.error) {
|
|
111
|
-
if (test.error.powerAssertContext) {
|
|
112
|
-
var message = formatter(test.error.powerAssertContext);
|
|
113
|
-
|
|
114
|
-
if (test.error.originalMessage) {
|
|
115
|
-
message = test.error.originalMessage + ' ' + message;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
test.error.message = message;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
109
|
if (test.error.name !== 'AssertionError') {
|
|
122
|
-
test.error.message = '
|
|
110
|
+
test.error.message = 'Error: ' + test.error.message;
|
|
123
111
|
}
|
|
124
112
|
|
|
125
113
|
this.errors.push(test);
|
|
@@ -139,26 +127,7 @@ RunStatus.prototype.prefixTitle = function (file) {
|
|
|
139
127
|
|
|
140
128
|
var separator = ' ' + chalk.gray.dim(figures.pointerSmall) + ' ';
|
|
141
129
|
|
|
142
|
-
|
|
143
|
-
.replace(this.base, function (match, offset) {
|
|
144
|
-
// only replace this.base if it is found at the start of the path
|
|
145
|
-
return offset === 0 ? '' : match;
|
|
146
|
-
})
|
|
147
|
-
.replace(/\.spec/, '')
|
|
148
|
-
.replace(/\.test/, '')
|
|
149
|
-
.replace(/test\-/g, '')
|
|
150
|
-
.replace(/\.js$/, '')
|
|
151
|
-
.split(path.sep)
|
|
152
|
-
.filter(function (p) {
|
|
153
|
-
return p !== '__tests__';
|
|
154
|
-
})
|
|
155
|
-
.join(separator);
|
|
156
|
-
|
|
157
|
-
if (prefix.length > 0) {
|
|
158
|
-
prefix += separator;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return prefix;
|
|
130
|
+
return prefixTitle(file, this.base, separator);
|
|
162
131
|
};
|
|
163
132
|
|
|
164
133
|
RunStatus.prototype.handleOutput = function (channel, data) {
|
package/lib/runner.js
CHANGED
|
@@ -46,6 +46,7 @@ function Runner(options) {
|
|
|
46
46
|
|
|
47
47
|
this.results = [];
|
|
48
48
|
this.tests = new TestCollection();
|
|
49
|
+
this.hasStarted = false;
|
|
49
50
|
this._bail = options.bail;
|
|
50
51
|
this._serial = options.serial;
|
|
51
52
|
this._match = options.match || [];
|
|
@@ -61,6 +62,11 @@ optionChain(chainableMethods, function (opts, args) {
|
|
|
61
62
|
var fn;
|
|
62
63
|
var macroArgIndex;
|
|
63
64
|
|
|
65
|
+
if (this.hasStarted) {
|
|
66
|
+
throw new Error('All tests and hooks must be declared synchronously in your ' +
|
|
67
|
+
'test file, and cannot be nested within other tests or hooks.');
|
|
68
|
+
}
|
|
69
|
+
|
|
64
70
|
if (typeof args[0] === 'string') {
|
|
65
71
|
title = args[0];
|
|
66
72
|
fn = args[1];
|
|
@@ -196,5 +202,9 @@ Runner.prototype.run = function (options) {
|
|
|
196
202
|
|
|
197
203
|
this.tests.on('test', this._addTestResult);
|
|
198
204
|
|
|
205
|
+
this.hasStarted = true;
|
|
206
|
+
|
|
199
207
|
return Promise.resolve(this.tests.build(this._bail).run()).then(this._buildStats);
|
|
200
208
|
};
|
|
209
|
+
|
|
210
|
+
Runner._chainableMethods = chainableMethods.chainableMethods;
|
package/lib/sequence.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
var isPromise = require('is-promise');
|
|
3
|
+
var autoBind = require('auto-bind');
|
|
3
4
|
var AvaError = require('./ava-error');
|
|
4
5
|
|
|
5
6
|
function noop() {}
|
|
@@ -21,10 +22,7 @@ function Sequence(tests, bail) {
|
|
|
21
22
|
this.tests = tests;
|
|
22
23
|
this.bail = bail || false;
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
Object.keys(Sequence.prototype).forEach(function (key) {
|
|
26
|
-
this[key] = this[key].bind(this);
|
|
27
|
-
}, this);
|
|
25
|
+
autoBind(this);
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
Sequence.prototype.run = function () {
|