PAPracticeAutomation
Se

Java ยท JUnit 5

Ticket booking with Selenium

Automate a movie booking โ€” dates, filters, a seat map, snacks, promos, OTP payment and a seat-hold timer.

App under test

ShowTime

URL
/tickets
Login
not required
Promos
MOVIE50 ยท FIRSTSHOW
Card OTP
123456
Seat hold
5 minutes
Launch ShowTime โ†’

Scenarios to automate

Work top to bottom โ€” each one adds a new technique.

  1. 1

    Date strip

    Beginner

    Seven date-option chips from today; dates are computed from the browser clock.

  2. 2

    Filters

    Beginner

    Combine genre-* toggles, language-filter and movie-search; assert movie-card count.

  3. 3

    Showtime states

    Intermediate

    data-status is available / filling / soldout / started โ€” disabled ones can't be clicked.

  4. 4

    Seat map

    Intermediate

    Pick seats by data-status, verify selected-seat chips and seat-total per tier.

  5. 5

    Seat limit

    Intermediate

    The 9th seat shows seat-limit-error.

  6. 6

    Snacks & promo codes

    Intermediate

    MOVIE50 halves tickets (max $10); FIRSTSHOW only works on a first booking.

  7. 7

    OTP payment

    Advanced

    Card payments open otp-modal; 123456 passes, anything else shows otp-error.

  8. 8

    Async UPI approval

    Advanced

    UPI shows payment-processing for ~3s before the confirmation page.

  9. 9

    Hold timer

    Advanced

    Seats are held for 5:00. Mock the clock to hit timer-expired without waiting.

  10. 10

    Cancel a booking

    Advanced

    Cancel from My bookings, confirm the dialog, and find it under the Cancelled tab.

Sample Selenium suite

A working starting point written against this app's real data-testids.

ShowTimeTest.java
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 static org.junit.jupiter.api.Assertions.*;
import static org.openqa.selenium.support.ui.ExpectedConditions.*;

class ShowTimeTest {
  static final String BASE = "http://localhost:3000";
  WebDriver driver = new ChromeDriver();
  WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

  By tid(String id) { return By.cssSelector("[data-testid='" + id + "']"); }
  void type(String id, String text) { driver.findElement(tid(id)).sendKeys(text); }

  @AfterEach
  void tearDown() { driver.quit(); }

  @Test
  void bookTwoSeatsAndPayByCard() {
    driver.get(BASE + "/tickets");
    wait.until(numberOfElementsToBeMoreThan(tid("date-option"), 1)).get(1).click(); // tomorrow
    new Select(wait.until(elementToBeClickable(tid("city-select")))).selectByVisibleText("London");
    wait.until(textToBePresentInElementLocated(tid("movie-list"), "Riverside Screens"));

    WebElement movie = driver.findElement(By.xpath(
        "//li[@data-testid='movie-card'][.//h2[normalize-space()='Nebula Drift']]"));
    movie.findElement(By.cssSelector("[data-testid='showtime']:enabled")).click();

    By freeSeat = By.cssSelector("[data-testid^='seat-'][data-status='available']");
    wait.until(elementToBeClickable(freeSeat)).click();
    driver.findElement(freeSeat).click();          // first *remaining* free seat
    wait.until(numberOfElementsToBe(tid("selected-seat"), 2));
    driver.findElement(tid("proceed-button")).click();

    wait.until(elementToBeClickable(tid("contact-name"))).sendKeys("Grace Hopper");
    type("contact-email", "grace@example.com");
    type("contact-phone", "5559876543");
    driver.findElement(tid("snack-popcorn-inc")).click();
    type("promo-input", "MOVIE50");
    driver.findElement(tid("apply-promo")).click();
    wait.until(textToBePresentInElementLocated(tid("promo-message"), "applied"));

    type("card-number", "4242424242424242");
    type("card-expiry", "1230");
    type("card-cvv", "123");
    driver.findElement(tid("accept-terms")).click();
    driver.findElement(tid("pay-button")).click();

    wait.until(visibilityOfElementLocated(tid("otp-input"))).sendKeys("123456");
    driver.findElement(tid("otp-submit")).click();

    String ref = wait.until(visibilityOfElementLocated(tid("booking-ref"))).getText();
    assertTrue(ref.matches("ST[A-Z0-9]{6}"), "Unexpected booking ref: " + ref);
  }
}

Practising another tool?