I'm trying to use Babel's "module-alias" plug-in with the "proxyquire" testing library, but I'm not having a lot of luck.
Library Backstory
(feel free to skip if you are familiar with both module-alias/proxyquire)
Proxyquire let's you mock out a module's dependencies for testing, like so:
const someFunctionToTest =
proxyquire(pathToSomeFunctionToTestsModule, {
pathToDependency: fakeVersionOfDependency
});
Babel's module-alias plugin let's you make your import paths more convenient and consistent. For instance, I can specify (in .babelrc):
"plugins": [
["module-alias", [
{ "src": "./", "expose": "~" }
]],
and then instead of having to type (when importing from a module nested three directories deep) require('../../../someModule') I can just type
require('~/someModule')`.
The Problem
My problem is, they don't work together. If I havesomeModule
that depends on someDependency
:
// src/someModule.js
const someDependency = require('~/src/someDependency');
doSomethingWith(someDependency);
and then I want to test someModule
with a mock version of someDependency
, I should be able to do:
const proxiedSomeModule =
proxyquire('~/src/someModule', {
'~/src/someDependency': fakeVersionOfSomeDependency
});
... but proxyquire
tells me `Error: Cannot find module '~/src/someModule'.
Presumably ("behind the scenes") Babel is converting '~/src/someModule' into its real path, so when Proxyquire looks for the aliased path it can't find it.
The Question
My question is: is there any way I can find out what the real path of '~/src/someModule' is, after Babel converts it (ie. when proxyquire deals with it)? Or alternatively is there any way to get proxyquire to just work with the aliased paths?
It turns out the "real" path (for '~/someModule'
) generated by module resolver is just the ../../someModule
path. However, it also turns out that there is no need to convert paths by hand.
The module resolver plug-in will convert the arguments to any functions on its transformFunctions
list. This means that you can convert any string to its non-aliased form by doing the following:
const resolveModulePath = path => path;
Add that function (along with proxyquire
) to the transformFunctions
list in .babelrc
:
["module-resolver", {
"transformFunctions": ["proxyquire", "resolveModulePath"]
}]
Wrap any paths which aren't arguments to a function with resolveModulePath
:
proxyquire('~/some/path/someModule', {
[resolveModulePath('~/some/other/path')]: {
someFunction: fakeSomeFunction
}
})
Note that the first path in the above doesn't need to be escaped, as its an argument to a transformed function. Only the second path ('~/some/other/path'
) needs to be wrapped, because it's part of an object which is an argument; the string itself isn't an argument, until it's wrapped.
For further info see: https://github.com/tleunen/babel-plugin-module-resolver/issues/241#issuecomment-350109168