It brings together the power of WebDriver, the elegance of jQuery content selection, the robustness of Page Object modelling and the expressiveness of the Groovy language.
simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.” - jquery.com
simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.” - jquery.com
Page Objects driver.findElement(By.name("username")).sendKeys("username"); driver.findElement(By.name("password")).sendKeys("password"); driver.findElement(By.name("submitButton")).click(); Don’t do this
{ container { $("div#container") } pageName { container.find("h1").text() } footer { module Footer, $("div#footer") } } } The content block is a DSL for naming the content on the page.
{ container { $("div#container") } pageName { container.find("h1").text() } footer { module Footer, $("div#footer") } } } The $() function is used to select page content It’s jQuery like
matchers») Any CSS expression supported by the browser (Complete CSS3, except for HTMLUnit) $("div.some-class p:first[title='something']") $("ul li a") $("table tr:nth-child(2n+1) td") $("div#content p:first-child::first-line")
text matchers») Select content by index or grab a bunch with a range <p>a</p> <p>b</p> <p>c</p> $("p", 0) // a $("p", 2) // c $("p", 0..1) // a & b $("p", 1..2) // b & c
{ container { $("div#container") } pageName { container.find("h1").text() } footer { module Footer, $("div#footer") } } } You can specify the base in the content DSL when defining the module in the owner
<tr> <td>Zero History</td><td>William Gibson</td> </tr> <tr> <td>The Evolutionary Void</td><td>Peter F. Hamilton</td> </tr> </tbody> </table> Modules are great for repeating content
{ auxillaryPageLink { $("ul.links a", text: iContains(it)) } contactUsLink(to: ContactUsPage) { auxillaryPageLink("contact us") } } } Content can define what page it navigates to when it is clicked
message"() { when: name = "Peter Niederwieser" email = "[email protected]" sendButton.click() then: at ContactUsPage errorMessage == "message is required" } Assigning to undefined properties sets the form value of the control with that name
a message"() { when: name = "Peter Niederwieser" email = "[email protected]" sendButton.click() then: at ContactUsPage errorMessage == "message is required" } Defined content in DSL can be anything
errorMessage(required: false) { $("span.errorMessage").text() } sendButton(to: [ContactUsPage, FrontPage]) { $("input#FeedbackAdd_0") } } } Pages can extend each other, inheriting all defined content and methods etc. Works for modules too
// use default waiting configuration waitFor { «something» } // wait for up to 10 seconds, using the default retry interval waitFor(10) { «something» } // wait for up to 10 seconds, waiting half a second between retries waitFor(10, 0.5) { «something» } // use the preset “quick” as the wait settings waitFor("quick") { «something» }
// wait for content to be present waitFor { $("p") } // wait for a condition waitFor { $("p").text() == "Message sent!" } // wait for any Groovy truth value waitFor { $("p").collect { it.text() } } // wait for a JavaScript redirect waitFor { at Somepage }
will automatically wait for it when it’s requested class DynamicPage extends Page { static content = { dynamicallyAdded(wait: true) { $("p.dynamic") } } }