'jest cannot resolve module aliases
I am using a npm module called module-alias. I map some modules in tsconfig.json and package.json
tsconfig.json
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@config/*": ["config/*"],
"@interfaces/*": ["interfaces/*"],
"@services/*": ["services/*"]
},
"module": "commonjs",
"target": "es2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"sourceMap": true,
"outDir": "./dist", /* Redirect output structure to the directory. */
"rootDir": "./src",
"allowSyntheticDefaultImports": true /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
}
package.json
...
"_moduleAliases": {
"@config": "src/config",
"@interface": "src/interface",
"@services": "src/services"
},
"jest": {
"moduleNameMapper": {
"@config/(.*)": "src/config/$1",
"@interface/(.*)": "src/interface/$1",
"@services/(.*)": "src/services/$1"
},
"moduleFileExtensions": ['js', 'json', 'jsx', 'ts', 'tsx', 'node']
},
...
server.ts
import { logger } from '@config/logger';
everything works fine when I run npm start, but it gives me an error when I run jest
FAIL src/test/article.spec.ts
● Test suite failed to run
Cannot find module '@config/logger' from 'server.ts'
However, Jest was able to find:
'rest/server.ts'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
Anyone know what the problem is? thanks
Solution works for me (Update 18/10/2019) :
Create a jest.config.js with code below:
module.exports = {
"roots": [
"<rootDir>/src/"
],
"transform": {
"^.+\\.tsx?$": "ts-jest"
}
}
and update moduleNameMapper in package.json:
...
"_moduleAliases": {
"@config": "./src/config",
"@interfaces": "./src/interfaces",
"@services": "./src/services"
},
"jest": {
"moduleNameMapper": {
"@config/(.*)": "<rootDir>/src/config/$1",
"@interfaces/(.*)": "<rootDir>/src/interfaces/$1",
"@services/(.*)": "<rootDir>/src/services/$1"
}
}
...
Solution 1:[1]
After a few hours I've managed to make this work. I'll try my best to simplify it to save others time and make it smooth.
My app is of the following stack:
- Typescript (
tscandts-node/register, no Babel) for the API build (.ts) - React (
.tsxusing Webpack) jestfor API testing (no Babel)testcafefor UI/E2E- VSCode as IDE
Key notes:
- The solution that works for me is must have "@" character in front of the alias. It's not required in theory by
module-alias, however Jest is getting lost when we apply the module name mapper. - There needs to be consistency for naming between 'webpack' aliases and 'tsconfig'. It is necessary for VSCode not to red underline module names in TSX files.
- This should work regardless of your document structure but remember to adapt
baseUrland jest config if encounter issues. - When applying changes in VSCode for
.tsxfiles do not be worried that some of the paths are underlined. It's temporary as VSCode seems to grasp it only when all files are correctly connected to each other. It demotivated me at the start.
First, install module-alias from https://www.npmjs.com/package/module-alias with
npm i --save module-alias
then add to your initial startup file (for .ts files only, i.e. your application server):
require('module-alias/register')
as the module-alias docs indicate. Then setup tsconfig.ts. Keep it mind that baseUrl is relevant here as well:
{
"compilerOptions": {
"baseUrl": ".",
...
"paths": {
"@helpers/*": ["src/helpers/*"],
"@root/*": ["src/*"]
...
}
}
then setup your webpack.js:
const path = require('path')
...
{
resolve: {
...
alias: {
'@helpers': path.resolve(__dirname, 'src', 'helpers'),
'@root': path.resolve(__dirname, 'src')
}
}
}
then setup your package.json:
{
...
"_moduleAliases": {
"@helpers": "src/helpers",
"@root": "src"
}
}
then setup your jest config (I attach only things that were relevant when applying my change):
{
rootDir: ".",
roots: ["./src"],
transform: {
"^.+\\.ts?$": "ts-jest"
},
moduleNameMapper: {
"@helpers/(.*)": "<rootDir>/src/helpers/$1",
"@root/(.*)": "<rootDir>/src/$1"
},
...
}
Now, we need to take care of the build process because tsc is not capable of transpiling aliases to their relative siblings.
To do that we will use tscpaths package: https://github.com/joonhocho/tscpaths . This one is simple.
So considering your build command was just:
tsc
Now it becomes
tsc && tscpaths -p tsconfig.json -s ./src -o ./dist/server
You need to adjust your -s and -o to your structure, but when you inspect your .js file after build you should see if the relative path is correctly linked (and debug accordingly).
That's it. It should work as ace. It's a lot but it's worth it.
Example of a call in the controller (.ts) and in React component (.tsx) file:
import { IApiResponse } from '@intf/IApi'
Solution 2:[2]
In my case to support @Greg Wozniak's answer, I only needed to fix my jest config file.
My app uses jest.config.ts
In my src/index.ts I have import "module-alias/register"
In package.json:
{
...
"_moduleAliases": {
"@helpers": "dist/helpers",
"@root": "dist"
}
}
In tsconfig.json:
{
"compilerOptions": {
"baseUrl": "./src",
...
"paths": {
"@helpers/*": ["helpers/*"],
"@root/*": ["*"]
...
}
}
In jest.config.ts:
- added roots, preset, the
(.*)and$1signs in moduleNameMapper*
{
roots: [
"<rootDir>/src/"
],
preset: "ts-jest",
transform: {
"^.+\\.(ts|tsx)$": "ts-jest",
},
moduleNameMapper: {
"@helpers/(.*)": "<rootDir>/src/helpers/$1",
"@root/(.*)": "<rootDir>/src/$1"
},
...
}
Solution 3:[3]
I think you don't have the routes properly configured in your tsconfig, since the paths lack the src folder (while they appear in your package.json module alias config):
Your tsconfig code:
"@config/*": ["config/*"],
"@interfaces/*": ["interfaces/*"],
"@services/*": ["services/*"]
How I think it should be:
"@config/*": ["src/config/*"],
"@interfaces/*": ["src/interfaces/*"],
"@services/*": ["src/services/*"]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Emmanuella |
| Solution 3 | Sergeon |
