Well, the title is pretty auto-explainable: I have set my tsconfig paths so that I can use @configs/logger
instead of ../../configs/logger
everytime in my APP files. But if I try to use those path mappings in the jest test files, it doesn't work.
Current setup:
package.json
:
...,
"scripts": {
"test": "jest -i",
...,
},
"devDependencies": {
...,
"@types/jest": "^28.1.4",
"@types/node": "^18.0.3",
"@types/supertest": "^2.0.12",
"jest": "^28.1.2",
"supertest": "^6.2.4",
"ts-jest": "^28.0.5",
"ts-node-dev": "^2.0.0",
"tsconfig-paths": "^4.0.0",
"typescript": "^4.7.4"
}
tsconfig.json
:
{
"compilerOptions": {
"target": "es2016",
"lib": ["ESNext"],
"module": "commonjs",
"baseUrl": "./src/",
"paths": {
"@configs/*": ["configs/*"],
"@controllers/*": ["controllers/*"],
"@middlewares/*": ["middlewares/*"],
"@routes/*": ["routes/*"],
"@services/*": ["services/*"],
"@utils/*": ["utils/*"],
"@src/*": ["./*"]
},
"rootDirs": ["src"],
"sourceMap": true,
"outDir": "dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
src/app.ts
:
import express, { Response } from 'express';
import helmet from 'helmet';
import cors from 'cors';
import Logger from '@configs/logger';
import morganMiddleware from '@configs/morgan';
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(helmet());
app.use(
cors({
origin: '*',
methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type']
})
);
app.use(morganMiddleware);
app.get('/logger', (_, res: Response) => {
Logger.info('Info log');
Logger.warn('Warn log');
Logger.debug('Debug log');
Logger.error('Error log');
res.send({ message: 'Logger works' });
});
export default app;
src/__tests__/example.test.ts
:
import supertest from 'supertest';
import app from '../app';
describe('test', () => {
it('test', async () => {
const response = await supertest(app).get('/logger');
expect(response?.body?.message).toEqual('Logger works');
});
});
jest.config.js
:
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig.json');
const { baseUrl, paths } = compilerOptions;
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
transform: {
'^.+\\.tsx?$': 'ts-jest'
},
modulePaths: [baseUrl],
moduleNameMapper: pathsToModuleNameMapper(paths)
};
With the above files, the testing command works well, but if I want to change in the src/__tests__/example.test.ts
, from import app from '../app'
to import app from '@src/app'
, I get the following error:
Configuration error:
Could not locate module @src/app mapped as:
./$1.
Please check your configuration for these entries:
{
"moduleNameMapper": {
"/^@src\/(.*)$/": "./$1"
},
"resolver": undefined
}
In an image to be even clearer:
What should I do in order to get a fully working ecosystem of path mappings, typescript, jest?
Apparently if I change in the tsconfig.json
from
"baseUrl": "./src/",
"paths": {
"@configs/*": ["configs/*"],
"@controllers/*": ["controllers/*"],
"@middlewares/*": ["middlewares/*"],
"@routes/*": ["routes/*"],
"@services/*": ["services/*"],
"@utils/*": ["utils/*"],
"@src/*": ["./*"]
}
to
"baseUrl": "./",
"paths": {
"@configs/*": ["src/configs/*"],
"@controllers/*": ["src/controllers/*"],
"@middlewares/*": ["src/middlewares/*"],
"@routes/*": ["src/routes/*"],
"@services/*": ["src/services/*"],
"@utils/*": ["src/utils/*"],
"@app": ["src/app"]
}
Fixes the problem. I am not sure why jest doesn't understand when the tsconfig baseUrl
is set to ./src/
and does when it's ./
.
Well, with that I think we can close this topic. I will wait a few hours or days to close it to see if someone can help us understanding this or giving another solution.