Skip to content

Commit

Permalink
Babel 7 support and additional enhancements
Browse files Browse the repository at this point in the history
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 authored Jan 27, 2018
1 parent a051d3e commit b33cb1d
Show file tree
Hide file tree
Showing 40 changed files with 1,199 additions and 829 deletions.
32 changes: 20 additions & 12 deletions api.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand All @@ -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;
});
Expand Down
115 changes: 115 additions & 0 deletions docs/recipes/babel.md
Original file line number Diff line number Diff line change
@@ -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.
148 changes: 3 additions & 145 deletions docs/recipes/babelrc.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
4 changes: 4 additions & 0 deletions docs/recipes/code-coverage.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
4 changes: 4 additions & 0 deletions docs/recipes/jspm-systemjs.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
4 changes: 4 additions & 0 deletions docs/recipes/precompiling-with-webpack.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
4 changes: 4 additions & 0 deletions docs/recipes/react.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
4 changes: 4 additions & 0 deletions docs/recipes/vue.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
Loading

0 comments on commit b33cb1d

Please # to comment.