ava 0.16.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 +238 -188
- package/cli.js +11 -174
- package/index.js +5 -98
- package/index.js.flow +218 -0
- package/lib/assert.js +3 -3
- package/lib/babel-config.js +11 -5
- package/lib/beautify-stack.js +23 -0
- package/lib/caching-precompiler.js +25 -29
- package/lib/cli.js +172 -0
- package/lib/colors.js +2 -0
- package/lib/concurrent.js +2 -3
- 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 -25
- package/lib/sequence.js +2 -4
- package/lib/test-worker.js +8 -71
- package/lib/throws-helper.js +1 -1
- package/lib/watcher.js +2 -5
- package/package.json +27 -26
- package/profile.js +10 -9
- package/readme.md +15 -12
- package/types/generated.d.ts +994 -192
- package/types/make.js +41 -9
- package/lib/send.js +0 -16
|
@@ -3,23 +3,25 @@ var path = require('path');
|
|
|
3
3
|
var fs = require('fs');
|
|
4
4
|
var convertSourceMap = require('convert-source-map');
|
|
5
5
|
var cachingTransform = require('caching-transform');
|
|
6
|
+
var packageHash = require('package-hash');
|
|
6
7
|
var stripBom = require('strip-bom');
|
|
8
|
+
var autoBind = require('auto-bind');
|
|
7
9
|
var md5Hex = require('md5-hex');
|
|
8
|
-
var packageHash = require('package-hash');
|
|
9
10
|
var babelConfigHelper = require('./babel-config');
|
|
10
11
|
|
|
11
|
-
function CachingPrecompiler(
|
|
12
|
+
function CachingPrecompiler(options) {
|
|
12
13
|
if (!(this instanceof CachingPrecompiler)) {
|
|
13
14
|
throw new TypeError('Class constructor CachingPrecompiler cannot be invoked without \'new\'');
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
this
|
|
17
|
-
this.cacheDirPath = cacheDirPath;
|
|
18
|
-
this.fileHashes = {};
|
|
17
|
+
autoBind(this);
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
options = options || {};
|
|
20
|
+
|
|
21
|
+
this.babelConfig = babelConfigHelper.validate(options.babel);
|
|
22
|
+
this.cacheDirPath = options.path;
|
|
23
|
+
this.powerAssert = Boolean(options.powerAssert);
|
|
24
|
+
this.fileHashes = {};
|
|
23
25
|
|
|
24
26
|
this.transform = this._createTransform();
|
|
25
27
|
}
|
|
@@ -37,35 +39,24 @@ CachingPrecompiler.prototype.precompileFile = function (filePath) {
|
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
// conditionally called by caching-transform when precompiling is required
|
|
40
|
-
CachingPrecompiler.prototype._factory = function () {
|
|
41
|
-
this._init();
|
|
42
|
-
|
|
43
|
-
return this._transform;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
42
|
CachingPrecompiler.prototype._init = function () {
|
|
47
43
|
this.babel = require('babel-core');
|
|
44
|
+
|
|
45
|
+
return this._transform;
|
|
48
46
|
};
|
|
49
47
|
|
|
50
48
|
CachingPrecompiler.prototype._transform = function (code, filePath, hash) {
|
|
51
49
|
code = code.toString();
|
|
52
50
|
|
|
53
|
-
var options = babelConfigHelper.build(this.babelConfig, filePath, code);
|
|
51
|
+
var options = babelConfigHelper.build(this.babelConfig, this.powerAssert, filePath, code);
|
|
54
52
|
var result = this.babel.transform(code, options);
|
|
55
53
|
|
|
56
54
|
// save source map
|
|
57
55
|
var mapPath = path.join(this.cacheDirPath, hash + '.js.map');
|
|
58
56
|
fs.writeFileSync(mapPath, JSON.stringify(result.map));
|
|
59
57
|
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
// require calls, however they won't know that different code was loaded.
|
|
63
|
-
// They may then attempt to resolve a source map from the original file
|
|
64
|
-
// location.
|
|
65
|
-
//
|
|
66
|
-
// Add a source map file comment to the cached code. The file path is
|
|
67
|
-
// relative from the directory of the original file to where the source map
|
|
68
|
-
// is cached. This will allow the source map to be resolved.
|
|
58
|
+
// append source map comment to transformed code
|
|
59
|
+
// so that other libraries (like nyc) can find the source map
|
|
69
60
|
var dirPath = path.dirname(filePath);
|
|
70
61
|
var relativeMapPath = path.relative(dirPath, mapPath);
|
|
71
62
|
var comment = convertSourceMap.generateMapFileComment(relativeMapPath);
|
|
@@ -74,13 +65,18 @@ CachingPrecompiler.prototype._transform = function (code, filePath, hash) {
|
|
|
74
65
|
};
|
|
75
66
|
|
|
76
67
|
CachingPrecompiler.prototype._createTransform = function () {
|
|
77
|
-
var
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
var pluginPackages = babelConfigHelper.pluginPackages;
|
|
69
|
+
var avaPackage = require.resolve('../package.json');
|
|
70
|
+
var packages = [avaPackage].concat(pluginPackages);
|
|
71
|
+
|
|
72
|
+
var majorNodeVersion = process.version.split('.')[0];
|
|
73
|
+
var babelConfig = JSON.stringify(this.babelConfig);
|
|
74
|
+
var packageSalt = babelConfig + majorNodeVersion;
|
|
75
|
+
|
|
76
|
+
var salt = packageHash.sync(packages, packageSalt);
|
|
81
77
|
|
|
82
78
|
return cachingTransform({
|
|
83
|
-
factory: this.
|
|
79
|
+
factory: this._init,
|
|
84
80
|
cacheDir: this.cacheDirPath,
|
|
85
81
|
hash: this._generateHash,
|
|
86
82
|
salt: salt,
|
package/lib/cli.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var path = require('path');
|
|
3
|
+
var updateNotifier = require('update-notifier');
|
|
4
|
+
var figures = require('figures');
|
|
5
|
+
var arrify = require('arrify');
|
|
6
|
+
var meow = require('meow');
|
|
7
|
+
var Promise = require('bluebird');
|
|
8
|
+
var pkgConf = require('pkg-conf');
|
|
9
|
+
var isCi = require('is-ci');
|
|
10
|
+
var hasFlag = require('has-flag');
|
|
11
|
+
var Api = require('../api');
|
|
12
|
+
var colors = require('./colors');
|
|
13
|
+
var verboseReporter = require('./reporters/verbose');
|
|
14
|
+
var miniReporter = require('./reporters/mini');
|
|
15
|
+
var tapReporter = require('./reporters/tap');
|
|
16
|
+
var Logger = require('./logger');
|
|
17
|
+
var Watcher = require('./watcher');
|
|
18
|
+
var babelConfig = require('./babel-config');
|
|
19
|
+
|
|
20
|
+
// Bluebird specific
|
|
21
|
+
Promise.longStackTraces();
|
|
22
|
+
|
|
23
|
+
exports.run = function () {
|
|
24
|
+
var conf = pkgConf.sync('ava');
|
|
25
|
+
|
|
26
|
+
var filepath = pkgConf.filepath(conf);
|
|
27
|
+
var pkgDir = filepath === null ? process.cwd() : path.dirname(filepath);
|
|
28
|
+
|
|
29
|
+
var cli = meow([
|
|
30
|
+
'Usage',
|
|
31
|
+
' ava [<file|directory|glob> ...]',
|
|
32
|
+
'',
|
|
33
|
+
'Options',
|
|
34
|
+
' --init Add AVA to your project',
|
|
35
|
+
' --fail-fast Stop after first test failure',
|
|
36
|
+
' --serial, -s Run tests serially',
|
|
37
|
+
' --tap, -t Generate TAP output',
|
|
38
|
+
' --verbose, -v Enable verbose output',
|
|
39
|
+
' --no-cache Disable the transpiler cache',
|
|
40
|
+
' --no-power-assert Disable Power Assert',
|
|
41
|
+
' --match, -m Only run tests with matching title (Can be repeated)',
|
|
42
|
+
' --watch, -w Re-run tests when tests and source files change',
|
|
43
|
+
' --source, -S Pattern to match source files so tests can be re-run (Can be repeated)',
|
|
44
|
+
' --timeout, -T Set global timeout',
|
|
45
|
+
' --concurrency, -c Maximum number of test files running at the same time (EXPERIMENTAL)',
|
|
46
|
+
'',
|
|
47
|
+
'Examples',
|
|
48
|
+
' ava',
|
|
49
|
+
' ava test.js test2.js',
|
|
50
|
+
' ava test-*.js',
|
|
51
|
+
' ava test',
|
|
52
|
+
' ava --init',
|
|
53
|
+
' ava --init foo.js',
|
|
54
|
+
'',
|
|
55
|
+
'Default patterns when no arguments:',
|
|
56
|
+
'test.js test-*.js test/**/*.js **/__tests__/**/*.js **/*.test.js'
|
|
57
|
+
], {
|
|
58
|
+
string: [
|
|
59
|
+
'_',
|
|
60
|
+
'timeout',
|
|
61
|
+
'source',
|
|
62
|
+
'match',
|
|
63
|
+
'concurrency'
|
|
64
|
+
],
|
|
65
|
+
boolean: [
|
|
66
|
+
'fail-fast',
|
|
67
|
+
'verbose',
|
|
68
|
+
'serial',
|
|
69
|
+
'tap',
|
|
70
|
+
'watch'
|
|
71
|
+
],
|
|
72
|
+
default: conf,
|
|
73
|
+
alias: {
|
|
74
|
+
t: 'tap',
|
|
75
|
+
v: 'verbose',
|
|
76
|
+
s: 'serial',
|
|
77
|
+
m: 'match',
|
|
78
|
+
w: 'watch',
|
|
79
|
+
S: 'source',
|
|
80
|
+
T: 'timeout',
|
|
81
|
+
c: 'concurrency'
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
updateNotifier({pkg: cli.pkg}).notify();
|
|
86
|
+
|
|
87
|
+
if (cli.flags.init) {
|
|
88
|
+
require('ava-init')();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (
|
|
93
|
+
((hasFlag('--watch') || hasFlag('-w')) && (hasFlag('--tap') || hasFlag('-t'))) ||
|
|
94
|
+
(conf.watch && conf.tap)
|
|
95
|
+
) {
|
|
96
|
+
throw new Error(colors.error(figures.cross) + ' The TAP reporter is not available when using watch mode.');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (hasFlag('--require') || hasFlag('-r')) {
|
|
100
|
+
throw new Error(colors.error(figures.cross) + ' The --require and -r flags are deprecated. Requirements should be configured in package.json - see documentation.');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
var api = new Api({
|
|
104
|
+
failFast: cli.flags.failFast,
|
|
105
|
+
serial: cli.flags.serial,
|
|
106
|
+
require: arrify(conf.require),
|
|
107
|
+
cacheEnabled: cli.flags.cache !== false,
|
|
108
|
+
powerAssert: cli.flags.powerAssert !== false,
|
|
109
|
+
explicitTitles: cli.flags.watch,
|
|
110
|
+
match: arrify(cli.flags.match),
|
|
111
|
+
babelConfig: babelConfig.validate(conf.babel),
|
|
112
|
+
resolveTestsFrom: cli.input.length === 0 ? pkgDir : process.cwd(),
|
|
113
|
+
pkgDir: pkgDir,
|
|
114
|
+
timeout: cli.flags.timeout,
|
|
115
|
+
concurrency: cli.flags.concurrency ? parseInt(cli.flags.concurrency, 10) : 0
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
var reporter;
|
|
119
|
+
|
|
120
|
+
if (cli.flags.tap && !cli.flags.watch) {
|
|
121
|
+
reporter = tapReporter();
|
|
122
|
+
} else if (cli.flags.verbose || isCi) {
|
|
123
|
+
reporter = verboseReporter();
|
|
124
|
+
} else {
|
|
125
|
+
reporter = miniReporter({watching: cli.flags.watch});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
reporter.api = api;
|
|
129
|
+
var logger = new Logger(reporter);
|
|
130
|
+
|
|
131
|
+
logger.start();
|
|
132
|
+
|
|
133
|
+
api.on('test-run', function (runStatus) {
|
|
134
|
+
reporter.api = runStatus;
|
|
135
|
+
runStatus.on('test', logger.test);
|
|
136
|
+
runStatus.on('error', logger.unhandledError);
|
|
137
|
+
|
|
138
|
+
runStatus.on('stdout', logger.stdout);
|
|
139
|
+
runStatus.on('stderr', logger.stderr);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
var files = cli.input.length ? cli.input : arrify(conf.files);
|
|
143
|
+
|
|
144
|
+
if (cli.flags.watch) {
|
|
145
|
+
try {
|
|
146
|
+
var watcher = new Watcher(logger, api, files, arrify(cli.flags.source));
|
|
147
|
+
watcher.observeStdin(process.stdin);
|
|
148
|
+
} catch (err) {
|
|
149
|
+
if (err.name === 'AvaError') {
|
|
150
|
+
// An AvaError may be thrown if chokidar is not installed. Log it nicely.
|
|
151
|
+
console.error(' ' + colors.error(figures.cross) + ' ' + err.message);
|
|
152
|
+
logger.exit(1);
|
|
153
|
+
} else {
|
|
154
|
+
// Rethrow so it becomes an uncaught exception.
|
|
155
|
+
throw err;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
api.run(files)
|
|
160
|
+
.then(function (runStatus) {
|
|
161
|
+
logger.finish(runStatus);
|
|
162
|
+
logger.exit(runStatus.failCount > 0 || runStatus.rejectionCount > 0 || runStatus.exceptionCount > 0 ? 1 : 0);
|
|
163
|
+
})
|
|
164
|
+
.catch(function (err) {
|
|
165
|
+
// Don't swallow exceptions. Note that any expected error should already
|
|
166
|
+
// have been logged.
|
|
167
|
+
setImmediate(function () {
|
|
168
|
+
throw err;
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
package/lib/colors.js
CHANGED
package/lib/concurrent.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
var Promise = require('bluebird');
|
|
3
3
|
var isPromise = require('is-promise');
|
|
4
|
+
var autoBind = require('auto-bind');
|
|
4
5
|
var AvaError = require('./ava-error');
|
|
5
6
|
|
|
6
7
|
function noop() {}
|
|
@@ -22,9 +23,7 @@ function Concurrent(tests, bail) {
|
|
|
22
23
|
this.tests = tests;
|
|
23
24
|
this.bail = bail || false;
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
this[key] = this[key].bind(this);
|
|
27
|
-
}, this);
|
|
26
|
+
autoBind(this);
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
Concurrent.prototype.run = function () {
|
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
|
+
};
|