Home > front end >  node.js: resolve path relative from a test file
node.js: resolve path relative from a test file

Time:02-12

I working on a function implementation that is going to be distributed as a npm package.

Once this package has been installed by a consumer as a devDependency, they should be able to load a configuration file by calling a function (let's call it setConfig) from their test files.

I am trying to understand how to resolve a relative path (relative to the test file) when the consumer invokes my function (setConfig('./../some/relative/path/to/config')).

For instance, in the following project structure:

|- node_modules
   |- my-published-package
      |- dist/file.js (<- this hold setConfig)
|- src
   |- configToLoad.json
   |- __tests__
      |- someTest.spec.js

The config could be specified as ../configToLoad.json and the setConfig should be able to resolve the path relatively to the test file path. In other words, the test author would write `importedClassFromPackage.setConfig('../configToLoad.json').

The setConfig function has the following signature:

setConfig(configPath: string): void {}

Where configPath can either be:

  • a relative path (from the test file that invokes that function)
  • an absolute path (absolute path of the configuration file)
  • a module specifier (i.e my-module/path/to/config.json)

CodePudding user response:

First off, when your setConfig() function runs, you have no idea at all where it was called from. You do not and cannot know the directory of the file that you were called from.

As such, it is the responsibility of the caller to give you a path that you you can just use directly. It needs to either be a fully qualified path or be a relative path that is relative to the current working directory. It cannot be a path that is relative to the directory that the caller's module was in (unless that happens to be the same as the current working directory) because you will have no idea what the caller's module directory is.

So, in your desired spec where you want configPath to be any of these:

  • a relative path (from the test file that invokes that function)
  • an absolute path (absolute path of the configuration file)
  • a module specifier (i.e my-module/path/to/config.json)

Only the absolute path option will work or can be made to work.

The relative path won't work because your function does not know the directory of the test file you were called from.

The module specifier won't work because you don't know how to get the directory of that module name and it's ambiguous because it is possible to have the same named module loaded from more than one place (this happens in the real world when dependencies use a common module, but are using different versions of it).

Note, the caller can use path.join() to join their own module directory with the name of the file and pass you that fully qualified path. In a CommonJS module, the caller gets their own directory from __dirname. In an ESM module, the caller has to extract the directory from import.meta.url.

  • Related