-
-
Save CyberLight/d9114aaf88b2a16a13b6ba8fc1aae6c1 to your computer and use it in GitHub Desktop.
Test webpack-shimmed and aliased modules with Jest
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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