The concept of Page Fragments and motivation behind them were already introduced in Page Abstractions. Here you can find more detailed info about:
- Relation to Page Objects
- Creating Page Fragments
- Samples of Page Fragments
Page Fragments and Page Objects are similar concepts. They both decouples HTML structure of the tested application from the tests. They both encapsulate some kind of page services or the interactions a user can do with the page.
The difference is that Page Objects are encapsulating a specific page (or its part) of specific application, while Page Fragments are dealing with parts of the page, its widgets, components, basically fragments which are reusable across the whole web UI framework in which the application under test is written.
To use Page Fragment in your tests only thing you need to do is use an implementation class of the Page Fragment together with @FindBy annotation pointing to the root of the fragment.
Use @FindBy annotation as you are used to with plain WebElement, so indeed you can use other locating strategies (xpath, id, className, ...) to reference the root of the Page fragment. The root of the fragment is DOM element which is parent for all other elements which are part of the Page fragment and need to be referenced from it (e.g. Calendar and its cells).
These Page fragments and other WebElement fields are dynamically initialized by Graphene so no need to initialize them via factories.
There is another way to create Page Fragments. You can create them dynamically with use of Graphene.createPageFragment(Class<T> clazz, WebElement root). This may be particularly useful when implementing Page Fragment for e.g. Tab Panel widget.
To define own Page Fragment one needs to:
- Recognize a fragment of the page which can be abstracted and encapsulated into a Page Fragment (Basically web UI components which are rendered always with the same DOM structure.)
- Create a class or if you find it appropriate also an interface for it.
- Define the parts you need for implementing the fragment's services, which will be referenced from the injected root. Annotate them with @FindBy annotation.
- Define the methods which are basically encapsulation of the fragment services (Calendar services - get date, set date, ...).
If you need to access the injected root of your Page Fragment, you ca do so by declaring a WebElement field with a @Root annotation. There are two packages from where you can import @FindBy annotation:
- org.openqa.selenium.support.FindBy - well know @FindBy from Selenium 2
- org.jboss.arquillian.graphene.enricher.findby.FindBy - [Graphene FindBy annotation] which adds on top of classic @FindBy many useful features
So the implementation can look like snippet below.
with the xpath locators. They can be written in a way that it does not matter from which element they are referenced. Prefer therefore locating according to id, css or class name.
Indeed you will need a reference for WebDriver instance. You can easily inject it with @Drone annotation.
|Note that you have to use private fields for all Graphene initialized WebElement/Page Fragments etc. Use their getters from tests.|
|Page fragments in Multiple Browsers scenario|
If you use page abstractions together with parallel browsers feature, be sure to check Using Page Abstractions with Multiple Browsers.
Let's consider following code snippets, which are reflecting some examples of the Page Fragments to start with. In each example you can find:
- An image of the page fragment to be clear what we are speaking about.
- HTML structure of the page fragment rendered in RichFaces framework.
- Example of the Page Fragment encapsulation, either the implementation or just the interface for it.