Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

moduleNameMapper doesn't work for me #364

Closed
siluri opened this issue Nov 6, 2017 · 35 comments
Closed

moduleNameMapper doesn't work for me #364

siluri opened this issue Nov 6, 2017 · 35 comments

Comments

@siluri
Copy link

siluri commented Nov 6, 2017

I change the path configuration in my tsconfig, for better paths. But now i cannot execute my testcases. So i checked the following documentaries:

Is that an error or a misconfiguration? By Error i will do a small repo.

Snippet tsconfig.json

...
        "rootDirs": [
          "src/",
          "test/"
        ],
        "baseUrl": ".",
        "paths": {
          "log": ["src/util/log"],
          "server": ["src/server"],
          "util/*": ["src/util/*"],
          "api/*": ["src/api/*"],
          "middleware/*": ["src/middleware/*"],
          "service/*": ["src/service/*"],
          "types/*": ["src/types/*"],
          "test/*": ["test/*"],
          "mocks/*": ["test/mocks/*"],
          "src/*": ["src/*"]
        },

Snippet package.json

...
    "globals": {
      "ts-jest": {
        "tsConfigFile": "tsconfig.json"
      }
...
    "moduleDirectories": [
      ".",
      "node_modules"
    ],
    "moduleNameMapper": {
      "log": "<rootDir>/src/util/log",
      "server": "<rootDir>/src/server",
      "util/(.*)": "<rootDir>/src/util/$1",
      "api/(.*)": "<rootDir>/src/api/$1",
      "middleware/(.*)": "<rootDir>/src/middleware/$1",
      "service/(.*)": "<rootDir>/src/service/$1",
      "types/(.*)": "<rootDir>/src/types/$1",
      "test/(.*)": "<rootDir>/test/$1",
      "mocks/(.*)": "<rootDir>/test/mocks/$1",
      "src/(.*)": "<rootDir>/src/$1"
    }
...

ERROR

● Test suite failed to run

   Configuration error:

   Could not locate module ../util/params (mapped as C:\Users\XXX\backend\src\util\params)

   Please check:

   "moduleNameMapper": {
     "/util\/(.*)/": "C:\Users\XXX\backend\src\util\$1"
   },
   "resolver": undefined
@kulshekhar
Copy link
Owner

Can you please create a minimal repo that reproduces this issue?

@siluri
Copy link
Author

siluri commented Nov 7, 2017

i hope u can understand the problem and reproduce the issue or the misconfig

repo

Thanks for ur help

@kulshekhar
Copy link
Owner

kulshekhar commented Nov 8, 2017

Changing the moduleDirectories key in the jest configuration got this working (I tested with jest --no-cache from the root directory)

    "moduleDirectories": [
      ".",
      "src",
      "src/util",
      "node_modules"
    ]

Hope this helps

@DmitryEfimenko
Copy link

This should not have been closed. There is an opportunity to automate this so that developer does not have to touch jest.config.

@huafu
Copy link
Collaborator

huafu commented Aug 30, 2018

@DmitryEfimenko if you are using webpack, you'd face the same issue where some path mapped in typescript thanks to the paths config needs its alias in resolve.alias in webpack config.

The option paths is used by the compielr to know that some/path will correspond, at run time, to the file which is NOW at another location. But the typescript compiler is NOT responsible for making those files accessible at runtime. In brief, TS paths setting doesn't affect compiled JS code neither the node resolver.

@DmitryEfimenko
Copy link

whatever it does, it seems that all we need to do to make jest work is to put corresponding mappings in the jest.config. I'm not talking about webpack. Just jest and what would it take to make it work.

@huafu
Copy link
Collaborator

huafu commented Aug 30, 2018

I understand, and I thought it'd be nice to have, until I had a project where some path mapping in jest were different. For example you'd expect it to not resolve during testing, while you still need to keep the paths for compiling. IF this has to be added, it must be an opt-in.

@DmitryEfimenko
Copy link

I'd think it's a rare case when you would not want it.
What if it was behind an option?

{
  "jest": {
    "globals": {
      "ts-jest": {
        "autoMapModuleNames": true
      }
    }
  }
}

@huafu
Copy link
Collaborator

huafu commented Sep 1, 2018

yup @DmitryEfimenko that is what I meant by being an opt-in.

Example of where you would not want it:

// tsconfig.json:
"paths": {
  "app": ["./src/app"],
  "common/*": ["../src/common/*"],
  "quasar": ["./node_modules/quasar-framework/dist/quasar.mat.esm.js"]
}

// jest.config.js:
moduleNameMapper: {
  '^app$': '<rootDir>/src/app',
}

And that is not the only project I work on where both don't match ;-)

But yeah, having an option for it is a good idea. It could be a helper so that people can customize it:

// jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest')
const { compilerOptions: { paths: tsconfigPaths } } = require('./tsconfig')

module.exports = {
  // ...
  moduleNameMapper: {
    ...pathsToModuleNameMapper(
      tsconfigPaths, // picking/omitting could happen here
      // options could be given here
    ),
    'someOtherMapping/(.*)': 'path/to/somewhere/else/$1',
  }
}

@huafu
Copy link
Collaborator

huafu commented Sep 1, 2018

@DmitryEfimenko
Copy link

awesome, thanks!

@MattMcFarland
Copy link

Anyone test this on windows? I can't seem to get this to work for windows.

@jdavidferreira
Copy link

jdavidferreira commented Jun 21, 2019

I have this problem that should be related to this issue. When I call a module "util" that links to src/util folder, it doesn't work.

  moduleNameMapper: {
    '^util(.*)$': '<rootDir>/src/util$1'
  }

And throws:

    Configuration error:

    Could not locate module util mapped as:
    C:\Users\itsme\Desktop\projecX\src\util.

    Please check your configuration for these entries:
    {
      "moduleNameMapper": {
        "/^util(.*)$/": "C:\Users\itsme\Desktop\projecX\src\util$1"
      },
      "resolver": null
    }

      at createNoMappedModuleFoundError (node_modules/jest-resolve/build/index.js:472:17)
      at Object.<anonymous> (node_modules/micromatch/index.js:7:12)

But when I rename the folder and the module to "utils", in plural... It works.

  moduleNameMapper: {
    '^utils(.*)$': '<rootDir>/src/utils$1'
  }

🤷‍♂️🙄

@sojungko
Copy link

@mrjdavidfg Observed the same exact phenomenon. Renaming the folder /util to /utils made the paths to resolve correctly. Seems like a bug.

@apflieger
Copy link

apflieger commented Nov 7, 2019

Hi there!

I'm experiencing the warning Mapping only to first target of "*" because it has more than one (2) when I use pathsToModuleNameMapper

Having multiple path mapping for a pattern is supported by typescript (see https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping). Is there a reason we can't do that here?

@loudmouth
Copy link

loudmouth commented Nov 13, 2019

@apflieger It looks like the issue with moduleNameMappers not accepting arrays of module paths in the same way that typescript config allows for is an issue with Jest itself. I'll try to muster up the courage to jump in lions' den over there and open an issue about it.

See #1072

@ShamithaSIlva
Copy link

@huafu and @apflieger :I have modules in node_modules folder and those dependancies are like below and use it like:

import { NxDatepickerComponent } from '@xyz/ngx-ndbx/datefield/xyz-ngx-ndbx-datefield';
import { NX_DATE_FORMATS } from '@xyz/ngx-ndbx/datefield';
Folder structure is \node_modules@xyz\ngx-ndbx\datefield

For this I have moduleNameMapper as having followings for jest configuaration in package.json file:

"moduleNameMapper": {
"@jkl(.)": "/src/app/modules/jkl/$1",
"@shared(.
)": "/src/app/@shared/$1",
"^@xyz/(.)$": "/node_modules/@xyz"
},
With this configuration only the first import is working and not the second one even if it is in the same folder. Anything I'm missing or doing wrong here?

