Selenium Webdriver - How do I skip the wait for page load after a click and continue - ruby

I have an rspec test using webdriver that clicks on a button... after clicking the button, the page never fully loads (which is expected and correct behaviour). After clicking the button, I want to wait 2 seconds and then navigate to a different URL... despite the fact that the page has not loaded. I don't want to throw an error because the page hasn't loaded, I want to just ignore that, and continue on as if everything is good. The page should never load, that is the expected and correct behaviour.
How can I avoid waiting until the timeout, and secondly, how can I have that not throw an error which casuses the test to fail.
Thank you!

WebDriver has a blocking API and it will always wait for page to be loaded. What you can do instead, is to press the button via JavaScript, i.e. trigger its onclick event. I am not familiar with Ruby, but in Java it would be:
WebDriver driver = ....; // Init WebDriver
WebElement button = ....; // Find your element for clicking
String script = "if (document.createEventObject){"+
"return arguments[0].fireEvent('onclick');"+
"}else{"+
"var evt = arguments[0].ownerDocument.createEvent('MouseEvents');"+
"evt.initMouseEvent('click',true,true,"+
"element.ownerDocument.defaultView,1,0,0,0,0,false,"+
"false,false,false,1,null);"+
"return !element.dispatchEvent(evt);}" ;
((JavascriptExecutor)driver).executeScript(script, button);
After this you can wait for 2 seconds and continue

I had this similar problem, I tried this solution which #Sergii mentioned but was getting below error:
org.openqa.selenium.JavascriptException: javascript error: element is not defined (Session info: chrome=84.0.4147.89)
As a workaround had to initialize element within java script code.
String script = "var element = document.querySelector('button[type=submit]');" +
"if (document.createEventObject){"+
"return element.fireEvent('onclick');"+
"}else{"+
"var evt = element.ownerDocument.createEvent('MouseEvents');"+
"evt.initMouseEvent('click',true,true,"+
"element.ownerDocument.defaultView,1,0,0,0,0,false,"+
"false,false,false,1,null);"+
"return !element.dispatchEvent(evt);}" ;
Thank you #Sergii for your answer, I was not able to add this as a comment due to limited characters, so added it as a separate answer.

why don't you try a simple trick of using "waiting()" after waitForPageToLoad() which makes it to neglect the previous command in Selenium and never fails that step

What if you used RSpec's expect method:
expect {
Thread.new() {
sleep(2)
raise RuntimeError
}
theButton.click()
}.to raise_error

Send the 'Enter' key to the link or button in question instead of a click, webdriver won't wait for the page to load and will return instantly (this is in C#, just translate to Ruby):
element.SendKeys(Key,Return);

Related

Watir 'Wait' doesn't wait

gem "watir", "6.9"
Trying to execute this code
2.times { next_button.when_present.click }
or like this
2.times { next_button.wait_until(&:present?).click }
And getting this error
Watir::Exception::UnknownObjectException:
unable to locate element: #<Watir::Button: located: false; {:class=>"course-player__content-next-btn", :tag_name=>"button"}>
But I'm telling Watir to wait for an element before clicking on that!
What's going on? I'm not a fan of sleeps and don't want to resort to using them!
Thank you!
P.S. next_button has been found and identified.
The code works with sleeps and doesn't wait for an element by default.
You can try for example -
if element is visible in gui and exist in html = continue to click
browser.element(class: button_ok).wait_until_present
browser.element(class: button_ok).click
or - if element is exist in html and it is visible in gui = continue to click
browser.element(class: button_ok).present?
browser.element(class: button_ok).click
or - if element is exist in html = continue to click
browser.element(class: button_ok).exists?
browser.element(class: button_ok).click
or - wait until element is not visible(disapear)
browser.element(class: button_ok).wait_while_present
browser.element(class: button_ok).click
Hope it will help you.
of course button_ok is variable
button_ok = "path"
As of 6.15 #wait_while_present and #wait_until_present are deprecated. For versions 6.2 through 6.14 these methods had subtly different behaviour or from .wait_until(&:present?) & .wait_while(&:present?). This is no longer the case and these methods should no longer be used.

how to reload page until a button appears using capybara and ruby

