RailsのSystemTest（headless chrome）をDocker上で動かす


以下のエラーに遭遇したときのメモ

```ruby
Selenium::WebDriver::Error::UnknownError:
 　unknown error: DevToolsActivePort file doesn't exist
  (Driver info: chromedriver=2.40.565383 (76257d1ab79276b2d53ee976b2c3e3b9f335cde7),platform=Linux 4.9.87-linuxkit-aufs x86_64)
```

# Dockerのインストール

はじめに、下記サイトからDocker for Macをインストール。

https://docs.docker.com/docker-for-mac/install/

# Docker環境構築
## Dockerfile、docker-compose.yml、Gemfile、Gemfile.lockの4つを作成
```bash:まずはディレクトリmyappを作成
mkdir myapp; cd myapp
```

```dockerfile:Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs libappindicator1 fonts-liberation libappindicator3-1 libasound2 libnspr4 libnss3 libxss1 xdg-utils
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - && apt-get install -y nodejs build-essential && npm install -g phantomjs-prebuilt
RUN npm install -g yarn
RUN rm -rf /var/lib/apt/lists/*
RUN curl -O https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN dpkg -i google-chrome-stable_current_amd64.deb

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
```

```yml:docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
  datastore:
    image: myapp_web
    volumes:
      - /bundle
```

```ruby:Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.0'
```

```bash:Gemfile.lockは以下のコマンドで作成
touch Gemfile.lock
```

####　ここまでのディレクトリ構成は以下
```bash
./myapp
├── Dockerfile
├── Gemfile
├── Gemfile.lock
└── docker-compose.yml
```

## rails プロジェクトの作成
```bash:myappディレクトリ配下で以下を実行
docker-compose run web rails new . --webpack=vue --force --database=postgresql
```

### rails newによって作成されたGemfileにrspec-railsを追加する
※　rspec-railsを `:test` のグループに追加する

```
gem 'rspec-rails'
```

### rspec-railsを追加した後、以下の2つのコマンドを実行する

```
docker-compose build
```

## DBのセットアップ
```yml:config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test
```

config/database.ymlの設定完了後、以下を実行する

```
docker-compose run web bundle exec rails db:drop db:create db:migrate
```

## Viewの準備
routesの設定

```ruby:config/routes.rb
Rails.application.routes.draw do
  root 'application#index'
end
```

viewの作成

```bash
mkdir app/views/application; echo "<%= javascript_pack_tag 'hello_vue' %>" >>  app/views/application/index.html.erb
```

## アプリケーションの起動
```
rm -rf tmp/pids/server.pid; docker-compose up
```

localhost:3000にアクセスすると、以下の画面が表示されています。
<img width="1680" alt="スクリーンショット 2018-06-09 22.27.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/60000/77d05851-89df-8525-4c74-2c0b19c1d6aa.png">


# RSpecの準備

以下のコマンドを実行する

```bash
docker-compose run web rails generate rspec:install
mkdir spec/system; touch spec/system/index_spec.rb
mkdir spec/support; touch spec/support/capybara.rb
```

### `spec/rails_helper.rb`　の以下の行をコメントアウトする

```
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
```

### Capybaraの設定

```ruby:spec/support/capybara.rb
Capybara.server = :puma, { Silent: true }

Capybara.register_driver :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')

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

Capybara.javascript_driver = :chrome_headless

# Setup rspec
RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :rack_test
  end

  config.before(:each, type: :system, js: true) do
    driven_by :chrome_headless
  end
end
```

```ruby:spec/system/index_spec.rb
require 'rails_helper'

describe "SystemTest", type: :system, js: true do
  it "hello_vue.js" do
    visit root_path

    expect(page).to have_content 'Hello Vue!'
  end
end
```

## テストを実行する
```
docker-compose run web rspec spec
```

参考URL
- https://stackoverflow.com/questions/50610316/capybara-headless-chrome-in-docker-returns-devtoolsactiveport-file-doesnt-exist
- https://github.com/GoogleChrome/puppeteer/issues/1834