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"
}
}
...
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:
tsc
and ts-node/register
, no Babel) for the API build (.ts
).tsx
using Webpack)jest
for API testing (no Babel)testcafe
for UI/E2EKey notes:
module-alias
, however Jest is getting lost when we apply the module name mapper.baseUrl
and jest config if encounter issues..tsx
files 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'