如何使用webpack的笑话?

我使用webpack来开发一个React组件。 这是一个简单的版本:

'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; 

现在,我想用jest来testing这个组件。 这里是我的package.json的相关位:

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

运行npm test ,出现以下错误:

SyntaxError:/Users/mishamoroshko/react-component/src/tests/MyComponent.js:/Users/mishamoroshko/react-component/src/MyComponent.js:/Users/mishamoroshko/react-component/src/MyComponent.less:Unexpected令牌非法

看起来webpack需要先处理require('./MyComponent.less')然后才能运行testing。

我想知道是否需要使用像jest-webpack这样的东西 。 如果是的话,有没有办法指定多个scriptPreprocessor ? (注意我已经使用了babel-jest

我结束了以下黑客:

 // 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, ''); } }; 

但是,我仍然想知道什么是正确的解决scheme。

我发现忽略所需模块的最干净的解决scheme是使用moduleNameMapperconfiguration (工作在最新版本0.9.2)

文档很难遵循。 我希望以下将有所帮助。

将moduleNameMapper键添加到你的packages.jsonconfiguration中。 项目的关键字应该是所需string的正则expression式。 “.less”文件示例:

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

将EmptyModule.js添加到根文件夹中:

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

这个注释很重要,因为moduleNameMapper使用EmptyModule作为这个模块的别名( 阅读更多有关providesModule的内容 )。

现在每个需要引用的匹配正则expression式将被replace为一个空string。

如果您使用带有“js”文件的moduleFileExtensionsconfiguration,那么请确保您还将EmptyModule添加到“unmockedModulePathPatterns”中。

这里是我结束了的笑话configuration:

 "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" ] } 

我最近发布了可能有帮助的Jestpack 。 它首先用Webpack构build你的testing文件,所以任何自定义的模块parsing/加载器/插件等都可以正常工作,并最终得到JavaScript。 然后为Jest提供一个定制的模块加载器,它可以理解Webpack模块的运行时间。

我发现使用Jest的moduleNameMapperconfiguration更简单。

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

我认为一个不太冒险的解决scheme是将你的预处理器封装在一个与JavaScript文件相匹配的文件名中:

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

即使您没有在require行中明确设置扩展名,并且不需要源代码中的正则expression式replace,也可以工作。

我遇到过类似的问题

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

请参阅https://github.com/kriasoft/react-starter-kit/blob/9204f2661ebee15dcb0b2feed4ae1d2137a8d213/src/components/ContactPage/ContactPage.js#L4-L7上的示例;

对于运行Jest我有两个问题:

  • 导入.css
  • 应用装饰@withStylesTypeError: <...> (0 , _appDecoratorsWithStyles2.default)(...) is not a function

第一个是通过在脚本预处理器中嘲笑.css本身来解决的。

第二个解决方法是使用unmockedModulePathPatterns将装饰器从automocking中unmockedModulePathPatterns

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

基于https://github.com/babel/babel-jest/blob/77a24a71ae2291af64f51a237b2a9146fa38b136/index.js的示例;

还要注意:当你使用jest预处理器的时候,你应该清理caching:

 $ rm node_modules/jest-cli/.haste_cache -r 

从Misha的回应中获得灵感,我创build了一个NPM包,解决了这个问题,同时处理了我遇到的几个场景:

的WebPack -巴贝尔,笑话

希望这可以节省下一个人几个小时。

如果你使用的是babel,你可以在babel转换过程中使用类似https://github.com/Shyp/babel-plugin-import-noop的方式;.babelrc不需要的input,并configuration你的.babelrc test来使用插件。 :

 { "env": { "development": { ... }, "test": { "presets": [ ... ], "plugins": [ ["import-noop", { "extensions": ["scss", "css"] }] ] } } } 

Webpack是一个很好的工具,但是我不需要用我的Jestunit testing来testing它的行为,并且在运行unit testing之前添加一个webpack构build只会减慢这个过程。 教科书的答案是使用"moduleNameMapper"选项来模拟非代码依赖关系

https://facebook.github.io/jest/docs/webpack.html#handling-static-assets

来自Jest文档 :

 // 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" } } } 

上面的代码片段将所有.less文件路由到新的依赖关系identity-obj-proxy ,这将在调用时返回一个带有类名的string,例如styles.styleName 'styleName'