Geb's page objects don't prevent one from making higher-level methods to abstract the WebDriver API, so I don't think it's a matter of something that Geb is doing. I haven't tried using an inner trait for that, so I'm not sure about the trade-offs. I guess it would give one some static type safety, but a false sense of safety, because it would seem to apply to the whole test class, but I wouldn't expect it to work unless the test were on the right page at the time.

For comparison, I use a page property with a closure, which I expect will be dynamically available where it is relevant in the test:

import grails.util.Holders as CH

class CasLoginPage extends Page {
    static at = {title =="University of Hawaii Web Login Service" }

    def login = { testuser ->
        $("input",name:"username").value( testuser )
        $("input",name:"password").value(casTestPassword())
        $("input",value:"Login").click()
    }

    private static casTestPassword() {
        def pw 
=System.getProperty('casTestPassword',CH.config?.cas?.test?.password ?:null)
        if (!pw) {
            def configMethods = [
'* define cas.test.password="xxx" in $HOME/grails-conf/taps-secret-config.groovy, or',
                    '* for running in IDE without Grails, use JVM option 
-DcasTestPassword=xxx' ]
            throw new IllegalStateException('configure password xxx for Load 
Testing CAS like so:\n' + configMethods.join('\n'))
        }
        pw
    }
}


My tests can use it like this:

def "main menu requires CAS login"() {

    when:
    via MainMenuPage then:
    at CasLoginPage }

def "can login as an hourly employee"() {

    given:
    assert at(CasLoginPage)

    when:
    login(emplData.username )

    then:
    at MainMenuPage displayName ==emplData.name


However, I wouldn't add levels of abstraction that don't reduce duplicate code or clarify the test. My tests often call click() directly on content, and use locators directly. Abstracting the content locator in a Page class makes sense if it makes the test easier to read, and allows for changing multiple uses of the locator in one place in case the HTML/CSS changes. But, what good would it do to abstract the click() call? Would it make the test more clear?

def "can get choices of old pay period"() {

    given:
    assert at(MainMenuPage)

    when:'revealing inactive appointments to choose from' 
previousAppointmentsLink?.click()

    and:'selecting an hourly Appointment with an empty previous period' 
$("label",text:contains((String)emplData.plcSummary)).click()

and:'creating for other than the current period (so this spec can use static dates)' createOtherTimesheetButton.click()

    then:
    at EmployeeCreateTimesheetForOtherPeriodPage $("#payPeriod\\.id 
option").size() >1 }


Cheers,
11011011

On 2017-02-03 03:44 , [email protected] wrote:
Hello everyone,

I'm a little confused about Page Object Pattern implementation at Geb. I'm talking about *test classes* extended from GebSpec/GebReportingSpec. I'm very impressed about Page implementation, especially about static url, content and at field but according to Martin Fowler blog https://martinfowler.com/bliki/PageObject.html <https://martinfowler.com/bliki/PageObject.html> and Simone Stewart (founder of WebDriver project):

    |If you have WebDriver APIs in your test methods, You're Doing It
    Wrong|

||
|
Let's talk about this piece of code

    source: http://www.gebish.org/pages:

|import geb.BrowserBrowser.drive { to LoginPageassert at(LoginPage) loginForm.with{ username ="admin" password ="password"} loginButton.click()assert at(AdminPage)}| |This example is excellent prove that Geb doesn't implement Page Object Pattern in obvious way. In my opinion this is not full support for Page Object Pattern. |
|I think that Martin Fowler is right about:|

    The page object should encapsulate the mechanics required to find
    and manipulate the data in the gui control itself.

Previously, I was working a lot with pure WebDriver API and Java. When I started use Groovy I was very impressed for a moment. After that I realised that dynamically typed language like Groovy is very helpful but not in this case. I resolved this in inner trait. That's the example:
|
|
|
classMyPage  extendsPage  {

     staticat =  {  ...  }

     staticcontent =  {  element{  ...  }  }

     trait MyPageTrait  {

         defdoSomethingOnMyElement()  {
             element.click()
         }
     }

}

classMyTest  extendsGebSpec  implementsMyPage.MyPageTrait  {

     def"do some test"()  {
         expect:
         doSomethingOnMyElement()
     }

}
|

|
What do you think about it? I'm open to have discuss. I'm not sure If I'm right but I've reason to think that Geb does it wrong. Please, fell free to suggest anything you like.
Ɓukasz
-- You received this message because you are subscribed to the Google Groups "Geb User Mailing List" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected] <mailto:[email protected]>. To post to this group, send email to [email protected] <mailto:[email protected]>. To view this discussion on the web visit https://groups.google.com/d/msgid/geb-user/ac68e36c-d488-4483-9654-ffa5027dfe56%40googlegroups.com <https://groups.google.com/d/msgid/geb-user/ac68e36c-d488-4483-9654-ffa5027dfe56%40googlegroups.com?utm_medium=email&utm_source=footer>. For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Geb User 
Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/geb-user/264f62bf-957c-81d1-a3ac-55bd5dfe97cf%40getsu.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to