Jest: Resolving peer modules when using local linked packages

Created on 27 Dec 2016  ·  11Comments  ·  Source: facebook/jest

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
Having the following structure:
````

  • MyModule
    | - MyDependency
    | - MyLibrary
    | - MyDependency
    ``` WhenMyLibraryrequiresMyDependency, it loads it fromMyModule/node_modules/MyLibrary/node_modulesfolder if it's available, when it should get the peer version. The problem that this issue arises is an inconsistent behaviour when using local linked packages, because when installing throughyarn installMyLibrary won't contain a node_modules folder, but when doing throughyarn link MyLibrary` it will, as it's a soft link.

In my case, MyDependency is rx, and MyLibrary creates a Reactive extension by defining some methods on Rx.Observable.prototype. When running jest without any local link, or when through nodejs, this works properly, but when running through jest with MyLibrary locally linked, Rx.Observable.prototype gets wiped when rx is loaded a second time.

If the current behavior is a bug, please provide the steps to reproduce and a minimal repository on GitHub that we can yarn install and yarn test.
https://github.com/voliva/jestpeer
You must locally link the modules by:
````

cd MyDep; yarn link; cd ..
cd MyLib; yarn link MyDep; yarn link; cd ..
cd MyModule; yarn; yarn link MyDep; yarn link MyLib;
````

If you run yarn start, that's just node running the app, you should get:
MyDep run/load C:\Users\victor\Documents\development\jestpeer\MyDep MyLib run/load C:\Users\victor\Documents\development\jestpeer\MyLib MyModule run/load C:\Users\victor\Documents\development\jestpeer\MyModule Done in 0.27s.

If you run yarn test, that's jest running the test, you should get:
````
Ran all test suites.
console.log node_modules\MyLibnode_modules\MyDep\index.js:1
MyDep run/load C:\Users\victor\Documents\development\jestpeer\MyModulenode_modules\MyLibnode_modules\MyDep

console.log node_modules\MyLib\index.js:3
MyLib run/load C:\Users\victor\Documents\development\jestpeer\MyModulenode_modules\MyLib

console.log node_modules\MyDep\index.js:1
MyDep run/load C:\Users\victor\Documents\development\jestpeer\MyModulenode_modules\MyDep

console.log index.js:4
MyModule run/load C:\Users\victor\Documents\development\jestpeer\MyModule

Done in 3.23s.
````
Notice how while when running through node MyLib doesn't get loaded twice, while when running through Jest it does

What is the expected behavior?
yarn test should output
````
Ran all test suites.
console.log node_modules\MyDep\index.js:1
MyDep run/load C:\Users\victor\Documents\development\jestpeer\MyModulenode_modules\MyDep

console.log node_modules\MyLib\index.js:3
MyLib run/load C:\Users\victor\Documents\development\jestpeer\MyModulenode_modules\MyLib

console.log index.js:4
MyModule run/load C:\Users\victor\Documents\development\jestpeer\MyModule

Done in 3.23s.
````

Please provide your exact Jest configuration and mention your Jest, node, yarn/npm version and operating system.
Default jest configuration, Jest 18.0.0, node 6.9.1, yarn 0.19.0, Windows 10 64bit.

Most helpful comment

Another solution will be:

"moduleDirectories": [
      "<rootDir>/node_modules",
      "node_modules"
],

And I might open a pull request to make it default behaviour

All 11 comments

When debugging, I found the logic where modules get resolved is in Jest's build\index.js _normalizeID(from, moduleName)

Just curious – have you tried linking with npm instead of yarn?

@thymikee Just tried and still having the same issue... Npm version 3.10.8

👍 I'm having the same problem when running tests against packages linked via lerna. I believe it prevents tracking coverage of linked packages as well.

@voliva @thymikee I just figured out this is a bug in the node-resolve package. I have a PR for a fix that seems to fix all the problems I've had with jest & linked packages here.

To fix temporarily, you can add an npm-shrinkwrap.json that overrides the version of resolve with my patched version.

{
  "dependencies": {
    "browser-resolve": {
      "version": "1.11.2",
      "from": "browser-resolve@>=1.11.2 <2.0.0",
      "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz",
      "dependencies": {
        "resolve": {
          "version": "https://s3.amazonaws.com/waldo-public/resolve-1.2.0-patched.tar.gz",
          "from": "[email protected]",
          "resolved": "https://s3.amazonaws.com/waldo-public/resolve-1.2.0-patched.tar.gz"
        }
      }
    },
    "resolve": {
      "version": "https://s3.amazonaws.com/waldo-public/resolve-1.2.0-patched.tar.gz",
      "from": "resolve@>=1.2.0 <2.0.0",
      "resolved": "https://s3.amazonaws.com/waldo-public/resolve-1.2.0-patched.tar.gz"
    }
  }
}

@L8D have you had any progress with getting your fix merged?

Until this is fixed, a workaround is to add a jest config remapping references to the linked module to the parent version.

In MyModule/package.json:

"jest": {
    "moduleNameMapper": {
        "^MyDep$": "<rootDir>/node_modules/MyDep"
    }
}

This produces the expected output in @voliva's test repo.

Another solution will be:

"moduleDirectories": [
      "<rootDir>/node_modules",
      "node_modules"
],

And I might open a pull request to make it default behaviour

Sorry, but I'm curious why this was closed? Was there a resolution? Because I'm having this issue with jest 24.9.0 and have tried every solution suggested in this thread. Nothing works. My linked module can't find @material-ui/core within a jest test (but no problems when running it linked in the linked app). Have we just given up on doing this? If so, this makes Jest useless to me.

@SevenZark the moduleNameMapper and moduleDirectories solution worked for me with [email protected], I kept just the moduleDirectories to avoid further issues without needing to map every lib I have inside linked modules.

@SevenZark the moduleNameMapper and moduleDirectories solution worked for me with [email protected], I kept just the moduleDirectories to avoid further issues without needing to map every lib I have inside linked modules.

Apologies, I neglected to mention something very important, which is that I'm using create-react-app and therefore cannot alter things with moduleNameMapper. I realize that's a big omission.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jardakotesovec picture jardakotesovec  ·  3Comments

paularmstrong picture paularmstrong  ·  3Comments

ticky picture ticky  ·  3Comments

StephanBijzitter picture StephanBijzitter  ·  3Comments

ianp picture ianp  ·  3Comments