-
Notifications
You must be signed in to change notification settings - Fork 1
Home
#Examples
Note: In the code example I refer to the Scala version. The Java version is less "fancy", but similar.
Unlike other libraries, declaring DOM elements has nothing to do with the browser. The browser will be accessed only when we need to perform an action or an assertion. This allows to easily define arbitrarily complex elements based on other elements, without worrying about impact to performance, stale elements or other timing issues.
Declare DOM element as you typically describe them in English. Debug them easily since their description is English-like. The DSL allows to build arbitrarily complex definitions easily.
val dialog = div withClass "ui-dialog" withText "foo"
println(dialog)
// div, that has class "ui-dialog", and has the text "foo"
val myButton = button withClass "foo" that((has textContaining "submit")) inside dialog
println(myButton)
// button, that has class "foo", and (has text containing "submit"), inside (div, that has class "ui-dialog", and has the text "foo")
val shoppingCart = dialog describedBy "\"shopping cart\" dialog"
println(shoppingCart withClasses ("foo", "bar"))
// "shopping cart" dialog, that has classes [foo, bar]
val buyButton = button inside shoppingCart that(has text "buy!")
println(buyButton)
// button, inside ("shopping cart" dialog), and has the text "buy!"
println(div that( has no cssClass("foo", "bar")) or (span withClass "moo"))
//(div, that has non of the classes: [foo, bar]) or (span, that has class "moo")
val name = listItem withClass "first-name" describedBy "first name entry"
println(!(name that(has text "Danny")))
// anything except (first name entry, that has the text "Danny")
val myEntry = name that(has text "Jason") describedBy "Jason's entry"
println(name that (is siblingOf myEntry))
// first name entry, that has sibling: Jason's entryNo need to remember a specific API or a brittle css/xpath. The grammar is flexible. Code it the way you think about it. EASY!
val dialog = div withClass "ui-dialog"
// All the following expressions are equivalent:
val row = has cssClass "abcd" inside dialog
val row = has cssClass "abcd" and (is inside dialog)
val row = has cssClass "abcd" and (is containedIn dialog)
val row = has cssClass "abcd" and (is descendantOf dialog)
val row = has cssClass "abcd" and (has ancestor dialog)
val row = element inside dialog withClass "abcd"
val row = is inside dialog withClass "abcd"
val row = element withClass "abcd" inside dialog
val row = element withClass "abcd" descendantOf dialog
val row = element that(has cssClass "abcd") inside dialog
val row = element that(has cssClass "abcd", has ancestor dialog)
val row = element that((has cssClass "abcd") and (has ancestor dialog))
val row = element that(has cssClass "abcd") and (has ancestor dialog)See the "test" folder for many examples of the expressiveness of the API to declar a "Path" object.
Alright. You defined the elements you want to interact with. The next time is probably to perform some actions. Some examples :
click on myButton / click at myButton
hover over myButton
doubleClick on myButton
sendKeys("a", "b", "c", "def") to el
sendKeys("abc") toBrowser()
pressKeyDown(Keys.ALT) inBrowser()
releaseKey(Keys.ALT) whileFocusedOn el
dragAndDrop(el) to anotherElement
dragAndDrop(el) to offset (10, 10)
scroll to el / scroll right 100The emphasis is on ease and readability. Simple!
The examples above use the single-browser flavor of the library, for simplicity. The "standard" flavor is multiple-browser.
The library includes custom matchers for ScalaTest and Hamcrest. These matchers are optimized for performance, readability, and clear error messages.
The following snippets are taken from:
dollarx-example/src/test/java/info/dollarx/ExampleTest.scala, and demonstrate the single-browser flavor of the library, for simplicity.
Note how simple it is to understand the tests.
val results = div that (has id "search")
val resultsLink = anchor inside results
val amazonAsFirstResult = first occurrenceOf resultsLink and (has textContaining "amazon.com")
amazonAsFirstResult must be(present)What would happen if an assertion fails? Let's say we assert:
val results = div that (has id "search")
val resultsLink = anchor inside results describedBy "search result"
val amazonResult = resultsLink that (has textContaining "amazon.com")
amazonResult must appear(1000 timesOrMore)Running the test will result in:
org.scalatest.exceptions.TestFailedException: search result, that has text
containing "amazon.com" should appear at least 1000 times, but it appears
5 times
at org.scalatest.MatchersHelper$....
at .....
...
Much more readable than "Expected 1000, found 5"...
But the difference is much more than skin deep. In the typical success scenario, the assertion above will query atomically for an html element that contains "amazonResult" a thousand or more times. This is not only a lot faster (one element compared to 1000), it is also more correct, since it solves issues related to race conditions, especially prominent when working with frameworks with dynamic templating, such as AngularJS.
More examples can be found under jdollarx-example, dollarx-example directories.
For the behavior tests examples (in dollarx-example, jdollarx-example) to work, you need to download the chrome selenium driver and set an environment variable 'CHROMEDRIVERPATH' to its path location.