Posted at

React + jestでテスト実行時にだけjQueryを読み込む(jquery-rails向け)

More than 3 years have passed since last update.


前置き

現在開発中の highlite では今までほぼRails + jQueryだけでゴリゴリとajax処理を書いていたんですが、何かとキツイ側面があります。

とは言え生のjsを書きまくるにしてもテストの仕方も分からないしRailsユーザとしては何か乗っかれる肩が欲しい!というわけでReact + jestに行き着いた感じです。

他のフレームワーク的なモノは少しずつ書き換えていくには重そうだし、reactがアツい!と言う話を聞いていたので試しに導入した所、非常にメリットを感じています。

TDD出来るし最高!と思ったら


発生した問題

ReactComponent内で $.ajax とかする時に、jquery-rails から読み出された $ を使いたいのでComponent内ではimport $ from 'jquery' したくないが、jestでテスト実行時に ReferenceError: $ is not defined として怒られてしまいます。

サンプル


reaction_list.jsx

import React from 'react';

// import $ from 'jquery'
// Component内で呼び出してしまうと、jquery-railsの恩恵(ajaxでPOSTする時に
// csrf-token回りを適宜やってくれるとか)が受けられなくなるので使いたくない

var ReactionList = React.createClass({

loadReactionsFromSever: function(){
$.ajax({
    //...諸々
});
module.exports = ReactionList;


Component内で$をimportしてない状態で jest すると…

● ReactionList Component › it is React element

- ReferenceError: $ is not defined
at loadReactionsFromSever (app/assets/javascripts/components/reaction/reaction_list.jsx:8:7)
at componentDidMount (app/assets/javascripts/components/reaction/reaction_list.jsx:24:10)
at CallbackQueue.assign.notifyAll (node_modules/react/lib/CallbackQueue.js:65:22)

こんな感じに怒られます。

が、実際のrails環境では browserify されているため、ちゃんと $ は存在するので動いています。(というのが前提なので、jquery-railsを使わない場合などはimportしたら良いと思います)


解決策

ここでタイトルの React + jestでテスト実行時にだけjQueryを読み込む、ですが、散々悩んだ割には1行で解決しました。

global.$ = require('jquery');

こいつをテストファイルで読み込んでやればOKです。(多分devDependenciesに追加しないと怒られますが)

サンプル


reaction_list_spec.js

import React from 'react';

import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
global.$ = require('jquery');

jest.dontMock('../../reaction/reaction_list.jsx');
const ReactionList = require('../../reaction/reaction_list.jsx');

describe('ReactionList Component', () => {
//てすと
)};


これでテスト実行時には$が定義され(node_modulesから読み込まれ)、rails環境ではjquery-rails$が利用可能になります。

reactは日本語での関連情報がまだ少なそうなので、こう言う比較的ニッチっぽいネタでも書いたほうが良いかもなーと思ったので書いてみました。