[describe the issue here]
Seems to not use path mappings from tsconfig.js that work fine with the rest of my Typescript project.
Instead, I have to implement the babel module resolver so I have to maintain two mappings which is not fun.
tsconfig.js:
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"jsx": "react",
"moduleResolution": "node",
"allowJs": true,
"importHelpers": true,
"allowSyntheticDefaultImports": true,
"isolatedModules": false,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"suppressImplicitAnyIndexErrors": true,
"pretty": true,
"sourceMap": false,
"skipLibCheck": true,
"baseUrl": "src",
"paths": {
"*": "../node_modules_local/*",
"~/*": "./*"
},
"typeRoots": [
"node_modules/@types"
]
}
}
[describe the expected behavior here]
[If you haven't already, create the smallest possible repo that reproduces this issue by running npm install and npm test. This will speed up any fixes that this issue might need]
This allows potential solutions to be tested against the minimal repo. This saves everyone time and avoids a lot of back and forth.
Please provide a minimal reproducible repo, this isn't enough for us to go on.
Here is a sample repository, run npm install and npm test (or npm run test:dev to run tests without coverage).
Uncommenting lines 3 and 4 make tests run, but breaks code splitting.
Same here. We find out that paths property in tsconfig is ignored.
I faced this as well, however I didn't think it was an issue. Although it does make sense that the paths in tsconfig are respected automatically from ts-jest.
I used the moduleNameMapper jest config property and set the same paths. You could try that as a workaround for the time being?
Bear in mind the syntax is different for setting the same paths in moduleNameMapper such that:
"my-path/*": ["src/my-path/*"]
would be:
"my-path/(.*)": "<rootDir>/src/my-path/$1"
Hope this helps for the time-being.
@alexanderby you need to add
moduleNameMapper: {
"malevic": "<rootDir>/entries",
},
in jest config.
ts-jest doesn't pick up or resolve any files. All files are resolved by jest and then passed in to ts-jest for processing. That's why jest needs to know how to resolve modules - the above code does that
Thanks, it worked and I used aliases in all my tests. One strange thing is that properties' order matters https://github.com/alexanderby/malevic/commit/5949e1b8413866d2ff3c3f4f3ae6f91440e2de03
@kulshekhar would you mind to take a look at this minimal reproduction repository?
I've a shared core (./core) project that I'm including into my project. It is located next to a nestjs typescript project (./api) that uses Jest for testing. For tsc I've added the correct path mapping in my tsconfig file.
After I experienced errors with jest not reading this configuration I found this issue. Therefore a moduleNameMapper was added to the ./api/package.json-File. Maybe my mapping is just wrong but I'm still experiencing errors when running npm run test:
Could not locate module @core/some-model (mapped as /home/.../path-issue/core) (which actually looks good to me - or like the correct path)
@CanKattwinkel
moduleNameMapper "@core/(.*)": "<rootDir>/../../core/$1"
I honestly don't know why ../.. is required but this seemed to work
install ts-jest in core's directory or in one of its ancestor directory
implement the core/some-shared-model.ts file
this should get tests passing
Oh the shared model was a refactoring corpse.. But yes after I applied your steps I got it working.
Therefore a very big thank you.
If you don't want to expend cycles trying to understand the regex patterns required to port your tsconfig.json paths key into jest.config.js's moduleNameMapper key, I found an npm module to do it for you.
Assuming you have thee tsconfig.json and jest.config.js both defined in the root of your project, from your project root run:
npm install jest-module-name-mapper
node
> let mapper = require('jest-module-name-mapper')
mapper()
// '^common/(.*)': '<rootDir>/./common/src/main/ts/$1'
Then add the output as the keys of your jest's moduleNameMapper field.
For anyone who might run into the same problem, you may want to specify the absolute path to the mapper in jest.config.js
const {
compilerOptions
} = require('./tsconfig');
const {
resolve
} = require('path');
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
"collectCoverageFrom": [
"**/*.{ts,tsx}",
"!**/node_modules/**",
"!**/lib/**",
"!**/vendor/**"
],
moduleNameMapper: {
'^@core/(.*)$': resolve(__dirname, './src/modules/core/$1'),
'^@components/(.*)$': resolve(__dirname, './src/components/$1'),
'^@products/(.*)$': resolve(__dirname, './src/modules/products/$1'),
'^@layouts/(.*)$': resolve(__dirname, './src/modules/layouts/$1'),
},
};
The way I approached this was to just map the values from the tsconfig.json into the jest.config.js file like so:
const tsconfig = require('./tsconfig.json')
const paths = tsconfig.compilerOptions.paths
const moduleNameMapper = Object.keys(paths).reduce((acc, curr) => {
return {
...acc,
[curr]: '<rootDir>' + paths[curr]
}
}, {})
module.exports = {
...
moduleNameMapper,
...
}
I am using the moduleNameMapper, after stugling to make it work, I finally had to pass: { prefix: '<rootDir>/' } to the second parameter. Here below is my workingjest-e2e.jsfile.
const { pathsToModuleNameMapper } = require('ts-jest/utils');
// In the following statement, replace `./tsconfig` with the path to your `tsconfig` file
// which contains the path mapping (ie the `compilerOptions.paths` option):
const { compilerOptions } = require('./tsconfig.e2e.json');
const { defaults } = require('jest-config');
module.exports = {
'moduleFileExtensions': [
...defaults.moduleFileExtensions,
],
'rootDir': '.',
'testEnvironment': 'node',
'testRegex': '.*spec.ts$',
'transform': {
'^.+\\.(t|j)s$': 'ts-jest',
},
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths , { prefix: '<rootDir>/' } ),
globals: {
"ts-jest": {
"tsConfig": "./tsconfig.e2e.json"
}
}
};
In my case I used modulePaths in jest.config.js and it solved the issue.
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-undef */
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig.json');
const moduleNameMapper = pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' });
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: [
'**/__tests__/**/*.+(ts|tsx|js)',
'**/?(*.)+(spec|test).+(ts|tsx|js)',
],
transform: {
'^.+\\.(t|j)s$': 'ts-jest',
},
moduleNameMapper,
modulePaths: ['<rootDir>/src']
};
And my tsconfig.json:
{
"compilerOptions": {
"target": "es2019",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./build",
"incremental": true,
"moduleResolution": "node",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"lib": [
"ES6"
],
"noImplicitAny": true,
"baseUrl": "src",
"paths": {
"src/*": [
"src/*"
]
}
},
"include": [
"src"
],
"exclude": [
"node_modules",
"dist"
]
}
So then I can import import { foo } from 'core/parser';
|____src
|____core
|____parser
|____index.ts
Most helpful comment
I faced this as well, however I didn't think it was an issue. Although it does make sense that the paths in tsconfig are respected automatically from ts-jest.
I used the
moduleNameMapperjest config property and set the same paths. You could try that as a workaround for the time being?Bear in mind the syntax is different for setting the same paths in
moduleNameMappersuch that:"my-path/*": ["src/my-path/*"]would be:
"my-path/(.*)": "<rootDir>/src/my-path/$1"Hope this helps for the time-being.