Back to Challenges
Extract a Page Object
intermediate Java 20 minThree tests repeat the same login steps with inline locators. Extract a LoginPage that hides locators and waits.
The Scenario
The login page is about to get a redesign: the email field becomes a username field and the submit button gets a test id. Three tests contain the same four locators, and there are twelve more tests in other files that log in the same way.
Your Task
Extract a LoginPage class so a locator change is a one-line fix, and rewrite the three tests to use it. Assume a DashboardPage with an isWelcomeVisible() method exists.
What Good Looks Like
- Locators are private and appear once.
- Public methods are named for what a user does, not for which element they touch.
- Navigation methods return the next page object; waits live inside the page object.
- The tests shrink to a few readable lines each.
Your task
Three tests repeat the same login steps with inline locators. Extract a LoginPage that hides locators and waits.
Problem Code
@Test void loginShowsDashboard() {
driver.get("https://app.example.com/login");
driver.findElement(By.id("email")).sendKeys("qa@example.com");
driver.findElement(By.id("password")).sendKeys("secret");
driver.findElement(By.cssSelector("button[type=submit]")).click();
new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.urlContains("/dashboard"));
assertTrue(driver.findElement(By.cssSelector("h1.welcome")).isDisplayed());
}
@Test void wrongPasswordShowsError() {
driver.get("https://app.example.com/login");
driver.findElement(By.id("email")).sendKeys("qa@example.com");
driver.findElement(By.id("password")).sendKeys("wrong");
driver.findElement(By.cssSelector("button[type=submit]")).click();
WebElement error = new WebDriverWait(driver, Duration.ofSeconds(10))
.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".alert-error")));
assertEquals("Invalid credentials", error.getText());
}
@Test void emptyFormShowsValidation() {
driver.get("https://app.example.com/login");
driver.findElement(By.cssSelector("button[type=submit]")).click();
assertEquals(2, driver.findElements(By.cssSelector(".field-error")).size());
}
Need Help?
Solution
Try to solve the challenge yourself before revealing the solution.
Lessons that cover this
- Page Object Model Learn the Page Object Model (POM) design pattern for writing maintainable and scalable Selenium tests.
- Driver Factory and Thread Safety Build a WebDriver factory that reads configuration, supports local, Grid and cloud targets, and hands each parallel test its own driver via ThreadLocal or fixtures without leaks.