Skip to content

Commit a3cb350

Browse files
committed
Support disabling of the Babel pipeline
Set babel=false to disable AVA's default test compilation. *Also* set compileEnhancements=false to disable the Babel pipeline altogether. Fixes #1556.
1 parent e253da4 commit a3cb350

File tree

15 files changed

+137
-26
lines changed

15 files changed

+137
-26
lines changed

api.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,13 @@ class Api extends EventEmitter {
5757
}
5858

5959
_runFile(file, runStatus, execArgv) {
60-
const hash = this.precompiler.precompileFile(file);
61-
const precompiled = Object.assign({}, this._precompiledHelpers);
62-
const resolvedfpath = fs.realpathSync(file);
63-
precompiled[resolvedfpath] = hash;
60+
const precompiled = {};
61+
if (this.precompiler) {
62+
Object.assign(precompiled, this._precompiledHelpers);
63+
const hash = this.precompiler.precompileFile(file);
64+
const resolvedfpath = fs.realpathSync(file);
65+
precompiled[resolvedfpath] = hash;
66+
}
6467

6568
const options = Object.assign({}, this.options, {precompiled});
6669
if (runStatus.updateSnapshots) {
@@ -120,16 +123,21 @@ class Api extends EventEmitter {
120123
const compileEnhancements = this.options.compileEnhancements !== false;
121124
return babelConfigHelper.build(this.options.projectDir, cacheDir, this.options.babelConfig, compileEnhancements)
122125
.then(result => {
123-
this.precompiler = new CachingPrecompiler({
124-
path: cacheDir,
125-
getBabelOptions: result.getOptions,
126-
babelCacheKeys: result.cacheKeys
127-
});
126+
if (result) {
127+
this.precompiler = new CachingPrecompiler({
128+
path: cacheDir,
129+
getBabelOptions: result.getOptions,
130+
babelCacheKeys: result.cacheKeys
131+
});
132+
}
128133
});
129134
}
130135

131136
_precompileHelpers() {
132137
this._precompiledHelpers = {};
138+
if (!this.precompiler) {
139+
return Promise.resolve();
140+
}
133141

134142
// Assumes the tests only load helpers from within the `resolveTestsFrom`
135143
// directory. Without arguments this is the `projectDir`, else it's
@@ -138,7 +146,7 @@ class Api extends EventEmitter {
138146
// processes, avoiding the need for precompilation.
139147
return new AvaFiles({cwd: this.options.resolveTestsFrom})
140148
.findTestHelpers()
141-
.map(file => { // eslint-disable-line array-callback-return
149+
.each(file => { // eslint-disable-line array-callback-return
142150
const hash = this.precompiler.precompileFile(file);
143151
this._precompiledHelpers[file] = hash;
144152
});

docs/recipes/babel.md

+13
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ You can disable AVA's stage-4 preset:
6161

6262
Note that this *does not* stop AVA from compiling your test files using Babel.
6363

64+
## Disable AVA's Babel pipeline
65+
66+
You can completely disable AVA's use of Babel:
67+
68+
```json
69+
{
70+
"ava": {
71+
"babel": false,
72+
"compileEnhancements": false
73+
}
74+
}
75+
```
76+
6477
## Use Babel polyfills
6578

6679
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.

lib/babel-config.js

+27-16
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ const syntaxObjectRestSpreadPath = require.resolve('@babel/plugin-syntax-object-
1414
const transformTestFilesPath = require.resolve('@ava/babel-preset-transform-test-files');
1515

1616
function validate(conf) {
17+
if (conf === false) {
18+
return null;
19+
}
20+
1721
if (conf === undefined) {
1822
return {testOptions: {}};
1923
}
@@ -77,6 +81,10 @@ function resolveOptions(baseConfig, cache, envName, optionsFile, verifierFile) {
7781
}
7882

7983
function build(projectDir, cacheDir, userOptions, compileEnhancements) {
84+
if (!userOptions && !compileEnhancements) {
85+
return Promise.resolve(null);
86+
}
87+
8088
// Note that Babel ignores empty string values, even for NODE_ENV. Here
8189
// default to 'test' unless NODE_ENV is defined, in which case fall back to
8290
// Babel's default of 'development' if it's empty.
@@ -102,24 +110,27 @@ function build(projectDir, cacheDir, userOptions, compileEnhancements) {
102110
const baseOptions = {
103111
babelrc: false,
104112
plugins: [],
105-
presets: [
106-
stage4Path // Always apply the stage-4 preset.
107-
]
113+
presets: []
108114
};
109115

110-
// By default extend the project's Babel configuration, but allow this to be
111-
// disabled through userOptions.
112-
if (userOptions.testOptions.babelrc !== false) {
113-
baseOptions.babelrc = true;
114-
}
115-
if (userOptions.testOptions.extends) {
116-
baseOptions.extends = userOptions.testOptions.extends;
117-
}
116+
if (userOptions) {
117+
// Always apply the stage-4 preset.
118+
baseOptions.presets.push(stage4Path);
118119

119-
// Include object rest spread support for Node.js versions that support it
120-
// natively.
121-
if (semver.satisfies(process.versions.node, '>= 8.3.0')) {
122-
baseOptions.plugins.push(syntaxObjectRestSpreadPath);
120+
// By default extend the project's Babel configuration, but allow this to be
121+
// disabled through userOptions.
122+
if (userOptions.testOptions.babelrc !== false) {
123+
baseOptions.babelrc = true;
124+
}
125+
if (userOptions.testOptions.extends) {
126+
baseOptions.extends = userOptions.testOptions.extends;
127+
}
128+
129+
// Include object rest spread support for Node.js versions that support it
130+
// natively.
131+
if (semver.satisfies(process.versions.node, '>= 8.3.0')) {
132+
baseOptions.plugins.push(syntaxObjectRestSpreadPath);
133+
}
123134
}
124135

125136
const baseConfig = configManager.createConfig({
@@ -131,7 +142,7 @@ function build(projectDir, cacheDir, userOptions, compileEnhancements) {
131142
});
132143

133144
let intermediateConfig = baseConfig;
134-
if (Object.keys(userOptions.testOptions).length > 0) {
145+
if (userOptions && Object.keys(userOptions.testOptions).length > 0) {
135146
// At this level, babelrc *must* be false.
136147
const options = Object.assign({}, userOptions.testOptions, {babelrc: false});
137148
// Any extends option has been applied in baseConfig.

test/cli.js

+40
Original file line numberDiff line numberDiff line change
@@ -824,3 +824,43 @@ test('doesn\'t set NODE_ENV when it is set', t => {
824824
t.end();
825825
});
826826
});
827+
828+
test('skips test file compilation when babel=false and compileEnhancements=false', t => {
829+
execCli(['import.js'], {dirname: 'fixture/no-babel-compilation'}, (err, stdout, stderr) => {
830+
t.ok(err);
831+
t.match(stderr, /SyntaxError: Unexpected (reserved word|token import)/);
832+
t.end();
833+
});
834+
});
835+
836+
test('skips helper file compilation when babel=false and compileEnhancements=false', t => {
837+
execCli(['require-helper.js'], {dirname: 'fixture/no-babel-compilation'}, (err, stdout, stderr) => {
838+
t.ifError(err);
839+
t.match(stderr, /1 passed/);
840+
t.end();
841+
});
842+
});
843+
844+
test('no power-assert when babel=false and compileEnhancements=false', t => {
845+
execCli(['no-power-assert.js'], {dirname: 'fixture/no-babel-compilation'}, (err, stdout, stderr) => {
846+
t.ok(err);
847+
t.notMatch(stripAnsi(stderr), /bool\n.*=> false/);
848+
t.end();
849+
});
850+
});
851+
852+
test('skips stage-4 transform when babel=false and compileEnhancements=true', t => {
853+
execCli(['import.js'], {dirname: 'fixture/just-enhancement-compilation'}, (err, stdout, stderr) => {
854+
t.ok(err);
855+
t.match(stderr, /SyntaxError: Unexpected (reserved word|token import)/);
856+
t.end();
857+
});
858+
});
859+
860+
test('power-assert when babel=false and compileEnhancements=true', t => {
861+
execCli(['power-assert.js'], {dirname: 'fixture/just-enhancement-compilation'}, (err, stdout, stderr) => {
862+
t.ok(err);
863+
t.match(stripAnsi(stderr), /bool\n.*=> false/);
864+
t.end();
865+
});
866+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import dependency from './dependency'; // eslint-disable-line no-unused-vars

test/fixture/just-enhancement-compilation/dependency.js

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import dependency from './dependency'; // eslint-disable-line no-unused-vars
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"ava": {
3+
"babel": false,
4+
"compileEnhancements": true
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
const test = require('../../../');
4+
5+
test(t => {
6+
const bool = false;
7+
t.true(bool);
8+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import dependency from './dependency'; // eslint-disable-line no-unused-vars

test/fixture/no-babel-compilation/dependency.js

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import dependency from './dependency'; // eslint-disable-line no-unused-vars
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
const test = require('../../../');
4+
5+
test(t => {
6+
const bool = false;
7+
t.true(bool);
8+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"ava": {
3+
"babel": false,
4+
"compileEnhancements": false
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
3+
const test = require('../../../');
4+
5+
test(t => {
6+
t.throws(() => require('./_helper'), SyntaxError);
7+
});

0 commit comments

Comments
 (0)