@tcoz
Copy link

tcoz commented Apr 1, 2020

I'm struggling with this as well. I'm using an nrwl/nx workspace, the paths in tsconfig.app allow the app to run fine, I put the module name mappings in jest.config, nothing. I've tried using the jest utils that do the path to module mappings from tsconfig.app prefixed with rootDir, explicitly putting the entries (so not pulling them in from tsconfig.app), and a hundred other things. Nothing works. You run the tests and any module mapped to a path is not found. The one and only solution I have that works is just to remove the paths and start typing '../../../..' everywhere (which would be dozens of imports).

@aaron-fuleki
Copy link

@tcoz I've found the same thing. Tried suggestions from a dozen or so threads/posts/issues, and nothing works, including the pathsToModuleNameMapper suggestion from the ts-jest docs. I remember getting this to work a few months ago, but for the life of me can't figure out why it doesn't now, even in the simplest of example projects. I wonder if there's a regression somewhere...

@ahnpnl
Copy link
Collaborator

ahnpnl commented Apr 9, 2020

path mapping works depending on your rootDir, see https://github.com/kulshekhar/ts-jest/blob/master/TROUBLESHOOTING.md

@aaron-fuleki
Copy link

🤦

In my many stabs-in-the-dark, I'd changed that line to '<rootDir>/src'

roots: ['<rootDir>'] fixed it!

@DarkLite1
Copy link

I almost gave up on this but finally fixed it.

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@environment": ["src/environment"],
      "@test-utils/*": ["src/test-utils/*"]
    },
}

The key below was that moduleDirectories was not required to get it to work but modulePaths is. Also a piece of advice is to use <rootDir> instead of ./.

// jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest/utils')
const { compilerOptions } = require('./tsconfig')

module.exports = {
  roots: ['<rootDir>'],
  modulePaths: ['<rootDir>'],
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
}

@lloydaf
Copy link

lloydaf commented Aug 15, 2020

Wish this was automated 🙈 🤦
@DarkLite1 Your solution works like a charm, many thanks!

@jasonkuhrt
Copy link

I have a situation where it works locally, but not in GitHub CI. I have no idea why, tried the various solutions listed here, none worked. 🤔

@bendelonlee
Copy link

