Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds modifyBabelConfig #235

Closed
wants to merge 12 commits into from
56 changes: 56 additions & 0 deletions config/__tests__/babel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,36 @@ const stubBabelrc = {
},
},
};
jest.mock('../../cli/logger');
jest.setMock('fs', {
readFileSync: () => JSON.stringify(stubBabelrc),
});
jest.setMock('path', {
resolve: a => a,
});

const modifyBabelConfig = jest.fn(c => c);
const mockKytConfig = jest.fn(() => ({ modifyBabelConfig }));
jest.setMock('../../utils/kytConfig', mockKytConfig);

const logger = require('../../cli/logger');

const babel = require('../babel');

describe('babel', () => {
beforeEach(() => {
modifyBabelConfig.mockClear();
mockKytConfig.mockClear();
global.process.exit = jest.fn();
Object.keys(logger).forEach(k => logger[k].mockClear());
});

it('does not call process.exit or logger.error on a successful run', () => {
babel();
expect(logger.error).not.toBeCalled();
expect(global.process.exit).not.toBeCalled();
});

it('sets flags', () => {
const babelrc = babel();
expect(babelrc.babelrc).toBe(false);
Expand All @@ -35,4 +55,40 @@ describe('babel', () => {
expect(babelrc.env.development.plugins).toEqual([thisResolved]);
expect(babelrc.env.development.presets).toEqual([[thisResolved]]);
});

it('calls kytConfig\'s modifyBabelConfig', () => {
const opts = {};
babel(opts);
const kytConfig = require('../../utils/kytConfig');
const config = kytConfig();
expect(config.modifyBabelConfig).toBeCalled();
expect(config.modifyBabelConfig.mock.calls[0][0]).toEqual(Object.assign({}, stubBabelrc, {
babelrc: false,
cacheDirectory: false,
plugins: [],
presets: [],
}));
expect(config.modifyBabelConfig.mock.calls[0][1]).toBe(opts);
});

it('logs an error and exits the process if modifyBabelConfig throws', () => {
const err = new Error('oh no');
modifyBabelConfig.mockImplementationOnce(() => { throw err; });
babel();
expect(logger.error).toBeCalledWith('Error in your kyt.config.js modifyBabelConfig():', err);
expect(global.process.exit).toBeCalledWith(1);
});

it('does not log out merged config if config.debug is falsy', () => {
babel();
expect(logger.debug).not.toBeCalled();
});

it('logs out the merged config if config.debug is truthy', () => {
mockKytConfig.mockImplementationOnce(() => ({ debug: true, modifyBabelConfig }));
babel();
expect(logger.debug).toBeCalled();
expect(typeof logger.debug.mock.calls[0][0]).toBe('string');
expect(typeof logger.debug.mock.calls[0][1]).toBe('object');
});
});
17 changes: 16 additions & 1 deletion config/babel.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const path = require('path');
const fs = require('fs');
const getKytConfig = require('../utils/kytConfig');
const logger = require('../cli/logger');

// Uses require.resolve to add the full paths to all of the plugins
// and presets, making sure that we handle the new array syntax.
Expand All @@ -16,6 +18,8 @@ const resolvePluginsPresets = (babelGroup) => {
};

module.exports = (options) => {
const config = getKytConfig();

// Create the babelrc query for the babel loader.
const babelrc = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../.babelrc'), 'utf8'));
babelrc.babelrc = false;
Expand All @@ -26,5 +30,16 @@ module.exports = (options) => {
}
Object.keys(babelrc.env || {}).forEach(env => resolvePluginsPresets(babelrc.env[env]));

return babelrc;
try {
// modify via userland kytConfig's `modifyBabelConfig`
const modifiedBabelrc = config.modifyBabelConfig(babelrc, options);
if (config.debug) {
logger.debug('Modified babel configuration:', modifiedBabelrc);
}
return modifiedBabelrc;
} catch (error) {
logger.error('Error in your kyt.config.js modifyBabelConfig():', error);
// return to satisfy eslint `consistent-return` rule
return process.exit(1);
}
};
1 change: 1 addition & 0 deletions utils/__tests__/kytConfig.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe('kytConfig', () => {
expect(logger.info).toBeCalled();
expect(typeof config.modifyWebpackConfig).toBe('function');
expect(typeof config.modifyJestConfig).toBe('function');
expect(typeof config.modifyBabelConfig).toBe('function');
expect(() => {
config.productionPublicPath = 'frozen!';
}).toThrow();
Expand Down
23 changes: 23 additions & 0 deletions utils/jest/__tests__/preprocessor.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const fakeTransformer = {};

jest.setMock('babel-jest', {
createTransformer: jest.fn(() => fakeTransformer),
});
const babelJest = require('babel-jest');

const fakeBabelResult = {};

jest.setMock('../../../config/babel', jest.fn(() => fakeBabelResult));
const babel = require('../../../config/babel');

describe('preprocessor', () => {
it('calls the babel utility and babel-jest\'s createTransformer', () => {
const preprocessor = require('../preprocessor'); // eslint-disable-line global-require
expect(preprocessor).toBe(fakeTransformer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this just testing Jest's ability to mock?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ha yeah I suppose, I'll drop this assertion

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

although, wait, I added it to verify that preprocessor exports the result of createTransformer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok gotcha!

expect(babel.mock.calls[0][0]).toEqual({
type: 'test',
environment: 'test',
});
expect(babelJest.createTransformer).toBeCalledWith(fakeBabelResult);
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this test!! 🙏

17 changes: 5 additions & 12 deletions utils/jest/preprocessor.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
const mergeAll = require('ramda').mergeAll;
const babel = require('../../config/babel')();
const babelJest = require('babel-jest');
const buildConfigs = require('../buildConfigs');
const config = require('../kytConfig')();

const { clientConfig } = buildConfigs(config);
const options = {
type: 'test',
environment: 'test',
};

// Merge userland babel config with our babel config
// This should go away after https://github.com/NYTimes/kyt/issues/134
const clientBabelConfig = clientConfig.module.loaders
.find(loader => loader.loader === 'babel-loader')
.query;

const babelConfigForJest = mergeAll([{}, babel, clientBabelConfig]);
const babelConfigForJest = require('../../config/babel')(options);

module.exports = babelJest.createTransformer(babelConfigForJest);
2 changes: 1 addition & 1 deletion utils/kytConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module.exports = (optionalConfig) => {
config = mergeAll([{}, baseConfig, config]);

// Create default identity functions for modify functions
['modifyWebpackConfig', 'modifyJestConfig'].forEach((m) => {
['modifyWebpackConfig', 'modifyJestConfig', 'modifyBabelConfig'].forEach((m) => {
if (typeof config[m] !== 'function') {
config[m] = c => c;
}
Expand Down