Client side I stub out paths to modules with SystemJS, like this
var systemJsConfig = {
baseURL: "./",
defaultJSExtensions: true,
map: {
'root-ponents': 'applicationRoot/rootComponents'
}
};
and so require('root-ponents/foo');
would map to applicationRoot/rootComponents/foo
.
The problem is, if I run a module with require('root-ponents/foo');
in Mocha, Node has no clue what that path means. Is there a sane way to acplish this path mapping in Node?
Is Proxyquire capable of this? I read through their docs but found nothing to indicate it was.
This is just for unit testing, so I'm happy with any solution using any sort of their party utility.
Client side I stub out paths to modules with SystemJS, like this
var systemJsConfig = {
baseURL: "./",
defaultJSExtensions: true,
map: {
'root-ponents': 'applicationRoot/rootComponents'
}
};
and so require('root-ponents/foo');
would map to applicationRoot/rootComponents/foo
.
The problem is, if I run a module with require('root-ponents/foo');
in Mocha, Node has no clue what that path means. Is there a sane way to acplish this path mapping in Node?
Is Proxyquire capable of this? I read through their docs but found nothing to indicate it was.
This is just for unit testing, so I'm happy with any solution using any sort of their party utility.
Share Improve this question asked Jun 2, 2016 at 15:17 Adam RackisAdam Rackis 83.4k57 gold badges278 silver badges400 bronze badges 4- 1 Have you seen this discussion? gist.github./branneman/8048520. I believe there are a few solutions/hacks mentioned that would be relevant to what you are trying to do . – user2263572 Commented Jun 10, 2016 at 14:40
- 1 Why would you use a different module load mechanism for tests ? Why not use SystemJs there too ? – s.d Commented Jun 14, 2016 at 11:24
- SystemJS is for loading things in the browser. Mocha runs in Node. – Adam Rackis Commented Jun 14, 2016 at 15:08
- @AdamRackis mocha tests can be run in the browser with karma-mocha – eenagy Commented Jun 15, 2016 at 14:48
3 Answers
Reset to default 6 +250If your only requirement is so simple you can make a utility function that overrides require
.
The new require applies a mapping to the path argument, looks for a module in the new path, and you can optionally fallback for modules that do not exist in the mapped path. The code should look like this
const oldRequire = require;
require = (path) => {
try {
const mapped = oldRequire(path.replace('root-ponents/foo', 'applicationRoot/rootComponents/foo'));
if (!mapped) {
throw new Error('module not found in mapped directory');
}
console.log('module resolved with mapping', path);
return mapped;
} catch (e) {
console.log('using old require without mapped path', path);
return oldRequire(path);
}
};
Option 1 - Modify NODE_PATH
(not remended):
Modify NODE_PATH
to include the module path in the shell prior to launching node.js.
exports NODE_PATH=./path/to/module:$NODE_PATH
This is not a great option because it requires a pre-launch step and -- since the NODE_PATH
contains many paths -- it's not always clear where the module is being loaded from and there's the possibility of name collisions.
Option 2 - Move the module into an external repo
Lets say you move the ponents into a separate 'rootponents' repo available on your GitHub profile.
Then you can install it directly via:
npm install --save github:arackaf/rootponents
Then you should be able to map the project source to a System.js alias.
var systemJsConfig = {
baseURL: "./",
defaultJSExtensions: true,
map: {
'root-ponents': 'github:arackaf/rootponents'
}
};
From there it should work as you expected:
require('root-ponents/foo');
Option 3 - Load the module via relative path:
The config.map
option is only for mapping external dependencies to aliases.
One simple alternative is to provide a relative path. Relatives paths are based on the baseURL.
For instance, If you're attempting to load:
src/rootComponents/foo.js
The require would be:
require('./src/rootComponents/foo')
Note: This all assumes that the require()
statements are following System.js patterns/rules.
One other possible option is to provide a System.paths[]
option that creates an alias to a local path. I can't verify how/whether this'll work (ie I have never tried it) but the specifics can be found here
You could do module aliasing a lot of different ways as described in this gist, but the simpler way is just to set the starting root path with NODE_PATH
, and go from there:
Here's what it looks like with the NODE_PATH
environment variable:
NODE_PATH=./src node src/server/index.js
Then in all your files, no matter where they are in the hierarchy, will resolve from the ./src
directory. This eliminates the need for aliases like you describe, but I realize that in your case, may require moving/renaming many files.
Example: require('root-ponents/foo');
=> ./src/root-ponents/foo.js