Skip to content
markysoft1 edited this page May 13, 2016 · 6 revisions

Element Locating

General

If Vani instantiates a PageObject or FragmentObject class, it will create a proxy for all fields annotated by locator annotation. So it's possible to instantiate the class although desired html elements are still unavailable.

If you don't want to get only a single matching element, the type of annotated field must be List. In that case, the generic type of the List is important, because this will be used for resolving target element type. For example

@FindBy(className= "componentBox")
private List<WebElement> components;

//or for using fragments
@FindBy(css = "${content.css.componentBox}")
private List<ComponentFragment> components;

In the above example, the list instance is also a proxy. So any call on the instance, will trigger the locating.

Caching

Selenium provides a feature called Cache Lookup. This means, that only the first access triggers the locating. After that, the same html object will be always used.

To enable this feature. you have to annotate the corresponding field with @CacheLookup.

The handling of this feature by Vani differs little bit from Selenium. Vani will always cache all matching element except single WebElement or JQueryElement due to performance reasons. If the page is changed, you must call the invalidate method on PageObject or only on single fragment when not the complete page was changed.

Selenium Selectors

Selenium brings some annotations for declaring specific locating strategy of elements. These are following:

  • FindBys - allows you to declare multiple selectors at once with AND conjunction (all selectors must be fulfilled)
 @FindBys({@FindBy(id = "foo"),
           @FindBy(className = "bar")})
  • FindAll - similar to FindBys but it uses OR as conjunction (at least one selector must be fulfilled)
 @FindAll({@FindBy(how = How.ID, using = "foo"),
           @FindBy(className = "bar")})
  • FindBy - allows various selectors like id, name, className, cssSelector, tagName, xpath or linkText
 @FindBy(id = "foobar")

Vani supports all of them and provide you the power of springs's placeholder mechanism. For example:

 @FindBy(id = "${content.id.login.username}")

JQuery Selectors

Additionally, Vani gives you the possibility to use jQuery's selectors. So you are more flexible and they are more powerful than Selenium's one. For example:

 @FindByJQuery("${content.jq.searchInput}")
 private JQueryElement inputSearch;

In the above example, we use the JQueryElement class as type for our field. It's also possible to use the normal WebElement class, because JQueryElement is only a subclass of it, which provides some jQuery function counterparts.

The regex selector can also be used in the @FindByJQuery annotation.

For more information about using jQuery, please see jQuery Integration or for complete documentation about all jQuery selectors.

If you want multiple matching elements, you should not use a list, because the JQueryElementLocator holds a reference on a jQuery object (which has itself an array of matching html elements).

Custom Selectors

If you want to implement an own locating strategy, you have to do following steps:

  • Create your Locator-annotation (like @FindByJQuery)
  • Create your By implementation (like ByJQuery)
  • Create an implementation of LocatorBuilder (This class is responsible for creating an instance of your By implementation by converting your Locator-annotation. For example see JQueryLocatorBuilder implementation).

That's all. You don't have to instantiate the locator builder. This will be done by Vani