Permalink
Browse files

Babel 7 support and additional enhancements

Fixes #1598. Switches AVA's Babel implementation to use Babel 7. This applies to test and helper file compilation.

Adds a `compileEnhancements` option which can be set to `false` to disable Power Assert and our `t.throws()` helper.

Changes the Babel configuration. If you had this before:

```json
"ava": {
  "babel": {
    "plugins": []
  }
}
```

You'll now need:

```json
"ava": {
  "babel": {
    "testOptions": {
      "plugins": []
    }
  }
}
```

`ava.babel.testOptions.babelrc` now defaults to `true`. You can disable our stage-4 preset by adding `["ava/stage-4", false]` to `ava.babel.testOptions.presets`. Set `ava.babel` to `false` to disable AVA's test file compilation, **whilst still compiling enhancements**. If `compileEnhancements` is *also* set to `false` then Babel is skipped completely.

Fixes #1225, #1488 and #1556.
  • Loading branch information...
novemberborn committed Jan 27, 2018
1 parent a051d3e commit b33cb1d533293c62f1244fb426e59d98de7890bc
Showing with 1,199 additions and 829 deletions.
  1. +20 −12 api.js
  2. +115 −0 docs/recipes/babel.md
  3. +3 −145 docs/recipes/babelrc.md
  4. +4 −0 docs/recipes/code-coverage.md
  5. +4 −0 docs/recipes/jspm-systemjs.md
  6. +4 −0 docs/recipes/precompiling-with-webpack.md
  7. +4 −0 docs/recipes/react.md
  8. +4 −0 docs/recipes/vue.md
  9. +93 −48 lib/babel-config.js
  10. +3 −7 lib/caching-precompiler.js
  11. +1 −3 lib/cli.js
  12. +2 −2 lib/enhance-assert.js
  13. +649 −414 package-lock.json
  14. +6 −6 package.json
  15. +4 −2 profile.js
  16. +18 −55 readme.md
  17. +1 −0 stage-4.js
  18. +38 −30 test/api.js
  19. +112 −99 test/babel-config.js
  20. +2 −2 test/caching-precompiler.js
  21. +41 −1 test/cli.js
  22. +1 −1 test/fixture/_generate-source-map-initial.js
  23. +1 −0 test/fixture/babel-noop-plugin-or-preset.js
  24. +7 −0 test/fixture/babelrc-js/.babelrc.js
  25. +4 −0 test/fixture/babelrc-js/package.json
  26. +11 −0 test/fixture/babelrc-js/test.js
  27. +0 −1 test/fixture/babelrc/.alt-babelrc
  28. +8 −1 test/fixture/babelrc/.babelrc
  29. +1 −0 test/fixture/just-enhancement-compilation/_helper.js
  30. 0 test/fixture/just-enhancement-compilation/dependency.js
  31. +1 −0 test/fixture/just-enhancement-compilation/import.js
  32. +6 −0 test/fixture/just-enhancement-compilation/package.json
  33. +8 −0 test/fixture/just-enhancement-compilation/power-assert.js
  34. +1 −0 test/fixture/no-babel-compilation/_helper.js
  35. 0 test/fixture/no-babel-compilation/dependency.js
  36. +1 −0 test/fixture/no-babel-compilation/import.js
  37. +8 −0 test/fixture/no-babel-compilation/no-power-assert.js
  38. +6 −0 test/fixture/no-babel-compilation/package.json
  39. +7 −0 test/fixture/no-babel-compilation/require-helper.js
  40. 0 test/fixture/no-babel-config/.gitkeep
