web-dev-qa-db-ja.com

jestを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 を使用してこのコンポーネントをテストします。 _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:予期しないトークン違法

Jestがテストを実行する前に、webpackはrequire('./MyComponent.less')を処理する必要があるようです。

jest-webpack のようなものを使用する必要があるのだろうか。はいの場合、複数のscriptPreprocessorsを指定する方法はありますか? (私はすでに_babel-jest_を使用していることに注意してください)

49
Misha Moroshko

必要なモジュールを無視するために見つけた最もクリーンなソリューションは、 moduleNameMapper config を使用することです(最新バージョン0.9.2で動作します)

ドキュメントを理解するのは困難です。以下が役立つことを願っています。

Packages.json構成にmoduleNameMapperキーを追加します。アイテムのキーは、必要な文字列の正規表現である必要があります。 「.less」ファイルの例:

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

EmptyModule.jsをルートフォルダーに追加します。

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

ModuleNameMapperはこのモジュールのエイリアスとしてEmptyModuleを使用するため、コメントは重要です( providesModuleの詳細 )。

正規表現に一致する必要な参照はそれぞれ空の文字列に置き換えられます。

「js」ファイルでmoduleFileExtensions構成を使用する場合は、「unmockedModulePathPatterns」にEmptyModuleも追加してください。

これが私が結んだjest構成です:

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

私は次のハックになりました:

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

しかし、私はまだこの問題の正しい解決策は何だろうと思っています。

19
Misha Moroshko

JestのmoduleNameMapper構成を使用すると、さらに簡単になることがわかりました。

// package.json

"jest": {
    "moduleNameMapper": {
      "^.+\\.scss$": "<rootDir>/scripts/mocks/style-mock.js"
    }
}

// style-mock.js

module.exports = {};

詳細については、Jestの チュートリアルページ を参照してください。

9
Tien Do

私は最近 Jestpack をリリースしました。最初にWebpackを使用してテストファイルをビルドするため、カスタムモジュールの解決/ローダー/プラグインなどが機能するだけで、JavaScriptになります。次に、Webpackモジュールランタイムを理解するJestのカスタムモジュールローダーを提供します。

4
riscarrott

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

上記のスニペットはすべての.lessファイルを新しい依存関係に追加identity-obj-proxyは、呼び出されたときにクラス名を含む文字列を返します。 'styleName' ために styles.styleName

3
tbraun

ハッカーの少ない解決策は、プリプロセッサをjavascriptファイルに一致するファイル名を条件にラップすることだと思います。

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

これは、require行で明示的に拡張子を設定せず、ソースで正規表現の置換を必要としない場合でも機能します。

2
Krustal

私はそのようなパターンで同様の問題を経験しました

_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を実行するには、2つの問題があります。

  • _.css_のインポート
  • デコレータを適用する_@withStyles_(TypeError: <...> (0 , _appDecoratorsWithStyles2.default)(...) is not a function

最初の1つは、スクリプトプリプロセッサで_.css_自体をモックすることで解決されました。

2番目のは、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プリプロセッサを使用する場合は、キャッシュを消去する必要があります。

_$ rm node_modules/jest-cli/.haste_cache -r
_
1
x'ES

CSSファイルにも同様の問題がありました。前述したように、 jest-webpack はこの問題を解決します。モックやモジュールマッパーを使用する必要もありません。私たちにとっては、npm testコマンドをjestからjest-webpackに置き換えたところ、うまくいきました。

0
Joseph Fehrman

Babelを使用している場合は、 https://github.com/Shyp/babel-plugin-import-noop のようなものを使用してbabel変換中に不要なインポートを削除し、.babelrctestプラグインを使用するenv。

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

Webpackは優れたツールですが、Jest単体テストでその動作をテストする必要はありません。単体テストを実行する前にwebpackビルドを追加しても、プロセスは遅くなります。 教科書の答えは、"moduleNameMapper"オプション

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

0
Samjones

Mishaの対応からインスピレーションを得て、私はこの問題を解決するNPMパッケージを作成し、同時に出会ったいくつかのシナリオも処理しました。

webpack-babel-jest

これが次の人を数時間節約できることを願っています。

0
Carlos Atencio