Project structure
selenium-java-ecommerce/
├─ [Link]
├─ src/
│ ├─ main/
│ │ └─ java/
│ │ ├─ [Link]/
│ │ │ ├─ driver/[Link]
│ │ │ ├─ pages/[Link]
│ │ │ ├─ pages/[Link]
│ │ │ ├─ pages/[Link]
│ │ │ ├─ pages/[Link]
│ │ │ ├─ pages/[Link]
│ │ │ ├─ pages/[Link]
│ │ │ ├─ utils/[Link]
│ │ │ ├─ utils/[Link]
│ │ │ └─ listeners/[Link]
│ └─ test/
│ └─ java/
│ └─ [Link]/
│ ├─ [Link]
│ └─ [Link]
└─ [Link]
1) [Link]
Paste this into your project's root [Link]. It uses Selenium 4, TestNG, WebDriverManager,
and slf4j-simple for basic logging.
<project xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<modelVersion>4.0.0</modelVersion>
<groupId>[Link]</groupId>
<artifactId>selenium-java-ecommerce</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<[Link]>11</[Link]>
<[Link]>11</[Link]>
<[Link]>4.14.0</[Link]>
<[Link]>5.4.1</[Link]>
<[Link]>7.8.0</[Link]>
</properties>
<dependencies>
<!-- Selenium -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>selenium-java</artifactId>
<version>${[Link]}</version>
</dependency>
<!-- WebDriverManager -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${[Link]}</version>
</dependency>
<!-- TestNG -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>testng</artifactId>
<version>${[Link]}</version>
<scope>test</scope>
</dependency>
<!-- SLF4J simple for minimal logs -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
</dependency>
<!-- Apache Commons IO for saving screenshots -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Surefire to run TestNG tests -->
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>[Link]</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</project>
2) DriverFactory
src/main/java/com/example/framework/driver/[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class DriverFactory {
private static ThreadLocal<WebDriver> tlDriver = new ThreadLocal<>();
public static WebDriver getDriver() {
if ([Link]() == null) {
[Link]().setup();
WebDriver driver = new ChromeDriver();
[Link]().window().maximize();
[Link]().timeouts().implicitlyWait([Link](5));
[Link](driver);
return [Link]();
public static void quitDriver() {
WebDriver driver = [Link]();
if (driver != null) {
[Link]();
[Link]();
3) BasePage
src/main/java/com/example/framework/pages/[Link]
package [Link];
import [Link];
import [Link];
import [Link];
public class BasePage {
protected WebDriver driver;
public BasePage() {
[Link] = [Link]();
[Link](driver, this);
public String getCurrentUrl() {
return [Link]();
4) WaitUtils
src/main/java/com/example/framework/utils/[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class WaitUtils {
private WebDriverWait wait;
public WaitUtils(WebDriver driver, int seconds) {
wait = new WebDriverWait(driver, [Link](seconds));
}
public WebElement waitForVisibility(WebElement element) {
return [Link]([Link](element));
public void waitForTitleContains(String part) {
[Link]([Link](part));
5) ScreenshotUtil
src/main/java/com/example/framework/utils/[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class ScreenshotUtil {
public static String takeScreenshot(String namePrefix) {
WebDriver driver = [Link]();
File src = ((TakesScreenshot) driver).getScreenshotAs([Link]);
String ts =
[Link]().format([Link]("yyyyMMdd_HHmmss"));
String filename = "screenshots/" + namePrefix + "_" + ts + ".png";
try {
File target = new File(filename);
[Link](target);
[Link](src, target);
return [Link]();
} catch (IOException e) {
[Link]();
return null;
6) TestListener (screenshot on failure)
src/main/java/com/example/framework/listeners/[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class TestListener implements ITestListener {
@Override
public void onTestFailure(ITestResult result) {
String testName = [Link]().getMethodName();
String path = [Link](testName);
[Link]("Saved screenshot for failure: " + path);
@Override
public void onStart(ITestContext context) { }
@Override
public void onFinish(ITestContext context) { }
@Override
public void onTestStart(ITestResult result) { }
@Override
public void onTestSuccess(ITestResult result) { }
@Override
public void onTestSkipped(ITestResult result) { }
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) { }
7) Pages: HomePage, LoginPage, ProductPage, CartPage, CheckoutPage
These are simplified but robust. Put them under [Link].
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class HomePage extends BasePage {
@FindBy(id = "search_query_top")
private WebElement searchInput;
@FindBy(name = "submit_search")
private WebElement searchButton;
@FindBy(css = "[Link]")
private WebElement signInLink;
public HomePage() {
super();
public void goToHome() {
[Link]("[Link]
new WaitUtils(driver, 10).waitForTitleContains("My Store");
}
public void clickSignIn() {
[Link]();
public void searchFor(String text) {
[Link]();
[Link](text);
[Link]();
public void openProductFromResults(String productName) {
// Find product link by product name text
WebElement productLink = [Link]([Link]("//a[@class='product-name'
and normalize-space()='" + productName + "']"));
[Link]();
[Link]
package [Link];
import [Link];
import [Link];
public class LoginPage extends BasePage {
@FindBy(id = "email")
private WebElement emailInput;
@FindBy(id = "passwd")
private WebElement passwordInput;
@FindBy(id = "SubmitLogin")
private WebElement submitButton;
public LoginPage() {
super();
public void login(String email, String password) {
[Link]();
[Link](email);
[Link]();
[Link](password);
[Link]();
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
public class ProductPage extends BasePage {
@FindBy(id = "add_to_cart")
private WebElement addToCartButton;
@FindBy(css = "[Link]-medium")
private WebElement proceedToCheckoutButton;
public ProductPage() {
super();
public void addToCart() {
[Link]();
// Wait for modal and proceed button
new WaitUtils(driver, 10).waitForVisibility(proceedToCheckoutButton);
public void proceedToCheckoutFromModal() {
[Link]();
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
public class CartPage extends BasePage {
@FindBy(css = "[Link]-checkout")
private WebElement proceedToCheckoutSummary;
public CartPage() {
super();
public void proceedFromSummary() {
// If the quick checkout button isn't present, fallback to alternative locator
try {
[Link]();
} catch (Exception e) {
WebElement alt = [Link]([Link]("//p//a[@title='Proceed to
checkout']"));
[Link]();
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
public class CheckoutPage extends BasePage {
@FindBy(name = "processAddress")
private WebElement processAddressBtn;
@FindBy(name = "processCarrier")
private WebElement processCarrierBtn;
@FindBy(id = "cgv")
private WebElement termsCheckbox;
@FindBy(className = "bankwire")
private WebElement bankWireOption;
@FindBy(xpath = "//button[contains(@class,'button-medium') and @type='submit']")
private WebElement confirmOrderButton;
public CheckoutPage() {
super();
public void proceedAddress() {
new WaitUtils(driver, 10).waitForVisibility(processAddressBtn);
[Link]();
public void acceptTermsAndProceed() {
new WaitUtils(driver, 10).waitForVisibility(termsCheckbox);
if (![Link]()) [Link]();
[Link]();
}
public void payByBankWire() {
[Link]();
public void confirmOrder() {
[Link]();
8) BaseTest and E2ETests
[Link] (test base for setup/teardown)
src/test/java/com/example/tests/[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link].*;
@Listeners({[Link]})
public class BaseTest {
protected WebDriver driver;
@BeforeMethod(alwaysRun = true)
@Parameters({"browser"})
public void setUp(@Optional("chrome") String browser) {
// Currently only chrome handled via DriverFactory - can extend to other browsers
[Link] = [Link]();
@AfterMethod(alwaysRun = true)
public void tearDown() {
[Link]();
[Link] (actual test flows)
src/test/java/com/example/tests/[Link]
package [Link];
import [Link].*;
import [Link];
import [Link];
public class E2ETests extends BaseTest {
@Test(description = "Login with valid credentials (the demo site may require you to create
an account beforehand)")
public void testLogin() {
HomePage home = new HomePage();
[Link]();
[Link]();
LoginPage login = new LoginPage();
// Use an existing demo account if you have one on the demo site
String email = "testuser@[Link]";
String password = "Password123";
[Link](email, password);
// After successful login, My account page title contains "My account"
[Link]([Link]().contains("my-account") ||
[Link]().contains("controller=my-account"),
"User should be on account page after login.");
@Test(description = "Search product, add to cart and proceed to checkout",
dependsOnMethods = {"testLogin"})
public void testSearchAddToCartAndCheckout() throws InterruptedException {
HomePage home = new HomePage();
[Link]();
// Search for a product (e.g., "Faded Short Sleeve T-shirts")
String productName = "Faded Short Sleeve T-shirts";
[Link]("Faded Short Sleeve T-shirts");
// open product from search results
[Link](productName);
ProductPage product = new ProductPage();
[Link]();
[Link]();
CartPage cart = new CartPage();
[Link]();
CheckoutPage checkout = new CheckoutPage();
// If not logged in, here demo site may require sign in; assume logged in (or handle
guest checkout)
[Link]();
[Link]();
[Link]();
[Link]();
// Verify order confirmation (URL or page contains "order-confirmation" or text)
String url = [Link]();
[Link]([Link]("controller=order-confirmation") || [Link]("order-
confirmation") || [Link]("history"),
"Order should be confirmed or in order history.");
Note: The demo site requires registration for full checkout. If you don’t have a user, you can
create one manually on the site or modify tests to skip login and only add-to-cart flow.
9) [Link]
Place at root:
<!DOCTYPE suite SYSTEM "[Link] >
<suite name="ECommerce Test Suite" verbose="1" parallel="false">
<test name="E2E Tests">
<classes>
<class name="[Link].E2ETests"/>
</classes>
</test>
</suite>
10) How to run
1. Make sure Java 11+ and Maven are installed.
2. Clone or create the project and paste files.
3. From the project root run:
mvn clean test
Maven surefire will run TestNG with [Link]. WebDriverManager will download
ChromeDriver automatically. Chrome must be installed.
Screenshots (on failure) will be created under screenshots/.
11) Tips & improvements you can add
• Add [Link] profiles to run headless (--headless) for CI.
• Parameterize base URL, browser, and test data via [Link] or properties.
• Add Page Factory @FindBy for all elements and centralize locators.
• Integrate Allure or ExtentReports for better reporting.
• Add a DataProvider for different products / credentials.
• Add CI config (GitHub Actions) to run tests on push.
12) Quick notes about the demo site & locators
• Demo websites may change their HTML occasionally; if a locator fails, update the
XPath/CSS accordingly.
• The E2ETests assume a registered user exists (testuser@[Link]) — change to a
real registered demo user, or create one on the demo site before running.
Alternatively, remove login dependency and keep only search-add-to-cart-check
modal flows.