[RUBY] [Circle CI 2.0] Set to support JavaScript

Introduction

** I have set up CircleCI to handle JavaScript **. It was a test of CircleCI that worked without problems until now, but since I did something, it did not pass, so I will describe the remedy.

The configuration file so far is here.

table of contents

--Environment

--Problem --Cause --Use js: true with RSpec --This time, the changes made to match the ** local environment ** and the ** CircleCI environment **

--Summary

environment

problem

SocketError: 
Failed to open TCP connection to chrome:4444 
(getaddrinfo: No address associated with hostname)
# chrome:Failed to open TCP connection to 4444
SocketError: getaddrinfo: No address associated with hostname
#There is no address associated with the host name

Cause

Use js: true in RSpec

When I implemented ** JavaScript test in RSpec **, the test that passed in the local environment did not pass in CircleCI's automatic test **. In conclusion, I think it is due to the difference between the local environment and the CircleCI environment **. I started a chrome container locally and passed through System Spec, but I got an error because the setting is also required in the CircleCI configuration file.

Changes made to match the local environment with the CircleCI environment

-** Added chrome ** in Dockerfile from chrome container -** The URL when using Chrome was specified **, so it was deleted --Added ** Chrome added ** and ** used in background ** in CircleCI config file

solution

spec/support/capybara.rb

It looks like a big change, but the point is that you didn't specify the url.

Change before


require 'capybara/rspec'
require 'selenium-webdriver'

module CapybaraSupport
  Capybara.javascript_driver = :selenium_chrome_headless
  Capybara.default_driver    = :selenium_chrome_headless
  Capybara.register_driver :selenium_chrome_headless do |app|
    url = 'http://chrome:4444/wd/hub'
    caps = ::Selenium::WebDriver::Remote::Capabilities.chrome(
      'goog:chromeOptions' => {
        'args' => [
          'no-sandbox',
          'headless',
          'disable-gpu',
          'window-size=1680,1050'
        ]
      }
    )
    Capybara::Selenium::Driver.new(app, browser: :chrome, url: url, desired_capabilities: caps)
  end

After change


require 'capybara/rspec'
require 'selenium-webdriver'

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

Capybara.javascript_driver = :selenium_chrome_headless

spec/rails_helper.rb

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 :selenium_chrome_headless
  end
end

Dockerfile ** I want to use Chrome for testing my local environment **, so I'm doing ** Add Chrome ** with Dockerfile. I wrote this description before RUN mkdir/myapp.

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

#Create a working directory with the name myapp directly under the root (application directory in the container)
RUN mkdir /myapp
WORKDIR /myapp

.circleci/config.yml

CircleCI configuration file. ** Added Chrome ** to eliminate the ** difference from the local environment **.

    steps:
      - run:
          name: Chrome Driver Install
          command: |
            curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
            echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
            sudo apt-get update && sudo apt-get install -y unzip
            wget -N http://chromedriver.storage.googleapis.com/87.0.4280.88/chromedriver_linux64.zip -P ~/
            unzip ~/chromedriver_linux64.zip -d ~/
            rm ~/chromedriver_linux64.zip
            sudo chown root:root ~/chromedriver
            sudo chmod 755 ~/chromedriver
            sudo mv ~/chromedriver /usr/bin/chromedriver
            sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -'
            sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
            sudo apt-get update && sudo apt-get install -y google-chrome-stable
          background: true

The entire .circleci/config.yml

I wrote no_output_timeout: 15m where I run RSpec. Even if you don't have this, it's not directly related to the test, so you can delete it.

If nothing is set, there is a ** standard time limit of 10 minutes **, and if it is exceeded, a ** timeout error ** will occur, so this is added just in case. It depends on the number of tests, but in reality it only takes a few minutes, so it's unnecessary.

version: 2

jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          - BUNDLER_VERSION: 2.0.2
          - RAILS_ENV: 'test'
      - image: circleci/mysql:8.0
        command: [--default-authentication-plugin=mysql_native_password]
        environment:
          - MYSQL_USER: root
          - MYSQL_DB: ci_test
          - MYSQL_ROOT_HOST: "127.0.0.1"

    working_directory: ~/myapp

    steps:
      - run:
          name: Chrome Driver Install
          command: |
            curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
            echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
            sudo apt-get update && sudo apt-get install -y unzip
            wget -N http://chromedriver.storage.googleapis.com/87.0.4280.88/chromedriver_linux64.zip -P ~/
            unzip ~/chromedriver_linux64.zip -d ~/
            rm ~/chromedriver_linux64.zip
            sudo chown root:root ~/chromedriver
            sudo chmod 755 ~/chromedriver
            sudo mv ~/chromedriver /usr/bin/chromedriver
            sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -'
            sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
            sudo apt-get update && sudo apt-get install -y google-chrome-stable
          background: true

      - checkout

      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-

      - run:
          name: install dependencies
          command: |
            gem install bundler -v 2.0.2
            bundle install --jobs=4 --retry=3 --path vendor/bundle

      - save_cache:
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}
          paths:
            - ./vendor/bundle

      - run: mv config/database.yml.ci config/database.yml
      - run: yarn install
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load

      - run:
          name: run tests
          command: |
            mkdir /tmp/test-results
            TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
              circleci tests split --split-by=timings)"
            bundle exec rspec \
              --format RspecJunitFormatter \
              --out /tmp/test-results/rspec.xml \
              --format progress \
              $TEST_FILES
          no_output_timeout: 15m

      - store_test_results:
          path: /tmp/test-results
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results

config/database.yml.ci

test:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: 'root'
  port: 3306
  host: '127.0.0.1'
  database: ci_test

Summary

--** Add Chrome with Dockerfile and CircleCI config file ** --Even if it works locally, it may fail on CircleCI. ――Thankfully, there are many articles (information), so it is important to understand which problem you are facing.

in conclusion

Previous article contains the CircleCI configuration file before the change. (Strictly speaking, a little refactoring etc.) ** Before applying JavaScript **, but please have a look if you like because it summarizes CircleCI.

References

-Launch Chrome Driver on CircleCI -Run Rails SystemTest (headless chrome) on Docker -[Rails 6.0 x MySQL 8.0 x RSpec x Circle CI] Error collection from CI/CD automation -I introduced CircleCI 2.0 to Rails app

Recommended Posts

[Circle CI 2.0] Set to support JavaScript
Set RSpec to DRY
Circle CI environment construction
How to set Docker nginx
How to set Java constants
[Circle CI] A story I was addicted to at Start Building