Search code examples
ruby-on-railsrspecselenium-chromedrivercapybara

How to set up system tests for a modal, using Rspec, Capybara, and Chromedriver


I am novice, and it is my current understanding that you can't mix javascript with Rspec tests (?).

For my first Rspec/Capybara system test, I would like the user to sign in, then click on a modal link to see that the modal is there (and later interact with the modal).

the related gems (it's an old 2017 project)

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri
  gem 'rspec-rails', '~> 3.5.0'
  gem 'puma', '~> 3.0'
end

group :test do
  gem 'capybara', '~> 3.6.0'
  gem 'factory_girl_rails', '~> 4.7'
  gem 'faker'
  gem 'selenium-webdriver', '~> 3.0.0'
  gem "database_cleaner", "~> 1.5"
  gem 'shoulda-matchers', '~> 3.1'
  gem 'launchy'
end

The rspec

scenario "Fans in Canada can sign in, visit signed in home page, and log out in" do

    create_fan_in_canada

    visit root_path

    #fist LOG IN link
    within('#myNavbar') do
      expect(page).to have_link "LOG IN"
    end

    #second LOG IN link
    within('.follow-login') do
      expect(page).to have_link "LOG IN"
    end

    within('#myNavbar') do
      click_link('LOG IN')
    end  

    fill_in "Email", with: @fan.email
    fill_in "Password", with: @fan.password
    click_button "Sign in"
    find('.dropdown-toggle').click
    expect(page).to have_link "Logout"
    expect(page).to have_current_path root_path

    ## MODAL TEST ##

    find('#actionLink').click
    within('#actionModal') do
      page.should have_content('#fan1') 
    end
    expect(page).to have_css '#fan1'

    ## MODAL TEST END ##

    click_link "Logout"
    expect(page).to have_css '#splash_page_loads'
  end

 ############
 ############ 

Selenium chromedrive is downloaded and put in a path file as per Selenium docs, and this rails-helper code courtesy of this blog.

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

Capybara.javascript_driver = :selenium_chrome

Results:

If I don't include the ## MODAL TEST ##code, the test passes.

If I include the ## MODAL TEST ##, the test fails with this error from the controller:

Failures:

  1) Splash and devise: Fans in Canada can sign in, visit signed in home page, and log out in
     Failure/Error:
       respond_to do |format|
         format.js    # this goes to actionMain.js.erb
       end
     
     ActionController::UnknownFormat:
       ActionController::UnknownFormat
     # ./app/controllers/actionmodal_controller.rb:41:in `actionMain'

if I add :js => true to the scenerio, I get this error:

Failures:

  1) Splash and devise: Fans in Canada can sign in, visit signed in home page, and log out in
     Failure/Error:
       within('#myNavbar') do
         expect(page).to have_link "LOG IN"
       end
     
     NameError:
       uninitialized constant Selenium::WebDriver::Error::ElementNotInteractableError

Leading me to believe I either have it set up wrong, or I have to add the modal test in it's own seperate scenerio, dedicated specifically to javascript Chromedriver.

If I did that however, I wouldn't be able to log in the user beforehand etc, would need to stub them maybe, but I also have multiple modals with numerous links on them that change the content of the modals, that I would also like to test later on, in which I don't believe deal with Chromedriver.

How do I set up Capybara and Rspec so I can seemlessly open the modals in a regular system test? Because to only deal with Chromedriver or the other in extensive system tests that deals with normal user actions doesn't seem correct.


Solution

  • NameError: uninitialized constant Selenium::WebDriver::Error::ElementNotInteractableError

    would be caused by using incompatible versions of Capybara and selenium-webdriver.