I want to click a button after an action and button does not appear until and unless I reload the page. And some times it takes some time to appear the button and I have to reload page for more than once. I don't want to put static delays. So is there a way to achieve following using capybara and ruby:
do
page.evaluate_script("window.location.reload()")
until a button appears
While Mesut's code should work fine, I would re-write it as:
Timeout.timeout(Capybara.default_max_wait_time) do
loop do
page.evaluate_script("window.location.reload()")
break if page.has_selector?(...)
end
end
This will make sure to fail if it will have to wait more than timeout defined in Capybara settings. It can be useful when for example specs are running on the CI server.
Be aware that it can still lead to unexpected behaviors in some drivers, because it can interrupt while some scripts are evaluating.
reoload until page.has_selector? returns true, check this:
while true
page.evaluate_script 'window.location.reload()'
if page.has_selector?("css_selector")
break
end
end

Verify for the text to be present in an overlay using watir-webdriver

I have an overlay form where i create an user for our application. After giving the details in the text fields i click on save and try to capture the Saved Successfully Text which appears for about a second on the overlay. But i am unable to do so as i get an error saying "Element is no longer attached to the DOM (Selenium::WebDriver::Error::StaleElementReferenceError)".I have used the below code:
if($browser.div(:class=>"validation-summary-valid").exists?)
message=$browser.div(:class=>"validation-summary-valid").li.text
if(message=="Saved Sucessfully")
puts("Save action complete")
else
fail("fail")
end
end
in capybara i would scope the code using ( within ) to the message element in the Dom then use have_content
within('#Browser div')do
page.should have_content('Saved Successfully')
end
hope this will help to try something similar in watir
What I understood from the situation is, the moment you click on save a transient message appears on the UI and a check needs to be performed.
The below approach should work fine in this case,
# the browser waits for 20 s until the element is present(exists+visible) on the UI
$browser.div(:class=>"validation-summary-valid").wait_until_present(20).li.text

How to handle Modals in cucumber + Capybara + Selenium

So I am trying to click a forgot password link (which causes a modal pop up) and confirm the pop up link so I can perform a test on the sent out email.
My code looks like this:
page.find(:css, '#launch-modal-link').click # code fails on this line, after clicking the link
page.driver.browser.switch_to.alert.accept # does not get to this line of code.
What am I doing wrong exactly when trying to click the "Ok" button in the modal pop up?
Do I need to add a try catch block (or whatever it is called in Ruby) around the link
Solved it - Found the answer somewhere else. Its a hack though, and not something done via cucumber directly.
page.evaluate_script('window.confirm = function() { return true; }')
This works because it over writes the confirm() to always return true and the confirm function seems to be a common javascript function to return the button clicked in a dialog box. Could be wrong about that. (read the javascript function being performed onclick. Might not always work)

intercepting the onload event fired by the browser in watir

I have a unique situation over here. I have a button on a form which produces a popup if there are some errors in the form. [I know this is not good practice, but the developers of the product would not be changing that behavior!] The form navigates to a different page if all the required fields are correctly populated. Now, I need to write a script in order to click the "Submit" button on the form which either might produce a popup or navigate to the next page.
I have the used the click_no_wait on the "Submit" button and handled the popup using AutoIt as per Javascript Popups in Watir. Now, if all the information is valid and the form navigates to the next page, I use a delay in the script by following some of the techniques described in How to wait with Watir. I am using a Watir::wait_until() to wait in the script.
Now sometimes because of some network issues, it takes time to go to the next page (report-generation) page when the form is submitted and thus the script fails because of the timeout value specified in the wait_until.
I was wondering whether there is a way to intercept the onload event of the HTML page in Watir, since the onload event isn't fired until the entire page is loaded. By that way I could have an accurate estimate of the timeout value and not experiment with it. Thus, my script will pass 100% rather than say 98% right now.
Thanks for any help on this topic.
You could try setting up a rescue for the time out, then looping a reasonable amount of times (2 or 3?) if it encounters a timeout.
E.g.
# All your button clicking and autoit stuff here
i = 0
begin
b.wait_until{ # the thing you're waiting to happen }
rescue TheSpecificTimeOutException
# Sorry I can't remember it, the command prompt will tell you exactly
# which one
if i < 3
i += 1
retry
else
raise
end
end
I'm sure i'll have messed something up in the above, or there'll be more concise ways of doing it, but you get the idea. When it times out, give it another few tries before giving up.

Resources