Ran into what I thought was this issue, but it was just a case of not providing regex boundaries (^$) to the module name

@fmoessle
Copy link

If you're using a different baseUrl in your tsconfig.json, you should set modulePaths to that baseUrl.

// tsconfig.json
{
  "compilerOptions": {
      "baseUrl": "./src",
      "paths": {
        ...
      }
  }
}
// jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest/utils')
const { compilerOptions } = require('./tsconfig')

module.exports = {
  roots: ['<rootDir>'],
  modulePaths: [compilerOptions.baseUrl], // <-- This will be set to './src'
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
}

@tetchel
Copy link

tetchel commented Dec 1, 2021

If you are like me and none of the above solutions work for you, and you have globalSetup set, you may be experiencing this related issue.

@skilbjo
Copy link

skilbjo commented Jan 15, 2023

none of the above solutions worked for me others (but they certainly helped), however this is what got me working, and it may help others... https://stackoverflow.com/a/73038898/2490091

@jonathanccalixto
Copy link

I have a new problem

my tsconfig.json is configured with

    "baseUrl": "./",
    "paths": {
      "*": ["./src/*"]
    },

when I use in Jest.config.ts

import type { Config } from 'jest';
import { pathsToModuleNameMapper } from 'ts-jest';
import { compilerOptions } from './tsconfig.json';

const config: Config = {
  // Resto das configurações...

moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
};

export default config;

raises a exception:

Configuration error:
    
    Could not locate module  mapped as:
    /Users/jonathanccalixto/Workspace/github/jonathanccalixto/maallaqa-monorepo/backend/src/$1.
    
    Please check your configuration for these entries:
    {
      "moduleNameMapper": {
        "/^(.*)$/": "/Users/jonathanccalixto/Workspace/github/jonathanccalixto/maallaqa-monorepo/backend/src/$1"
      },
      "resolver": undefined
    }

how do I resolve this?

My dependencies:

"dependencies": {
    "fastify": "^4.13.0",
    "reflect-metadata": "^0.1.13",
    "semaphore-async-await": "^1.5.1",
    "tsyringe": "^4.7.0",
    "uuid": "^9.0.0"
  },
  "devDependencies": {
    "@types/jest": "^29.5.2",
    "@types/node": "^20.4.1",
    "@types/uuid": "^9.0.1",
    "@yanotec/eslint-config-node": "^1.0.7",
    "eslint": "^8.35.0",
    "eslint-plugin-prettier": "^5.0.0-alpha.1",
    "jest": "^29.6.1",
    "ts-jest": "^29.1.1",
    "ts-node": "^10.9.1",
    "tsx": "^3.12.3",
    "typescript": "^5.1.6"
  }

@aliaksandrIt
Copy link

@jonathanccalixto did u resolve your ussue?

@prathikvel
Copy link

@jonathanccalixto @aliaksandrIt I'm not sure if we had the exact same problem, but I had a similar problem and solved it. Make sure that your paths in tsconfig.json are not prefixed by ./.

For example, this configuration...

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
           // ^ notice the "./"
    },
}

...should become the following.

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
           // ^ notice the lack of "./"
    },
}

This was really frustrating because I couldn't find any documentation that pointed this out.

@toby-j
Copy link

toby-j commented Jul 17, 2024

If you're using a different baseUrl in your tsconfig.json, you should set modulePaths to that baseUrl.

// tsconfig.json
{
  "compilerOptions": {
      "baseUrl": "./src",
      "paths": {
        ...
      }
  }
}
// jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest/utils')
const { compilerOptions } = require('./tsconfig')

module.exports = {
  roots: ['<rootDir>'],
  modulePaths: [compilerOptions.baseUrl], // <-- This will be set to './src'
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
}

If you're using a monorepo like I was, where the local tsconfig extended the root tsconfig and therefore didn't have a paths variable: you can use the prefix option in pathsToModuleNameMapper which will then convert the module mapper paths in your root correctly for a monorepo.

jest.config.ts

import { pathsToModuleNameMapper } from 'ts-jest';
import { compilerOptions } from '../../../../../tsconfig.json';

module.exports = {
	transform: {},
	preset: 'ts-jest',
	testEnvironment: 'node',
	testMatch: [
		"**/tests/**/*test.[tj]s"
	],
	moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {prefix: "<rootDir/>/../../../../../"})
};

@ahnpnl
Copy link
Collaborator

ahnpnl commented Jul 17, 2024

moduleNameMapper is a part of Jest module resolution which ts-jest can't interfere with. We are open to improve the function pathsToModuleNameMapper to cover more use cases.

Please keep in mind that pathsToModuleNameMapper is a utility function to help Jest module resolution. Right now I think it doesn't cover all use cases.

@toby-j
Copy link

toby-j commented Jul 17, 2024

Yes I agree, this is verging on a Jest bug/feat.

In the docs, it still says pathsToModuleNameMapper is imported from ts-jest/utils when I believe it's now just the root.

@ahnpnl
Copy link
Collaborator

ahnpnl commented Jul 17, 2024

Oh right, we are working on documentation these days. PR is welcome 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests