前置き
現在開発中の highlite では今までほぼRails + jQueryだけでゴリゴリとajax処理を書いていたんですが、何かとキツイ側面があります。
とは言え生のjsを書きまくるにしてもテストの仕方も分からないしRailsユーザとしては何か乗っかれる肩が欲しい!というわけでReact + jestに行き着いた感じです。
他のフレームワーク的なモノは少しずつ書き換えていくには重そうだし、reactがアツい!と言う話を聞いていたので試しに導入した所、非常にメリットを感じています。
TDD出来るし最高!と思ったら
発生した問題
ReactComponent内で $.ajax
とかする時に、jquery-rails
から読み出された $
を使いたいのでComponent内ではimport $ from 'jquery'
したくないが、jestでテスト実行時に ReferenceError: $ is not defined
として怒られてしまいます。
サンプル
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に追加しないと怒られますが)
サンプル
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は日本語での関連情報がまだ少なそうなので、こう言う比較的ニッチっぽいネタでも書いたほうが良いかもなーと思ったので書いてみました。