Skip to content

Commit ccc12c6

Browse files
committed
Change Babel options used for test compilation
Always extend the project's Babel configuration, if any. Always apply the `@ava/stage-4` preset. Fixes #1488. Users can disable this preset by adding it to the AVA's Babel configuration with the `false` option: ``` "ava": { "babel": { "presets": [ ["ava/stage-4", false] ] } } And yes, `ava/stage-4` so now an alias for the preset, which means it can be used even if the preset is not installed as a top-level dependency. Fixes #1225. `@ava/transform-test-files` is applied as part of the test compilation, but cannot be overridden by users like `@ava/stage-4` can.
1 parent d523939 commit ccc12c6

File tree

4 files changed

+108
-31
lines changed

4 files changed

+108
-31
lines changed

lib/babel-config.js

+51-23
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ const makeDir = require('make-dir');
99
const semver = require('semver');
1010
const colors = require('./colors');
1111

12+
const stage4Path = require.resolve('../stage-4');
13+
const syntaxObjectRestSpreadPath = require.resolve('@babel/plugin-syntax-object-rest-spread');
14+
const transformTestFilesPath = require.resolve('@ava/babel-preset-transform-test-files');
15+
1216
function validate(conf) {
1317
if (conf === undefined || conf === null) {
1418
conf = 'default';
@@ -28,9 +32,6 @@ function validate(conf) {
2832
return conf;
2933
}
3034

31-
const SOURCE = '(AVA) Base Babel config';
32-
const AVA_DIR = path.join(__dirname, '..');
33-
3435
function verifyExistingOptions(verifierFile, baseConfig, cache, envName) {
3536
return new Promise((resolve, reject) => {
3637
try {
@@ -108,48 +109,75 @@ function build(projectDir, cacheDir, userOptions, compileEnhancements) {
108109
const baseOptions = {
109110
babelrc: false,
110111
plugins: [],
111-
presets: []
112+
presets: [
113+
stage4Path // Always apply the stage-4 preset.
114+
]
112115
};
113-
if (compileEnhancements) {
114-
baseOptions.presets.push(['@ava/transform-test-files', {powerAssert: true}]);
116+
117+
// By default extend the project's Babel configuration, but allow this to be
118+
// disabled in userOptions.
119+
if (userOptions === 'default' || userOptions === 'inherit' || userOptions.babelrc !== false) {
120+
baseOptions.babelrc = true;
115121
}
116-
if (userOptions === 'default') {
117-
baseOptions.presets.unshift('@ava/stage-4');
122+
if (userOptions.extends) {
123+
baseOptions.extends = userOptions.extends;
118124
}
119125

120-
// Include object rest spread support for node versions that support it
126+
// Include object rest spread support for Node.js versions that support it
121127
// natively.
122-
if (userOptions === 'default' && semver.satisfies(process.versions.node, '>= 8.3.0')) {
123-
baseOptions.plugins.push('@babel/plugin-syntax-object-rest-spread');
128+
if (semver.satisfies(process.versions.node, '>= 8.3.0')) {
129+
baseOptions.plugins.push(syntaxObjectRestSpreadPath);
124130
}
125131

126132
const baseConfig = configManager.createConfig({
127-
dir: AVA_DIR, // Presets are resolved relative to this directory
133+
dir: projectDir,
128134
fileType: 'JSON',
129135
hash: md5Hex(JSON.stringify(baseOptions)),
130136
options: baseOptions,
131-
source: SOURCE
137+
source: '(AVA) baseConfig'
132138
});
133139

134-
if (userOptions !== 'default') {
135-
baseConfig.extend(configManager.createConfig({
140+
let intermediateConfig = baseConfig;
141+
if (userOptions !== 'default' && userOptions !== 'inherit') {
142+
// At this level, babelrc *must* be false.
143+
const options = Object.assign({}, userOptions, {babelrc: false});
144+
// Any extends option has been applied in baseConfig.
145+
delete options.extends;
146+
intermediateConfig = configManager.createConfig({
147+
dir: projectDir,
148+
fileType: 'JSON',
149+
hash: md5Hex(JSON.stringify(options)),
150+
options,
151+
source: path.join(projectDir, 'package.json') + '#ava.babel'
152+
});
153+
intermediateConfig.extend(baseConfig);
154+
}
155+
156+
let finalConfig = intermediateConfig;
157+
if (compileEnhancements) {
158+
finalConfig = configManager.createConfig({
136159
dir: projectDir,
137-
options: userOptions === 'inherit' ?
138-
{babelrc: true} :
139-
userOptions,
140-
source: path.join(projectDir, 'package.json') + '#ava.babel',
141-
hash: md5Hex(JSON.stringify(userOptions))
142-
}));
160+
fileType: 'JSON',
161+
hash: '', // This is deterministic, so no actual value necessary.
162+
options: {
163+
babelrc: false,
164+
presets: [
165+
[transformTestFilesPath, {powerAssert: true}]
166+
]
167+
},
168+
source: '(AVA) compileEnhancements'
169+
});
170+
finalConfig.extend(intermediateConfig);
143171
}
144172

145173
const cache = configManager.prepareCache();
146-
return verifyExistingOptions(verifierFile, baseConfig, cache, envName)
174+
return verifyExistingOptions(verifierFile, finalConfig, cache, envName)
147175
.then(cacheKeys => {
148176
if (cacheKeys) {
149177
return cacheKeys;
150178
}
151179

152-
return resolveOptions(baseConfig, cache, envName, optionsFile, verifierFile);
180+
return resolveOptions(finalConfig, cache, envName, optionsFile, verifierFile);
153181
})
154182
.then(cacheKeys => {
155183
const getOptions = require(optionsFile).getOptions;

stage-4.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('@ava/babel-preset-stage-4');

test/api.js

+25-4
Original file line numberDiff line numberDiff line change
@@ -841,22 +841,22 @@ function generateTests(prefix, apiCreator) {
841841
}, t.threw);
842842
});
843843

844-
test(`${prefix} Default babel config doesn't use .babelrc`, t => {
845-
t.plan(2);
844+
test(`${prefix} Default babel config uses .babelrc`, t => {
845+
t.plan(3);
846846

847847
const api = apiCreator({
848848
projectDir: path.join(__dirname, 'fixture/babelrc')
849849
});
850850

851851
api.on('test-run', runStatus => {
852852
runStatus.on('test', data => {
853-
t.is(data.title, 'foo');
853+
t.ok((data.title === 'foo') || (data.title === 'repeated test: foo'));
854854
});
855855
});
856856

857857
return api.run()
858858
.then(result => {
859-
t.is(result.passCount, 1);
859+
t.is(result.passCount, 2);
860860
});
861861
});
862862

