Search code examples
seleniumspockgeb

How to use a Geb module as content in another Geb module and verify content?


I am using Geb (1.1.1) and Spock (1.1-groovy-2.4) and the selenium drivers (2.53.1) to test an Angular 4 web application. If I have a single-page webapp and if I want to set up the content to be a hierarchy of Modules, how can I ensure that if I navigate to a page object, it will look at the hierarchy of modules and verify the content? For example, if I have the following page class:

class HomePage extends Page {
    static url = 'home'
    static at = {
        title == 'Home Page' && mainViewModule.displayed
    }
    static content = {
        mainViewModule { module MainViewModule }
    }
}

and then MainViewModule is defined like this:

class MainViewModule extends Module {
    static content = {
        mainView { $('div', class: 'main-view') }
        dashboardModule { module DashboardModule }
    }
}

then DashboardModule:

class DashboardModule extends Module {
    static content = {
        dashboard = { MainViewModule.find 'dashboard' }
        subModule1 = { module SubModule1 }
        subModule2 = { module SubModule2 }
    }
}

where the submodules generally look like this:

class SubModuleX extends Module {
    static content = {
        ...
    }
}

If my tests (using Spock) do the following:

class SomeSpec extends GebReportingSpec {
    def 'navigate to the home page'() {
        when:
        to HomePage

        then:
        at HomePage
    }
}

How can I ensure that it verifies the content defined in the HomePage class, as well as down through the hierarchy of modules? The way that I have the code (as described above), I can change the selectors to incorrect values, but it still doesn't fail the test.

Since this is a single-page application, I want to avoid making the HomePage class inordinately long, so it makes sense to me to break up the page's parts and functionality into logical pieces through the use of modules. I prefer to relate the modules through aggregation, rather than composition via extending a higher-level (or containing) module, and it makes sense that it should be able to verify the content down through the hierarchy of aggregated modules, but please let me know if my assumption is wrong. If I am wrong in my assumption, how should I approach this and avoid including everything in the HomePage class?

Thanks, Steve


Solution

  • You could do something like this:

    class HomePage extends Page {
        static url = 'home'
        static at = {
            title == 'Home Page' && mainViewModule.verify()
        }
        static content = {
            mainViewModule { module MainViewModule }
        }
    }
    

    then inside of your mainViewModule:

    class MainViewModule extends Module {
        static content = {
            mainView { $('div', class: 'main-view') }
            dashboardModule { module DashboardModule }
        }
    
        def verify(){
            try{
                //assert content for this module here
                return dashboardModule.verify()
            }
            catch(GebAssertionError ae){
                return false
            }
        }
    }
    

    Then in the DashboardModule:

    class DashboardModule extends Module {
        static content = {
            dashboard = { MainViewModule.find 'dashboard' }
            subModule1 = { module SubModule1 }
            subModule2 = { module SubModule2 }
        }
        def verify(){
            try{
                //assert content for this module here
                return subModule1.verify() && subModule2.verify()
            }
            catch(GebAssertionError ae){
                return false
            }
        }
    }
    

    I assume you can follow the pattern from here, but let me know if you can't and I will explain further.