How to use jokes with webpack?

I use webpack to develop the React component. Here is its simple version:

'use strict'; require('./MyComponent.less'); var React = require('react'); var MyComponent = React.createClass({ render() { return ( <div className="my-component"> Hello World </div> ); } }); module.exports = MyComponent; 

Now I would like to test this component using jest . Here is the corresponding bit from my package.json :

 "scripts": { "test": "jest" }, "jest": { "rootDir": ".", "testDirectoryName": "tests", "scriptPreprocessor": "<rootDir>/node_modules/babel-jest", "unmockedModulePathPatterns": [ "react" ] } 

When running npm test I get the following error:

SyntaxError: /Users/mishamoroshko/react-component/src/tests/MyComponent.js: /Users/mishamoroshko/react-component/src/MyComponent.js: / Users / mishamoroshko / react-component / src / MyComponent. less: Unexpected ILLEGAL token

It looks like the web package should handle require('./MyComponent.less') before jest can run the test.

I wonder if I need to use something like jest-webpack . If so, is there a way to specify multiple scriptPreprocessor s? (note that I'm already using babel-jest )

+42
reactjs webpack jestjs
Mar 05 '15 at 4:54
source share
10 answers

I ended up with the following hack:

 // package.json "jest": { "scriptPreprocessor": "<rootDir>/jest-script-preprocessor", ... } // jest-script-preprocessor.js var babelJest = require("babel-jest"); module.exports = { process: function(src, filename) { return babelJest.process(src, filename) .replace(/^require.*\.less.*;$/gm, ''); } }; 

But I'm still wondering what the correct solution to this problem is.

+19
Mar 05 '15 at 9:22
source share

The cleanest solution I found to ignore the required module is to use moduleNameMapper config (works with the latest version 0.9.2)

The documentation is hard to follow. I hope the following helps.

Add the moduleNameMapper key to the packages.json configuration. The key for the item must be a regular expression of the desired string. Example with ".less" files:

 "moduleNameMapper": { "^.*[.](less|LESS)$": "EmptyModule" }, 

Add EmptyModule.js to the root folder:

 /** * @providesModule EmptyModule */ module.exports = ''; 

The comment is important because moduleNameMapper uses the EmptyModule as an alias for this module ( more about providing a Module).

Now each of them requires a link that matches the regular expression will be replaced with an empty string.

If you are using the moduleFileExtensions configuration with the "js" file, be sure to also add the EmptyModule to your "unmockedModulePathPatterns".

Here is the jest configuration I ended up with:

 "jest": { "scriptPreprocessor": "<rootDir>/node_modules/babel-jest", "moduleFileExtensions": ["js", "json","jsx" ], "moduleNameMapper": { "^.*[.](jpg|JPG|gif|GIF|png|PNG|less|LESS|css|CSS)$": "EmptyModule" }, "preprocessorIgnorePatterns": [ "/node_modules/" ], "unmockedModulePathPatterns": [ "<rootDir>/node_modules/react", "<rootDir>/node_modules/react-dom", "<rootDir>/node_modules/react-addons-test-utils", "<rootDir>/EmptyModule.js" ] } 
+18
Mar 21 '16 at 17:22
source share

I just found that it is even easier with the Jest moduleNameMapper configuration.

 // package.json "jest": { "moduleNameMapper": { "^.+\\.scss$": "<rootDir>/scripts/mocks/style-mock.js" } } // style-mock.js module.exports = {}; 

Read more on the Jest page.

+5
Nov 08 '16 at 2:56
source share

I recently posted a Jestpack that might help. First it creates your test files using Webpack, so any user permission / module loaders / plugins, etc. Just work and you get javascript. It then provides a custom module loader for Jest, which understands the runtime of a Webpack module.

+4
Oct 18 '15 at 20:00
source share

I think a less hacky solution would be to turn your preprocessor into a conditional file name corresponding to a javascript file:

 if (filename.match(/\.jsx?$/)) { return babelJest.process(src, filename); } else { return ''; } 

This works even if you do not explicitly install the extension in the require line and do not need to substitute regular expressions in the source.

+2
Oct 17 '15 at 19:27
source share

I had a similar problem with such a template

 import React, { PropTypes, Component } from 'react'; import styles from './ContactPage.css'; import withStyles from '../../decorators/withStyles'; @withStyles(styles) class ContactPage extends Component { 

see example https://github.com/kriasoft/react-starter-kit/blob/9204f2661ebee15dcb0b2feed4ae1d2137a8d213/src/components/ContactPage/ContactPage.js#L4-L7

To run Jest, I have 2 problems:

  • import .css
  • Using the decorator @withStyles ( TypeError: <...> (0 , _appDecoratorsWithStyles2.default)(...) is not a function )

The first was resolved by mocking .css in a script preprocessor.

The second was resolved by excluding decorators from auto-tracking using unmockedModulePathPatterns

 module.exports = { process: function (src, filename) { ... if (filename.match(/\.css$/)) src = ''; ... babel.transform(src, ... } } 

based on https://github.com/babel/babel-jest/blob/77a24a71ae2291af64f51a237b2a9146fa38b136/index.js

Please note: when working with the jest preprocessor, you must clear the cache:

 $ rm node_modules/jest-cli/.haste_cache -r 
+1
Nov 08 '15 at 0:04
source share

Inspiring Misha's answer, I created an NPM package that solves this problem and also handles a few more scripts that I came across:

webpack-babel-jest

Hope this can save the next person in a few hours.

0
Jul 10 '15 at 21:24
source share

If you use babel, you can remove the unwanted import during the babel conversion, using something like https://github.com/Shyp/babel-plugin-import-noop and configure .babelrc test env to use the plugin, for example:

 { "env": { "development": { ... }, "test": { "presets": [ ... ], "plugins": [ ["import-noop", { "extensions": ["scss", "css"] }] ] } } } 
0
Nov 10 '16 at 19:09
source share

Webpack is a great tool, but I don’t need to test its behavior with Jest unit tests, and adding a webpack assembly before running unit tests only slows down the process. The textbook answer is to make fun of non-code dependencies using the "moduleNameMapper" option

https://facebook.imtqy.com/jest/docs/webpack.html#handling-static-assets

0
Apr 27 '17 at 18:39
source share

From Jest docs :

 // in terminal, add new dependency: identity-obj-proxy npm install --save-dev identity-obj-proxy // package.json (for CSS Modules) { "jest": { "moduleNameMapper": { "\\.(css|less)$": "identity-obj-proxy" } } } 

The above snippet redirects all .less files to the new identity-obj-proxy dependency, which will return a string with the class name when called, for example. 'styleName' for styles.styleName .

0
Aug 29 '17 at 21:19
source share



All Articles