diff --git a/api.js b/api.js index cedd69d..da1db9c 100644 --- a/api.js +++ b/api.js @@ -28,6 +28,7 @@ function Api(options) { this.options = options || {}; this.options.require = (this.options.require || []).map(resolveCwd); + this.options.match = this.options.match || []; this.excludePatterns = [ '!**/node_modules/**', @@ -194,35 +195,57 @@ Api.prototype.run = function (files) { var tests = files.map(self._runFile); // receive test count from all files and then run the tests - var statsCount = 0; + var unreportedFiles = self.fileCount; return new Promise(function (resolve) { - tests.forEach(function (test) { - function tryRun() { - if (++statsCount === self.fileCount) { - self.emit('ready'); + function run() { + if (self.options.match.length > 0 && !self.hasExclusive) { + self._handleExceptions({ + exception: new AvaError('Couldn\'t find any matching tests'), + file: undefined + }); + + tests.forEach(function (test) { + // No tests will be run so tear down the child processes. + test.send('teardown'); + }); + resolve([]); + return; + } - var method = self.options.serial ? 'mapSeries' : 'map'; - var options = { - runOnlyExclusive: self.hasExclusive + self.emit('ready'); + + var method = self.options.serial ? 'mapSeries' : 'map'; + var options = { + runOnlyExclusive: self.hasExclusive + }; + + resolve(Promise[method](files, function (file, index) { + return tests[index].run(options).catch(function (err) { + // The test failed catastrophically. Flag it up as an + // exception, then return an empty result. Other tests may + // continue to run. + self._handleExceptions({ + exception: err, + file: file + }); + + return { + stats: {passCount: 0, skipCount: 0, todoCount: 0, failCount: 0}, + tests: [] }; + }); + })); + } - resolve(Promise[method](files, function (file, index) { - return tests[index].run(options).catch(function (err) { - // The test failed catastrophically. Flag it up as an - // exception, then return an empty result. Other tests may - // continue to run. - self._handleExceptions({ - exception: err, - file: file - }); - - return { - stats: {passCount: 0, skipCount: 0, todoCount: 0, failCount: 0}, - tests: [] - }; - }); - })); + tests.forEach(function (test) { + var tried = false; + function tryRun() { + if (!tried) { + unreportedFiles--; + if (unreportedFiles === 0) { + run(); + } } } diff --git a/lib/runner.js b/lib/runner.js index 1da2822..eb0aba7 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -43,7 +43,7 @@ function Runner(options) { this.tests = new TestCollection(); this._bail = options.bail; this._serial = options.serial; - this._match = options.match; + this._match = options.match || []; this._addTestResult = this._addTestResult.bind(this); } @@ -71,8 +71,8 @@ optionChain(chainableMethods, function (opts, title, fn) { opts.serial = true; } - if (opts.type === 'test' && title !== null && this._match && this._match.length > 0) { - opts.exclusive = matcher([title], this._match).length > 0; + if (opts.type === 'test' && this._match.length > 0) { + opts.exclusive = title !== null && matcher([title], this._match).length === 1; } this.tests.add({ diff --git a/test/api.js b/test/api.js index 980d202..36bd811 100644 --- a/test/api.js +++ b/test/api.js @@ -715,3 +715,18 @@ test('Default babel config doesn\'t use .babelrc', function (t) { t.is(api.passCount, 1); }); }); + +test('using --match with no matching tests causes an AvaError to be emitted', function (t) { + t.plan(2); + + var api = new Api({ + match: ['can\'t match this'] + }); + + api.on('error', function (err) { + t.is(err.name, 'AvaError'); + t.match(err.message, /Couldn't find any matching tests/); + }); + + return api.run([path.join(__dirname, 'fixture/match-no-match.js')]); +}); diff --git a/test/fixture/match-no-match.js b/test/fixture/match-no-match.js new file mode 100644 index 0000000..904bc63 --- /dev/null +++ b/test/fixture/match-no-match.js @@ -0,0 +1,13 @@ +import test from 'ava'; + +test('foo', t => { + t.pass(); +}); + +test.only('bar', t => { + t.pass(); +}); + +test.only(t => { + t.pass(); +}); diff --git a/test/fixture/pkg-conf/precedence/c.js b/test/fixture/pkg-conf/precedence/c.js index 8baf3b6..51ef8b5 100644 --- a/test/fixture/pkg-conf/precedence/c.js +++ b/test/fixture/pkg-conf/precedence/c.js @@ -3,7 +3,7 @@ import path from 'path'; const opts = JSON.parse(process.argv[2]); -test(t => { +test('foo', t => { t.is(opts.failFast, false); t.is(opts.serial, false); t.is(opts.cacheEnabled, true);