Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Element#exists doesn't relocate element when it becomes stale #810

Closed
abotalov opened this issue Oct 19, 2018 · 5 comments
Closed

Element#exists doesn't relocate element when it becomes stale #810

abotalov opened this issue Oct 19, 2018 · 5 comments

Comments

@abotalov
Copy link
Contributor

Expected Behavior -

In some circumstances user may assume that Watir relocates stale element when it doesn't.
I thought that:

browser.element(class_name="x").wait_until_not(lambda e: e.exists)

may wait for page to have no elements with class "x". But it actually waits for the first element with class "x" to disappear.
I'd like to ask if there's a reason behind current behavior of not relocating stale element.

The user currently should wait until list of elements becomes empty in this example case.

Actual Behavior -

If element is stale and exists is called, the method doesn't relocate element to check if there is another element that corresponds to locator.

Steps to reproduce -

from nerodia import browser

br = browser.Browser()
# this page contains two elements, first one disappears after one second
br.goto("http://jsfiddle.net/sbhnru40/show")
li = br.iframe().li()
print li.exists  # prints True
li.wait_until_not(lambda e: e.exists, timeout=3)
print li.exists  # prints False
br.quit()
@titusfortner
Copy link
Member

Yeah, I see your point and there are a bunch of related issues here.

I do want the notion of a Watir Element to be "whatever exists at the location provided". BUT. For performance reasons we cache the element and don't always re-look it up. AND for consistency reasons we call a referenced element dead.

Your expectation here is that after the DOM changes, the first time you call li.exists it should return false, and the second time you call it, it should be true. When the DOM doesn't change, you shouldn't get different results on subsequent calls of the same method. It should either never returns false because it immediately finds the second element (probably the most internally consistent approach, but would have negative performance ramifications), or it always returns false once the cache is invalidated, which I see your point seems a little weird if you can actually still do something with an element that exists at that address.

It probably depends on the actual use case you have and not this easily reproducible issue as to how best to approach it. You might be looking for li.wait_until(&:stale?)for when the cached value goes stale.

@titusfortner
Copy link
Member

titusfortner commented Oct 19, 2018

Hmmm, maybe calling #exists? on a stale element, should call reset, then attempt to relocate instead of just returning false. That wouldn't be a huge performance hit.

@abotalov
Copy link
Contributor Author

abotalov commented Oct 19, 2018

Your expectation here is that after the DOM changes, the first time you call li.exists it should return false, and the second time you call it, it should be true.

To be honest, my assumption was that li.exists will return true both times. So I expected script in "Steps to reproduce" to fail.

But that would prevent the use case to check that the first of elements becomes removed (it could be checked by checking length of element collection).

@titusfortner
Copy link
Member

Ok, just realized that this should be part of the stale_present deprecation (http://watir.com/staleness-changes/) and I just missed it. It'll go on the list of things to actually be fixed in 7.0, but I'll add the deprecation notifications about this for 6.15.

@titusfortner
Copy link
Member

Thanks for bringing this inconsistency to my attention.

Not sure how Nerodia is doing this, but for 7.0 we'll go through and remove all deprecations. I'll close this issue since we'll be tracking it separately.

Expected behavior is:

br = Watir::Browser.new
br.goto("http://jsfiddle.net/sbhnru40/show")
li = br.iframe.li
br.iframe.lis.size # => 2
li.exists?  # => true
# this will time out because there is always an li in the iframe
# li.wait_while(&:exists?) 
sleep 2
li.exists? # => true
br.iframe.lis.size # => 1
br.quit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants