Skip to content

Higher level abstractions

nico78 edited this page Dec 14, 2014 · 3 revisions

####Extracted Method Often in webapps there are particular concepts that are specific to the app or domain, which we want to refer to frequently. For example we may have an introduction section on a page, that is represented in html like:

<div class="section-introduction">...</div>

To locate this, we can of course use div().that( hasCssClass("section-introduction"))

but if it's needed frequently this can get repetitive and error-prone.

We can easily abstract this by creating a method :

private static MFinder<...> introductionSection() {
  return div().that( hasCssClass("section-introduction"));
}

and the assertion becomes: browser.assertPresenceOf( introductionSection() );

This also means if we change what an introduction section looks like in html we just have to change it in one place.

####..with parameters

If we have lots of types of sections:

<div class="section-introduction">...</div>
<div class="section-conclusion">...</div>

we can just parameterise the method :

private static MFinder<...> section(String sectionType) {
   return div().that( hasCssClass("section-"+sectionType));
 }

and assertions become

browser.assertPresenceOf( section("introduction") );
browser.assertPresenceOf( section("conclusion") );

...

####..and a nice description

For the above examples, if something wasn't found, you'd still get the message in terms of divs and css class.

Expected: a(n) div that has css class "section-introduction"
but:
No element with cssClass "section-introduction" found at all

If instead, you think it makes more sense to use your domain/abstraction's terminology then it's easy to make that happen by using the Describer.describedAs method, which just wraps a Finder and gives it a new name to refer to it as:

private static MFinder<...> section(String sectionType) {
  return Describer.describedAs(sectionType +" section", div().that( ...));
}

Now if your assertion fails you would get:

Expected: a(n) introduction section
but:
No element with cssClass "section-introduction" found at all

The expectation part is now in your domain's terms, although the explanation is always in low-level terms.

####More complex example This is particularly useful when you have more complex finder expressions:

public MFinder<...> menuItem(String optionText) {
   return  describedAs("Menu item " +optionText, 
                     div().that(hasCssClass("menu-option"))
                          .that(hasSubElement( link(optionText))));
}

The above defines a "menu item" by looking for a div with css class "menu-option" which surrounds a link (<a> tag) with the text shown. So: menuItem("Home") would be a finder for the div element below:

<div class="menu-option">
  <a href="...">Home</a>
 ...
</div>