Voxorin
Voxorin

Reputation: 119

Issues with system test setup using Capybara and Selenium on Rails 5.1 app (upgraded from Rails 4)

I'm attempting to set up system tests with Capybara and Selenium on an existing Rails 5.1 (Upgraded from Rails 4) app that already had capybara based feature tests. Here's what I've done so far.

In the gem file under group :development, :test:

gem 'chromedriver-helper'  
gem 'selenium-webdriver'
gem 'rack_session_access'

In the environments/development.rb and environments/test.rb:

config.action_mailer.default_url_options = { host: 'localhost:3000' } 

In the spec\rails_helper.rb:

Capybara.register_driver :selenium do |app|
  Capybara::Selenium::Driver.new(app, browser: :chrome)
end

Capybara.configure do |config|
  config.default_max_wait_time = 10 # seconds
  config.default_driver = :selenium
  config.app_host = 'http://localhost:3000'
  config.server_host = 'localhost'
end

The issues I'm having are both with new systems tests and old feature tests.

With the system tests it appears that Capybara isn't creating a page object as I get undefined local variable or method 'page' Additionally when I duplicate the same test under the feature test directory I don't have this issue.

With the old Capybara feature tests, working with the rackTest driver, a Chrome window opens but I get No route matches [GET] "/rack_session/edit"

config.middleware.use RackSessionAccess::Middleware is already present in the environments/test.rb

Example system test:

require 'rails_helper'

describe User do
  let(:user) { create :user }
  let(:membership) { create :membership, admin: true}
  let(:admin) { create :user, memberships: [membership] }

  context 'viewing the index' do
    it 'directs you to the appropriate page' do
      set_current_user(admin)
      visit root_url
      click_button 'Manage Users'
      expect(page.current_url).to end_with users_path
      expect(page).to have_selector 'h1', text: 'Users'
    end
  end
end

Example feature test:

require 'rails_helper'

describe 'edit an assignment' do
  let(:roster) { create :roster }
  let(:user) { create :user, rosters: [roster] }
  before :each do
    Timecop.freeze Date.new(2018, 1, 10)
    set_current_user(user)
  end
  after :each do
    Timecop.return
  end

  context 'returns the user to the appropriate index page' do
    let(:date_today) { Date.new(2017, 4, 4) }
    let(:start_date) { Date.new(2017, 3, 31) }
    let(:month_date) { date_today.beginning_of_month }
    it 'redirects to the correct URL' do
      visit roster_assignments_url(roster, date: date_today)
      visit new_roster_assignment_url(roster, date: start_date)
      click_button 'Create'
      expect(current_url)
        .to eq roster_assignments_url(roster,
                                      date: month_date)
    end

In the spec_helper:

def set_current_user(user)
  page.set_rack_session user_id: user.id
end

Upvotes: 4

Views: 2331

Answers (2)

Anbranin
Anbranin

Reputation: 26

You need to have the gem puma installed. New rails 5 projects have it installed by default, but your app was made in Rails 4, which is why it didn't.

Why is this? Well, if you were to do a bundle update (and I'll admit I can't explain why) you'd get this error when trying to run the specs, which is a lot more explanatory:

System test integration requires Rails >= 5.1 and has a hard dependency on a webserver and `capybara`, please add capybara to your Gemfile and configure a webserver (e.g. `Capybara.server = :webrick`) before attempting to use system tests.

Googling this error led me to this page, which explains Capybara needs a server. After adding puma, I'm able to run system tests on your application.

Upvotes: 1

Thomas Walpole
Thomas Walpole

Reputation: 49950

A number of issues here.

  1. Why are you setting - config.app_host = 'http://localhost:3000' ??? That would run the tests against your dev instance rather than the test instance Capybara starts. app_host really should only ever need to be set if you are doing subdomain based testing. This could be the reason for the no route error (normally rack_session_access would only be included in the test environment), or that could be caused by having not actually included the middleware as specified in the rack_session_access gem readme.

  2. NEVER do expectations against current_path/current_url directly, instead use the provided matchers or you'll have flaky tests

    expect(page).to have_current_path(users_path)

  3. page is just an alias for Capybara.current_session and is a member of the module Capybara::DSL. If it's not available in the scope of your tests that it most likely means Capybara::DSL isn't included. That would normally be done by rspec-rails - https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/vendor/capybara.rb#L21 - so it's possible you haven't actually set the test type to 'system'. If it's that it's not available in your spec_helper methods, just using Capybara.current_session instead is usually easier.

Upvotes: 0

Related Questions