32 api.js
@@ -57,10 +57,13 @@ class Api extends EventEmitter {
}
_runFile(file, runStatus, execArgv) {
const hash = this.precompiler.precompileFile(file);
const precompiled = Object.assign({}, this._precompiledHelpers);
const resolvedfpath = fs.realpathSync(file);
precompiled[resolvedfpath] = hash;
const precompiled = {};
if (this.precompiler) {
Object.assign(precompiled, this._precompiledHelpers);
const hash = this.precompiler.precompileFile(file);
const resolvedfpath = fs.realpathSync(file);
precompiled[resolvedfpath] = hash;
}
const options = Object.assign({}, this.options, {precompiled});
if (runStatus.updateSnapshots) {
@@ -117,19 +120,24 @@ class Api extends EventEmitter {
this.options.cacheDir = cacheDir;
const isPowerAssertEnabled = this.options.powerAssert !== false;
return babelConfigHelper.build(this.options.projectDir, cacheDir, this.options.babelConfig, isPowerAssertEnabled)
const compileEnhancements = this.options.compileEnhancements !== false;
return babelConfigHelper.build(this.options.projectDir, cacheDir, this.options.babelConfig, compileEnhancements)
.then(result => {
this.precompiler = new CachingPrecompiler({
path: cacheDir,
getBabelOptions: result.getOptions,
babelCacheKeys: result.cacheKeys
});
if (result) {
this.precompiler = new CachingPrecompiler({
path: cacheDir,
getBabelOptions: result.getOptions,
babelCacheKeys: result.cacheKeys
});
}
});
}
_precompileHelpers() {
this._precompiledHelpers = {};
if (!this.precompiler) {
return Promise.resolve();
}
// Assumes the tests only load helpers from within the `resolveTestsFrom`
// directory. Without arguments this is the `projectDir`, else it's
@@ -138,7 +146,7 @@ class Api extends EventEmitter {
// processes, avoiding the need for precompilation.
return new AvaFiles({cwd: this.options.resolveTestsFrom})
.findTestHelpers()
.map(file => { // eslint-disable-line array-callback-return
.each(file => { // eslint-disable-line array-callback-return
const hash = this.precompiler.precompileFile(file);
this._precompiledHelpers[file] = hash;
});
@@ -0,0 +1,115 @@
# Configuring Babel
AVA uses [Babel 7](https://babeljs.io) so you can use the latest JavaScript syntax in your tests. We do this by compiling test and helper files using our [`@ava/stage-4`](https://github.com/avajs/babel-preset-stage-4) preset. We also use a [second preset](https://github.com/avajs/babel-preset-transform-test-files) to enable [enhanced assertion messages](../../readme#enhanced-assertion-messages) and detect improper use of `t.throws()` assertions.
By default our Babel pipeline is applied to test and helper files ending in `.js`. If your project uses Babel then we'll automatically compile files using your project's Babel configuration.
AVA only looks for Babel configuration files in your project directory. That is, `.babelrc` or `.babelrc.js` files next to your `package.json` file, or the `package.json` file itself.
## Customize how AVA compiles your test files
You can override the default Babel configuration AVA uses for test file compilation in `package.json`. For example, the configuration below adds support for JSX syntax and stage 3 features:
```json
{
"ava": {
"babel": {
"testOptions": {
"plugins": ["@babel/plugin-syntax-jsx"],
"presets": ["@babel/preset-stage-3"]
}
}
}
}
```
All `.babelrc` options are allowed inside the `testOptions` object.
## Make AVA skip your project's Babel options
You may not want AVA to use your project's Babel options, for example if your project is relying on Babel 6. You can set the `babelrc` option to `false`:
```json
{
"ava": {
"babel": {
"testOptions": {
"babelrc": false
}
}
}
}
```
## Disable AVA's stage-4 preset
You can disable AVA's stage-4 preset:
```json
{
"ava": {
"babel": {
"testOptions": {
"presets": [
["module:ava/stage-4", false]
]
}
}
}
}
```
Note that this *does not* stop AVA from compiling your test files using Babel.
## Disable AVA's Babel pipeline
You can completely disable AVA's use of Babel:
```json
{
"ava": {
"babel": false,
"compileEnhancements": false
}
}
```
## Use Babel polyfills
AVA lets you write your tests using new JavaScript syntax, even on Node.js versions that otherwise wouldn't support it. However, it doesn't add or modify built-ins of your current environment. Using AVA would, for example, not provide modern features such as `Object.entries()` to an underlying Node.js 6 environment.
By loading [Babel's `polyfill` module](https://babeljs.io/docs/usage/polyfill/) you can opt in to these features. Note that this will modify the environment, which may influence how your program behaves.
You can enable the `polyfill` module by adding it to AVA's `require` option:
```json
{
"ava": {
"require": [
"@babel/polyfill"
]
}
}
```
You'll need to install `@babel/polyfill` yourself.
## Compile sources
AVA does not currently compile source files. You'll have to load [Babel's `register` module](http://babeljs.io/docs/usage/require/), which will compile source files as needed.
You can enable the `register` module by adding it to AVA's `require` option:
```json
{
"ava": {
"require": [
"@babel/register"
]
}
}
```
You'll need to install `@babel/register` yourself.
Note that loading `@babel/register` in every worker process has a non-trivial performance cost. If you have lots of test files, you may want to consider using a build step to compile your sources *before* running your tests. This isn't ideal, since it complicates using AVA's watch mode, so we recommend using `@babel/register` until the performance penalty becomes too great. Setting up a precompilation step is out of scope for this document, but we recommend you check out one of the many [build systems that support Babel](http://babeljs.io/docs/setup/). There is an [issue](https://github.com/avajs/ava/issues/577) discussing ways we could make this experience better.
@@ -2,150 +2,8 @@
Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/babelrc.md)
There are multiple options for configuring how AVA transpiles your tests using Babel.
This recipe has moved. Please see our [new Babel recipe](babel.md).
- [AVA's default transpiler behavior](#avas-default-transpiler-behavior)
- [Customizing how AVA transpiles your tests](#customizing-how-ava-transpiles-your-tests)
- [Transpiling Sources](#transpiling-sources)
- [Transpiling tests and sources the same way](#transpiling-tests-and-sources-the-same-way)
- [Extend your source transpilation configuration](#extend-your-source-transpilation-configuration)
- [Extend an alternate config file (i.e. not `.babelrc`)](#extend-an-alternate-config-file)
---
## AVA's default transpiler behavior
AVA lets you use some nifty JavaScript features, like [async functions](https://github.com/avajs/ava#async-function-support). To make this work on older Node.js versions AVA transpiles the tests and helper files using the [`@ava/stage-4`](https://github.com/avajs/babel-preset-stage-4) Babel preset. This is great for projects where you do not use Babel for your source, but do want to use the newest JavaScript features for your tests.
### Using object rest/spread properties
As of Node.js [8.3.0](https://github.com/nodejs/node/blob/v8.3.0/doc/changelogs/CHANGELOG_V8.md#8.3.0) [object rest/spread properties](https://github.com/tc39/proposal-object-rest-spread) is supported directly. This new language feature however has not yet reached [stage 4](http://2ality.com/2015/11/tc39-process.html#stage-4-finished), which means that AVA won't support it by default. That said, if you're using Node.js 8.3.0 or newer, AVA will load the [`syntax-object-rest-spread`](https://www.npmjs.com/package/babel-plugin-syntax-object-rest-spread) plugin for you. This means you *can* use object rest/spread properties in your tests as long as you're not targeting older Node.js versions.
Note that if you customize the Babel configuration you'll have to explicitly specify the `syntax-object-rest-spread` plugin.
## Customizing how AVA transpiles your tests
You can override the default Babel configuration AVA uses for test transpilation in `package.json`. For example, the configuration below adds the Babel `rewire` plugin, and adds the Babel [`stage-3`](http://babeljs.io/docs/plugins/preset-stage-3/) preset.
```json
{
"ava": {
"babel": {
"plugins": ["rewire"],
"presets": ["@ava/stage-4", "stage-3"]
}
}
}
```
Note that this only affects how AVA transpiles your tests. If you use `babel-register` you'll still need to add separate Babel configuration as explained [here](#transpiling-sources).
## Use Babel Polyfills
AVA lets you write your tests using new JavaScript syntax, even on Node.js versions that otherwise wouldn't support it. However, it doesn't add or modify built-ins of your current environment. Using AVA would, for example, not provide modern features such as `Array.prototype.includes()` to an underlying Node.js 4 environment.
By loading [Babel's Polyfill module](https://babeljs.io/docs/usage/polyfill/) you can opt in to these features. Note that this will modify the environment, which may influence how your program behaves.
You can enable `babel-polyfill` by adding it to AVA's `require` option:
```json
{
"ava": {
"require": [
"babel-polyfill"
]
}
}
```
## Transpiling Sources
To transpile your sources, you will need to define a [`babel config` ](http://babeljs.io/docs/usage/babelrc/) in `package.json` or a `.babelrc` file. Also, you will need to tell AVA to load [`babel-register`](http://babeljs.io/docs/usage/require/) in every forked process, by adding it to the `require` section of your AVA config:
`package.json`
```json
{
"ava": {
"require": ["babel-register"]
},
"babel": {
"presets": ["@ava/stage-4"]
}
}
```
Note that loading `babel-register` in every forked process has a non-trivial performance cost. If you have lots of test files, you may want to consider using a build step to transpile your sources *before* running your tests. This isn't ideal, since it complicates using AVA's watch mode, so we recommend using `babel-register` until the performance penalty becomes too great. Setting up a precompilation step is out of scope for this document, but we recommend you check out one of the many [build systems that support Babel](http://babeljs.io/docs/setup/). There is an [open issue](https://github.com/avajs/ava/issues/577) discussing ways we could make this experience better.
## Transpiling tests and sources the same way
Using the `"inherit"` shortcut will cause your tests to be transpiled the same as your sources (as specified in your [`babelrc`](http://babeljs.io/docs/usage/babelrc/)). AVA will add a few additional [internal plugins](#notes) when transpiling your tests, but they won't affect the behavior of your test code.
`package.json`:
```json
{
"ava": {
"require": "babel-register",
"babel": "inherit"
},
"babel": {
"presets": [
"@ava/stage-4",
"react"
]
}
}
```
In the above example, both tests and sources will be transpiled using the [`@ava/stage-4`](https://github.com/avajs/babel-preset-stage-4) and [`react`](http://babeljs.io/docs/plugins/preset-react/) presets.
AVA will only look for a `.babelrc` file in the same directory as the `package.json` file. If not found then it assumes your Babel config lives in the `package.json` file.
## Extend your source transpilation configuration
When specifying the Babel config for your tests, you can set the `babelrc` option to `true`. This will merge the specified plugins with those from your [`babelrc`](http://babeljs.io/docs/usage/babelrc/).
`package.json`:
```json
{
"ava": {
"require": "babel-register",
"babel": {
"babelrc": true,
"plugins": ["custom-plugin-name"],
"presets": ["custom-preset"]
}
},
"babel": {
"presets": [
"@ava/stage-4",
"react"
]
}
}
```
In the above example, *sources* are compiled use [`@ava/stage-4`](https://github.com/avajs/babel-preset-stage-4) and [`react`](http://babeljs.io/docs/plugins/preset-react/), *tests* use those same plugins, plus the additional `custom` plugins specified.
AVA will only look for a `.babelrc` file in the same directory as the `package.json` file. If not found then it assumes your Babel config lives in the `package.json` file.
## Extend an alternate config file.
If, for some reason, your Babel config is not specified in one of the default locations ([`.babelrc` or `package.json`](http://babeljs.io/docs/usage/babelrc/), you can set the `extends` option to the alternate config you want to use during testing.
`package.json`:
```json
{
"ava": {
"require": "babel-register",
"babel": {
"extends": "./babel-test-config.json",
"plugins": ["custom-plugin-name"],
"presets": ["custom-preset"]
}
}
}
```
The above uses `babel-test-config.json` as the transpilation config for *sources*, and as the base config for *tests*. For *tests*, it extends that base config with the custom plugins and presets specified.
If you're using an older AVA version, please see [version 0.25.0 of this recipe](https://github.com/avajs/ava/blob/v0.25.0/docs/recipes/babelrc.md).
@@ -1,3 +1,7 @@
> **Please note, this recipe has not yet been updated for Babel 7 support in AVA 1.0.**
---
# Code coverage
Translations: [Español](https://github.com/avajs/ava-docs/blob/master/es_ES/docs/recipes/code-coverage.md), [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/code-coverage.md), [Italiano](https://github.com/avajs/ava-docs/blob/master/it_IT/docs/recipes/code-coverage.md), [日本語](https://github.com/avajs/ava-docs/blob/master/ja_JP/docs/recipes/code-coverage.md), [Português](https://github.com/avajs/ava-docs/blob/master/pt_BR/docs/recipes/code-coverage.md), [Русский](https://github.com/avajs/ava-docs/blob/master/ru_RU/docs/recipes/code-coverage.md), [简体中文](https://github.com/avajs/ava-docs/blob/master/zh_CN/docs/recipes/code-coverage.md)
@@ -1,3 +1,7 @@
> **Please note, this recipe has not yet been updated for Babel 7 support in AVA 1.0.**
---
# JSPM and SystemJS for ES2015
Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/jspm-systemjs.md)
@@ -1,3 +1,7 @@
> **Please note, this recipe has not yet been updated for Babel 7 support in AVA 1.0.**
---
## Precompiling source files with webpack
Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/precompiling-with-webpack.md)
@@ -1,3 +1,7 @@
> **Please note, this recipe has not yet been updated for Babel 7 support in AVA 1.0.**
---
# Testing React components
Translations: [Español](https://github.com/avajs/ava-docs/blob/master/es_ES/docs/recipes/react.md), [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/react.md)
@@ -1,3 +1,7 @@
> **Please note, this recipe has not yet been updated for Babel 7 support in AVA 1.0.**
---
# Testing Vue.js components
Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/vue.md)
Oops, something went wrong.

0 comments on commit b33cb1d

Please sign in to comment.