How to add wait condition in capybara scenarios?
Asked Answered
Q

4

9

I am using capybara for testing my rails application for integration testing. In my application there are many Lightbox and Ajax and js calls.

 @javascript   
  Scenario: I agree functionatilty
   Given I go to the create account page
   When I click on button which is given as image "lnkTerms2"
   And I follow "i_agree"
   Then I go to the create account page

Here in above code lnkTerms2 is and id which will help in calling js function to open a lightbox. And i am getting an error as

   Element is not currently visible and so may not be interacted with (Selenium::WebDriver::Error::ElementNotDisplayedError)
      [remote server] resource://fxdriver/modules/atoms.js:9519:in `unknown'
      [remote server] file:///tmp/webdriver-profile20111117-6876-18cfcfp/extensions/[email protected]/components/nsCommandProcessor.js:256:in `unknown'
      [remote server] file:///tmp/webdriver-profile20111117-6876-18cfcfp/extensions/[email protected]/components/nsCommandProcessor.js:305:in `unknown'
      [remote server] file:///tmp/webdriver-profile20111117-6876-18cfcfp/extensions/[email protected]/components/nsCommandProcessor.js:320:in `unknown'
      [remote server] file:///tmp/webdriver-profile20111117-6876-18cfcfp/extensions/[email protected]/components/nsCommandProcessor.js:197:in `unknown'
      (eval):2:in `send'
      (eval):2:in `click_link'
      ./features/step_definitions/web_steps.rb:300:in `/^I click on button which is given as image "([^"]*)"$/'
      features/Sign_up_process.feature:61:in `When I click on button which is given as image "lnkTerms2"'

The problem is as this function called in webdriver, it is not getting time to load javascript and ajax calls. And lightbox is not opening. So Please suggest me any solution.

Also if suppose i write the line

When I click on button which is given as image "lnkTerms2"

after 4 to 5 statements then it is working fine as it gets time to load js.

Quincentenary answered 17/11, 2011 at 6:8 Comment(0)
R
3

For a pause after step to wait ajax try:

And I wait 5 seconds

Your must add to web_steps.rb next code:

When /^I wait (\d+) seconds?$/ do |seconds|
  sleep seconds.to_i
end
Randeerandel answered 21/11, 2011 at 21:18 Comment(2)
that's not a good solution, it's adding a forced delay to your test execution, if reused this can add lot of time. the proper way to solve this problem is waiting until an element is visible.Burgener
any form of fixed sleep, even if it is taking the value from the scenario is generally a terrible idea, unless the scenario is really about the user experience that involves waiting that specific amount of time (as opposed waiting for the display to update etc, e.g. 'syncing')Microgamete
M
14

Generally fixed sleeps/waits are a bad thing.. They are a brute force approach that either results in brittle scripts, slow scripts, or often both. If you don't set them long enough then occasionally tests break, if you set them too long, then tests never break but they are SLOW because of all the fixed thumb twiddling time.

Most automation tools either take care of the waiting automagically, or they provide more graceful ways to synchronize your scripts with your app

A recent blog posting by JNicklas explanes some recent changes to Capybara in this regard, provides some examples of some ways to do specific wait-for-condition type of code for a few special cases, and in general recommends to learn more about the tool and how it deals with waiting for stuff, ajax actions, and synchronizing.

Microgamete answered 15/2, 2013 at 22:51 Comment(1)
The site appears to be down, this is archive link web.archive.org/web/20230926000401/https://www.varvet.com/blog/…Mier
R
3

For a pause after step to wait ajax try:

And I wait 5 seconds

Your must add to web_steps.rb next code:

When /^I wait (\d+) seconds?$/ do |seconds|
  sleep seconds.to_i
end
Randeerandel answered 21/11, 2011 at 21:18 Comment(2)
that's not a good solution, it's adding a forced delay to your test execution, if reused this can add lot of time. the proper way to solve this problem is waiting until an element is visible.Burgener
any form of fixed sleep, even if it is taking the value from the scenario is generally a terrible idea, unless the scenario is really about the user experience that involves waiting that specific amount of time (as opposed waiting for the display to update etc, e.g. 'syncing')Microgamete
L
1

Waiting for a fixed number of seconds in hope that your scenario will be fast enough is not the best strategy, because it may lead to random tests failings. I recommend you to wait until some condition is met instead:

And I wait until '#meow' is visible

#...
When /^I wait until '([^']+)' is visible$/ do |selector|
  wait_until do # you can also specify timeout here
    find(selector).visible?
  end
end
Luna answered 28/12, 2012 at 12:19 Comment(6)
wait_until isn't available in Capybara 2Mistook
The general point about fixed waits being bad remains true however. See discussion here: groups.google.com/forum/?fromgroups=#!topic/ruby-capybara/… as to why they removed wait_until..Microgamete
find(selector) is enough instead of this wait_until block if Capybara.ignore_hidden_elements = true. If it's false, find(selector, visible: true) can be usedMistook
Good summary of the points above: elabs.se/blog/53-why-wait_until-was-removed-from-capybaraDacca
isn't that the same link from my answer posted back in feb?Microgamete
I'm not super convinced by the arguments to remove wait_for but here's the archive link as the original blogs appear to be discontinued web.archive.org/web/20230926000401/https://www.varvet.com/blog/…Mier
B
0

you can add a parameter called wait

page.find(:css, "#button", wait: 5).click

Basham answered 2/2, 2023 at 12:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.