Chris
Chris

Reputation: 3698

How to use absolute import paths when writing tests for a specific module

I am working on a NodeJS (v. 8.12.0, EcmaScript 6) project, whose project structure is similar to:

project_root/
    src/
        utils/
            protocol_messages/
                helpers.js
    tests/
        unit/
            utils/
                protocol_messages/
                    helpers.js

I am writing tests using Mocha as a test framework.

Question
In the helpers.js under tests/unit/utils/protocol_messages/, what's the proper way of importing the module-under-test?

To elaborate:
I want to avoid the relative path in: require('../../../../../src/utils/protocol_messages/helpers').
It works, but it's ugly, and if the project structure changes, I would have to rewrite the test imports, as well.

(I am new to Javascript so I might be doing several things wrong.)

Update
Solutions provided in this question:

  1. require.main.require: in a comment to this answer, "This solution will not work if code covered with unit tests like Mocha test".
  2. Extracting my utils to a node module doesn't make sense for me, since the code is very application specific.
  3. Having an extra node_modules under my src/ project root of a NodeJS project doesn't seem to make sense.
  4. Using a Javascript transpiler when I am using only features available in NodeJS and writing CommonJS projects seems a bit of an overkill.

If I am mistaken on any of the above points, please point it out, as I am at a loss. It seems to me like NodeJS doesn't not provide a native way to import CommonJS modules with absolute paths.

Upvotes: 5

Views: 1986

Answers (2)

user8273956
user8273956

Reputation:

Assume you need a config.js file present at your project's root in a file which is present at /routes/api/users/profile.js, you do not want to import it as ../../../config.js

  1. Create a directory structure in your project's root directory as described below:
    • /Modules
      • index.js
      • package.json
  2. Modules/index.js
    module.exports.config = require('../config.js')
    
  3. Modules/package.js
    {
        "name": "modules",
        "main": "index.js",
        "version": "1.0.0",
        "dependencies": {}
    }
    
  4. Now run
    npm install ./Modules
    
  5. /routes/api/users/profile.js
    const { config } = require('modules')
    

This way autocomplete feature of your code editor will also work. No more global variables pollution, long relative imports, no dependency on environment variables and the best part is, it will work with pm2 and nodemon.

Upvotes: 1

Rafal Enden
Rafal Enden

Reputation: 3184

You can use wavy npm package.

This module lets you turn things like require('../../../../foo') into something like require('~/foo'). The way it works is that on postinstall it creates a symlink in app/node_modules/~ to point to app/

Upvotes: 1

Related Questions