Skip to content

Instantly share code, notes, and snippets.

@okonet
Created March 9, 2017 09:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save okonet/9b718e743a8e89560cd2003633765c73 to your computer and use it in GitHub Desktop.
Save okonet/9b718e743a8e89560cd2003633765c73 to your computer and use it in GitHub Desktop.
Test webpack-shimmed and aliased modules with Jest
/* eslint-env node */
const path = require('path');
const webpack = require('webpack');
const MemoryFileSystem = require('memory-fs');
const EnhancedResolve = require('enhanced-resolve');
const transform = require('transform-jest-deps');
const babel = require('babel-jest');
const createConfig = require('../build/utils/createWebpackConfig');
const SyncNodeJsInputFileSystem = EnhancedResolve.SyncNodeJsInputFileSystem;
// Create test webpack config
const config = createConfig('test', {
isTestRunner: true,
platform: 'test'
});
// Store FS among preprocess calls
const memoryFs = new MemoryFileSystem();
const syncFs = new SyncNodeJsInputFileSystem();
// Filter all loaders
const shimLoaders = config.module.rules.filter(
(rule) => rule.loader && rule.loader.indexOf('exports-loader') !== -1
);
const specialLoaders = config.module.rules.filter(
(rule) => rule.loader && rule.loader.indexOf('raw-loader') !== -1
);
const babelLoaders = config.module.rules.filter(
(rule) => rule.loader && rule.loader.indexOf('babel') >= 0
);
const aliasResolver = EnhancedResolve.create.sync(config.resolve);
function aliasPreprocessor(src, filename) {
return transform(src, {
sourceType: 'module'
}, (name) => {
try {
const resolved = aliasResolver({}, process.cwd(), name);
return path.normalize(resolved, process.cwd());
} catch (e) {
return name;
}
});
}
function webpackPreprocessor(filename) {
const options = Object.assign(config, {
entry: path.normalize(filename, process.cwd()),
output: {
path: '/',
filename: filename,
libraryTarget: 'commonjs2'
},
devtool: 'eval' // Fastest devtool
});
const compiler = webpack(options);
compiler.outputFileSystem = memoryFs;
compiler.inputFileSystem = syncFs;
let stats = null;
compiler.run((err, compilationStats) => {
stats = compilationStats;
});
while (stats === null) {
require('deasync').sleep(10);
}
return stats.compilation.assets[filename].source();
}
module.exports = {
process: (src, filename) => {
// This transforms with Babel all JS files that doesn't match `exclude`
if (!babelLoaders.find((l) => new RegExp(l.exclude).test(filename))) {
src = babel.process(src, filename);
}
// This transforms with Babel all JS files which are not in `node_modules`
// Files in ``/app/js/libs/`` still need to be sent to aliasPreprocessor
// because they might require modules aliased in webpack
// e.g. `backbone` requires `jquery`
if (!babelLoaders.find((l) => new RegExp(/node_modules[\/\\]/).test(filename))) {
// Use aliases from webpack config
src = aliasPreprocessor(src, filename);
}
const hasShims = shimLoaders.some(
(loader) => new RegExp(loader.test).test(filename)
);
const hasSpecialRequires = specialLoaders.some(
(loader) => src.match(loader.test)
);
if (hasShims || hasSpecialRequires) {
// Use shims from webpack config
src = webpackPreprocessor(filename);
}
return src;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment