Jest + Typescript + Absolute paths (baseUrl) gives error: Cannot find module

故事扮演 提交于 2019-12-08 14:59:51

问题


I am setting a configuration to run my tests in a create-react-app + typescript app (from which I have ejected). I am using jest + enzyme. In my tsconfig.json I have set baseUrl='./src' so I can use absolute paths when I import modules. For example this is a typical import statement in one of my files:

import LayoutFlexBoxItem from 'framework/components/ui/LayoutFlexBoxItem';

You can see that the path is absolute (from /src folder) and not relative. This works fine when I run in debug mode ( yarn start )

But when I run my test ( yarn test ), I get this error:

 Cannot find module 'framework/components/Navigation' from 'index.tsx'

So it looks like jest is not able to resolve this absolute path although I have set it up in my tsconfig.json. This is my tsconfig.json:

{
  "compilerOptions": {
    "outDir": "dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "baseUrl": "./src"    
  },
  "exclude": [
    "node_modules",
    "build",
    "dist",
    "config",    
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ]
}

Now I can see that there is a generated tsconfig.test.json at the root of my project. This is the ts configuration used for test. And here is its content:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs"
  }
}

As you can see the "module" is commonjs here whereas in the default configuration it is esnext. Could this be one reason?

Has any one been able to unit test his typescript project with Jest and absolute path? or is this a known bug? Since I have ejected from default configuration, are there some settings to put in my webpack configuration?

Thanks for your input and suggestion.


回答1:


I was struggling with the same problem and actually it turns out that a simple change seems to do the trick.

I just updated the moduleDirectories field in jest.config.js

Before

moduleDirectories: ['node_modules']

After

moduleDirectories: ['node_modules', 'src']

Hope it helps,
Antoine




回答2:


Here is how I got moduleNameMapper working.

With the below config in my tsconfig:

    "paths": {
      "@App/*": [
        "src/*"
      ],
      "@Shared/*": [
        "src/Shared/*"
      ]
    },

Here's the moduleNameMapper:

"moduleNameMapper": {
  "@App/(.*)": "<rootDir>/src/$1",
  "@Shared/(.*)": "<rootDir>/src/Shared/$1"
}



回答3:


my solution was,

  "jest": {
    "moduleDirectories": [
      "node_modules",
      "src"
    ],
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "roots": [
      "src"
    ],
    "testRegex": ".spec.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "coverageDirectory": "../coverage",
    "testEnvironment": "node",
    "moduleNameMapper": {
      "src/(.*)": "<rootDir>/src/$1"
    }
  }



回答4:


I've using React with Typescript, I removed react-scripts-ts test --env=jsdom from npm test and added jest --watch as my default test, after I added jest.config.js to my project following these instructions https://basarat.gitbooks.io/typescript/docs/testing/jest.html

and I used the the configuration mentioned by @Antonie Laffargue (add/edit property moduleDirectories: ['node_modules', 'src']), it works perfectly.




回答5:


As many here pointed out moduleNameMapper in jest.config.js needs to define paths specified in tsconfig.json. For example, if you have paths in tsconfig.json defined as follows

// tsconfig.json
{
 ...
 "baseUrl": "src",
 "paths": {
    "@alias/*": [ 'path/to/alias/*' ]
 }
 ...
}

then your jest.config.js needs to provide those paths in moduleNameMapper in the following format:

// jest.config.js
module.exports = {
    'roots': [
        '<rootDir>/src'
    ],
    'transform': {
        '^.+\\.tsx?$': 'ts-jest'
    },
    'moduleNameMapper': {
         '@alias/(.*)': '<rootDir>/src/path/to/alias/$1'
    }
};

Having that we can improve our jest.config.js to convert paths defined in tsconfig.json automatically. Here is a Gist code snippet for that:

// jest.config.js

function makeModuleNameMapper(srcPath, tsconfigPath) {
    // Get paths from tsconfig
    const {paths} = require(tsconfigPath).compilerOptions;

    const aliases = {};

    // Iterate over paths and convert them into moduleNameMapper format
    Object.keys(paths).forEach((item) => {
        const key = item.replace('/*', '/(.*)');
        const path = paths[item][0].replace('/*', '/$1');
        aliases[key] = srcPath + '/' + path;
    });
    return aliases;
}

const TS_CONFIG_PATH = './tsconfig.json';
const SRC_PATH = '<rootDir>/src';

module.exports = {
    'roots': [
        SRC_PATH
    ],
    'transform': {
        '^.+\\.tsx?$': 'ts-jest'
    },
    'moduleNameMapper': makeModuleNameMapper(SRC_PATH, TS_CONFIG_PATH)
};



回答6:


I had a similar problem. I hope this could help to spare time for some of you.

My problem:

  • using create-react-app with typescript
  • using absolute paths (src/MyComp) to import components inside other components (e.g. App.tsx)
  • it was working on compile/run/build
  • it was not working on test

I found that the error was due to a different value of the NODE_PATH. So I set it on tests run.

I recreated the issue and the fix in here: https://github.com/alessandrodeste/...

I'm not sure if this could bring side effects on tests. Let me know if you have feedback ;)




回答7:


You probably want moduleNameMapper feature of jest config. It will map your custom import namespaces to real module locations.

see official documentation here:

https://facebook.github.io/jest/docs/en/configuration.html#modulenamemapper-object-string-string




回答8:


ts-jest can resolve this problem perfectly!
https://kulshekhar.github.io/ts-jest/user/config/#paths-mapping
just modify jest.config.js like this:

    const { pathsToModuleNameMapper } = require('ts-jest/utils');
    const { compilerOptions } = require('./tsconfig.json');
    module.exports = {
        preset: 'ts-jest',
        moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths)
    }


来源:https://stackoverflow.com/questions/50171412/jest-typescript-absolute-paths-baseurl-gives-error-cannot-find-module

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!