Rspec(システムスペック)において Ajaxのテストを行う方法（Docker）

Rspecのシステムスペックを用いて、統合テストを行うことがあると思います。
その際、Ajaxのテストを行うにはChromeDriverを用いた自動ブラウザテストが必要になると思います。
ローカル環境における自動ブラウザテストを行うためのセッティングを解説した記事は多いのですが、Docker環境下での記事はあまり見当たらなかったため、ここでご紹介したいと思います。

## 環境
- MacOS
- Docker 20.10.2
- docker-compose 1.27.4
- Ruby 2.5.7
- Rails 5.2.4
- Rspec 3.10
- capybara 2.15
- ChromeDriver 88.0.4324.96
- MySQL 5.7

## 前提
- Dockerによる環境構築ができていること（<a href="https://qiita.com/Yusuke_Hoirta/items/3a50d066af3bafbb8641">環境構築の方法はこちら</a>）
- Rspecが導入済であること（つまり単体テストは可能な状態である）

## コンテナ内にChromeDriverをインストール
自動ブラウザテストを行うにはChromeDriverをコンテナ内にインストールする必要があります。

① コンテナが起動中の場合は停止してください。

② `Gemfile`の`:test`グループ内を以下のGemを追加してください。

```ruby:Gemfile
group :test do
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  gem 'rspec-rails'
end
```

③ `Dockerfile`を以下のように編集してください。（`myapp`の箇所はご自身のプロジェクト名に変えてください。）

```dockerfile:Dockerfile
FROM ruby:2.5.7

RUN apt-get update -qq && \
	apt-get install -y build-essential \
	libpq-dev \
	nodejs \
	default-mysql-client \
	vim

# ChromeDriverを追加
RUN apt-get update && apt-get install -y unzip && \
    CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` && \
    wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/ && \
    unzip ~/chromedriver_linux64.zip -d ~/ && \
    rm ~/chromedriver_linux64.zip && \
    chown root:root ~/chromedriver && \
    chmod 755 ~/chromedriver && \
    mv ~/chromedriver /usr/bin/chromedriver && \
    sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' && \
    sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' && \
    apt-get update && apt-get install -y google-chrome-stable

RUN mkdir /myapp

WORKDIR /myapp

COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock

RUN bundle install

COPY . /myapp
```

③ コンテナをビルド・起動

```
$ docker-compose build
$ docker-compose up -d
```

## 自動ブラウザテストを行うためのセッティング

① `rails_helper.rb`の最後に以下を追加

```ruby:rails_helper.rb
Capybara.register_driver :selenium_chrome_headless do |app|
  options = ::Selenium::WebDriver::Chrome::Options.new


  options.add_argument('--headless')
  options.add_argument('--no-sandbox')
  options.add_argument('--disable-dev-shm-usage')
  options.add_argument('--window-size=1400,1400')


  driver = Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end
```

② `rails_helper.rb`の`RSpec.configure do |config| ~ end`内の最後に以下を追加

```ruby:rails_helper.rb
  config.before(:each) do |example|
    if example.metadata[:type] == :system
      if example.metadata[:js]
        driven_by :selenium_chrome_headless, screen_size: [1400, 1400]
      else
        driven_by :rack_test
      end
    end
  end
```

## Ajaxの処理が発生するテストに`js: true`を記述する
以下の例のように自動ブラウザテストを行いたい箇所に`js: true`を記述します。

```ruby:spec/system/books_spec.rb
describe "書籍のテスト", type: :system do
  describe "書籍一覧画面" do
    before do
      book
      visit books_path
    end
    context "リンクの確認", js: true do
      it "削除リンクをクリックすると、対象の書籍が削除される" do
        click_link "削除", href: "/books/" + book.id
        expect(page).to have_content book.title
      end
    end
  end
end
```

## 参考サイト
https://eiji-hb.hatenablog.com/entry/2019/12/18/194357