From cac9f9e188697bf4593dfd664bce06d33f2393cc Mon Sep 17 00:00:00 2001 From: James Talmage Date: Mon, 23 May 2016 19:05:44 -0400 Subject: [PATCH 1/3] ava-files should honor a `cwd` option. --- api.js | 5 ++-- lib/ava-files.js | 10 +++++-- lib/watcher.js | 5 +++- test/ava-files.js | 29 ++++++++++++++++---- test/fixture/ava-files/cwd/dir-a/test/bar.js | 1 + test/fixture/ava-files/cwd/dir-a/test/foo.js | 1 + test/fixture/ava-files/cwd/dir-b/test/baz.js | 1 + 7 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 test/fixture/ava-files/cwd/dir-a/test/bar.js create mode 100644 test/fixture/ava-files/cwd/dir-a/test/foo.js create mode 100644 test/fixture/ava-files/cwd/dir-b/test/baz.js diff --git a/api.js b/api.js index 2b20af905..44b0335ed 100644 --- a/api.js +++ b/api.js @@ -23,7 +23,8 @@ function Api(options) { EventEmitter.call(this); - this.options = options || {}; + this.options = objectAssign({}, options); + this.options.cwd = this.options.cwd || process.cwd(); this.options.match = this.options.match || []; this.options.require = (this.options.require || []).map(function (moduleId) { var ret = resolveCwd(moduleId); @@ -73,7 +74,7 @@ Api.prototype._onTimeout = function (runStatus) { Api.prototype.run = function (files, options) { var self = this; - return new AvaFiles(files) + return new AvaFiles({files: files}) .findTestFiles() .then(function (files) { return self._run(files, options); diff --git a/lib/ava-files.js b/lib/ava-files.js index ef4938942..11f6530a8 100644 --- a/lib/ava-files.js +++ b/lib/ava-files.js @@ -25,11 +25,14 @@ function defaultIncludePatterns() { ]; } -function AvaFiles(files, sources) { +function AvaFiles(options) { if (!(this instanceof AvaFiles)) { throw new TypeError('Class constructor AvaFiles cannot be invoked without \'new\''); } + options = options || {}; + var files = options.files; + if (!files || !files.length) { files = defaultIncludePatterns(); } @@ -37,11 +40,13 @@ function AvaFiles(files, sources) { this.excludePatterns = defaultExcludePatterns(); this.files = files; - this.sources = sources || []; + this.sources = options.sources || []; + this.cwd = options.cwd || process.cwd(); } AvaFiles.prototype.findTestFiles = function () { return handlePaths(this.files, this.excludePatterns, { + cwd: this.cwd, cache: Object.create(null), statCache: Object.create(null), realpathCache: Object.create(null), @@ -222,6 +227,7 @@ function handlePaths(files, excludePatterns, globOptions) { return files .map(function (file) { + file = path.resolve(globOptions.cwd, file); if (fs.statSync(file).isDirectory()) { if (alreadySearchingParent(file)) { return null; diff --git a/lib/watcher.js b/lib/watcher.js index a2ae9569d..a12bd8f13 100644 --- a/lib/watcher.js +++ b/lib/watcher.js @@ -26,7 +26,10 @@ function rethrowAsync(err) { function Watcher(logger, api, files, sources) { this.debouncer = new Debouncer(this); - this.avaFiles = new AvaFiles(files, sources); + this.avaFiles = new AvaFiles({ + files: files, + sources: sources + }); this.isTest = this.avaFiles.makeTestMatcher(); diff --git a/test/ava-files.js b/test/ava-files.js index 4426b769c..a0b459550 100644 --- a/test/ava-files.js +++ b/test/ava-files.js @@ -25,7 +25,7 @@ test('requires new', function (t) { }); test('testMatcher', function (t) { - var avaFiles = new AvaFiles(['**/foo*']); + var avaFiles = new AvaFiles({files: ['**/foo*']}); var matcher = avaFiles.makeTestMatcher(); @@ -55,7 +55,7 @@ test('testMatcher', function (t) { }); test('sourceMatcher - defaults', function (t) { - var avaFiles = new AvaFiles(['**/foo*']); + var avaFiles = new AvaFiles({files: ['**/foo*']}); var matcher = avaFiles.makeSourceMatcher(); @@ -90,7 +90,10 @@ test('sourceMatcher - defaults', function (t) { }); test('sourceMatcher - allow matching specific node_modules directories', function (t) { - var avaFiles = new AvaFiles(['**/foo*'], ['node_modules/foo/**']); + var avaFiles = new AvaFiles({ + files: ['**/foo*'], + sources: ['node_modules/foo/**'] + }); var matcher = avaFiles.makeSourceMatcher(); @@ -100,7 +103,10 @@ test('sourceMatcher - allow matching specific node_modules directories', functio }); test('sourceMatcher - providing negation patterns', function (t) { - var avaFiles = new AvaFiles(['**/foo*'], ['!**/bar*']); + var avaFiles = new AvaFiles({ + files: ['**/foo*'], + sources: ['!**/bar*'] + }); var matcher = avaFiles.makeSourceMatcher(); @@ -111,7 +117,7 @@ test('sourceMatcher - providing negation patterns', function (t) { }); test('findFiles - does not return duplicates of the same file', function (t) { - var avaFiles = new AvaFiles(['**/ava-files/no-duplicates/**']); + var avaFiles = new AvaFiles({files: ['**/ava-files/no-duplicates/**']}); avaFiles.findTestFiles().then(function (files) { t.is(files.length, 2); @@ -119,6 +125,19 @@ test('findFiles - does not return duplicates of the same file', function (t) { }); }); +test('findFiles - honors cwd option', function (t) { + var avaFiles = new AvaFiles({ + files: ['**/test/*.js'], + cwd: path.join(__dirname, 'fixture', 'ava-files', 'cwd', 'dir-b') + }); + + avaFiles.findTestFiles().then(function (files) { + t.is(files.length, 1); + t.is(path.basename(files[0]), 'baz.js'); + t.end(); + }); +}); + test('findFiles - finds the correct files by default', function (t) { var fixtureDir = fixture('default-patterns'); process.chdir(fixtureDir); diff --git a/test/fixture/ava-files/cwd/dir-a/test/bar.js b/test/fixture/ava-files/cwd/dir-a/test/bar.js new file mode 100644 index 000000000..8b1a39374 --- /dev/null +++ b/test/fixture/ava-files/cwd/dir-a/test/bar.js @@ -0,0 +1 @@ +// empty diff --git a/test/fixture/ava-files/cwd/dir-a/test/foo.js b/test/fixture/ava-files/cwd/dir-a/test/foo.js new file mode 100644 index 000000000..8b1a39374 --- /dev/null +++ b/test/fixture/ava-files/cwd/dir-a/test/foo.js @@ -0,0 +1 @@ +// empty diff --git a/test/fixture/ava-files/cwd/dir-b/test/baz.js b/test/fixture/ava-files/cwd/dir-b/test/baz.js new file mode 100644 index 000000000..8b1a39374 --- /dev/null +++ b/test/fixture/ava-files/cwd/dir-b/test/baz.js @@ -0,0 +1 @@ +// empty From 2286786056b9434849e5ffe56041e86228f350e0 Mon Sep 17 00:00:00 2001 From: James Talmage Date: Mon, 23 May 2016 21:14:11 -0400 Subject: [PATCH 2/3] Properly resolve test files in non-watch mode. --- api.js | 3 +- cli.js | 4 +++ test/cli.js | 33 +++++++++++++++++++ .../dir-a-wrapper/dir-a/dir-a-wrapper-3.js | 5 +++ .../dir-a-wrapper/dir-a/dir-a-wrapper-4.js | 5 +++ .../resolve-dir/dir-a/dir-a-base-1.js | 5 +++ .../resolve-dir/dir-a/dir-a-base-2.js | 5 +++ .../fixture/pkg-conf/resolve-dir/package.json | 7 ++++ 8 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 test/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js create mode 100644 test/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js create mode 100644 test/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-1.js create mode 100644 test/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-2.js create mode 100644 test/fixture/pkg-conf/resolve-dir/package.json diff --git a/api.js b/api.js index 44b0335ed..ec99e621b 100644 --- a/api.js +++ b/api.js @@ -25,6 +25,7 @@ function Api(options) { this.options = objectAssign({}, options); this.options.cwd = this.options.cwd || process.cwd(); + this.options.resolveTestsFrom = this.options.resolveTestsFrom || this.options.cwd; this.options.match = this.options.match || []; this.options.require = (this.options.require || []).map(function (moduleId) { var ret = resolveCwd(moduleId); @@ -74,7 +75,7 @@ Api.prototype._onTimeout = function (runStatus) { Api.prototype.run = function (files, options) { var self = this; - return new AvaFiles({files: files}) + return new AvaFiles({files: files, cwd: this.options.resolveTestsFrom}) .findTestFiles() .then(function (files) { return self._run(files, options); diff --git a/cli.js b/cli.js index d4b313c21..28197e2c6 100755 --- a/cli.js +++ b/cli.js @@ -1,6 +1,7 @@ #!/usr/bin/env node 'use strict'; +var path = require('path'); var debug = require('debug')('ava'); // Prefer the local installation of AVA. @@ -43,6 +44,8 @@ var conf = pkgConf.sync('ava', { } }); +var pkgDir = path.dirname(pkgConf.filepath(conf)); + // check for valid babel config shortcuts (can be either "default" or "inherit") var isValidShortcut = ['default', 'inherit'].indexOf(conf.babel) !== -1; @@ -136,6 +139,7 @@ var api = new Api({ explicitTitles: cli.flags.watch, match: arrify(cli.flags.match), babelConfig: conf.babel, + resolveTestsFrom: cli.input.length === 0 ? pkgDir : process.cwd(), timeout: cli.flags.timeout, concurrency: cli.flags.concurrency ? parseInt(cli.flags.concurrency, 10) : 0 }); diff --git a/test/cli.js b/test/cli.js index 907f1bbc3..eb81c6e3a 100644 --- a/test/cli.js +++ b/test/cli.js @@ -176,6 +176,39 @@ test('pkg-conf: cli takes precedence', function (t) { }); }); +test('pkg-conf(resolve-dir): works as expected when run from the package.json directory', function (t) { + execCli(['--verbose'], {dirname: 'fixture/pkg-conf/resolve-dir'}, function (err, stdout, stderr) { + t.ifError(err); + t.match(stderr, /dir-a-base-1/); + t.match(stderr, /dir-a-base-2/); + t.notMatch(stderr, /dir-a-wrapper/); + t.notMatch(stdout, /dir-a-wrapper/); + t.end(); + }); +}); + +test('pkg-conf(resolve-dir): resolves tests from the package.json dir if none are specified on cli', function (t) { + execCli(['--verbose'], {dirname: 'fixture/pkg-conf/resolve-dir/dir-a-wrapper'}, function (err, stdout, stderr) { + t.ifError(err); + t.match(stderr, /dir-a-base-1/); + t.match(stderr, /dir-a-base-2/); + t.notMatch(stderr, /dir-a-wrapper/); + t.notMatch(stdout, /dir-a-wrapper/); + t.end(); + }); +}); + +test('pkg-conf(resolve-dir): resolves tests process.cwd() if globs are passed on the command line', function (t) { + execCli(['--verbose', 'dir-a/*.js'], {dirname: 'fixture/pkg-conf/resolve-dir/dir-a-wrapper'}, function (err, stdout, stderr) { + t.ifError(err); + t.match(stderr, /dir-a-wrapper-3/); + t.match(stderr, /dir-a-wrapper-4/); + t.notMatch(stderr, /dir-a-base/); + t.notMatch(stdout, /dir-a-base/); + t.end(); + }); +}); + test('watcher reruns test files when they changed', function (t) { var killed = false; diff --git a/test/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js b/test/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js new file mode 100644 index 000000000..f7f3994d5 --- /dev/null +++ b/test/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js @@ -0,0 +1,5 @@ +import test from '../../../../../../'; + +test(t => { + t.pass(); +}); diff --git a/test/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js b/test/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js new file mode 100644 index 000000000..f7f3994d5 --- /dev/null +++ b/test/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js @@ -0,0 +1,5 @@ +import test from '../../../../../../'; + +test(t => { + t.pass(); +}); diff --git a/test/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-1.js b/test/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-1.js new file mode 100644 index 000000000..f5af94d7a --- /dev/null +++ b/test/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-1.js @@ -0,0 +1,5 @@ +import test from '../../../../../'; + +test(t => { + t.pass(); +}); diff --git a/test/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-2.js b/test/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-2.js new file mode 100644 index 000000000..f5af94d7a --- /dev/null +++ b/test/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-2.js @@ -0,0 +1,5 @@ +import test from '../../../../../'; + +test(t => { + t.pass(); +}); diff --git a/test/fixture/pkg-conf/resolve-dir/package.json b/test/fixture/pkg-conf/resolve-dir/package.json new file mode 100644 index 000000000..7634802f2 --- /dev/null +++ b/test/fixture/pkg-conf/resolve-dir/package.json @@ -0,0 +1,7 @@ +{ + "name": "application-name", + "version": "0.0.1", + "ava": { + "files": "dir-a/*.js" + } +} From d9e96eef2d216cd828fc202ae95413c047d2a903 Mon Sep 17 00:00:00 2001 From: James Talmage Date: Mon, 23 May 2016 22:06:58 -0400 Subject: [PATCH 3/3] update test/watcher.js to reflect new AvaFiles Api --- test/watcher.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/watcher.js b/test/watcher.js index 993fd2729..5c27192e8 100644 --- a/test/watcher.js +++ b/test/watcher.js @@ -553,8 +553,8 @@ group('chokidar is installed', function (beforeEach, test, group) { test('initial exclude patterns override whether something is a test file', function (t) { t.plan(2); - avaFiles = function (files, sources) { - var ret = new AvaFiles(files, sources); + avaFiles = function (options) { + var ret = new AvaFiles(options); // Note: There is no way for users to actually set exclude patterns yet. // This test just validates that internal updates to the default excludes pattern will be obeyed. ret.excludePatterns = ['!*bar*']; @@ -632,8 +632,8 @@ group('chokidar is installed', function (beforeEach, test, group) { test('exclude patterns override directory matches', function (t) { t.plan(2); - avaFiles = function (files, sources) { - var ret = new AvaFiles(files, sources); + avaFiles = function (options) { + var ret = new AvaFiles(options); // Note: There is no way for users to actually set exclude patterns yet. // This test just validates that internal updates to the default excludes pattern will be obeyed. ret.excludePatterns = ['!**/exclude/**'];