Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest cannot locate @babel/code-frame when trying to use @ alias

Our app imports files using import ES2015 style syntax, utilizing Webpack 4.6.0 native support for ES2015 modules. We also use an alias to shorten our relative file paths.

Webpack.conf.js

resolve: {
        extensions: ['.js', '.json', '.less'],
        alias: {
            '@': resolve('public/js'),
            'handlebars': 'handlebars/dist/handlebars.js',
        },
        modules: ['less', 'node_modules']
    },

example.js

import widget from '@/widgets/widget';

file structure

- webpack.conf.js
- .babelrc
- test/
- public/
- - js/
- - - widgets/
- - - - widget.js

When I imported for example example.js, which has an alias'd import, Jest would throw an error, "cannot resolve module '@/widgets/widget'.

According to a remarkably specific article as well as the Jest documentation, the solution is to use Jest's ModuleNameMapper config property to set up matching alias'. I have attempted to do so:

package.json

  "jest": {
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
      "@(.*)$": "<rootDir>/public/js/$1"
    },
    "verbose": true,
    "transform": {
      "^.+\\.js$": "babel-jest"
    },
    "globals": {
      "NODE_ENV": "test"
    },
    "moduleFileExtensions": [
      "js"
    ],
    "moduleDirectories": [
      "node_modules"
    ]
  },

As well as properly configure babel:

.babelrc

{
    "presets": [
        [
            "env",
            {
                "modules": false,
                "test": {
                    "plugins": ["transform-es2015-modules-commonjs"]
                }
            }
        ],
        "es2015",
        "stage-2"
    ],
    "plugins": [
        "syntax-dynamic-import"
    ]
}

Now, when I run Jest (with the --no-cache flag just in case), I get this error:

test/test.test.js
  ● Test suite failed to run

    Configuration error:

    Could not locate module @babel/code-frame (mapped as /home/calebjay/Documents/ide/public/js/babel/code-frame)

    Please check:

    "moduleNameMapper": {
      "/@(.*)$/": "/home/calebjay/Documents/ide/public/js/$1"
    },
    "resolver": undefined

I can't find @babel/code-frame anywhere outside of package-lock.json, and just for giggles I stripped all mentions of @{{anything}} from there and ran tests again, same result.

Is jest stepping over babel somehow? How can I get my tests to run with Jest using aliases?

EDIT: To try to narrow down what is calling @babel/code-frame, I tried deleting es2015 and stage-2 from .babelrc, to no effect. I tried deleting the transform property of the Jest config in package.json, to no effect. I tried deleting the env.test.plugins property from .babelrc, to no effect. Same error.

EDIT2: Thinking maybe some other package is requiring it, I checked package.json. It seems jest-message-util requires @babel/code-frame. I do see @babel/code-frame in my node_modules though... so perhaps the problem is that jester is saying "ok, all instances of @, turn into public/js" ?

like image 205
Caleb Jay Avatar asked Jun 07 '18 18:06

Caleb Jay


1 Answers

"@(.*)$": "<rootDir>/public/js/$1"

will convert @babel/code-frame to

"<rootDir>/public/js/babel/code-frame"

which doesn't exist. You need to make your pattern more specific and do

"@/(.*)$": "<rootDir>/public/js/$1"

Note the additional / at the beginning. That way it will still match your @/widgets/widget, but it won't match other scoped packages.

like image 162
loganfsmyth Avatar answered Nov 10 '22 02:11

loganfsmyth