facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.47k stars 26.77k forks source link

node_modules Mocks are not picked up by jest with latest react-scripts #7539

Open tomitrescak opened 5 years ago

tomitrescak commented 5 years ago

Describe the bug

When upgrading from react-scripts@3.0.1 to latest the mocks are no longer picked up from /__mocks__ directory

Did you try recovering your dependencies?

YES

Which terms did you search for in User Guide?

jest manual mocks broken

Environment

Environment Info:

System: OS: macOS 10.14.5 CPU: (8) x64 Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz Binaries: Node: 12.8.0 - /usr/local/bin/node Yarn: 1.17.3 - ~/.yarn/bin/yarn npm: 6.10.2 - /usr/local/bin/npm Browsers: Chrome: 76.0.3809.100 Firefox: 68.0.1 Safari: 12.1.1 npmPackages: react: ^16.9.0 => 16.9.0 react-dom: ^16.9.0 => 16.9.0 react-scripts: 3.1.1 => 3.1.1 npmGlobalPackages: create-react-app: 2.1.3

Steps to reproduce

(Write your steps here:)

  1. create a manual mock of any node_modules package
  2. put it to mocks directory
  3. run your test

Expected behavior

Mocks are picked up by jest

Actual behavior

Mocks are not picked up

Reproducible demo

(Paste the link to an example project and exact instructions to reproduce the issue.)

  1. git clone https://github.com/tomitrescak/react-boilerplate -b Demo
  2. cd react-boilerplate
  3. yarn
  4. yarn test
  5. p -> 'button'
  6. error: Trans not found (not being picked up by mocks)

To see that is works with previous react-scripts do

  1. yarn add react-scripts@3.0.1
  2. yarn test
  3. You will recieve a snapshot erro which is fine
FezVrasta commented 5 years ago

I can't reproduce this with 3.1.1, we have a __mocks__ folder under src/ with 2 different mocks (one of a node module and one of an internal module) and they both work

jnak commented 5 years ago

@FezVrasta __mocks__ for node modules should be located immediately next to the node_modules directory.

https://jestjs.io/docs/en/manual-mocks#mocking-node-modules

ianschmitz commented 5 years ago

This may have been caused by #7480.

jnak commented 5 years ago

This is problematic because __mocks__ for user modules may collide with the __mocks__ for node_modules.

If we're not going to revert https://github.com/facebook/create-react-app/pull/7480, I feel we should at least document the new jest source since it is not standard and document the risk of collision.

FezVrasta commented 5 years ago

@jnak even under src the mocks work just fine. I always did it that way

jnak commented 5 years ago

@jnak even under src the mocks work just fine. I always did it that way

I know they work. But it is not standard (as per the jest documentation) and you may be running into a __mocks__ collision.

Anyway, I don't feel strongly about it. I just wanted to let you know of this undocumented gotcha.

tomitrescak commented 5 years ago

What to do guys? Shall we just move the mocks to src folder and hope for no collisions? We only have about 3-4 projects to upgrade.

ultimagriever commented 5 years ago

Honestly I think #7480 should be reverted, or at least just let us set the roots config in our package.json so we can avoid anti-patterns like this.

tomitrescak commented 5 years ago

No pressure, but would be good to know the decision if we should move the mocks to upgrade. Thanks!

ianschmitz commented 5 years ago

We may be able to specify __mocks__ living in the project root as another entry in the roots configuration. If someone has time could they try this? This may be a good solution to keep the performance benefits of #7480 and supporting the __mocks__ next to node_modules convention.

ultimagriever commented 5 years ago

@ianschmitz I've tried adding the project root to the roots configuration in package.json, but CRA threw an error saying that it wasn't supported and didn't run my tests at all.

ianschmitz commented 5 years ago

Correct - we don't support modifying roots. What you'll have to do test this is edit the createJestConfig.js file in node_modules/react-scripts as was done here: https://github.com/facebook/create-react-app/pull/7480/files#diff-40a56a7d41499eab85303b5e977f9742.

Try something like:

{
  roots: ['<rootDir>/src', '<rootDir>/__mocks__'],
  ...
}
KennethSundqvist commented 4 years ago

I'm working on a PR for this to add '<rootDir>/__mocks__' to roots.

