Hi again. I am in need of some help, and though my track record suggests
the possibility I've overlooked something obvious, I've dug as deep as I'm
able and haven't come up with an answer yet so I thought to ask here.
I commonly implement a click() method override within modules. I do this to
redirect clicks directed toward the module to a more appropriate content
element within the module for easier/thoughtless clicking from specs. I
discovered the pattern when modeling checkbox facades, and to date, it's
worked without issue, though my use cases have been relatively
straightforward so far.
I'm modeling a new application now though, and my page objects are becoming
increasingly complex. At this point, I'm implementing parameterized modules
from within modules that are extended from parameterized module classes,
and I'm finding I'm unable to intercept clicks bound for my innermost
modules.
That is to say, I write a method in the module to intercept and redirect
the click, as I always have:
class SideNavItem extends Module {
String itemName
static content = {
container (required: false)
{ label.closest('a') }
label (required: false)
{ $('.mat-list-item-content', text: iEndsWith(itemName)) }
}
@Override
Navigator click() {
log.debug("DOING CUSTOM CLICK")
container.click()
}
@Override
boolean isDisplayed() {
log.debug("DOING CUSTOM ISDISPLAYED")
container.isDisplayed()
}
Navigator click(boolean please) {
log.debug("DOING CUSTOM CLICK WITH BOOLEAN")
container.click()
}
}
But, the click() ends up being directed to the navigator on which the
module is based, resulting in the wrong element being clicked, and my
custom log line is never logged. If I am more specific in the spec, and
click the container directly, my custom method isn't called of course, but
I get the expected result, so I know my override method would work if it
were invoked.
To check my logic, I did two things. First I implemented a custom
isDisplayed() override just as I did the click() override, and it works as
expected. If I call .isDisplayed() on the module, my custom isDisplayed()
override method is invoked as the debug line is logged.
To take it one step further, I created a click(boolean) method; and if I
call .click(true) on the module from my spec, again my override method is
invoked and I get the expected result.
So I'm at a bit of a loss at this point - I'm not sure why I can't invoke
my custom click() method, or what I could adjust to maintain my level of
abstraction and still get the desired effect.
I know it probably doesn't mean much with Groovy, but if I switch my spec
syntax to use fully-qualified page class names, when I 'go to definition'
on the module's click() method within IntelliJ IDEA, it goes straight to my
custom method.
Have I indeed overlooked something simple? Is there anything further I can
do to troubleshoot?
As I mentioned, the parent module extends from a base class that is also
parameterized. Here's the child class:
class TrafficReports extends SideNavGroup {
static content = {
financeTrafficDetailsReport (to: FinanceTrafficDetailsReport,
required: false)
{ panel.module(new SideNavItem(itemName: 'Finance Traffic
Details Report')) }
}
}
Here's the base class (whose @Override click() method works as expected):
class SideNavGroup extends Module {
String groupName
static content = {
container
{ label.closest('mat-expansion-panel') }
header
{ container.$('mat-expansion-panel-header') }
label
{ $('mat-panel-title', text: groupName) }
disclosureWidget
{ header.$('.mat-expansion-indicator') }
panel (required: false)
{ container.$('.mat-expansion-panel-body') }
}
@Override
Navigator click() { disclosureWidget.click() }
boolean isExpanded() { header.hasClass('mat-expanded') }
boolean isCollapsed() { !isExpanded() }
Navigator expand() {
Navigator nav
if (isCollapsed()) {
nav = click()
waitFor { isExpanded() }
}
nav
}
Navigator collapse() {
Navigator nav
if (isExpanded()) {
nav = click()
waitFor { isCollapsed() }
}
nav
}
@Override
// Return only the content names unique to the child class
Set<String> getContentNames() {
super.getContentNames() - ['container', 'header', 'label',
'disclosureWidget', 'panel']
}
}
Here is the root SideNav module which instantiates the groups:
class SideNav extends Module {
static content = {
trafficReports
{ module(new TrafficReports(groupName: 'Traffic Reports')) }
}
Navigator open() {
Navigator nav
if (!navigator.isDisplayed()) {
nav = browser.page.mainNav.menu.click()
waitFor { navigator.isDisplayed() }
}
nav
}
}
Finally, SideNav is implemented on a base page class from which all pages
extend:
abstract class MyAppPage extends Page {
static at = {
// The menu icon is lazy loaded and can take a few seconds
mainNav.menu
// Wait for side nav to close in case we used it to navigate
!sideNav.isDisplayed()
}
static content = {
mainNav
{ $('.primary-nav-bar').module(MainNav) }
sideNav
{ $('mat-sidenav').module(SideNav) }
}
}
Infinite thanks,
Trey
--
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 view this discussion on the web visit
https://groups.google.com/d/msgid/geb-user/CAErttkUYerejEjBBYUn92bBzqm_AWwDe%3DVh6vO23BcuqowGphw%40mail.gmail.com.