-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds support for ava.config.js files #1761
Conversation
Have you checked cosmiconfig? It would fulfill a lot of the requirements, and the one missing might be implement over there. |
We'd end up using very little of @good-idea thanks for your PR. I've been quite busy lately so I make need another few days before I can get back to you. |
@novemberborn No hurry, I don't think I'll be able to chip away at this until the end of the week. This is my first contribution to OSS 🤓 so any feedback is welcome! |
Some quick responses to your questions (I'll try and get to the other stuff later):
No strong feelings either way, though I suppose I should look into what
No that's fine. The test case we're looking for is where there are
A newer Babel 7 is being picked up in one of the test jobs, and it's causing test failures. I'm a little surprised at that, to be honest! Feel free to ignore the Travis run with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great start @good-idea! There seems to be some confusion around where the ava.config.js
file is supposed to be. It's either next to a package.json
file or in the current directory. I don't want it to be a secondary way for AVA to determine the project directory. If this proves too confusing we can change it, but for now I like the simplicity of AVA determining what is a "project" based on package.json
files only.
lib/load-config.js
Outdated
const findConfigFiles = () => { | ||
const packageFile = findPackageDotJson(); | ||
const configFile = findConfigFile( | ||
packageFile ? path.dirname(packageFile) : process.cwd(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's simplify this. We can keep the current pkg-conf
logic to find the package.json
, if any. Afterwards, the ava.config.js
file must be in the projectDir
. We won't walk the file system to find it. (This means the findFileUp
logic above is not necessary.)
test/cli.js
Outdated
@@ -40,7 +40,9 @@ function execCli(args, opts, cb) { | |||
|
|||
child.on('close', (code, signal) => { | |||
if (code) { | |||
const err = new Error(`test-worker exited with a non-zero exit code: ${code}`); | |||
const err = new Error( | |||
`test-worker exited with a non-zero exit code: ${code}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you're using Prettier. Could you exclude unrelated changes from the PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it!
@good-idea if you could merge in (or rebase on) master, that should fix some of the CI issues. |
@novemberborn thanks, I'll working on this later today! |
And adds test for factory function in config file
Should have merged before but I rebased?
thought i fixed this!
@novemberborn I think this just about does it, let me know if you see anything else that should change! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@good-idea this is looking great!
I haven't actually played with the implementation yet, and I must admit I haven't really looked at the tests just yet either. There's a few things that should be addressed (see inline comments).
Looking at the diff on GitHub it seems to want to add things that are already in master
. Not quite sure what's happening. Perhaps try merging in master
or rebasing 😄
I'm very excited about landing this!
lib/load-config.js
Outdated
'use strict'; | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
// ESM seems to break `path` and `fs`, require them first before setting it up.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
esm
shouldn't impact require()
calls though. Happy to see the Node.js builtins loaded first, but your comment hints at an esm
bug. Is this still happening for you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked into why, but if I set up ESM first like so:
'use strict';
require = require('esm')(module);
const path = require('path');
console.log(path);
path
is null
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works for me, Node.js 8.11.0, and esm@3.0.22
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
esm@3.0.15
was installed, I updated to 3.0.22
and it now works as expected.
I also moved esm
from devDependencies to dependencies, since it's now being used in the main code -- does this make sense?
lib/load-config.js
Outdated
|
||
const loadConfigFile = projectDir => { | ||
const loaded = requireESM(path.resolve(projectDir, 'ava.config.js')); | ||
const config = (loaded.__esModule) ? loaded.default : loaded; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does esm
take care of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it doesn't seem to. There's a test for this that fails if you don't do the check for __esModule
.
lib/load-config.js
Outdated
if (config.then) { | ||
throw new Error('Config file must not return a promise'); | ||
} | ||
return (typeof config === 'function') ? config(projectDir) : config; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's pass {projectDir}
, so we can extend this with other options later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I meant doing config({projectDir})
, not loadConfigFile({projectDir})
.
lib/load-config.js
Outdated
projectDir | ||
}; | ||
|
||
return Object.assign(config, defaults, {_meta}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This copies the defaults
into config
. The _meta
bit seems unnecessary to me.
Better would be Object.assign({}, defaults, config, {projectDir})
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅
profile.js
Outdated
@@ -38,9 +38,9 @@ const conf = pkgConf.sync('ava', { | |||
} | |||
}); | |||
|
|||
const filepath = pkgConf.filepath(conf); | |||
const projectDir = filepath === null ? process.cwd() : path.dirname(filepath); | |||
console.log(conf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't forget to remove 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅
Oh, one more thing. The Line 136 in 718349e
'JS' when the config originates from a .js file. I'm happy to fix and test that myself though.
|
@novemberborn This last update should address the notes in your review -- I didn't look into the fileType issue in babel-conifg yet, though. I updated the initial PR description to include a todo for this. |
@good-idea fantastic. I probably won't be able to look at this until the weekend, but thank you for your hard work on this 👍 |
lib/load-config.js
Outdated
@@ -0,0 +1,33 @@ | |||
'use strict'; | |||
const requireEsm = require('esm')(module); // eslint-disable-line no-global-assign |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think think // eslint-disable-line no-global-assign
is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left some comments below.
I'll have a look at the fileType: 'JS
thing.
I also want to see if we can restrict this to supporting just export default
/ ESM.
lib/load-config.js
Outdated
|
||
const loadConfigFile = projectDir => { | ||
const loaded = requireEsm(path.resolve(projectDir, 'ava.config.js')); | ||
const config = (loaded.__esModule) ? loaded.default : loaded; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to play around with the esm
options. I think we can make it always treat these files as ESM, so we don't have to support the module.exports
workarounds etc. Would be neat to start with that. What do you think @sindresorhus?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
lib/load-config.js
Outdated
if (config.then) { | ||
throw new Error('Config file must not return a promise'); | ||
} | ||
return (typeof config === 'function') ? config({projectDir}) : config; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The config({projectDir})
return value also must not be a promise. Happy to fix this up myself.
readme.md
Outdated
}; | ||
``` | ||
|
||
The config file may also export a factory function, which will be called with an object containing a `projectDir` property. This function must return a config object, and cannot be a promise. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps:
This function must return a config object, it mustn't return a promise.
readme.md
Outdated
|
||
```js | ||
const config = ({projectDir}) => { | ||
if (projectDir === '...') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
projectDir
will be an absolute path, so it'd be good if the example didn't show dots which imply it's somehow relative.
Providing the directory is useful if you have share AVA config amongst projects, e.g. in a work setting or a monorepo. You could then differentiate between projects when necessary. Perhaps this is something we should cover in a recipe, outside of this PR.
readme.md
Outdated
export default config; | ||
``` | ||
|
||
Or, return different configuration based on the environment: `NODE_ENV=development ava` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about advocating AVA to be run with different NODE_ENV
settings. It'd be more interesting to detect CI environments — although at that point we should forward the detection to the function. Perhaps remove for now and track in a follow-up issue?
@novemberborn I made some changes to address the above -- there another big diff with |
@good-idea I haven't had a chance yet to look into this. I just realized we need some changes with Babel (#1789) so I might try and land that before doing my work here. Anyway this is super close so once that unblocks we should be good to go. |
@good-idea just wanted to say I haven't forgotten about this 😄 #1789 is pretty much done so I'm hoping to land that next weekend. I'll then try and get this in as well before cutting a release. |
@novemberborn No hurry on my end! I've been using my own fork for now :) |
@good-idea I've merged latest There's a few scenarios that are lacking tests. Once I've done that I'll land this 🎉 |
Fixes #520
Smart JS/JSON filetype in babel-config.jsesm
options so we don't have to support the module.exports workarounds etc