sensiolabs / BehatPageObjectExtension

MIT License
117 stars 48 forks source link

Have Page subclasses to hold site-wide element locators and methods #125

Closed mgiagante closed 5 years ago

mgiagante commented 5 years ago

In the site I want to test there are element locators and methods to click/get them that are present in various pages. I'd like to have a MySitePage class inheriting from Page to hold those locators and methods, and then have, for instance MySiteHomePage, MySiteAboutPage, etc. inheriting from MySitePage to obtain those element locators and methods plus the ones specific to the page in the site they model. Like so:

abstract MySitePage extends Page
{
    protected $elements = array(
        'Facebook Share' => '.headerbar-share .share-facebook',
    );
}

MySiteHomePage extends MySitePage
{
    protected $elements = array(
        'Title H1' => 'h1.ng-binding'
    );
}

So far I've tried this but I got the following error when I try to get one of the elements whose locators are in the MySitePage class from one of the feature context methods:

class MySiteHomePageContext extends PageObjectContext
{
    public function iClickOnTheFacebookShareIcon()
    {
        $this->getPage('My Site Homepage')->getElement('Facebook Share')->click();
    }
}

Could not find a class for the "Facebook Share" element. None of the configured namespaces worked: "\Pages\Element\FacebookShare, \Pages\MySite\Element\FacebookShare" (InvalidArgumentException)

I'm aware that the $element array is being overriden by MySiteHomePage, so I thought I'd need to access the same property in the parent class and merge them, but that doesn't seem to work too.

Is there any approach for having inheritance work with Pages or any other plausible approach to achieve the same kind of element locator reuse?

Thanks in advance!

DonCallisto commented 5 years ago

I suppose you could take advantage of custom elements for this kind of scenarios.

mgiagante commented 5 years ago

Thanks @DonCallisto . Looking at the documentation for custom elements

https://behat-page-object-extension.readthedocs.io/en/stable/guide/working_with_elements.html#custom-elements

it seems like a custom element is used by the page that contains it, but I can't find exactly how (namespacing, use, etc.).

If I could write custom element classes and use them across pages, that'd be what I'm looking for.

Is this possible?

DonCallisto commented 5 years ago

@mgiagante I think is not something constrained to PHP concepts (like namespace). AFAIK underlying mechanism works by perfoming a DOM search in the "current" page. If you have some elements that you use inside other elements, the search will be performed by "chaining" the selectors in order to query the DOM. To use the custom element inside the page, just follow the link and see the example.

mgiagante commented 5 years ago

Thank you!