Search code examples
javagroovyspockgeb

Is this the right way to use "at" closure in Geb


Scenario: I have a login page which uses ajax to validate a user and if invalid login, it stays on the same page.

I am wondering if this is the correct way to use the at in Geb or I can improvise on this. Concerns:

  1. I am using waitFor with hard-coded timeout etc.
  2. Should waitFor be in at block?
  3. Is there a better way of writing this?

Spec def

def "perform invald login"()
{
    given: "I am at the login page"
    to LoginPage

    when : "I entered invalid data"
    loginForm.loginClientCode = "test"
    loginForm.loginSystemCode = "test"
    loginForm.loginUserId = "test"
    loginForm.loginPassword = "test"

    loginButton().click()

    then: "Log in attempt unsuccessful"
    at(LoginPage)
}

Page object

class LoginPage extends Page
{
    static url = "login/login.jsf";

    static at =
    {
        waitFor(10,0.5)
        {  $("div.ic-h1").text() == "User Authentication" }
    }

    static content =
    {
        loginForm
        {
            $("form",id: "loginForm")
        }

        loginButton
        {
            $("button", id: "loginButton")
        }

        statusMessages
        {
            $('div.ui-messages').text()
        }
    }
}

Solution

  • We usually keep the at only for the purpose of verification and then do:

    waitFor{ at LoginPage }
    

    But this might not be needed given the new support for implicit assertions in 0.7. http://www.gebish.org/manual/snapshot/implicit-assertions.html#at_verification

    I think what you really want here is to test for the existence of an error message and waitFor that.

    i.e,

     loginButton().click()
    
     then: "Log in attempt unsuccessful"
     waitFor{ statusMessage == 'this login failed' }
    

    since you can't really get your then condition to fail otherwise.

    Moreover, you could probably put the condition into a state of your page object, so something like

    def isErrorState() {
        statusMessage == 'this login failed'
    }
    

    and in your test, it becomes easier to read.

    waitFor{ isErrorState() }