Watir webdriver - click an element and not wait for load - ruby

I have 2 sides in my page, clicking one of the buttons on the left side, refreshes the right side.
Now I want to see whether the site gets stuck if i click the buttons too fast while not letting the right side to fully load.
Right now watir waits for the click command to return, so the test doesnt do what it should:
arr = ["div1", "div2", "div3"]
for i in 1..20
print "#{i}\r"
choise = arr.sample
b.div(:id=>choise).click
end
Any way to make it send the command and return without any delays?

Are you getting the same result in multiple browsers?
The spec (which may or may not be implemented or implemented the same way by the different browsers), says that webdriver prevents other commands from being executed while there are outstanding network requests. Though, it also says it should wait for document.readyState to be present for the frame currently handling the commands, so it is unclear if the outstanding network request is supposed to apply to only the current frame or to all frames.
But since Webdriver is designed for commands to be handled in a synchronous manner, it is likely just not designed to do what you are trying to do.

Not sure but you can try with javascripts:
#browser.execute_script("document.getElementById('choise').click")

b.div(:id => 'choise').exist? - to check exist it or aren't
b.div(:id => 'choise').click

I think titusfortner is right. But look this answer.
begin
Timeout::timeout(10) do
# perform actions that may hang here
end
rescue Timeout::Error => msg
put "Recovered from Timeout"
end

Related

Last index can't be located

I have a very different problem here.
I have this code
xpath = "//div[#class='z-listheader-content'][normalize-space()='Name']/ancestor::table/../following-sibling::div/table"
array = #browser.table(xpath: xpath, visible: true).rows.map { |row| [row.cells[0], row.cells[0].text] }
col = array.filter_map { |x| x if x[1].eql?(result) }
When I am executing the aforementioned code, it throws the following error
timed out after 10 seconds, waiting for #<Watir::Row: located: false; {:xpath=>\"//div[#class='z-listheader-content'][normalize-space()='Name']/ancestor::table/../following-sibling::div/table\", :visible=>true, :tag_name=>\"table\"} --> {:index=>10}> to be located\""
10 is actually the last index of the table.
But it works fine if I put sleep 5 before my code segment. However, I was expecting WATIR to be automatically waited, but this is not the case, May I know why?
Here is more clear explanation
I am printing this line
p #browser.table(xpath: xpath, visible: true).rows.count
With sleep this is printing 10
without sleep, this is throwing the following error ends with {:index=>11}> to be located\, you could see the full error below
"timed out after 10 seconds, waiting for #<Watir::Row: located: false; {:xpath=>\"//div[#class='z-listheader-content'][normalize-space()='Name']/ancestor::table/../following-sibling::div/table\", :visible=>true, :tag_name=>\"table\"} --> {:index=>11}> to be located\""
Per the Documentation on waiting there are a few key points that should be noted:
The idea behind implicit waits is good, but there are two main issues with this form of implementation, so Watir does not recommend and does not provide direct access for setting them.
The wait happens during the locate instead of when trying to act on the element. This makes it impossible to immediately query the state of an element before it is there.
Implicit waits by themselves will not be sufficient to handle all of the synchronization issues in your code. The combination of delegating waiting responsibilities to the driver and leveraging polling in the code (explicit waits) can cause weirdness that is difficult to debug...
...The second and recommended approach to waiting in Selenium is to use explicit waits...
...Note that Watir does its automatic waiting when taking actions, not when attempting to locate...
In your case the wait is needed for location and thus the "automatic" wait you were expecting is not actually how watir works.
The Watir library does however provide mechanisms for explicit waits:
wait_until which waits until a specific condition is true
wait Waits until readyState of document is complete.
It appears that based on your posted issue that a waiting timeout has expired for your location before the element could be found.
It is possible that wait_until would resolve this e.g.
table = #browser.table(xpath: xpath).wait_until(&:visible?)
puts table.rows.count

Non helpfull error message Calabash with page objects pattern

