Cameron Bass Cameron Bass - 1 month ago 9
Ruby Question

Feature spec breaking when turning on js: true - Capybara - Rails

I have some feature specs with capybara for my application. Right now I have a modal that I'm trying to test. The modal is using Javascript. But when I run my specs. I get this really weird error. Here it is.

ERROR



Failure/Error: page.driver.browser.set_cookie("account_id=#{account_id}")

TypeError:
no implicit conversion of Symbol into Integer
# /Users/intern/.rvm/gems/ruby-2.3.1/gems/poltergeist-1.11.0/lib/capybara/poltergeist/browser.rb:313:in `[]'
# /Users/intern/.rvm/gems/ruby-2.3.1/gems/poltergeist-1.11.0/lib/capybara/poltergeist/browser.rb:313:in `set_cookie'
# ./spec/support/_request_macros.rb:20:in `set_current_account'
# ./spec/features/manage_accounts_spec.rb:101:in `block (3 levels) in <top (required)>'
# /Users/intern/.rvm/gems/ruby-2.3.1/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in `block (2 levels) in <top (required)>'


Here is the file that is breaking

def set_current_account(account_id)
page.driver.browser.set_cookie("account_id=#{account_id}")
end


Here is my test

Test



it "redirects to the previous account if a user accesses an account they are not on" do
third_account = create(:account, name: "Third Account", users: [user])

set_current_account(third_account.id)
visit root_path
expect(current_account).to eq(third_account.id)

user.accounts.delete(account1)
click_on "Test Account"

expect(current_path).to eq(snitches_path)
expect(page).to have_content("You don't have access to that account!")
expect(current_account).to eq(third_account.id)
expect(page).to have_content("Third Account")
end


I have js:true in the context above.

I really don't know what is wrong. Hopefully some of you out there are more familiar with capybara and javascript test. Let me know what you think

Answer

From looking at poltergeist, which you appear to be using - https://github.com/teampoltergeist/poltergeist/blob/28cb0d6fd427424acaddc4800514c13efedcb199/lib/capybara/poltergeist/browser.rb the passed cookie needs to be a hash - and really you shouldn't be calling anything on page.driver.browser (99% of the time that means you're doing something you shouldn't be). You could call set_cookie on page.driver - https://github.com/teampoltergeist/poltergeist/blob/master/lib/capybara/poltergeist/driver.rb - which takes (name, value, options = {}) so

page.driver.set_cookie("account_id", account_id)

which will fix the issue you're currently having. However, calling something on page.driver means you're probably doing something wrong about 50% of the time. You really shouldn't be setting cookies manually to fake logins, rather you should either be actually logging in or setting whatever auth library you're using into test mode and doing it that way (example if using devise - https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara)

Additionally your test has a number of issues which can lead to flaky tests.

  1. visit is not guaranteed to wait for the page to finish loading before returning, so any assertion immediately following that which isn't based on visible items on the screen is likely to be flaky.
  2. Calling current_account (assuming that's an app method) when in a JS supporting driver, which means separate threads and your test not having access to the controller data, isn't really going to work well - instead just check for visible items on the page.
  3. click_on doesn't wait for actions triggered by it to complete so immediately checking the path after will be highly flaky - instead use the have_current_path matcher which will retry

    expect(page).to have_current_path(snitches_path)

Comments