Jest: /scss/ in preprocessorIgnorePatterns has no effect

Created on 7 Apr 2016  路  16Comments  路  Source: facebook/jest

We're using CSS modules in our React components, which are importing .scss files, like this:

import styles from './ReviewFeedItem.scss';

To ignore them when running jest, I've excluded /scss/ from the module loader (or so I think):

// package.json

"preprocessorIgnorePatterns": [
  "/scss/"
],

However, when running the tests, the module loader still tries (and fails) to parse the .scss file as javascript and yields this error:

Runtime Error
SyntaxError: Unexpected token ILLEGAL in file 'src/components/navigation/Navigation.scss'.

Make sure your preprocessor is set up correctly and ensure your 'preprocessorIgnorePatterns' configuration is correct: http://facebook.github.io/jest/docs/api.html#config-preprocessorignorepatterns-array-string
If you are currently setting up Jest or modifying your preprocessor, try `jest --no-cache`.
Preprocessor: jest-preprocessor.js.
Jest tried to the execute the following preprocessed code:
body { height: 0; }

Any variation of the exclude Pattern, such as \\.scss, scss and so forth has no effect.
We're using babel-jest as the scriptPreprocessor (so no specific entry for that in package.json)

Most helpful comment

This doesn't work because ignoring scss from the preprocessor just means that it will not be run through babel-jest. Jest will then try to require the scss file directly and then fail because it isn't valid JavaScript.

There are two solutions:

Use the moduleNameMapper option and a stub file:

Jest config:

"moduleNameMapper": {
  "\.scss$": "path/to/SCSSStub.js"
}

SCSSStub.js:

module.exports = {}; // Or other stub data for all SCSS modules.

Build your own preprocessor using node-sass.

I'm not entirely sure what webpack does to export scss files as JavaScript, but basically you'll want to wrap babel-jest and do something like this:

module.exports = function(src, filename) {
  if (fileName.endsWith('.scss')) {
    return processSass(src);
  }
  return babelJest.process(src, filename);
}

where the processSass would use node-sass and whatever the webpack loaders do :)

I hope one of these is a satisfying solution. If you do build a preprocessor that wraps babel-jest, I'd be happy to add it to Jest as an officially supported package.

All 16 comments

Any updates on this?

This doesn't work because ignoring scss from the preprocessor just means that it will not be run through babel-jest. Jest will then try to require the scss file directly and then fail because it isn't valid JavaScript.

There are two solutions:

Use the moduleNameMapper option and a stub file:

Jest config:

"moduleNameMapper": {
  "\.scss$": "path/to/SCSSStub.js"
}

SCSSStub.js:

module.exports = {}; // Or other stub data for all SCSS modules.

Build your own preprocessor using node-sass.

I'm not entirely sure what webpack does to export scss files as JavaScript, but basically you'll want to wrap babel-jest and do something like this:

module.exports = function(src, filename) {
  if (fileName.endsWith('.scss')) {
    return processSass(src);
  }
  return babelJest.process(src, filename);
}

where the processSass would use node-sass and whatever the webpack loaders do :)

I hope one of these is a satisfying solution. If you do build a preprocessor that wraps babel-jest, I'd be happy to add it to Jest as an officially supported package.

The moduleNameMapper solution worked great for me. Here's what I used (took me a while to figure out the magic that would make all imports for SCSS files load the same stub):

    "moduleNameMapper": {
      "^.*\\.scss$": "./src/shared/test/SCSSStub.js"
    }

Now requiring SCSS in Jest works exactly like requiring CSS.

that's great!

preprocessorIgnorePatterns does not need slashes around the entries. It should work with .scss$, although to @cpojer 's point that won't fix your problem.

I worked around that by having my preprocessor return an empty string if the filename ends in css|less|etc

@cpojer I just tried upgrading to v16.0.1 (from v14.1.0) and all our tests now fail because it complains about syntax errors related scss files. We have moduleNameMapper set up and the setup worked fine with v14.1.0. Wondering if you have any thoughts on what might be the issue?

jest setup:

"jest": {
    "moduleFileExtensions": [
      "",
      "js",
      "json"
    ],
    "modulePaths": [
      "./src"
    ],
    "moduleDirectories": [
      "node_modules"
    ],
    "testRegex": "/.*\\-snapshot\\.js$",
    "moduleNameMapper": {
      "^testUtils": "./src/utils/tests.js",
      "^.+\\.(s?css|less)$": "./src/utils/styleMock.js",
      "^.+\\.(gif|ttf|eot|svg)$": "./src/utils/fileMock.js"
    },
    "setupFiles": [
      "./src/utils/setupJest.js"
    ]
  },

styleMock.js

// Return an object to emulate css modules
import idObj from 'identity-obj-proxy';

export default idObj;

Example of an error:
screen shot 2016-10-06 at 11 37 51 am

@iam-peekay I was getting the same error due to sass imports. Following the instructions in the Jest webpack tutorial resolved the issue for me - specifically adding the moduleNameMapper for files and styles, and the mocks they reference.
I also had to add md to the mapped file extensions as I'm importing markdown content in the project.
Edit - looked at your setup and I see you have a styleMock - maybe try just using an empty object instead of the idObj.

Took me a while to get this to work for me because I thought the path was relative to the project.

Below works for me:

  "jest": {
    "modulePaths": [
      "v2/app"
    ],
    "moduleNameMapper": {
      ".scss$": "SassStub.js"  // <-- lives in v2/app
    },
    "testPathIgnorePatterns": [
      "/node_modules/",
      "/build/"
    ]
  }

__SassStub.js__

module.exports = {}

Hi guys, I'm running into this problem too. What is a SassStub.js file? What goes inside it? Can't find anything about it.

@leongaban See https://github.com/facebook/jest/issues/870#issuecomment-286575674:

SassStub.js

module.exports = {}

Just a note for future readers, the moduleNameMapper ordering is important.

I wanted to stub style imported in modules, something like:

// module.js
import Style from '@/path/to/style.scss';
import App from './App';

So I created a style stub file:

// test/unit/stubs/style.js
module.exports = '.style-stub{color:red;}';

After messing around with the following jest.conf.js:

moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1', // '@' alias
    '^.*\\.scss$': '<rootDir>/test/unit/stubs/style.js',
}

The @ alias rule was resolving before my .scss rule, so the style file was loaded as a normal module and would crash the test.

The solution was to put specific rules first.

moduleNameMapper: {
    '^.*\\.scss$': '<rootDir>/test/unit/stubs/style.js',
    '^@/(.*)$': '<rootDir>/src/$1',
}

@emileber it's generally advised to have as moduleNameMapper regexes as specific as possible, to avoid such problems and confusion to consumers.

@thymikee Regexes are a maintenance nightmare, so keeping them as simple as possible is best in my opinion.

I feel like it's much more likely that any confusion in this regard comes from the missing documentation rather than under-specific regexes.

@emileber interested in contributing to docs? 馃檪 Patterns are indeed checked one-by-one until they fit and then bailout.

Struggling to get this to work, I have:

"jest": {
  "transform": {
    "^.+\\.jsx?$": "babel-jest"
  },
  "collectCoverageFrom": [
    "src/**/*.{js,jsx}"
  ],
  "moduleNameMapper": {
    "^.*[.](jpe?g|gif|png|less|css)$": "./emptyTestModule.js"
  },
  "setupFiles": [
    "<rootDir>/setupTests.js"
  ]
}

And I'm not exactly sure where to put the emptyTestModule, I've tried both the root and src/ but I get:

 Test suite failed to run

    Configuration error:

    Could not locate module ag-grid/dist/styles/ag-grid.css (mapped as emptyTestModule.js)

    Please check:

    "moduleNameMapper": {
      "/^.*[.](jpe?g|gif|png|less|css)$/": "./emptyTestModule.js"
    },
    "resolver": undefined

Edit: I fixed this by using rootDir: "^.*[.](jpe?g|gif|png|less|css)$": "<rootDir>/emptyTestModule.js"

Was this page helpful?
0 / 5 - 0 ratings