Last index can't be located - ruby

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

Related

Cypress check that text either does not exist or is invisible

I want to check that a piece of text either does not even exist in the DOM or that if it exists, it is invisible.
cy.contains(text).should("not.visible) handles the second case, cy.contains(text).should("not.exist") the first, but either of them fails in the case of the other.
Before trying a conditional solution, have a read through this paragraph
https://docs.cypress.io/guides/core-concepts/conditional-testing#Error-Recovery
This is a feature that they intentionally made not available
Enabling this would mean that for every single command, it would recover from errors, but only after each applicable command timeout was reached. Since timeouts start at 4 seconds (and exceed from there), this means that it would only fail after a long, long time.
every cy...should has a built-in timeout, so if you have multiple your wait time would stack.
TL;DR;
If you can get around having to use a conditional, try that approach first
Alternatively, you can use this trick (at your peril 😉).
cy.get("body").then(($body) => {
if ($body.find(":contains(texta)").length > 0) {
cy.contains("texta").should("not.be.visible");
} else {
cy.contains("texta").should("not.exist");
}
});
cy.get("body").then(($body) => { will get the copy of body(DOM) in the current state and make it available for synchronous querying using jQuery. With jQuery we can determine synchronously whether an element contains the text string with $body.find(":contains(text)")
using the result's length you can make a condition that will then fire off cypress' asynchronous assertions.

watir/ruby waiting for iframe to exist

I have a problem waiting for an iframe to exist on page after entering a date range and I would rather not use sleep. I am using ruby/watir
I have tried solutions like this -
wait_until(10, "iFrame has not loaded") do
#browser.iframe(id: "dtl00_DP1_content").exists?
end
but this simply returns this error - Selenium::WebDriver::Error::NoSuchWindowError: no such window
So how do I wait for an iframe that does not yet exist please?
I am not sure whether you only want to wait for an Iframe, If you want to perform any operation on an element which is present in the iframe, then you could do as I mentioned in my comment.
#browser.iframe(name: "something").text_field(name: "username").set 'raja'
Or If you still wait for an iframe to appear, then write the following code
#browser.wait_until { #browser.iframe(id: "dtl00_DP1_content").exists? }
The above code waits for 30 seconds, but If you want to increase the time to wait, then write the following code, the following code would wait fo 50 seconds.
#browser.wait_until(timeout: 50) { #browser.iframe(id: "dtl00_DP1_content").exists? }

Watir webdriver - click an element and not wait for load

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

Combining implicit wait and explicit wait together results in unexpected wait times

My two scenarios -
1) First
#driver.manage.timeouts.implicit_wait = 30
#wait = Selenium::WebDriver::Wait.new(:timeout => 45) # Time greater than implicit
#wait.until {#driver.find_element(:tag_name => "body").text.include?("hey")}
Which gives the driver 45 seconds to search for the text(which is expected)
2) Second
#driver.manage.timeouts.implicit_wait = 30
#wait = Selenium::WebDriver::Wait.new(:timeout => 5) # Time less than implicit
#wait.until {#driver.find_element(:tag_name => "body").text.include?("hey")}
This now gives the driver 30 seconds to search for the text(not expected)
Is there a way to make selenium wait only for the explicit wait time and not for the greater of the two?
Note - Not declaring the implicit wait time is not an option, cause I cannot afford to let selenium hang each time the driver is unable to find something.
Using Selenium version 30, windows, ff
Don't mix implicit and explicit waits. Part of the problem is that implicit waits are often (but may not always be!) implemented on the "remote" side of the WebDriver system. That means they're "baked in" to IEDriverServer.exe, chromedriver.exe, the WebDriver Firefox extension that gets installed into the anonymous Firefox profile, and the Java remote WebDriver server (selenium-server-standalone.jar). Explicit waits are implemented exclusively in the "local" language bindings. Things get much more complicated when using RemoteWebDriver, because you could be using both the local and remote sides of the system multiple times.
This is how that would work: local code -> Java remote server -> local Java language bindings on the remote server -> "remote" component like the Firefox extension, chromedriver.exe or IEDriverServer.exe. It's even more complex in the grid case, since there could be other hops in between.
Thus, when you try to mix implicit and explicit waits, you've strayed into "undefined behavior". You might be able to figure out what the rules of that behavior are, but they'll be subject to change as the implementation details of the drivers change. So don't do it.
You shouldn't be experiencing "hangs" when an element can't be found if you're not using implicit waits. The driver should throw a NoSuchElement exception immediately.
The best practice is to set implicitlyWait() at the beginning of each test, and use WebDriverWait() for waiting an element, or AJAX element to load.
However, implicitlyWait() and WebDriverWait() do not work well together in the same test.
You would have to nullify implicitlyWait() before calling WebDriverWait because implicitlyWait() also sets the "driver.findElement()" wait time.
Whenever you are using WebDriverWait() with implicitlyWait() already set some initial value, follow the steps -
nullifying implicitlyWait()
executing WebDriverWait (), and return element
reset implicitlyWait() again
Example Java code -
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //nullify implicitlyWait()
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS);

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