Search code examples
ruby-on-railsrspec-railspoltergeist

Poltergeits doesn't working well in rspec tests


I have the following feature tests passing:

require 'rails_helper'

describe "Create a quetsion", type: :feature do
  let(:question) { build(:question) }
  before do
    login_as create(:user, :teacher)
    exercise = create(:exercise)
    visit new_exercise_question_url(exercise.id)
  end

  context "whit valid attributes" do
    subject do
      fill_in "question_score", with: question.score
      fill_in "question_description", with: question.description
      click_on "Criar"
    end

    it "create the question" do
      expect{ subject }.to change(Question, :count).by(1)
      expect(page).to have_current_path(question_path(Question.first.id))
    end
  end

  context "whit invalid attributes" do
    subject do
      click_on "Criar"
    end

    it "doesn't create the exercise" do
      expect{ subject }.to change(Question, :count).by(0)
      expect(page).to have_selector("div.alert.alert-danger")
    end
  end
end

That works fine, unless I add js: true. In this case, I have the following errors:

  1) Create a quetsion whit valid attributes create the question
     Failure/Error: fill_in "question_score", with: question.score

     Capybara::ElementNotFound:
       Unable to find field "question_score"
     # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/node/finders.rb:44:in `block in find'
     # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/node/base.rb:85:in `synchronize'
     # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/node/finders.rb:33:in `find'
     # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/node/actions.rb:85:in `fill_in'
     # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/session.rb:735:in `block (2 levels) in <class:Session>'
     # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/dsl.rb:52:in `block (2 levels) in <module:DSL>'
     # ./spec/features/create_a_question_spec.rb:14:in `block (3 levels) in <top (required)>'
     # ./spec/features/create_a_question_spec.rb:20:in `block (4 levels) in <top (required)>'
     # ./spec/features/create_a_question_spec.rb:20:in `block (3 levels) in <top (required)>'

  2) Create a quetsion whit invalid attributes doesn't create the exercise
     Got 0 failures and 2 other errors:

     2.1) Failure/Error: visit new_exercise_question_url(exercise.id)

          Capybara::Poltergeist::StatusFailError:
            Request to 'http://www.example.com/exercises/1/questions/new' failed to reach server, check DNS and/or server status
          # /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:376:in `command'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:35:in `visit'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/driver.rb:97:in `visit'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/session.rb:240:in `visit'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/dsl.rb:52:in `block (2 levels) in <module:DSL>'
          # ./spec/features/create_a_question_spec.rb:8:in `block (2 levels) in <top (required)>'

     2.2) Failure/Error: @socket.send(command.id, command.message, receive_timeout) or raise DeadClient.new(command.message)

          Capybara::Poltergeist::DeadClient:
            PhantomJS client died while processing {"id":"2928bf26-2dd8-45d7-8822-41b2923fd40d","name":"reset","args":[]}
          # /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/server.rb:38:in `send'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:369:in `command'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:224:in `reset'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/poltergeist-1.13.0/lib/capybara/poltergeist/driver.rb:183:in `reset!'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/session.rb:109:in `reset!'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `block in reset_sessions!'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reverse_each'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reset_sessions!'
          # /usr/local/rvm/gems/ruby-2.3.1/gems/capybara-2.10.1/lib/capybara/rspec.rb:21:in `block (2 levels) in <top (required)>'

I checked, whit js: true my page html isn't written too (instead the desired HTML, I only receive <html><head></head><body></body></html>).

I added poltergeist gem to test javascritp, and configured it in my rspec rails_helper.rb file:

require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist

PhantomJS is already instaled and available in my $PATH. I'm completelly out of ideas, what can be happening here?


Solution

  • There are a number of potential issues here.

    1. If you have set Capybara.server = :puma, make sure you're not running puma 3.7.0 which has a bug in it that will be fixed when 3.7.1 is released. For now use 3.6.9

    2. If this is the first time you're setting up js tests make sure you have setup and correctly configured DatabaseCleaner so that you are no running in transaction mode for js: true tests. See https://github.com/teamcapybara/capybara#transactions-and-database-setup and https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example for the recommended configuration

    3. Once you have #1 and #2 worked out then you'll need to look at your tests and deal with the fact that after a click/click_on type action you need to check for a visible page change to ensure the action has completed before you move on. This is because clicks happen but the actions those clicks trigger can occur asynchronously. In your current example that means you would need something like

      ...
      click_on "Criar"
      expect(page).to have_text("Question created!") #whatever message is shown when the action has completed, or check the page etc.
      

    Without something like that the change check will fail because it will check the count before the actual actually occurs.

    1. Default to _path helpers rather than _url helpers when there's no need for a specific host name (99.9% of the time). This lets Capybara fill_in the correct host/port for the server being run. To visit _url helpers there are a number of configuration parameters that need to be carefully set.

    Note: It's generally not best practice to be checking database counts in feature tests, they should generally be limited to checking on visible page changes.