Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capybara doesn't recognize dynamically added DOM elements?

I seem to be having trouble testing the slick javascript things I do with jQuery when using Capybara and Selenium. The expected behavior is for a form to be dynamically generated when a user clicks on the link "add resource". Capybara will be able to click the link, but fails to recognize the new form elements (i.e. "resource[name]").

Is there a way to reload the DOM for Capybara, or is there some element of this gem that I just haven't learned of yet?

Thanks in advance!

==Edit==

Currently trying my luck with selenium's:

wait_for_element 

method.

==Edit==

I keep getting an "undefined method 'wait_for_element` for nill class" when attempting to do the following:

@selenium.wait_for_element

It appears that that specific method, or perhaps wait_for with a huge selector accessing the DOM element I expect is the correct course of action, but now trying to get the selenium session is starting to be a huge headache.

like image 204
kelly.dunn Avatar asked Oct 06 '10 20:10

kelly.dunn


1 Answers

I use the Webdriver based driver for Capybara in RSpec, which I configure and use like this and it will definitely handle JS and doesn't need a reload of the dom. The key is using a wait_until and a condition that will be true when your AJAX response has finished.

before(:each) do
  select_driver(example)  
  logout
  login('databanks') 
end

 def select_driver(example)
   if example.metadata[:js]
    Capybara.current_driver = :selenium
  else
    Capybara.use_default_driver
  end
end

it "should let me delete a scenario", :js=>true do
    select("Mysite Search", :from=>'scenario_id')  
    wait_until{ page.has_content?('mysite_searchterms')}    
    click_on "delete"     
    wait_until{ !page.has_content?('mysite_searchterms')}   
    visit '/databanks'
    page.should_not have_content('Mysite Search')
  end

I also figured out a hack to slow down webdriver last night, like this, if you want to watch things in slo-mo:

   #set a command delay
   require 'selenium-webdriver'

   module ::Selenium::WebDriver::Remote
     class Bridge
       def execute(*args)
         res = raw_execute(*args)['value']
         sleep 0.5
         res
       end
     end
   end  

As someone else mentioned, if you are getting a timeout waiting for the element, you could look at upping this:

Capybara.default_wait_time = 10
like image 85
ebeland Avatar answered Oct 04 '22 23:10

ebeland