How do you force the absolute path for node modules?
Asked Answered
A

1

4

I have a Titanium project which uses the CommonJS module style. However the code uses absolute paths so that when it builds the absolute path is sandboxed to the application directory.

var foo = require("/lib/module");

I want to run some tests on the command line and have jasmine-node working. However when a test executes a module the module will have the above absolute paths in their require statements.

Is there a way to isolate (maybe chroot) node to resolve absolute require paths to a specific directory? If so how?

-- RepositoryRoot/
   |- app/
   |  \- Resources/
   |     |- app.js  # Has require("/lib/module1.js")
   |     \- lib/
   |        |- module1.js # Has require("/lib/module2.js")
   |        \- module2.js
   \- tests/
      \- module1.spec.js # Has require("../app/Resources/lib/module1")
                         # Or require("/lib/module1")
Alliaceous answered 3/2, 2013 at 4:3 Comment(4)
You can write your own require function, or just not do it like that.Shove
So far I attempted to use proxyquire Which worked except when the modules being tested developed circular dependencies. I really wanted to avoid changing the code in hopes that I could unobtrusively run tests on it. Unfortunately the only solution I could find so far was to run through every source file and remove the leading slash then set NODE_PATH to the Resources directory. This blog post offers some insight.Alliaceous
Is this third party code you're inheriting? Why is it coded this way?Shove
@JacobGroundwater: Yes it is inherited. It was written originally when Titanium had no intention of unit testing. Things have gotten better but the code is still legacy. Trying to do the best with what I got without scrapping a lot of it.Alliaceous
A
4

After finding a solution here is what I learned: The short answer to the exact above question is you can't do that. Node reads absolute paths as absolute paths. So the answer in short was to change my paths from absolute to pseudo-absolute (relative) paths. Here is a quote from this blog post that sheds some light:

the Titanium implementation of CommonJS require() is buggy and doesn’t correctly support relative paths. This represents a major problem when trying to integrate jasmine-node test runners in projects with even minimally complex directory trees.

A possible solution to the issue is to not use relative paths in require() in Titanium (but you are free to use them in your jasmine specs run through node). Instead of relative paths we need to use full paths with Resources as the root directory.

This is accomplished by setting the NODE_PATH environment variable prior to running any node commands. That way a path such as `require("module/path") is resolved by node and titanium.

There are a few caveats. Some module force the need for absolute paths. In this case one needs proxyquire to mock out the absolute paths as long as there are not any circular dependancies this will work. Also since node does not have Titanium API's you also have to include the mockti package to mock out the Titanium API. Use this in your spec_helper.js:

global.Ti = require("mockti");

and

proxyquire = require("proxyquire");
var myModule = proxyquire("relative/path/to/MyModule", {
    "/absolute/path/to/some/module": require("absolute/path/to/some/module")
});
Alliaceous answered 5/2, 2013 at 10:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.