@@ -902,6 +902,27 @@ function generateTests(prefix, apiCreator) {
902902
});
903903
});
904904

905+
test(`${prefix} babelConfig:{babelrc:false} does not use .babelrc`, t => {
906+
t.plan(2);
907+
908+
const api = apiCreator({
909+
babelConfig: {babelrc: false},
910+
cacheEnabled: false,
911+
projectDir: path.join(__dirname, 'fixture/babelrc')
912+
});
913+
914+
api.on('test-run', runStatus => {
915+
runStatus.on('test', data => {
916+
t.is(data.title, 'foo');
917+
});
918+
});
919+
920+
return api.run()
921+
.then(result => {
922+
t.is(result.passCount, 1);
923+
});
924+
});
925+
905926
test(`${prefix} babelConfig:{babelrc:true, plugins:[...]} merges plugins with .babelrc`, t => {
906927
t.plan(3);
907928

test/babel-config.js

+31-4
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,37 @@ test('uses userOptions for babel options when userOptions is an object', t => {
8686
.then(result => {
8787
const options = result.getOptions();
8888
t.false(options.babelrc);
89-
t.is(options.plugins[0][0].wrapped, custom);
90-
t.is(options.presets[0][0].wrapped, custom);
91-
t.is(options.presets[1][0].wrapped, require('@ava/babel-preset-transform-test-files'));
92-
t.same(options.presets[1][1], {powerAssert: true});
89+
if (options.plugins.length === 1) {
90+
t.is(options.plugins[0][0].wrapped, custom);
91+
} else {
92+
t.is(options.plugins[1][0].wrapped, custom);
93+
}
94+
t.is(options.presets[0][0].wrapped, require('@ava/babel-preset-stage-4'));
95+
t.is(options.presets[1][0].wrapped, custom);
96+
t.is(options.presets[2][0].wrapped, require('@ava/babel-preset-transform-test-files'));
97+
t.same(options.presets[2][1], {powerAssert: true});
98+
});
99+
});
100+
101+
test('userOptions can disable ava/stage-4', t => {
102+
const userOptions = {
103+
presets: [['module:ava/stage-4', false]]
104+
};
105+
const transpileEnhancements = true;
106+
107+
const projectDir = uniqueTempDir();
108+
const cacheDir = path.join(projectDir, 'cache');
109+
fs.mkdirSync(projectDir);
110+
fs.mkdirSync(path.join(projectDir, 'node_modules'));
111+
fs.mkdirSync(path.join(projectDir, 'node_modules', 'ava'));
112+
fs.writeFileSync(path.join(projectDir, 'node_modules', 'ava', 'stage-4.js'), `module.exports = require(${JSON.stringify(require.resolve('@ava/babel-preset-stage-4'))})`);
113+
114+
return babelConfigHelper.build(projectDir, cacheDir, userOptions, transpileEnhancements)
115+
.then(result => {
116+
const options = result.getOptions();
117+
t.false(options.babelrc);
118+
t.is(options.presets[0][0].wrapped, require('@ava/babel-preset-stage-4'));
119+
t.is(options.presets[0][1], false);
93120
});
94121
});
95122

0 commit comments

Comments
 (0)