Assume that you have 2 page classes implemented with Page Factory.
HomePage first:
public class HomePage {
private WebDriver driver;
private static final String HOME_PAGE_URL = "https://www.vpl.ca/";
@FindBy(id = "edit-search")
public WebElement searchBox;
@FindBy(id = "edit-submit")
public WebElement searchButton;
public HomePage(WebDriver driver) {
PageFactory.initElements(driver, this);
this.driver = driver;
}
public void open() {
driver.get(HOME_PAGE_URL);
}
public boolean isDisplayed() {
return driver.getCurrentUrl().equalsIgnoreCase(HOME_PAGE_URL);
}
}
ResultsPage second:
public class ResultsPage {
private WebDriver driver;
private static final String RESULTS_PAGE_URL =
"https://vpl.bibliocommons.com";
@FindBy(xpath = "(//span[@data-key = 'pagination-text'])[1]")
public WebElement resultsFoundLabel;
@FindBy(xpath = "//li[contains(@class, 'page-number')]/a[@data-page = '2']")
public WebElement page2;
@FindBy(xpath = "//li[contains(@class, 'page-number')]/a[@data-page = '3']")
public WebElement page3;
@FindBy(xpath = "//li[contains(@class, 'page-number')]/a[@data-page = '4']")
public WebElement page4;
public ResultsPage(WebDriver driver) {
PageFactory.initElements(driver, this);
this.driver = driver;
}
public boolean isDisplayed() {
return getUrl().startsWith(RESULTS_PAGE_URL);
}
public String getUrl() {
return driver.getCurrentUrl();
}
public void scrollToBottom() throws InterruptedException {
((JavascriptExecutor) driver).executeScript(
"window.scrollTo(0, document.body.scrollHeight)");
}
}
Both page classes have all web elements declared as public.
This means that we can use them directly in a test script:
@Test
public void canNavigateToOtherPagesTest() throws InterruptedException {
HomePage homePage = new HomePage(driver);
homePage.open();
Verify.verify(homePage.isDisplayed(), "home page is not displayed!");
homePage.searchBox.sendKeys(KEYWORD);
homePage.searchButton.click();
ResultsPage resultsPage = new ResultsPage(driver);
Verify.verify(resultsPage.isDisplayed(), "results page is not displayed!");
Verify.verify(resultsPage.resultsFoundLabel.getText().contains("1 to 10"),
"results found label does not include 1 to 10!");
resultsPage.scrollToBottom();
resultsPage.page2.click();
Assert.assertTrue(resultsPage.getUrl().contains("page=2"));
resultsPage.scrollToBottom();
resultsPage.page3.click();
Assert.assertTrue(resultsPage.getUrl().contains("page=3"));
resultsPage.scrollToBottom();
resultsPage.page4.click();
Assert.assertTrue(resultsPage.getUrl().contains("page=4"));
}
The page classes seem shorter since there are less methods in them (because we interact with the page elements directly in the test script).
The test script is clear enough.
Is this a good practice then? To have all elements declared as public?
It is not.
Let’s see why:
no class should have any fields declared as public; this exposes the objects of the class to changes in their state which could lead to unpredictable situations; imagine that an element of the ResultsPage class is set in the test script; what could the implications of this be?
the test script is written at a very low level as it focuses not on what is being done but instead on how it is being done; instead of focusing on user actions like searching or going to a page, it prefers to do things like clicking, typing and getting values of elements
the test script mixes page methods that work at the page level with methods that work with web elements
We create the ResultsPage object in the test script
The navigation from home page to results page is no longer clear in the test script
All these are bad ideas.
Do not have public fields of any page class, regardless of using Page Object Model or Page Factory.