The Shopping Portal (/shopping) tests a different set of patterns than banking. Here you deal with product catalogs, search results, cart management, and multi-step checkout. Let us build page objects and tests for the complete shopping flow.
package com.testerrank.pages.shopping;
import com.testerrank.base.BasePage;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import java.util.List;
public class ShopHomePage extends BasePage {
private final By searchBox =
By.cssSelector("[data-testid='search-input']");
private final By searchButton =
By.cssSelector("[data-testid='search-btn']");
private final By featuredProducts =
By.cssSelector("[data-testid='featured-product']");
private final By cartIcon =
By.cssSelector("[data-testid='cart-icon']");
private final By cartBadge =
By.cssSelector("[data-testid='cart-count']");
public ShopHomePage(WebDriver driver) {
super(driver);
}
public CatalogPage searchFor(String keyword) {
logger.info("Searching for: " + keyword);
type(searchBox, keyword);
click(searchButton);
return new CatalogPage(driver);
}
public int getFeaturedProductCount() {
return getElementCount(featuredProducts);
}
public CartPage openCart() {
logger.info("Opening cart");
click(cartIcon);
return new CartPage(driver);
}
public String getCartCount() {
try {
return getText(cartBadge);
} catch (Exception e) {
return "0";
}
}
}package com.testerrank.pages.shopping;
import com.testerrank.base.BasePage;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import java.util.List;
public class CatalogPage extends BasePage {
private final By productCards =
By.cssSelector("[data-testid='product-card']");
private final By productNames =
By.cssSelector("[data-testid='product-name']");
private final By productPrices =
By.cssSelector("[data-testid='product-price']");
private final By addToCartButtons =
By.cssSelector("[data-testid='add-to-cart']");
private final By sortDropdown =
By.cssSelector("[data-testid='sort-select']");
private final By noResultsMessage =
By.cssSelector("[data-testid='no-results']");
private final By categoryFilter =
By.cssSelector("[data-testid='category-filter']");
public CatalogPage(WebDriver driver) {
super(driver);
}
public int getProductCount() {
return getElementCount(productCards);
}
public List<String> getProductNames() {
return getTexts(productNames);
}
public List<String> getProductPrices() {
return getTexts(productPrices);
}
public void addProductToCart(int index) {
List<org.openqa.selenium.WebElement> buttons =
driver.findElements(addToCartButtons);
if (index < buttons.size()) {
logger.info("Adding product at index "
+ index + " to cart");
buttons.get(index).click();
} else {
throw new RuntimeException(
"Product index " + index
+ " out of range. Total: " + buttons.size());
}
}
public void sortBy(String sortOption) {
logger.info("Sorting by: " + sortOption);
selectByVisibleText(sortDropdown, sortOption);
}
public boolean isNoResultsDisplayed() {
return isDisplayed(noResultsMessage);
}
public void filterByCategory(String category) {
logger.info("Filtering by category: " + category);
click(By.xpath(
"//label[contains(text(),'" + category + "')]"));
}
}package com.testerrank.pages.shopping;
import com.testerrank.base.BasePage;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import java.util.List;
public class CartPage extends BasePage {
private final By cartItems =
By.cssSelector("[data-testid='cart-item']");
private final By itemNames =
By.cssSelector("[data-testid='cart-item-name']");
private final By removeButtons =
By.cssSelector("[data-testid='remove-item']");
private final By checkoutButton =
By.cssSelector("[data-testid='checkout-btn']");
private final By emptyCartMessage =
By.cssSelector("[data-testid='empty-cart']");
private final By totalPrice =
By.cssSelector("[data-testid='cart-total']");
public CartPage(WebDriver driver) {
super(driver);
}
public int getItemCount() {
return getElementCount(cartItems);
}
public List<String> getItemNames() {
return getTexts(itemNames);
}
public String getTotal() {
return getText(totalPrice);
}
public void removeItem(int index) {
List<org.openqa.selenium.WebElement> buttons =
driver.findElements(removeButtons);
if (index < buttons.size()) {
logger.info("Removing item at index " + index);
buttons.get(index).click();
}
}
public CheckoutPage proceedToCheckout() {
logger.info("Proceeding to checkout");
click(checkoutButton);
return new CheckoutPage(driver);
}
public boolean isCartEmpty() {
return isDisplayed(emptyCartMessage);
}
}package com.testerrank.pages.shopping;
import com.testerrank.base.BasePage;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class CheckoutPage extends BasePage {
private final By firstNameField = By.id("firstName");
private final By lastNameField = By.id("lastName");
private final By emailField = By.id("email");
private final By addressField = By.id("address");
private final By cityField = By.id("city");
private final By zipField = By.id("zip");
private final By placeOrderButton =
By.cssSelector("[data-testid='place-order-btn']");
private final By orderConfirmation =
By.cssSelector("[data-testid='order-confirmation']");
private final By orderNumber =
By.cssSelector("[data-testid='order-number']");
public CheckoutPage(WebDriver driver) {
super(driver);
}
public void fillShippingDetails(String firstName,
String lastName,
String email,
String address,
String city,
String zip) {
logger.info("Filling shipping details for: "
+ firstName + " " + lastName);
type(firstNameField, firstName);
type(lastNameField, lastName);
type(emailField, email);
type(addressField, address);
type(cityField, city);
type(zipField, zip);
}
public void placeOrder() {
logger.info("Placing order");
click(placeOrderButton);
}
public boolean isOrderConfirmed() {
try {
waitForVisible(orderConfirmation);
return true;
} catch (Exception e) {
return false;
}
}
public String getOrderNumber() {
return getText(orderNumber);
}
}package com.testerrank.tests.shopping;
import com.testerrank.base.BaseTest;
import com.testerrank.pages.shopping.*;
import com.testerrank.utils.DataProviders;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.List;
public class ShoppingE2ETests extends BaseTest {
private ShopHomePage homePage;
@BeforeMethod
public void navigateToShop() {
navigateTo("/shopping");
homePage = new ShopHomePage(getDriver());
}
@Test(priority = 1,
groups = {"smoke", "regression"},
description = "Verify home page loads with products")
public void testHomePageLoads() {
Assert.assertTrue(
homePage.getFeaturedProductCount() > 0,
"Featured products should be displayed");
}
@Test(priority = 2,
groups = {"smoke", "regression"},
description = "Search for product and verify results")
public void testProductSearch() {
CatalogPage catalog = homePage.searchFor("laptop");
Assert.assertTrue(catalog.getProductCount() > 0,
"Search should return results for 'laptop'");
List<String> names = catalog.getProductNames();
logger.info("Found " + names.size() + " products");
}
@Test(priority = 3,
groups = {"regression"},
dataProvider = "searchTerms",
dataProviderClass = DataProviders.class,
description = "Data-driven search with multiple terms")
public void testSearchDataDriven(String keyword,
String expectedMinCount) {
logger.info("DDT Search: keyword=" + keyword);
CatalogPage catalog = homePage.searchFor(keyword);
int count = catalog.getProductCount();
int minExpected = Integer.parseInt(expectedMinCount);
Assert.assertTrue(count >= minExpected,
"Expected at least " + minExpected
+ " results for '" + keyword
+ "', got " + count);
}
@Test(priority = 4,
groups = {"regression"},
description = "Search with invalid term shows no results")
public void testSearchNoResults() {
CatalogPage catalog = homePage.searchFor(
"xyznonexistent12345");
Assert.assertTrue(
catalog.isNoResultsDisplayed()
|| catalog.getProductCount() == 0,
"No results for invalid search");
}
@Test(priority = 5,
groups = {"smoke", "regression"},
description = "Add product to cart and verify count")
public void testAddToCart() {
CatalogPage catalog = homePage.searchFor("laptop");
Assert.assertTrue(catalog.getProductCount() > 0);
catalog.addProductToCart(0);
// Navigate back to home to check cart count
navigateTo("/shopping");
homePage = new ShopHomePage(getDriver());
CartPage cart = homePage.openCart();
Assert.assertEquals(cart.getItemCount(), 1,
"Cart should have 1 item");
}
@Test(priority = 6,
groups = {"regression"},
description = "Remove item from cart and verify empty")
public void testRemoveFromCart() {
// Add a product first
CatalogPage catalog = homePage.searchFor("headphones");
catalog.addProductToCart(0);
// Open cart and remove
navigateTo("/shopping");
homePage = new ShopHomePage(getDriver());
CartPage cart = homePage.openCart();
Assert.assertEquals(cart.getItemCount(), 1);
cart.removeItem(0);
Assert.assertTrue(cart.isCartEmpty(),
"Cart should be empty after removal");
}
@Test(priority = 7,
groups = {"smoke", "regression"},
description = "Full E2E: Search > Add > Checkout > Confirm")
public void testCompleteCheckoutFlow() {
// Step 1: Search and add product
logger.info("Step 1: Search and add to cart");
CatalogPage catalog = homePage.searchFor("laptop");
String productName =
catalog.getProductNames().get(0);
catalog.addProductToCart(0);
logger.info("Added: " + productName);
// Step 2: Open cart and verify
logger.info("Step 2: Verify cart");
navigateTo("/shopping");
homePage = new ShopHomePage(getDriver());
CartPage cart = homePage.openCart();
Assert.assertEquals(cart.getItemCount(), 1);
Assert.assertTrue(
cart.getItemNames().contains(productName));
// Step 3: Proceed to checkout
logger.info("Step 3: Checkout");
CheckoutPage checkout = cart.proceedToCheckout();
checkout.fillShippingDetails(
"Rahul", "Sharma", "rahul@test.com",
"123 MG Road", "Bangalore", "560001");
// Step 4: Place order and verify
logger.info("Step 4: Place order");
checkout.placeOrder();
Assert.assertTrue(checkout.isOrderConfirmed(),
"Order should be confirmed");
String orderNum = checkout.getOrderNumber();
Assert.assertNotNull(orderNum,
"Order number should be generated");
logger.info("Order placed: " + orderNum);
}
@Test(priority = 8,
groups = {"regression"},
description = "Sort products by price and verify order")
public void testSortByPrice() {
CatalogPage catalog = homePage.searchFor("laptop");
catalog.sortBy("Price: Low to High");
List<String> prices = catalog.getProductPrices();
logger.info("Sorted prices: " + prices);
Assert.assertTrue(prices.size() > 1,
"Need multiple products to verify sorting");
}
@Test(priority = 9,
groups = {"regression"},
description = "Verify empty cart shows message")
public void testEmptyCart() {
CartPage cart = homePage.openCart();
Assert.assertTrue(cart.isCartEmpty(),
"Empty cart message should be displayed");
}
}Q: How do you test an e-commerce checkout flow? What are the key scenarios?
A: For an e-commerce checkout, I test the complete happy path first: search for a product, add to cart, verify cart contents, fill shipping details, place order, and verify the order confirmation with an order number. Then I cover negative scenarios: checkout with empty cart (should be blocked), removing items from cart, invalid shipping details (missing required fields), and searching for products that do not exist. I also test sorting and filtering in the catalog. Each test is independent — @BeforeMethod navigates to the shop home page fresh, so no test depends on cart state from a previous test.
Cart state can leak between tests if you are not careful. Always start each test with a known state. Either clear the cart in @BeforeMethod, or navigate to a fresh session. Tests that depend on leftover cart items from previous tests will fail randomly in parallel execution.
Key Point: Shopping portal tests cover search, filter, cart, and checkout. Each test starts fresh. Data-driven search tests the catalog with multiple keywords.