Search code examples
typescriptjestjsts-jest

Path alias issue with .js extension in TypeScript project


I'm experiencing an issue with Jest in a TypeScript project where my tests fail if I include the .js extension in import statements. However, if I remove the .js extension, the tests work, but then my build process fails.

Jest configuration (jest.config.cjs):

const tsconfig = require('./tsconfig.json');
const moduleNameMapper = require('tsconfig-paths-jest')(tsconfig);

module.exports = {
  preset: 'ts-jest',
  rootDir: './',
  modulePaths: ['<rootDir>'],
  testEnvironment: 'node',
  moduleFileExtensions: ['ts', 'js'],
  moduleNameMapper,
  moduleDirectories: ['src', 'test', 'node_modules'],
};

TypeScript configuration (tsconfig.json):

{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "~sourceService/*": ["src/services/source/*"],
      "~crawlService/*": ["src/services/crawl/*"],
      "~searchService/*": ["src/services/search/*"],
      "~test/*": ["test/*"],
      "~/*": ["src/*"]
    },
    "rootDir": "./"
  }
}

Test file example:

jest.mock('~/config', () => {
  return {
    CONFIG: {},
  };
});

import { validateSourceRequest } from '~sourceService/source.utils';

describe(...);

Error message:

test/unit/sourceService/sourceServiceFunctions.test.ts
● Test suite failed to run

  Configuration error:

  Could not locate module ~/config.js mapped as:
  C:\\Users\\USER\\dir\\project\\src\\$1.

  Please check your configuration for these entries:
  {
    "moduleNameMapper": {
      "/~\\/(.*)/": "  C:\\Users\\USER\\dir\\project\\src\\$1"
    },
    "resolver": undefined
  }

  at createNoMappedModuleFoundError (node_modules/jest-resolve/build/resolver.js:759:17)
  at Object.require (src/services/source/source.utils.ts:4:1)
  at Object.<anonymous> (test/unit/sourceService/sourceServiceFunctions.test.ts:8:1)

The error occurs when my import statement includes the .js extension. If I remove the extension, Jest tests run correctly, but then the build process fails, saying it cannot find the module ../../../config due to the missing .js extension.

I tried mocking ~/config.js, but it didn't solve the issue.

How can I configure Jest and TypeScript to correctly resolve path aliases with .js extensions in import statements, so that both my tests and build process work correctly?

I tried making __mocks__ in the same directory my test is stored and within create a file config.ts:

const CONFIG = {}

export { CONFIG }

Edited:

I manage to find a not ideal solution:

jest.config.cjs:

/** @type {import('ts-jest').JestConfigWithTsJest} */
const tsconfig = require('./tsconfig.json')
const moduleNameMapper = require('tsconfig-paths-jest')(tsconfig)

module.exports = {
  preset: 'ts-jest',
  rootDir: './',
  roots: ['<rootDir>'],
  modulePaths: ['<rootDir>'],
  testEnvironment: 'node',
  moduleFileExtensions: ['ts', 'js', 'json', 'node'],
  moduleDirectories: ['node_modules', 'src'],
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1', // <-- added this line
    ...moduleNameMapper,
  },
}

and replace absolute path with relative path

from: import { CONFIG } from '~/config.js' to import { CONFIG } from '../../config.js'

Still looking for a better solution


Solution

  • For anyone looking for an answer here you have:

    I changed my config from jest.congif.mjs to jest.config.ts and installed couple of packages, all needed informations are in gist:

    https://gist.github.com/wojtekKrol/1556f4ba5e00b9a581ca8377845c828e