Testing with Jest and Webpack aliases

43,994

Solution 1

This seems to have been fixed.

Below is a working setup:

Versions

"jest": "~20.0.4"

"webpack": "^3.5.6"

package.json

"jest": {
  "moduleNameMapper": {
    "^@root(.*)$": "<rootDir>/src$1",
    "^@components(.*)$": "<rootDir>/src/components$1",
  } 
}

webpack.shared.js

const paths = {
  APP_DIR: path.resolve(__dirname, '..', 'src'),
};

exports.resolveRoot = [paths.APP_DIR, 'node_modules'];

exports.aliases = {
  '@root': path.resolve(paths.APP_DIR, ''),
  '@components': path.resolve(paths.APP_DIR, 'components'),
};

Solution 2

Since I had the same problem before I read again, and this time more carefully the documentation. Correct config should be:

  "jest": {
    "moduleNameMapper": {
      "^@shared(.*)$": "<rootDir>/shared$1",
      "^@components(.*)$": "<rootDir>/shared/components$1"
    }
  },

Solution 3

Using: "jest": "^26.5.3", and "webpack": "4.41.5", I was able to properly match my webpack/typescript aliases in the jest.config.js with this pattern:

Webpack config:

module.exports = {
   // the rest of your config
    resolve: {
      alias: {
        'components': path.resolve(__dirname, 'js/app/components'),
        'modules': path.resolve(__dirname, 'js/app/modules'),
        'types': path.resolve(__dirname, 'js/types'),
        'hooks': path.resolve(__dirname, 'js/app/hooks'),
        'reducers': path.resolve(__dirname, 'js/app/reducers'),
        '__test-utils__': path.resolve(__dirname, 'js/app/__test-utils__') 
      }
    },
}

Jest.config.js:

  moduleNameMapper: {
    '^types/(.*)$':  '<rootDir>/js/types/$1',
    '^components/(.*)$': '<rootDir>/js/app/components/$1',
    '^modules/(.*)$':  '<rootDir>/js/app/modules/$1',
    '^hooks/(.*)$':  '<rootDir>/js/app/hooks/$1',
    '^reducers/(.*)$':  '<rootDir>/js/app/reducers/$1',
    '^__test-utils__/(.)$': '<rootDir>/js/app/__test-utils__/$1' 
  }

Here's an explanation of the symbols:

  • (.*)$: capture whatever comes after the exact match (the directory)
  • $1: map it to this value in the directory I specify.

and tsconfig.json:

    "paths": {
      "config": ["config/dev", "config/production"],
      "components/*": ["js/app/components/*"],
      "modules/*": ["js/app/modules/*"],
      "types/*": ["js/types/*"],
      "hooks/*": ["js/app/hooks/*"],
      "reducers/*": ["js/app/reducers/*"],
      "__test-utils__/*": ["js/app/__test-utils__/*"]
    }

Solution 4

For anyone using @ as the root of their modules, you have to be more specific since other libs can use the @ in node modules.

  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1"
  },

It translates to "anything that matches @/ should be sent to <rootDir>/src/<rest of the path>

Solution 5

FWIW, Try switching the alias order, keep the more specific up and less specific down, e.g.

"moduleNameMapper": {
  "^@components$": "<rootDir>/shared/components/",
  "^@shared$": "<rootDir>/shared/"
}
Share:
43,994
speak
Author by

speak

Updated on May 21, 2021

Comments

  • speak
    speak about 3 years

    I am looking to be able to use webpack aliases to resolve imports when using jest, and optimally, reference the webpack.aliases to avoid duplication.

    Jest conf:

      "jest": {
        "modulePaths": ["src"],
        "moduleDirectories": ["node_modules"],
        "moduleNameMapper": {
          "^@shared$": "<rootDir>/shared/",
          "^@components$": "<rootDir>/shared/components/"
        }
      },
    

    Webpack aliases:

    exports.aliases = {
        '@shared': path.resolve(paths.APP_DIR, 'shared'),
        '@components': path.resolve(paths.APP_DIR, 'shared/components'),
    };
    

    Imports:

    import Ordinal from '@shared/utils/Ordinal.jsx';
    import Avatar from '@components/common/Avatar.jsx';
    

    For some reason the @ causes issues, so when removed (in both alias and import), it can find shared but components still cannot be resolved.

     FAIL  src/shared/components/test/Test.spec.jsx
      ● Test suite failed to run
    
        Cannot find module '@shared/utils/Ordinal.jsx' from 'Test.jsx'
    

    I have tried using jest-webpack-alias, babel-plugin-module-resolver and the Jest/Webpack docs

  • speak
    speak about 7 years
    Tried in combination with leo's answer, still have the same errors.
  • hazardous
    hazardous about 7 years
    Is it possible for you to share the complete code, github preferably?
  • speak
    speak about 7 years
    unfortunately not as it's a private corporate repository.
  • hazardous
    hazardous about 7 years
    Could you create a git repo with the minimally viable code where this issue is reproducible?
  • speak
    speak about 7 years
    I tried implementing this configuration, but still have the same issue. It cannot find the imported file: Cannot find module '@shared/utils/Ordinal.jsx' from 'Test.jsx'.
  • James Fremen
    James Fremen about 7 years
    I'm also getting the same error message for a scoped package. I've created a very small project at gist.github.com/batwicket/da72ffa7d5324d8f7c5eb11f0ba07fad . I tried the alias approach.. no luck. I'm probably missing something simple. Any help appreciated.
  • Wes Duff
    Wes Duff almost 7 years
    Yes we have the same issue. Importing from a location called "@location" and it seems the "@" is causing an issue.
  • mayid
    mayid over 6 years
    I had to resolve my path with "modulePaths": ["src"]. Then yes, this solution worked: "^Commons$": "./Commons"
  • Ross Sheppard
    Ross Sheppard over 5 years
    I was having the same issue as the OP and @mayid's solution was what finally resolved the issue for me.
  • Fortune
    Fortune almost 4 years
    In case you're a total newbie like me, this configuration is found in your package.json file
  • Pat Migliaccio
    Pat Migliaccio almost 4 years
    As a note, configuration may otherwise be located in jest.config.js.
  • jyjin
    jyjin almost 3 years
    My question seems is moduleNameMapper just work to your source code, but doesn't work to your package code. How to resolve some packages in node_modules which has @ or @@ alias in jest? Such as package umi.
  • Tyler Hitzeman
    Tyler Hitzeman over 2 years
    If you're confident you did everything right but TS is still complaining about not finding the import: friendly reminder to restart your TS server.
  • sigfried
    sigfried over 2 years
    This answer deserves more upvotes =)
  • CodeFinity
    CodeFinity over 2 years
    It was the dang $1 for me.
  • Subham kuswa
    Subham kuswa about 2 years
    Worked like charm! Thanks.