The watcher used by Jest (jest-haste-map > './lib/FSEventsWatcher.js' > walker) will throw an error if '<rootDir>/__mocks__' doesn't exist.

I assume we want to use heuristics to check if the directory exists and push it onto roots if it does?

Would this be the correct way to check for the directory?

const nodeMocksRootPath = path.join(rootDir || paths.appPath, '__mocks__');
const nodeMocksRootStats =
  fs.existsSync(nodeMocksRootPath) && fs.statSync(nodeMocksRootPath);
if (nodeMocksRootStats && nodeMocksRootStats.isDirectory()) {
  roots.push('<rootDir>/__mocks__');
}

rootDir is used in the test script and is set to the template directory. It's not used in the eject script, is paths.appPath the correct value to use then?

brendanmc6 commented 4 years ago

For those whose test's are completely broken by this: Moving __mocks__ under ./src solved the problem for me.

ultimagriever commented 4 years ago

@brendanmc6 the issue is this is an anti-pattern.

The Jest documentation says that any external module manual mocks must live in the same level as node_modules, see https://jestjs.io/docs/en/manual-mocks#mocking-node-modules

ShamansCoding commented 4 years ago

As a temporary solution, I moved mocks to /src folder. But this is kind of very annoying bug, which blocks a very useful feature of Jest. As an example, I do want to mock Axios only once in my code for the whole project and it will be nice if it could be done according to Jest documentation.

brendanmc6 commented 4 years ago

Strangely this happened to me in two other projects as well, a Next.JS and a React Native project, both times because my CI was failing (local tests were passing). In both cases moving it to a subfolder other than root solved the problem. Just leaving this here for the paper trail-- I can't seem to find any other issues listed anywhere.

yugandhar-pathi commented 4 years ago

Can this be fixed soon, I can't mock node_modules as per jest documentation.

jameschao commented 4 years ago

Hi @KennethSundqvist, how's it going with your proposed fix?

Wgil commented 4 years ago

@brendanmc6 Thanks! spent about three hours to figure this out.

lewisloofis commented 4 years ago

Is there any progress with the PR for this issue fix? This feature is quite helpful for my testing

StarryFire commented 4 years ago

still no fix? :/ This is also not working on React Native 0.62

gforceg commented 3 years ago

I spent a lot of time today trying to figure out what I was doing wrong while following the jest module mock documentation very closely. Ideally CRA templates that use jest should contain the same defaults as plain-old-jest since react documentation directs newbies to use CRA.

louy2 commented 3 years ago

Learning Create React App and trying to follow TDD, it is very frustrating to have spent two days doubting myself what I have done wrong only to find out it is due to a downstream change and that the patch to fix it has stagnated for more than half a year. If the fix is not making it in anytime soon, could you please at least leave a note in the documentation?

ken-nah commented 3 years ago

It's been more than half a year, should we expect the patch to fix this soon?

tejasjadhav commented 3 years ago

Not sure if this would solve the issue for everyone else. For me, I ended up using CRACO to override the default Jest configs.

Here's an example (my additional tests were in electron folder) of my craco.config.js in my project root,

module.exports = {
  jest: {
    configure: {
      roots: [
        '<rootDir>/electron',
      ],
      testMatch: [
        '<rootDir>/electron/**/__tests__/**/*.{js,jsx,ts,tsx}',
        '<rootDir>/electron/**/*.{spec,test}.{js,jsx,ts,tsx}',
      ],
    },
  },
};
cjsilva-umich commented 1 year ago

Please update the documentation if there is no plan to rectify this. I (and many others, I'm sure) have wasted a lot of time trying to figure out why what is specified in the documentation doesn't work.

felipefreitag commented 1 year ago

I've gone and used patch-package to fix this on my repos:

Step 1: create the __mocks__ dir

├── src ├── mocks ├── node_modules ├── package.json

Step 2: patch react-scripts

// node_modules/react-scripts/scripts/utils/createJestConfig.js
   const config = {
-    roots: ['<rootDir>/src'],
+    roots: ['<rootDir>/src', '<rootDir>/__mocks__'],

Warning: This breaks jest if the <rootDir>/__mocks__ dir doesn't exist.