typescriptjestjsts-jesttsconfigtsconfig-paths

Can't use TSConfig Paths in the Jest test files


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: test error

What should I do in order to get a fully working ecosystem of path mappings, typescript, jest?


Solution

  • 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.