Skip to content

Commit 097e01e

Browse files
committed
Upgrade hullabaloo-config-manager
* Adds support for .babelrc.js files * By default use 'test' environment rather than 'development'
1 parent 52fef57 commit 097e01e

File tree

7 files changed

+126
-55
lines changed

7 files changed

+126
-55
lines changed

lib/babel-config.js

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function validate(conf) {
3131
const SOURCE = '(AVA) Base Babel config';
3232
const AVA_DIR = path.join(__dirname, '..');
3333

34-
function verifyExistingOptions(verifierFile, baseConfig, cache) {
34+
function verifyExistingOptions(verifierFile, baseConfig, cache, envName) {
3535
return new Promise((resolve, reject) => {
3636
try {
3737
resolve(fs.readFileSync(verifierFile));
@@ -54,7 +54,7 @@ function verifyExistingOptions(verifierFile, baseConfig, cache) {
5454
if (baseConfig.extends) {
5555
fixedSourceHashes.set(baseConfig.extends.source, baseConfig.extends.hash);
5656
}
57-
return verifier.verifyCurrentEnv({sources: fixedSourceHashes}, cache)
57+
return verifier.verifyEnv(envName, {sources: fixedSourceHashes}, cache)
5858
.then(result => {
5959
if (!result.cacheKeys) {
6060
return null;
@@ -69,26 +69,33 @@ function verifyExistingOptions(verifierFile, baseConfig, cache) {
6969
});
7070
}
7171

72-
function resolveOptions(baseConfig, cache, optionsFile, verifierFile) {
73-
return configManager.fromConfig(baseConfig, {cache})
72+
function resolveOptions(baseConfig, cache, envName, optionsFile, verifierFile) { // eslint-disable-line max-params
73+
return configManager.fromConfig(baseConfig, {cache, expectedEnvNames: [envName]})
7474
.then(result => {
7575
fs.writeFileSync(optionsFile, result.generateModule());
7676

7777
return result.createVerifier()
7878
.then(verifier => {
7979
fs.writeFileSync(verifierFile, verifier.toBuffer());
80-
return verifier.cacheKeysForCurrentEnv();
80+
return verifier.cacheKeysForEnv(envName);
8181
});
8282
});
8383
}
8484

8585
function build(projectDir, cacheDir, userOptions, powerAssert) {
86+
// Note that Babel ignores empty string values, even for NODE_ENV. Here
87+
// default to 'test' unless NODE_ENV is defined, in which case fall back to
88+
// Babel's default of 'development' if it's empty.
89+
const envName = process.env.BABEL_ENV || ('NODE_ENV' in process.env ? process.env.NODE_ENV : 'test') || 'development';
90+
8691
// Compute a seed based on the Node.js version and the project directory.
8792
// Dependency hashes may vary based on the Node.js version, e.g. with the
8893
// @ava/stage-4 Babel preset. Sources and dependencies paths are absolute in
8994
// the generated module and verifier state. Those paths wouldn't necessarily
9095
// be valid if the project directory changes.
91-
const seed = md5Hex([process.versions.node, projectDir]);
96+
// Also include `envName`, so options can be cached even if users change
97+
// BABEL_ENV or NODE_ENV between runs.
98+
const seed = md5Hex([process.versions.node, projectDir, envName]);
9299

93100
// Ensure cacheDir exists
94101
makeDir.sync(cacheDir);
@@ -117,8 +124,8 @@ function build(projectDir, cacheDir, userOptions, powerAssert) {
117124

118125
const baseConfig = configManager.createConfig({
119126
dir: AVA_DIR, // Presets are resolved relative to this directory
127+
fileType: 'JSON',
120128
hash: md5Hex(JSON.stringify(baseOptions)),
121-
json5: false,
122129
options: baseOptions,
123130
source: SOURCE
124131
});
@@ -135,19 +142,24 @@ function build(projectDir, cacheDir, userOptions, powerAssert) {
135142
}
136143

137144
const cache = configManager.prepareCache();
138-
return verifyExistingOptions(verifierFile, baseConfig, cache)
145+
return verifyExistingOptions(verifierFile, baseConfig, cache, envName)
139146
.then(cacheKeys => {
140147
if (cacheKeys) {
141148
return cacheKeys;
142149
}
143150

144-
return resolveOptions(baseConfig, cache, optionsFile, verifierFile);
151+
return resolveOptions(baseConfig, cache, envName, optionsFile, verifierFile);
145152
})
146-
.then(cacheKeys => ({
147-
getOptions: require(optionsFile).getOptions,
148-
// Include the seed in the cache keys used to store compilation results.
149-
cacheKeys: Object.assign({seed}, cacheKeys)
150-
}));
153+
.then(cacheKeys => {
154+
const getOptions = require(optionsFile).getOptions;
155+
return {
156+
getOptions() {
157+
return getOptions(envName, cache);
158+
},
159+
// Include the seed in the cache keys used to store compilation results.
160+
cacheKeys: Object.assign({seed}, cacheKeys)
161+
};
162+
});
151163
}
152164

153165
module.exports = {

test/babel-config.js

Lines changed: 69 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use strict';
2+
const assert = require('assert');
23
const fs = require('fs');
34
const path = require('path');
45
const test = require('tap').test;
@@ -22,6 +23,19 @@ function withNodeVersion(version, run) {
2223
return promise;
2324
}
2425

26+
function withNodeEnv(value, run) {
27+
assert(!('NODE_ENV' in process.env));
28+
process.env.NODE_ENV = value;
29+
const reset = () => {
30+
delete process.env.NODE_ENV;
31+
};
32+
const promise = new Promise(resolve => {
33+
resolve(run());
34+
});
35+
promise.then(reset, reset);
36+
return promise;
37+
}
38+
2539
test('uses default presets when userOptions is "default"', t => {
2640
const userOptions = 'default';
2741
const powerAssert = true;
@@ -33,13 +47,9 @@ test('uses default presets when userOptions is "default"', t => {
3347
const options = result.getOptions();
3448

3549
t.false(options.babelrc);
36-
t.same(options.presets, [
37-
require.resolve('@ava/babel-preset-stage-4'),
38-
[
39-
require.resolve('@ava/babel-preset-transform-test-files'),
40-
{powerAssert}
41-
]
42-
]);
50+
t.is(options.presets[0][0].wrapped, require('@ava/babel-preset-stage-4'));
51+
t.is(options.presets[1][0].wrapped, require('@ava/babel-preset-transform-test-files'));
52+
t.same(options.presets[1][1], {powerAssert});
4353
});
4454
});
4555

@@ -54,39 +64,68 @@ test('uses options from babelrc when userOptions is "inherit"', t => {
5464
const options = result.getOptions();
5565

5666
t.false(options.babelrc);
57-
t.same(options.plugins, [require.resolve(fixture('babel-plugin-test-doubler'))]);
58-
t.same(options.presets, [
59-
require.resolve('@ava/babel-preset-stage-4'),
60-
[
61-
require.resolve('@ava/babel-preset-transform-test-files'),
62-
{powerAssert}
63-
]
64-
]);
67+
t.is(options.plugins[0][0].wrapped, require(fixture('babel-plugin-test-doubler')));
68+
t.is(options.presets[0][0].wrapped, require('@ava/babel-preset-stage-4'));
69+
t.is(options.presets[1][0].wrapped, require('@ava/babel-preset-transform-test-files'));
70+
t.same(options.presets[1][1], {powerAssert});
6571
});
6672
});
6773

6874
test('uses userOptions for babel options when userOptions is an object', t => {
69-
const custom = require.resolve(fixture('empty'));
75+
const customFile = require.resolve(fixture('babel-noop-plugin-or-preset'));
76+
const custom = require(fixture('babel-noop-plugin-or-preset'));
7077
const userOptions = {
71-
presets: [custom],
72-
plugins: [custom]
78+
plugins: [customFile],
79+
presets: [customFile]
7380
};
7481
const powerAssert = true;
7582

7683
const projectDir = uniqueTempDir();
7784
const cacheDir = path.join(projectDir, 'cache');
85+
return babelConfigHelper.build(projectDir, cacheDir, userOptions, powerAssert)
86+
.then(result => {
87+
const options = result.getOptions();
88+
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});
93+
});
94+
});
95+
96+
test('uses "development" environment if NODE_ENV is the empty string', t => {
97+
const userOptions = 'inherit';
98+
const powerAssert = true;
99+
100+
const projectDir = fixture('babelrc');
101+
const cacheDir = path.join(uniqueTempDir(), 'cache');
102+
return withNodeEnv('', () => babelConfigHelper.build(projectDir, cacheDir, userOptions, powerAssert))
103+
.then(result => {
104+
const options = result.getOptions();
105+
106+
t.false(options.babelrc);
107+
t.is(options.plugins[0][0].wrapped, require(fixture('babel-plugin-test-capitalizer')));
108+
t.is(options.presets[0][0].wrapped, require('@ava/babel-preset-stage-4'));
109+
t.is(options.presets[1][0].wrapped, require('@ava/babel-preset-transform-test-files'));
110+
t.same(options.presets[1][1], {powerAssert});
111+
});
112+
});
113+
114+
test('supports .babelrc.js files', t => {
115+
const userOptions = 'inherit';
116+
const powerAssert = true;
117+
118+
const projectDir = fixture('babelrc-js');
119+
const cacheDir = path.join(uniqueTempDir(), 'cache');
78120
return babelConfigHelper.build(projectDir, cacheDir, userOptions, powerAssert)
79121
.then(result => {
80122
const options = result.getOptions();
81123

82124
t.false(options.babelrc);
83-
t.same(options.presets, userOptions.presets.concat([
84-
[
85-
require.resolve('@ava/babel-preset-transform-test-files'),
86-
{powerAssert}
87-
]
88-
]));
89-
t.same(options.plugins, userOptions.plugins);
125+
t.is(options.plugins[0][0].wrapped, require(fixture('babel-plugin-test-doubler')));
126+
t.is(options.presets[0][0].wrapped, require('@ava/babel-preset-stage-4'));
127+
t.is(options.presets[1][0].wrapped, require('@ava/babel-preset-transform-test-files'));
128+
t.same(options.presets[1][1], {powerAssert});
90129
});
91130
});
92131

@@ -97,9 +136,7 @@ test('adds babel-plugin-syntax-object-rest-spread for node versions > 8.3.0', t
97136
return withNodeVersion('9.0.0', () => babelConfigHelper.build(projectDir, cacheDir, 'default', true))
98137
.then(result => {
99138
const options = result.getOptions();
100-
t.same(options.plugins, [
101-
require.resolve('@babel/plugin-syntax-object-rest-spread')
102-
]);
139+
t.is(options.plugins[0][0].wrapped, require('@babel/plugin-syntax-object-rest-spread').default);
103140
});
104141
});
105142

@@ -110,9 +147,7 @@ test('adds babel-plugin-syntax-object-rest-spread for node versions == 8.3.0', t
110147
return withNodeVersion('8.3.0', () => babelConfigHelper.build(projectDir, cacheDir, 'default', true))
111148
.then(result => {
112149
const options = result.getOptions();
113-
t.same(options.plugins, [
114-
require.resolve('@babel/plugin-syntax-object-rest-spread')
115-
]);
150+
t.is(options.plugins[0][0].wrapped, require('@babel/plugin-syntax-object-rest-spread').default);
116151
});
117152
});
118153

@@ -123,7 +158,7 @@ test('does not add babel-plugin-syntax-object-rest-spread for node versions < 8.
123158
return withNodeVersion('8.2.0', () => babelConfigHelper.build(projectDir, cacheDir, 'default', true))
124159
.then(result => {
125160
const options = result.getOptions();
126-
t.same(options.plugins, []);
161+
t.true(!options.plugins);
127162
});
128163
});
129164

@@ -138,13 +173,7 @@ test('should disable power-assert when powerAssert is false', t => {
138173
const options = result.getOptions();
139174

140175
t.false(options.babelrc);
141-
t.same(options.presets, [
142-
require.resolve('@ava/babel-preset-stage-4'),
143-
[
144-
require.resolve('@ava/babel-preset-transform-test-files'),
145-
{powerAssert}
146-
]
147-
]);
176+
t.same(options.presets[1][1], {powerAssert});
148177
});
149178
});
150179

@@ -204,7 +233,7 @@ test('updates cached verifier if dependency hashes change', t => {
204233
const depFile = path.join(projectDir, 'plugin.js');
205234

206235
makeDir.sync(cacheDir);
207-
fs.writeFileSync(depFile, 'foo');
236+
fs.writeFileSync(depFile, 'module.exports = () => ({})');
208237

209238
const userOptions = {
210239
plugins: ['./plugin.js']
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = () => ({});

test/fixture/babelrc-js/.babelrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = api => {
2+
api.cache.forever();
3+
return {
4+
'plugins': ['../babel-plugin-test-doubler'],
5+
'presets': ['@ava/stage-4']
6+
};
7+
};

test/fixture/babelrc-js/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "application-name",
3+
"version": "0.0.1"
4+
}

test/fixture/babelrc-js/test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import test from '../../../';
2+
3+
const fixture = [1, 2];
4+
5+
test('foo', t => {
6+
// Using destructuring to ensure it transpiles on Node.js 4
7+
// since that is a Node.js 6 feature
8+
const [one, two] = fixture;
9+
t.is(one, 1);
10+
t.is(two, 2);
11+
});

test/fixture/babelrc/.babelrc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
{
22
"presets": ["@ava/stage-4"],
3-
"plugins": ["../babel-plugin-test-doubler"]
3+
"env": {
4+
"development": {
5+
"plugins": ["../babel-plugin-test-capitalizer"]
6+
},
7+
"test": {
8+
"plugins": ["../babel-plugin-test-doubler"],
9+
}
10+
}
411
}

0 commit comments

Comments
 (0)