Reactを使用したRailsアプリをRspecで統合テストする方法

#はじめに
 この記事では, Reactを使用したRailsアプリでRspecの統合テストを書く方法をまとめました. 個人的にハマったポイントなどを備忘録的にまとめています. 

```
【動作環境】
Rails 6.1.4
RSpec 3.10
```

#1. Capybaraを使用する
まずCapybaraというgemをインストールします. 
これによりユーザーがブラウザで行うような操作をCapybaraのメソッドで実行することができます. 統合テストで重宝するgemです.

```ruby:spec/features/signup.rb
gem 'capybara', '>= 2.15'
```


早速, featureというフォルダの中に統合テストファイルを作成し, 
topページに行ってアカウント登録ボタンを押す操作を書きます
以下のvisitやclick_buttonなどがCapybaraのメソッドになります.

```ruby:spec/features/signup.rb
require 'rails_helper'

feature "Signup" do
  example "新規登録後にユーザーページが表示される" do
    visit "/"
    click_button "新規アカウント登録"
  end
end
```



統合テストデビューに歓喜し意気揚々とでbundle exec specを実行すると以下のエラーが.


```
Failures:

  1) Signup 新規登録後にユーザーページが表示される
     Failure/Error: click_button("新規アカウント登録")
     
     Capybara::ElementNotFound:
       Unable to find button "新規アカウント登録" that is not disabled
     # ./spec/features/user_spec.rb:6:in `block (2 levels) in <top (required)>'

```

指定された"新規アカウント登録"なんてbuttonタグないけど？と怒られています.
いやあるでしょ？ こっちはchromeの検証機能使ってあるのを確認してるんですが？

いろいろ調べたところ, 純粋なRailsアプリであればこれで動くようですが, 今回はReactを導入したことが原因で動きません.


#2. :js => true　が必要
解決するには, 以下のように「:js => true」を追記してやります.
これを書かないとjsファイルが読み込まれず, Reactのコンポーネントが描画されないようです.

```diff_ruby:spec/features/signup.rb
require 'rails_helper'

+ feature "Signup", :js => true do
- feature "Signup" do
  example "新規登録後にユーザーページが表示される" do
    visit "/"
    click_button "新規アカウント登録"
  end
end
```

これでreactのcomponentも描画されるようになりました.

#3. selenium-webdriver が必要
もう一度, ターミナルでbundle exec specを実行してみると今度は以下のエラーが出ます.

```
Failures:

  1) Signup 新規登録後にユーザーページが表示される
     Failure/Error: visit "/"
     
     LoadError:
       Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler.
```

「Capybaraのselenium driverは`selenium-webdriver`を読み込めないので, gem 'selenium-webdriver'をインストールしてください」と教えてくれています.
その通りにgemを追加しbundle installします.


```diff_ruby:Gemfile
group :test do
  gem 'capybara', '>= 2.15'
+ gem 'selenium-webdriver'
  gem 'rspec-rails'
  gem "factory_bot_rails"
  gem 'faker'
end
```

#4. Firefoxをダウンロード
3度目の正直で, ターミナルでbundle exec specを実行するとFirefoxがないと怒られました. seleniumがデフォルトでFirefoxを使用するのでダウンロードしておきましょう. 


```
Failures:

  1) Signup 新規登録後にユーザーページが表示される
     Failure/Error: visit "/"
     
     Selenium::WebDriver::Error::WebDriverError:
       Could not find Firefox binary (os=macosx). Make sure Firefox is installed or set the path manually with Selenium::WebDriver::Firefox::Binary.path=

```

言われた通りにFirefoxをダウンロードします.

```bash
$ brew  install --appdir="/Applications" firefox
```

もう一度, ターミナルでbundle exec specを叩きますが, 以下のエラー.

```
Failures:

  1) Signup 新規登録後にユーザーページが表示される
     Failure/Error: visit "/"
     
     Selenium::WebDriver::Error::WebDriverError:
       Unable to find Mozilla geckodriver. Please download the server from
       https://github.com/mozilla/geckodriver/releases and place it somewhere on your PATH.
       More info at https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/WebDriver.

```

以下で解決します.

```bash
$ brew install geckodriver
```


以上で　テストが通るようになりました. これで, bundle exec rspecを叩くとfirefoxが起動して実際にブラウザの操作をしてくれます.お疲れ様でした. 


#5. 新規登録Formに値を入力し, 登録ボタンを押すまで
あとは以下のようにCapybaraを使って統合テストを書いていくだけです. 
ここでは新規登録Formに値を入力し登録ボタンを押しています. 
なお, 今回はReactによってSPA化しているため正しいページにリダイレクトされているか確認するコードは含まれていません.

```ruby:spec/features/signup.rb
require 'rails_helper'

feature "Signup" , :js => true do
  example "新規登録後にユーザーページが表示される" do
    visit "/"
    click_button("新規アカウント登録")
    fill_in 'user_name', with:'test_user'
    fill_in 'email', with:'hogehoge@hoge.com'
    fill_in 'password', with:'password'
    fill_in 'password_confirm', with:'password'
    click_button("登録")
  end
end

```


#最後に
私は原因がわからず解決に2時間ほどハマってしまいました. この記事によって少しでも救われる人がいれば幸いです.