Java Β· JUnit 5
E-commerce with Selenium
Automate a full shopping journey β login, catalogue, cart, coupons, checkout and order history.
App under test
Nova Shop
- URL
- /shop
- User
- demo_user
- Password
- Demo@123
- Coupons
- SAVE10 Β· FLAT20
- Declined card
- 4000 0000 0000 0002
Scenarios to automate
Work top to bottom β each one adds a new technique.
- 1
Valid & invalid login
Beginnerdemo_user / Demo@123 succeeds; wrong password and empty fields show login-error.
- 2
Locked-out user
Beginnerlocked_user gets βSorry, this user has been locked out.β
- 3
Slow login
Intermediateslow_user takes ~3s β wait for the URL or product grid, never sleep.
- 4
Route guard
BeginnerVisiting /shop/cart signed out redirects to /shop.
- 5
Search, filter & sort
IntermediateAssert product-count text, no-results state, and that product-price values are sorted.
- 6
Cart badge & quantities
IntermediateAdd/remove from the grid, change qty in the cart, check line-total and totals maths.
- 7
Coupons
IntermediateSAVE10 = 10% off, FLAT20 = $20 off above $100, anything else is rejected.
- 8
Checkout validation
IntermediateSubmit empty to collect error-* messages; fix them one by one.
- 9
Declined card
Advanced4000 0000 0000 0002 shows payment-error; switch to Cash on delivery and succeed.
- 10
Order history
AdvancedOrder id on the success page must appear in orders-table after navigation.
Sample Selenium suite
A working starting point written against this app's real data-testids.
import org.junit.jupiter.api.*;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.*;
import java.time.Duration;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.openqa.selenium.support.ui.ExpectedConditions.*;
class NovaShopTest {
static final String BASE = "http://localhost:3000";
WebDriver driver;
WebDriverWait wait;
By tid(String id) { return By.cssSelector("[data-testid='" + id + "']"); }
void type(String id, String text) { driver.findElement(tid(id)).sendKeys(text); }
@BeforeEach
void signIn() {
driver = new ChromeDriver();
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
driver.get(BASE + "/shop");
wait.until(elementToBeClickable(tid("username"))).sendKeys("demo_user");
type("password", "Demo@123");
driver.findElement(tid("login-button")).click();
wait.until(urlContains("/shop/products"));
}
@AfterEach
void tearDown() { driver.quit(); }
@Test
void buyHeadphonesWithCoupon() {
wait.until(elementToBeClickable(tid("search-input"))).sendKeys("headphones");
wait.until(numberOfElementsToBe(tid("product-card"), 1));
driver.findElement(tid("add-to-cart-p1")).click();
wait.until(textToBe(tid("cart-badge"), "1"));
driver.findElement(tid("cart-link")).click();
wait.until(elementToBeClickable(tid("coupon-input"))).sendKeys("SAVE10");
driver.findElement(tid("apply-coupon")).click();
wait.until(textToBePresentInElementLocated(tid("discount"), "$13.00"));
driver.findElement(tid("checkout-button")).click();
wait.until(elementToBeClickable(tid("first-name"))).sendKeys("Ada");
type("last-name", "Lovelace");
type("email", "ada@example.com");
type("phone", "5551234567");
type("address", "1 Analytical Way");
type("city", "Austin");
new Select(driver.findElement(tid("state"))).selectByVisibleText("Texas");
type("zip", "73301");
type("card-name", "Ada Lovelace");
type("card-number", "4242424242424242");
type("card-expiry", "1230");
type("card-cvv", "123");
driver.findElement(tid("accept-terms")).click();
driver.findElement(tid("place-order")).click();
// ~2s of "processing" β an explicit wait, not Thread.sleep.
String orderId = wait.until(visibilityOfElementLocated(tid("order-id"))).getText();
assertTrue(orderId.matches("NS-\\d+"), "Unexpected order id: " + orderId);
}
@Test
void sortsByPriceLowToHigh() {
new Select(wait.until(elementToBeClickable(tid("sort-select")))).selectByValue("price-asc");
List<Double> prices = driver.findElements(tid("product-price")).stream()
.map(e -> Double.parseDouble(e.getText().replace("$", ""))).toList();
assertEquals(prices.stream().sorted().toList(), prices);
}
}