Skip to content
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

Add a recipe for configuring .babelrc. #708

Merged
merged 2 commits into from
Apr 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions docs/recipes/babelrc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Configuring Babel

There are multiple options for configuring how AVA transpiles your tests using Babel.

- [Specify a complete config in `package.json`](#specify-a-complete-config-in-packagejson)
- [Extend existing `.babelrc` without modification](#extend-existing-babelrc-without-modification)
- [Extend existing `.babelrc` with additional plugins or presets](#extend-existing-babelrc-with-additional-plugins-or-presets)
- [Extend an alternate config file (i.e. not `.babelrc`)](#extend-alternate-config-file)
- [Notes](#notes)

## Specify a complete config in `package.json`

The `babelrc` option defaults to `false`, meaning `.babelrc` files are not considered when transpiling tests. This means you must specify your complete config in `package.json`.

```json
{
"ava": {
"babel": {
"plugins": ["rewire"],
"presets": ["es2015"]
}
}
}
```

## Extend existing `.babelrc` without modification

Use the `"inherit"` shortcut if you want your tests transpiled the same as your sources. This will use your `.babelrc` directly (with a few additional [internal plugins](#notes)).

`package.json`:

```json
{
"ava": {
"babel": "inherit"
}
}
```

## Extend existing `.babelrc` with additional plugins or presets

Set `babelrc` to `true`. This will use your `.babelrc` and extend it with any additional plugins specified.

`package.json`:

```json
{
"ava": {
"babel": {
"babelrc": true,
"plugins": ["custom-plugin-name"],
"presets": ["custom-preset"]
}
}
}
```

## Extend alternate config file.


If, for some reason, you do not want to extend `.babelrc`, set the `extends` option to the alternate config you want to use during testing.

`package.json`:

```json
{
"ava": {
"babel": {
"extends": "./babel-test-config.json",
"plugins": ["custom-plugin-name"],
"presets": ["custom-preset"]
}
}
}
```

The above uses `babel-test-config.json` as the base config, and extends it with the custom plugins and presets specified.

## Notes

AVA *always* adds a few custom Babel plugins when transpiling your plugins. They serve a variety of functions:

* Enable `power-assert` support.
* Rewrite require paths internal AVA dependencies like `babel-runtime` (important if you are still using `npm@2`).
* Generate test metadata to determine which files should be run first (*future*).
* Static analysis of dependencies for precompilation (*future*).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add these now, or update later?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to just add those like that and we can expand on them later.

3 changes: 3 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ You can also use the special `"inherit"` keyword. This makes AVA defer to the Ba
}
```

See AVA's [`.babelrc` recipe](docs/recipes/babelrc.md) for further examples and a more detailed explanation of configuration options.

Note that AVA will *always* apply the [`espower`](https://github.com/power-assert-js/babel-plugin-espower) and [`transform-runtime`](https://babeljs.io/docs/plugins/transform-runtime/) plugins.

### TypeScript support
Expand Down Expand Up @@ -916,6 +918,7 @@ It's the [Andromeda galaxy](https://simple.wikipedia.org/wiki/Andromeda_galaxy).
- [When to use `t.plan()`](docs/recipes/when-to-use-plan.md)
- [Browser testing](docs/recipes/browser-testing.md)
- [TypeScript](docs/recipes/typescript.md)
- [Configuring Babel](docs/recipes/babelrc.md)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also add a link in the ES2015 section.


## Support

Expand Down
101 changes: 94 additions & 7 deletions test/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var figures = require('figures');
var rimraf = require('rimraf');
var test = require('tap').test;
var Api = require('../api');
var testDoublerPlugin = require('./fixture/babel-plugin-test-doubler');
var testCapitalizerPlugin = require('./fixture/babel-plugin-test-capitalizer');

test('must be called with new', function (t) {
t.throws(function () {
Expand Down Expand Up @@ -731,29 +731,116 @@ test('verify test count', function (t) {
});

test('Custom Babel Plugin Support', function (t) {
t.plan(1);
t.plan(2);

var api = new Api({
babelConfig: {
presets: ['es2015', 'stage-2'],
plugins: [testDoublerPlugin]
}
plugins: [testCapitalizerPlugin]
},
cacheEnabled: false
});

api.run([path.join(__dirname, 'fixture/es2015.js')])
api.on('test', function (data) {
t.is(data.title, 'FOO');
});

api.run([path.join(__dirname, 'fixture/babelrc/test.js')])
.then(
function () {
t.is(api.passCount, 2);
t.is(api.passCount, 1);
},
t.threw
);
});

test('Default babel config doesn\'t use .babelrc', function (t) {
t.plan(1);
t.plan(2);

var api = new Api();

api.on('test', function (data) {
t.is(data.title, 'foo');
});

return api.run([path.join(__dirname, 'fixture/babelrc/test.js')])
.then(function () {
t.is(api.passCount, 1);
});
});

test('babelConfig:"inherit" uses .babelrc', function (t) {
t.plan(3);

var api = new Api({
babelConfig: 'inherit',
cacheEnabled: false
});

api.on('test', function (data) {
t.ok((data.title === 'foo') || (data.title === 'repeated test: foo'));
});

return api.run([path.join(__dirname, 'fixture/babelrc/test.js')])
.then(function () {
t.is(api.passCount, 2);
});
});

test('babelConfig:{babelrc:true} uses .babelrc', function (t) {
t.plan(3);

var api = new Api({
babelConfig: {babelrc: true},
cacheEnabled: false
});

api.on('test', function (data) {
t.ok((data.title === 'foo') || (data.title === 'repeated test: foo'));
});

return api.run([path.join(__dirname, 'fixture/babelrc/test.js')])
.then(function () {
t.is(api.passCount, 2);
});
});

test('babelConfig:{babelrc:true, plugins:[...]} merges plugins with .babelrc', function (t) {
t.plan(3);

var api = new Api({
babelConfig: {
plugins: [testCapitalizerPlugin],
babelrc: true
},
cacheEnabled: false
});

api.on('test', function (data) {
t.ok((data.title === 'FOO') || /^repeated test:/.test(data.title));
});

return api.run([path.join(__dirname, 'fixture/babelrc/test.js')])
.then(function () {
t.is(api.passCount, 2);
});
});

test('babelConfig:{extends:path, plugins:[...]} merges plugins with .babelrc', function (t) {
t.plan(2);

var api = new Api({
babelConfig: {
plugins: [testCapitalizerPlugin],
extends: path.join(__dirname, 'fixture/babelrc/.alt-babelrc')
},
cacheEnabled: false
});

api.on('test', function (data) {
t.ok((data.title === 'BAR'));
});

return api.run([path.join(__dirname, 'fixture/babelrc/test.js')])
.then(function () {
t.is(api.passCount, 1);
Expand Down
19 changes: 19 additions & 0 deletions test/fixture/babel-plugin-foo-to-bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = function (babel) {
var t = babel.types;

return {
visitor: {
CallExpression: function (path) {
// skip require calls
var firstArg = path.get('arguments')[0];
if (!isRequire(path) && firstArg && firstArg.isStringLiteral() && /foo/i.test(firstArg.node.value)) {
firstArg.replaceWith(t.stringLiteral(firstArg.node.value.replace('foo', 'bar').replace('FOO', 'BAR')));
}
}
}
};
};

function isRequire(path) {
return path.isCallExpression() && path.get('callee').isIdentifier() && (path.get('callee').node.name === 'require');
}
19 changes: 19 additions & 0 deletions test/fixture/babel-plugin-test-capitalizer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = function (babel) {
var t = babel.types;

return {
visitor: {
CallExpression: function (path) {
// skip require calls
var firstArg = path.get('arguments')[0];
if (!isRequire(path) && firstArg && firstArg.isStringLiteral() && !/repeated test/.test(firstArg.node.value)) {
firstArg.replaceWith(t.stringLiteral(firstArg.node.value.toUpperCase()));
}
}
}
};
};

function isRequire(path) {
return path.isCallExpression() && path.get('callee').isIdentifier() && (path.get('callee').node.name === 'require');
}
4 changes: 4 additions & 0 deletions test/fixture/babelrc/.alt-babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["es2015", "stage-2"],
"plugins": ["../babel-plugin-foo-to-bar"]
}
3 changes: 2 additions & 1 deletion test/fixture/babelrc/.babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"plugins": ["this-plugin-does-not-exist"]
"presets": ["es2015", "stage-2"],
"plugins": ["../babel-plugin-test-doubler"]
}
2 changes: 1 addition & 1 deletion test/fixture/babelrc/test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import test from '../../../'

test(t => t.pass());
test('foo', t => t.pass());