Cast clj- webelement to https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/WebElement.html

57 views
Skip to first unread message

Jon Bannister

unread,
Dec 6, 2015, 9:06:29 PM12/6/15
to clj-webdriver
I noticed casting to the underlying selenium webdriver throws - should casting be supported natively in the API?

semperos

unread,
Dec 7, 2015, 6:00:00 PM12/7/15
to clj-webdriver
Could you elaborate on what you mean? The 0.7.x release of clj-webdriver uses a custom Element record which has a :webelement key in it containing the underlying Selenium-WebDriver WebElement object. Did you need something more?

FYI In an upcoming release, the WebElement will likely be used directly, without any Clojure record as a wrapper.

Jon Bannister

unread,
Dec 7, 2015, 7:09:30 PM12/7/15
to clj-webdriver
Thanks for your reply. I'm a newbie to clojure so apologies. 

So does that mean I can do:

(def n (find-element {:css "a.foo"}))
(= (type org.openqa.selenium.Webelement :webelement n))?

My use case is basically to return a list of all elements under a given element without any type metadata, but because find-elements-under returns the currently selected element if it is a (clj) webelement, I thought I needed to cast it to the implementing WebElement to " use ".//" to limit your search to the children of this WebElement"https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/remote/RemoteWebElement.html#findElements(org.openqa.selenium.By)

Jon

Niels van Klaveren

unread,
Dec 9, 2015, 12:31:10 PM12/9/15
to clj-webdriver
With correct parenthesis, that's exactly what you'd get

(def n (find-element {:css "a.foo"}))
(= org.openqa.selenium.Webelement (type (:webelement n)))
=> true
 
 

Niels van Klaveren

unread,
Dec 9, 2015, 12:48:58 PM12/9/15
to clj-webdriver


On Tuesday, December 8, 2015 at 1:09:30 AM UTC+1, Jon Bannister wrote:

My use case is basically to return a list of all elements under a given element without any type metadata, but because find-elements-under returns the currently selected element if it is a (clj) webelement, I thought I needed to cast it to the implementing WebElement to " use ".//" to limit your search to the children of this WebElement"https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/remote/RemoteWebElement.html#findElements(org.openqa.selenium.By)

Jon

Can you just not use the css wildcard and parent operators ?  {:css "table > *"} will return all elements (regardless of type) that have a parent of type table. No mucking about with elements necessary.


Jon Bannister

unread,
Dec 10, 2015, 11:59:01 PM12/10/15
to clj-webdriver
Thanks Niels, 

Yes, after further investigation I discovered css is a much better selector than xpath for traversing parent/child nodes. It also seems more reliable in general, as it returns a greater number of nodes than xpath - not sure what that's all about but anyway.

As for your initial reply, my type check returns the instance class (in my case, org.openqa.selenium.remote.RemoteWebElement) but that's fine in my case. 

1. How do I call an implemented class method though? I tried (prn (.getId :webelement n)) but then get an exception No matching field found: getId for class clj_webdriver.element.Element?

2. If I ever had the need to get the interface and not the instance, is there a way to do that?

Niels van Klaveren

unread,
Dec 11, 2015, 5:10:56 AM12/11/15
to clj-webdriver


On Friday, December 11, 2015 at 5:59:01 AM UTC+1, Jon Bannister wrote:
Thanks Niels, 

Yes, after further investigation I discovered css is a much better selector than xpath for traversing parent/child nodes. It also seems more reliable in general, as it returns a greater number of nodes than xpath - not sure what that's all about but anyway.

As for your initial reply, my type check returns the instance class (in my case, org.openqa.selenium.remote.RemoteWebElement) but that's fine in my case. 

1. How do I call an implemented class method though? I tried (prn (.getId :webelement n)) but then get an exception No matching field found: getId for class clj_webdriver.element.Element?

Another case of errant parenthisation. A keyword (:webelement) can be used as a function for lookup in a map (n), as a shorthand alternative to a full get function call . A function call is done by using it as the first element in an S-expressions. So (.getId (:webelement n)) should work, as shorthand for (.getID (get n :webelement))


2. If I ever had the need to get the interface and not the instance, is there a way to do that?
 
An interface is transparent. If a class implements an interface, you can just call its methods on that class instance
 

semperos

unread,
Dec 16, 2015, 1:36:41 PM12/16/15
to clj-webdriver
Thanks to everyone for helping to answer Jon's questions.

On CSS vs. XPath queries, the Selenium-WebDriver maintainers strongly encourage CSS queries due to more robust support for them.

On classes, interfaces, methods, and functions, Niels is correct. To add a little more information: If you need to see what class something is, you can call (class your-object). If you need to see what interfaces are implemented by that class, you can do (supers (class your-object)) which will include both super-classes and interfaces implemented by the class of your-object.

The situation in clj-webdriver is confusing due to wrapping Java objects in Clojure records which, as I mentioned earlier, will be removed in a future release. Instead of having to do (:webelement element) to get the pertinent Java object, you're element will be that object already.
Reply all
Reply to author
Forward
0 new messages