68

I am trying to get my first Jest Test to pass with React and Babel.

I am getting the following error:

SyntaxError: /Users/manueldupont/test/avid-sibelius-publishing-viewer/src/components/TransportButton/TransportButton.less: Unexpected token

    >  7 | @import '../variables.css';
          | ^

My package.json config for jest look like this:

"babel": {
    "presets": [
      "es2015",
      "react"
    ],
    "plugins": [
      "syntax-class-properties",
      "transform-class-properties"
    ]
  },
  "jest": {
    "moduleNameMapper": {
      "^image![a-zA-Z0-9$_-]+$": "GlobalImageStub",
      "^[./a-zA-Z0-9$_-]+\\.png$": "RelativeImageStub"
    },
    "testPathIgnorePatterns": [
      "/node_modules/"
    ],
    "collectCoverage": true,
    "verbose": true,
    "modulePathIgnorePatterns": [
      "rpmbuild"
    ],
    "unmockedModulePathPatterns": [
      "<rootDir>/node_modules/react/",
      "<rootDir>/node_modules/react-dom/",
      "<rootDir>/node_modules/react-addons-test-utils/",
      "<rootDir>/node_modules/fbjs",
      "<rootDir>/node_modules/core-js"
    ]
  },

So what am I missing?

Rick Hanlon II
  • 16,833
  • 7
  • 42
  • 52
Mano Dupont
  • 681
  • 1
  • 5
  • 7

7 Answers7

82

moduleNameMapper is the setting that tells Jest how to interpret files with different extension. You need to tell it how to handle Less files.

Create a file like this in your project (you can use a different name or path if you’d like):

config/CSSStub.js

module.exports = {};

This stub is the module we will tell Jest to use instead of CSS or Less files. Then change moduleNameMapper setting and add this line to its object to use it:

'^.+\\.(css|less)$': '<rootDir>/config/CSSStub.js'

Now Jest will treat any CSS or Less file as a module exporting an empty object. You can do something else too—for example, if you use CSS Modules, you can use a Proxy so every import returns the imported property name.

Read more in this guide.

Rich Warrior
  • 1,310
  • 6
  • 17
Dan Abramov
  • 241,321
  • 75
  • 389
  • 492
  • 4
    I am using Jest v19+ and have the following key value pair in `moduleNameMappers`: `"\\.(css|sass)$": "identity-obj-proxy"`, but, I have some `.sass` files which use the `@import` keyword that makes the transformAndBuildScript function throw. Is there any way to fix this? – JaKXz Apr 18 '17 at 22:29
  • 1
    In fact, even with a `sassMock.js` file that just exports an empty object for all `\\.sass$` files, I'm seeing the same error. – JaKXz Apr 18 '17 at 23:03
  • 4
    Using `"\\.(css|less)$": "identity-obj-proxy"` worked for me – nbkhope Aug 16 '17 at 17:04
  • 1
    @JaKXz how did you solve that problem? I am getting the same problem, I am using css-modules to import css files. You can find more details about the question at: https://stackoverflow.com/questions/48286678/css-module-import-fails-the-jest-test-suit?noredirect=1#comment83558957_48286678 – Bharat Soni Jan 16 '18 at 18:01
  • I only had *.scss before, adding *.css also fixed my issues. Thanks. – ATOzTOA Sep 19 '18 at 16:06
  • I found this very helpful: https://stackoverflow.com/questions/54627028/jest-unexpected-token-when-importing-css#comment113260726_54646930 – Ryan Sep 24 '20 at 15:25
48

I solved this by using the moduleNameMapper key in the jest configurations in the package.json file

{
   "jest":{
        "moduleNameMapper":{
             "\\.(css|less|sass|scss)$": "<rootDir>/__mocks__/styleMock.js",
             "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
        }
   }
}

After this you will need to create the two files as described below

  • __mocks__/styleMock.js

    module.exports = {};

  • __mocks__/fileMock.js

    module.exports = 'test-file-stub';

If you are using CSS Modules then it's better to mock a proxy to enable className lookups. hence your configurations will change to:

{
  "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|scss|sass)$": "identity-obj-proxy"
    },
  }
}

But you will need to install identity-obj-proxy package as a dev dependancy i.e.

yarn add identity-obj-proxy -D

For more information. You can refer to the jest docs

Community
  • 1
  • 1
Jjagwe Dennis
  • 1,032
  • 6
  • 9
  • 2
    For anyone who arrives here from create-react-app, `moduleNameMapper` is not a supported override. The version is 1.1.4 at the point of the comment. – Prabu Jun 07 '18 at 14:16
  • I don't use CRA and none of these solutions works. I'm so frustrated :( – Rodrigo Manguinho May 09 '20 at 02:59
  • as identity-obj-proxy is old, not sure it should be used or not, but using the stub definitely worked with my webpack react jest project – Vipul Dessai Dec 20 '20 at 10:51
19

UPDATE who use create-react-app from feb 2018. You cannot override the moduleNameMapper in package.json but in jest.config.js it works, unfortunately i havent found any docs about this why it does. So my jest.config.js look like this:

module.exports = {
...,
  "moduleNameMapper": {
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
    "\\.(scss|sass|css)$": "identity-obj-proxy"
  }
}

and it skips scss files and @import quite well.

Backing my answer i followed jest webpack

Alexey Nikonov
  • 2,164
  • 1
  • 19
  • 33
8

Similar situation, installing identity-object-proxy and adding it to my jest config for CSS is what worked for me.

//jest.config.js

module.exports = {
  moduleNameMapper: {
    "\\.(css|sass)$": "identity-obj-proxy",
  },
};

The specific error I was seeing:

Jest encountered an unexpected token

/Users/foo/projects/crepl/components/atoms/button/styles.css:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.button { }
                                                                                         ^

SyntaxError: Unexpected token .

  1 | import React from 'react';
> 2 | import styles from './styles.css';
Jadam
  • 991
  • 1
  • 13
  • 30
3

If you're using ts-jest, none of the solutions above will work! You'll need to mock transform.

jest.config.js

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  roots: [
    "<rootDir>/src"
  ],
  transform: {
    ".(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/jest-config/file-mock.js",
    '.(css|less)$': '<rootDir>/jest-config/style-mock.js'
  },
};

file-mock.js

module.exports = {
  process() {
    return `module.exports = 'test-file-stub'`;
  },
};

style-mock.js

module.exports = {
    process() {
      return 'module.exports = {};';
    }
  };

I found this working example

Melchia
  • 16,699
  • 16
  • 70
  • 93
  • Also make sure that you have a types.d.ts file with `declare module '*.scss';` or similar if you still get the Cannot Find Module error. – Cyral Mar 25 '21 at 19:46
1

Solution of @import Unexpected token=:)

Install package:

npm i --save-dev identity-obj-proxy

Add in jest.config.js

module.exports = {
  "moduleNameMapper": {
    "\\.(css|less|scss)$": "identity-obj-proxy"
  }
}
0

I added moduleNameMapper at the bottom of my package.json where I configured my jest just like this:

"jest": {
    "verbose": true,
    "moduleNameMapper": {
        "\\.(scss|less)$": "<rootDir>/config/CSSStub.js"
    }
}
aqteifan
  • 310
  • 2
  • 13