rspec testing: putting :js => true also affects the before block

3.5k views Asked by At

I have a page that is for booking an appointment and it has some javascript code that selects the earliest time and day when the appointment is available, after which user can click on the button to schedule the appointment.

So in order to test that, I was writing some rspec test like the following,

book_appointment_spec.rb

context "when on the profile page" do 
  before do 
    click_linkedin_button
  end

  it 'book an appointment', :js => true do 
    click_link "new-appointment"
    choose "doctor1"
    click_button "Submit and Schedule"
    expect(page).to have_content "Congrats!"
  end
end

click_linkedin_button is a method definition that just logins a user via linkedin oauth. The problem is that even after setting OmniAuth.config.mock_auth[:linkedin], whenever I set :js => true around it block, it asks me to login via linkedin, https://i.stack.imgur.com/0hJHC.jpg

I was wondering if anyone knows how to fix this problem.

Following are other files that might be relevant to this problem.

spec_helper.rb

require 'capybara/webkit/matchers'
Capybara.javascript_driver = :webkit

Gemfile

gem 'capybara-webkit'
gem 'database_cleaner'
gem 'capybara'
3

There are 3 answers

0
diabolist On BEST ANSWER

As you've discoverd, you can't run part of a test using one driver and part of the test using another. This would be equivalent to saying

Given I login in using Safari.
Then I should be logged in using Firefox.

So your solution is that you have to run your js login code in the test environment to login. This is actually a good thing (you want to test your js login code). If you want to avoid actually connecting to linkedin, every time you run this test, then you need to mock the connection to linkedin. Have a look at VCR (https://github.com/vcr/vcr), this will allow you to record your connection to linkedin, so that in subsequent test runs you don't have to goto linkedin.

0
Benjamin Bouchet On

Setting js: true in your rspec block is a shortcut to use the javascript-enabled driver for the whole example. So this driver will be available and used during the whole execution or the example, which includes all before/after/around blocks.

To work around this, instead of using js: true, you can manually set which driver to use at the point(s) of your example where you need to.

it {
  do_some_stuff_with_default_driver

  Capybara.current_driver = :webkit
  do_some_stuff_with_webkit

  Capybara.current_driver = :selenium
  do_some_stuff_with_selenium
}

EDIT

Oops I just read this, so perhaps that solution will not be working. please let me know

Note: switching the driver creates a new session, so you may not be able to switch in the middle of a test.

0
kchoi On

I solved it by creating an actual linkedin account, put that auth info in the .env and just called fill_in method to fill out email and password field during its callback. And stuck with running a js driver throughout the entire context block.

EDIT: This is of course not the best answer so I am still accepting other answers.