I'm currently using Calabash framework to automate functional testing for a native Android and IOS application. During my time studying it, I stumbled upon this example project from Xamarin that uses page objects design pattern which I find to be much better to organize the code in a Selenium fashion.
I have made a few adjustments to the original project, adding a file called page_utils.rb in the support directory of the calabash project structure. This file has this method:
def change_page(next_page)
sleep 2
puts "current page is #{current_page_name} changing to #{next_page}"
#current_page = page(next_page).await(PAGE_TRANSITION_PARAMETERS)
sleep 1
capture_screenshot
#current_page.assert_info_present
end
So in my custom steps implementation, when I want to change the page, I trigger the event that changes the page in the UI and update the reference for Calabash calling this method, in example:
#current_page.click_to_home_page
change_page(HomePage)
PAGE_TRANSITION_PARAMETERS is a hash with parameters such as timeout:
PAGE_TRANSITION_PARAMETERS = {
timeout: 10,
screenshot_on_error: true
}
Just so happens to be that whenever I have a timeout waiting for any element in any screen during a test run, I get a generic error message such as:
Timeout waiting for elements: * id:'btn_ok' (Calabash::Android::WaitHelpers::WaitError)
./features/support/utils/page_utils.rb:14:in `change_page'
./features/step_definitions/login_steps.rb:49:in `/^I enter my valid credentials$/'
features/04_support_and_settings.feature:9:in `And I enter my valid credentials'
btn_ok is the id defined for the trait of the first screen in my application, I don't understand why this keeps popping up even in steps ahead of that screen, masking the real problem.
Can anyone help getting rid of this annoyance? Makes really hard debugging test failures, specially on the test cloud.
welcome to Calabash!
As you might be aware, you'll get a Timeout waiting for elements: exception when you attempt to query/wait for an element which can't be found on the screen. When you call page.await(opts), it is actually calling wait_for_elements_exist([trait], opts), which means in your case that after 10 seconds of waiting, the view with id btn_ok can't be found on the screen.
What is assert_info_present ? Does it call wait_for_element_exists or something similar? More importantly, what method is actually being called in page_utils.rb:14 ?
And does your app actually return to the home screen when you invoke click_to_home_page ?
Unfortunately it's difficult to diagnose the issue without some more info, but I'll throw out a few suggestions:
My first guess without seeing your application or your step definitions is that #current_page.click_to_home_page is taking longer than 10 seconds to actually bring the home page back. If that's the case, simply try increasing the timeout (or remove it altogether, since the default is 30 seconds. See source).
My second guess is that the element with id btn_ok is not actually visible on screen when your app returns to the home screen. If that's the case, you could try changing the trait definition from * id:'btn_ok' to all * id:'btn_ok' (the all operator will include views that aren't actually visible on screen). Again, I have no idea what your app looks like so it's hard to say.
My third guess is it's something related to assert_info_present, but it's hard to say without seeing the step defs.
On an unrelated note, I apologize if our sample code is a bit outdated, but at the time of writing we generally don't encourage the use of #current_page to keep track of a page. Calabash was written in a more or less stateless manner and we generally encourage step definitions to avoid using state wherever possible.
Hope this helps! Best of luck.

How to control test execution speed in watir-webdriver with the Watir::Browser#speed= method? [duplicate]

This question already has answers here:
Is there a way to slow down execution of Watir Webdriver under Cucumber?
(2 answers)
Closed 7 years ago.
Is there any way to control test execution speed in watir? How can I slow down the speed of test execution?
Someone suggested me to use following method browser.speed = :slow but, there is no such method for the Watir::Browser class with the browser driver I'm currently using.
Speed Defaults to Slow
According to the documentation, Watir::Browser#speed= already defaults to :slow. However, as far as I can tell changing this option is only valid for Internet Explorer, and has no effect on other browsers. In fact, with Chrome or Firefox the constructor won't accept a speed argument, and provides no public interface for the option.
However, as with most things Ruby, you can always access the variables directly and tweak them. This may or may not work for your use case, but you could certainly do something like this:
browser = Watir::Browser.new :chrome
#=> #<Watir::Browser:0x..fee868224270c4e1c url="data:," title="data:,">
browser.instance_variable_set :#speed, :slow
#=> :slow
browser.instance_variable_get :#speed
#=> :slow
Other Alternatives
In practice, testing browsers often involves a lot of asynchronous JavaScript events, so you probably want to wait for events or elements rather than trying to slow down the test itself. To do that, you can use explicit or implicit waits.
Implicit Waits
You can add an implicit wait in seconds. For example, to wait up to 30 seconds for each event or element:
browser.driver.manage.timeouts.implicit_wait = 30
Explicit Waits
Watir supports both Watir::Wait#until and Watir::Wait#while. For example, to wait until a login field is visible:
Watir::Wait.until { browser.text_field(name: 'login').visible? }
Use Sleep
Under the hood, Watir is Ruby, so you can also put explicit sleeps into your tests with Kernel#sleep. The main downside to doing this is that it isn't responsive. Your code will sleep for the defined time period even if the event or element you are waiting on triggers or changes earlier. This can make your tests unnecessarily slow.

How can I implement wait_for_page_to_load in Selenium 2?

I am new to automated web testing and I am currently migrating from an old Selenium RC implementation to Selenium 2 in Ruby. Is there a way to halt the execution of commands until the page gets loaded, similar to "wait_for_page_to_load" in Selenium RC?
I fixed a lot of issues I was having in that department adding this line after starting my driver
driver.manage.timeouts.implicit_wait = 20
This basically makes every failed driver call you make retry for maximum 20 seconds before throwing an exception, which is usually enough time for your AJAX to finish.
Try using Javascript to inform you!
I created a couple methods that checks via our javascript libraries and waits to see if the page has finished loading the DOM and that all ajax requests are complete. Here's a sample snippet. The javascript you will need to use is just going to depend on your library.
Selenium::WebDriver::Wait.new(:timeout => 30).until { #driver.execute_script("[use javascript to return true once loaded, false if not]"}
I then wrapped these methods in a clickAndWait method that clicks the element and calls the waitForDomLoad and waitForAjaxComplete. Just for good measure, the very next command after a clickAndWait is usually a waitForVisble element command to ensure that we are on the right page.
# Click element and wait for page elements, ajax to complete, and then run whatever else
def clickElementAndWait(type, selector)
#url = #driver.current_url
clickElement(type, selector)
# If the page changed to a different URL, wait for DOM to complete loading
if #driver.current_url != #url
waitForDomLoad
end
waitForAjaxComplete
if block_given?
yield
end
end
If you are using capybara, whenever you are testing for page.should have_content("foo"), capybara will not fail instantly if the page doesn't have the content (yet) but will wait for a while to see if an ajax call will change that.
So basically: after you click, you want to check right away for have_content("some content that is a consequence of that click").

Stop loading page watir-webdriver

Is there a way to stop loading a page with watir-webdriver on firefox? Or is there a way to force something in my script even if the page is still loading? At a point in my script, the website will hang and the script eventually timeouts.
You can use the Timeout class to force it to give up after waiting a reasonable amount of time (and this is internally how Watir performs it's waits as well)
begin
Timeout::timeout(10) do
# perform actions that may hang here
end
rescue Timeout::Error => msg
put "Recovered from Timeout"
end
If the website hangs, you should be able to use a wait method to timeout the script if an element does not appear. These are mainly used as an answer to AJAX, but they should work for this condition as well. For example, if the script hangs after you click a link, and you expect the next page to have a specific title or text:
#browser.link(:name => "Let's Hang!").click
Watir::Wait.until(30) { #browser.title == "new page" }
or
Watir::Wait.until(30) { #browser.text.include? ("confirmation text") }
or
#browser.image(:src => "awesome.jpg").wait_until_present(30)
Each of these will wait 30 seconds for the condition to be met before exiting with an error. You can change the time (30) to exit within your app's hang window.
please have a look at the Selenium issue http://code.google.com/p/selenium/issues/detail?id=687 it's not fixed yet, watir-webdriver is also based on Selenium, hope it answers your question.

Resources