why present? doesn't rely on exists?

26 views
Skip to first unread message

Andrew

unread,
Oct 24, 2011, 2:09:55 PM10/24/11
to clj-we...@googlegroups.com
Why is present? written to throw an exception if the element cannot be found, whereas exists? tries the find-it form and is capable of returning a falsey nil?

present? appears to be written this way...
(defn present? [element]
  (and element (visible? element)))

... but I thought it would be more like this...
(defmacro present? [find-it-form]
  `(let [element# (exists? ~find-it-form)]
     (and element# (visible? element#))))

... since exists? is written like this:
(defmacro exists? [find-it-form]
  `(try 
      ~find-it-form
      (catch org.openqa.selenium.NoSuchElementException e#
        nil)))

semperos

unread,
Oct 24, 2011, 7:06:01 PM10/24/11
to clj-we...@googlegroups.com
A very good question. There's a fine, but ultimately irrelevant, reason for why I coded it that way originally, but I agree it's not quite right.

There are two choices:

(1) Change the way present? works, and require a find-it-form instead of a WebElement object.  This does a double-check for "existence" and "visibility," at the cost of changing the way the function is called.
(2) Remove any explicit check for "existence" in present? and make it another alias for visible?. This changes part of the intent of the function, but accomplishes the same goal (at this point in clj-webdriver's life) and does not change how present? is called.

The reason that exists? even needs to take a find-it form (instead of an object or record) is that clj-webdriver drops down to WebDriver directly when instantiating WebElement objects. This means that, if a find-it query fails to find an object, WebDriver itself throws an exception; that's why exists? uses the try/catch block with find-it.

As a result, this makes the current implementation of present? superfluous, because if an element doesn't exist, the exception will be thrown before present? is ever called, which is the behavior you're seeing.

If at some point I introduce a pure Clojure layer of abstraction over WebElements, then it will be possible to delay the actual instantiation of WebElement objects and we can write exists? like all the other functions that work on elements; by taking an element as its parameter. Until then, I'd like not to leak any more macros of this kind (that take find-it forms instead of WebElement objects) into the API, so I think I'll make present? an alias for visible?. The exists? function is a compromise of the current design, one that has not yet justified adding any more layers of abstraction to the rest of clj-webdriver.

Thanks for pointing this out! If anyone doesn't agree with the above, I'm game for further discussion.

-Daniel

semperos

unread,
Oct 24, 2011, 7:33:35 PM10/24/11
to clj-we...@googlegroups.com
I've added this fix to the fix-present-q branch on Github, located here:


If I don't hear any complaints about this by tomorrow afternoon, I'll commit these changes to master.

-Daniel

semperos

unread,
Oct 25, 2011, 5:21:32 PM10/25/11
to clj-we...@googlegroups.com
Alrighty, I'll take silence as consent.

-Daniel

semperos

unread,
Nov 11, 2011, 12:06:53 AM11/11/11
to clj-we...@googlegroups.com
Follow up:

On the master branch, I've now completed a lot of work in leveraging an Element record in place of direct manipulation of WebElement objects.

What this means for this thread, is that I've refactored the exists? function to work as expected, and have re-defined the present? function in terms of the exists? function.

-Daniel
Reply all
Reply to author
Forward
0 new messages