I'm trying to use the page object model for my tests and I'm trying to structure my page classes to be able to do a "builder pattern-like" structure (I've not seen it very often so I don't know if it has a name or if it is even a thing) like in this example:
public class Page1 implements Page {
public static Page1 goOn(){
return new Page1();
}
public Page1 action1() {
return this;
}
public Page2 gotoPage2() {
return new Page2();
}
}
public class Page2 implements Page {
public Page2 action2() {
return this;
}
public Page2 gotoPage1() {
return new Page2();
}
}
And then use it like:
Page1.goOn()
.action1()
.gotoPage2() //it return a Page2 object which mean you cant use Page1 methods anymore
.action2() // avoiding using the Page1 object which wouldnt be usable anymore if we stored it
.goToPage1() //and poof we can only use Page1 methods again
.action1()
//etc...
So this is how I would manage "linear" page change, it allows some nice stuff with auto-completion and forces you to only do valid actions before compile time (which I think is great since I hate runtime errors >:( )
Then I'm trying to handle a login page (its mostly a simple example of what I'm gonna have to do next), there are 2 different outputs possible depending on if the login fails or not. For that specific case I could have done 2 functions: public Page1 logIn(){...}
and public Page2 "logInButFail(){...}
but for several reasons I would like to do something like:
public Page logIn(User user) {
//do the login in the page
//IF login worked:
//return new Page2();
//ELSE
//return this; // or new Page1(),
}
The problem is, to keep going with that the methods chain thingy I had before I have to do unsafe casts, which... I can handle them fairly nicely and safely but it means breaking java's sacred rule about typing... And well, my static typing fan's lil' brain has been struggling deciding what to do.
So:
Thanks for any help on the subject, if you need more explanation ask me I will do my best to explain it more precisely (also if you know how this practice is called I'm interested) :)
EDIT: after using the dynamic logIn()
I use the following function to assert the type of the page (this is where I have to do the unsafe cast I try to avoid):
public <T extends Page> T assertPage(Class<T> type){
boolean isgood = (this.getClass.equals(type));
assertTrue(isgood);
if(isgood){
return (T)this; //this is the unsafe cast im trying to avoid
}else{
//throw an exception as this is not supposed to happen
}
}
Page Object Model, also known as POM, is a design pattern in Selenium that creates an object repository for storing all web elements. It is useful in reducing code duplication and improves test case maintenance. In Page Object Model, consider each web page of an application as a class file.
POM stands for Page Object Model. It is a design pattern for creating an Object Repository for web UI elements. Every single web page in the application must have its own corresponding page class, which is in charge of searching the WebElements in that page and then execute operations on them.
One of the Selenium best practices with Page Factory is to create all the web element variables at the beginning of the class and initialize those variables when the page is loaded. The initialization of web elements can be done through the use of initElements methods of the PageFactory class.
static WebDriver driver; Use the same driver inside your @BeforeTest . So inside the before method, instead of doing WebDriver driver = new FirefoxDriver(); write like driver = new FirefoxDriver(); Do same for other browser types (ie, safari, chrome).
So, you want to page-object method, wich will conditionaly return instance of Page1 or Page2. For that, you created method of type Page. And you want to execute this method and continue to work with instance of Page1 or Page2 depends on condition without cast. Right? You can do it via generics. Here is simplified example:
class Page{
<T extends Page> T conditionalAction( T pageObject ){
return pageObject;
}
}
class Page1 extends Page{
Page1 action1(){ return this; }
}
class Page2 extends Page{
Page2 action2(){ return this; }
}
Now, you can do something like:
Page1 page1 = new Page1();
Page2 page2 = new Page2();
page1.action1()
.conditionalAction( page1 )
.action1()
.conditionalAction( page2 )
.action2();
You are free to use such method of generic return type anywhere in your parent/clild class.
And if you want just to assert the class you get from a method, you can do the check:
public Page conditionalAction( boolean condition ) {
if ( condition ) {
return new Page1();
} else {
return new Page2();
}
}
// in test
Page result = new Page1().conditionalAction( true );
if ( result instanceof Page1 ){
Page1 page1 = (Page1) result;
} else if ( result instanceof Page2 ){
Page2 page2 = (Page2) result;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With