Waiting for Element DOM Change

194 views
Skip to first unread message

Jeff Nyman

unread,
Nov 3, 2017, 8:43:22 AM11/3/17
to Watir General
I have a Watir script that works against one of my sample sites. I'll provide that below. There's one part where I have to put a `sleep` statement. I'm curious how Watir can be used to handle this without the sleep statement. All of these will not work:


browser.element(:id, "navlist").wait_until(&:visible?).click
browser
.element(:id, "navlist").wait_until(&:present?).click
browser
.element(:id, "navlist").wait_until(&:enabled?).click

Here is the script:

#!/usr/bin/env ruby


require 'rspec/expectations'
include
RSpec::Matchers


require 'watir'


browser
= Watir::Browser.new


browser
.window.move_to 0, 0
width
= browser.execute_script("return screen.width;")
height
= browser.execute_script("return screen.height;")
browser
.window.resize_to(width, height)


browser
.goto 'https://veilus.herokuapp.com'


expect
(browser.title).to match 'Veilus'
expect
(browser.img(:id, "site-image").exists?).to be_truthy


browser
.element(:id, "open").click
browser
.text_field(:id, "username").set! "admin"
browser
.text_field(:id, "password").set! "admin"
browser
.input(:id, "login-button").click


login_text
= browser.div(:class, "notice").text
expect
(login_text).to eq("You are now logged in as admin.")


sleep
2
browser
.element(:id, "navlist").click

browser
.link(:id, "stardate").click


expect
(browser.title).to match 'Stardate Calculator'
expect
(browser.url).to match 'stardate'
expect
(browser.img(:id, "stardate-logo").exists?).to be_truthy


browser
.quit


You can see the sleep statement there before the navlist is clicked. If you take out the sleep, the script will fail. As mentioned, the waiting until aspects do not work because it's never the case that the element isn't there nor that it isn't visible. It's just that a put a little JavaScript in place that makes the element pop out after a brief delay.

I'm just curious regarding what the idiomatic Watir solution for this would be.

- Jeff

rajagopal...@gmail.com

unread,
Nov 3, 2017, 9:22:34 AM11/3/17
to Watir General
browser.element(:id, "navlist")


Is it a pop up?

And are you aware that `set!` function is using JavaScript not Selenium send_keys?

Jeff Nyman

unread,
Nov 3, 2017, 10:07:59 AM11/3/17
to Watir General


On Friday, November 3, 2017 at 8:22:34 AM UTC-5, rajagopal...@gmail.com wrote:
browser.element(:id, "navlist")


Is it a pop up?

And are you aware that `set!` function is using JavaScript not Selenium send_keys?

It's not a pop-up, no. That script will actually run against it and you can see. It's basically just a paragraph element that pops out from the right edge of the screen. That element is only partly visible when the page is first loaded; then there's a delay, and then some JavaScript causes the paragraph to "pop out" a bit so it's selectable.

Also, yes, I am aware of the `set!` function and how that works. In this case, however, set! is not being used for the element in question. It's just a click. These two lines are really the key ones:

sleep 2
browser
.element(:id, "navlist").click

Without that sleep, the next line fails. But wait_until checks also fail because the element in question is always present, visible, and enabled.

So I'm just curious how people, using Watir, handle these kinds of situations.

- Jeff


Titus Fortner

unread,
Nov 3, 2017, 10:45:07 AM11/3/17
to watir-general
You have to look at what is different in the condition you want vs the condition you don't.
In this case you want to wait for `element.div(id: 'areas').style('left') == '-50em'` (or  something)
If you have open the inspector you can see that value changing during page load.

--
--
Before posting, please read http://watir.com/support. In short: search before you ask, be nice.
 
watir-...@googlegroups.com
http://groups.google.com/group/watir-general
watir-general+unsubscribe@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "Watir General" group.
To unsubscribe from this group and stop receiving emails from it, send an email to watir-general+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jeff Nyman

unread,
Nov 3, 2017, 11:18:32 AM11/3/17
to Watir General

On Friday, November 3, 2017 at 9:45:07 AM UTC-5, Titus Fortner wrote:
You have to look at what is different in the condition you want vs the condition you don't.
In this case you want to wait for `element.div(id: 'areas').style('left') == '-50em'` (or  something)
If you have open the inspector you can see that value changing during page load.

I've tried things like that but it doesn't seem to work. Maybe I'm doing things wrong. For example, I tried this originally: 

browser.wait_until { browser.element(:id, "navlist").style("right") == "-20px" }

That's for the navlist element. That's where it rests after it pops out. That still leads to this error when trying to click it:

unknown error: Element is not clickable at point (-4, 130) (Selenium::WebDriver::Error::UnknownError)

Basically, the same error that would happen if the sleep statement wasn't there. I did do something similar to what you suggest, like this:

browser.wait_until { browser.element(:id, "areas").style("left") == "-50em" }

That's for the div element that wraps the navlist. That simply gives this:

in `until': timed out after 30 seconds, waiting for true condition on

Basically, it just times out, never recognizing the condition.

The line in my project that causes the pop-out is this:


These things were put in place specifically to trip up automation to see how different libraries handle it.

- Jeff

Titus Fortner

unread,
Nov 3, 2017, 11:25:06 AM11/3/17
to Watir General
Call the style('left') method after your sleep to see what the correct final value is. I didn't actually test it.

Jeff Nyman

unread,
Nov 3, 2017, 11:45:56 AM11/3/17
to Watir General

On Friday, November 3, 2017 at 10:25:06 AM UTC-5, Titus Fortner wrote:
Call the style('left') method after your sleep to see what the correct final value is. I didn't actually test it.

Yep, just played around with it some more. So the trick is that the style returns the pixels. I can do something like this:

browser.wait_until { browser.element(:id, "areas").style("left") == "-700px" }

It starts out at -714px. So here the check is for the pixel location after the pop-out.

Reply all
Reply to author
Forward
0 new messages