Trouble interacting with Bootstrap modals via Capybara (v2)
Asked Answered
O

4

15

In a Rails application I'm trying to test a Bootstrap modal with a jQuery TokenInput field in Rspec using Capybara with the capybara-webkit driver. The portion in question is as follows:

click_link 'Create Team Modal'
sleep 1

within('div#modal_popup') do
  fill_in 'input#token-input-team_name', with: 'Fancy team name'
  sleep 1
  fill_in 'input#token-input-team_name', with: '\t'
  sleep 1

  click_button 'Create Team'
end

page.should have_content('Fancy team name')
  • Click button to get modal
  • Fill in TokenInput with a team name
  • Simulate a Tab key-press to get it selected
  • Create the team
  • Verify the name shows up on the page

This will only work with all those sleep 1s in place; otherwise Capybara crashes at have_content, eventually resulting in a server error because the team name was never able to be selected properly. Other Bootstrap modals without a TokenInput field do not require a sleep 1 before they load, however.

With all that said, is there any way to get rid of the sleeps and have this proceed as normal? Capybara 2 took out wait_until (with good reason) since it will wait within the default wait time to test for something...but that doesn't seem to be reflected in my above test; it's as if Capybara does not engage in that wait period upon entering/exiting this modal. Anyone have any experience with this? Using Rails 3.2.10, Rspec 2.12, Capybara 2, capybara-webkit 0.14.0, TokenInput 1.6.

Orsola answered 23/1, 2013 at 20:32 Comment(2)
This might be helpful: blog.crowdint.com/2013/09/20/…Kenyakenyatta
See also github.com/teamcapybara/capybara/issues/1890Caspar
S
10

Try disabling animations in test env, layouts/application.html.erb

<% if Rails.env.test? %>
 <style type="text/css">
    .modal.fade, .fade {
      -webkit-transition: opacity 0.01s;
      -moz-transition: opacity 0.01s;
      -ms-transition: opacity 0.01s;
      -o-transition: opacity 0.01s;
      transition: opacity 0.01s;
    }
 </style>
<%end%>
Sale answered 22/8, 2013 at 8:42 Comment(2)
As pointed out in the croudint article that @matt linked, this can also go in a separate stylesheet.Avigation
Which version of Bootstrap is this applicable to? I'm encountering the same issue, but I am using Bootstrap 3 and the recommendation above doesn't seem to address the issue for me.Nitwit
S
10

I suggest adding the following css into your test env:

  div, a, span, footer, header {
      -webkit-transition: none !important;
      -moz-transition: none !important;
      -ms-transition: none !important;
      -o-transition: none !important;
      transition: none !important;
  }

  .modal {
    display: none !important;
  }

  .modal.in {
    display: block !important;
  }

  .modal-backdrop {
    display: none !important;
  }

Add this js in the and of body:

$(".fade").removeClass("fade");

That has solved most of my problems with capybara and bootstrap.

Stoller answered 11/3, 2014 at 10:0 Comment(1)
It was also required (in my case) to use gem 'capybara-webkit'Spinifex
P
2

We just do this and it seems to work (for example to click on $('.tp-header-login'):

# instead of find(".tp-header-login")

find(".tp-header-login") # still do the find so you are sure its loaded then...
execute_script "$('.tp-header-login').click()"
Patman answered 22/1, 2016 at 22:4 Comment(0)
B
1

For those wishing to avoid Rails.env.___? hacks*, the following seemed to work (so far -- fingers crossed) in avoiding problems with testing jQuery UI drag-and-drop functionality on a Bootstrap-based modal.

First, we were already "waiting" for the modal to appear, using a helper method like this:

def wait_for_modal_to_appear
  modal = wait_until {
    # Look for the modal by ID/whatever...
  }
  raise Capybara::ModalNotFound.new('...') if modal.nil?
  return modal
end

Yet still, we were having spurious issues when trying to drag-and-drop elements in that modal. The following code addition, added just before the return line, seems to have done the trick:

page.execute_script("document.getElementById('#{modal[:id]}').classList.remove('fade');")

* Just such a hack recently led to the need for an emergency deployment at a company I work with... A bad code-change managed to make it into production because it was only activated by a if Rails.env.production? qualifier; it would have failed half of the test-suite otherwise.

Blueing answered 19/8, 2016 at 19:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.