Flight Booking Automation Practice

A realistic multi-step booking flow — search, choose flights, enter passenger details, pay, and confirm — for Selenium, Cypress, or Playwright.

SearchSelect flightsPassengersPaymentDone

Search Flights

How to Automate This Flight Booking Page

A realistic multi-step booking wizard: search, then sort and filter a list of flights, choose a departure (and return for round-trips), enter passenger details, pay, and get a confirmation with a booking reference. Great practice for a step flow, conditional fields, dynamic lists, and sorting/filtering.

The same scenario written for two popular frameworks. These use the stable id and data-testid locators documented in the cheat sheet below.

import { test, expect } from '@playwright/test';

test('book a one-way flight through the wizard', async ({ page }) => {
  await page.goto('https://www.qapractice.com/flight-booking-scenarios');

  // Step 1 — search
  await page.getByTestId('flight-from').selectOption('New York');
  await page.getByTestId('flight-to').selectOption('London');
  await page.getByTestId('flight-departure-date').fill('2026-08-01');
  await page.getByTestId('flight-one-way').check();   // hides the return date
  await page.getByTestId('flight-search').click();

  // Step 2 — sort, then select a flight (flight numbers are stable)
  await page.getByTestId('flight-sort').selectOption('price-asc');
  await page.getByTestId('flight-select-GW100').click();
  await page.getByTestId('flight-continue-to-passengers').click();

  // Step 3 — passenger details
  await page.getByTestId('flight-passenger-name').fill('Ada Lovelace');
  await page.getByTestId('flight-passenger-email').fill('ada@example.com');
  await page.getByTestId('flight-passenger-phone').fill('+15550100');
  await page.getByTestId('flight-continue-to-payment').click();

  // Step 4 — payment
  await page.getByTestId('flight-card-number').fill('4111111111111111');
  await page.getByTestId('flight-expiry').fill('12/30');
  await page.getByTestId('flight-cvv').fill('123');
  await page.getByTestId('flight-book').click();

  // Step 5 — confirmation
  await expect(page.getByTestId('flight-booking-success'))
    .toContainText('Booking Confirmed');
});
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;

public class FlightBookingTest {
  public static void main(String[] args) {
    WebDriver driver = new ChromeDriver();
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    driver.get("https://www.qapractice.com/flight-booking-scenarios");

    // Step 1 — search
    new Select(driver.findElement(By.id("flight-from"))).selectByVisibleText("New York");
    new Select(driver.findElement(By.id("flight-to"))).selectByVisibleText("London");
    driver.findElement(By.id("flight-departure-date")).sendKeys("2026-08-01");
    driver.findElement(By.id("flight-one-way")).click();
    driver.findElement(By.id("flight-search")).click();

    // Step 2 — select a flight and continue
    wait.until(ExpectedConditions.elementToBeClickable(
        By.cssSelector("[data-testid='flight-select-GW100']"))).click();
    driver.findElement(By.cssSelector("[data-testid='flight-continue-to-passengers']")).click();

    // Step 3 — passenger details
    driver.findElement(By.id("flight-passenger-name")).sendKeys("Ada Lovelace");
    driver.findElement(By.id("flight-passenger-email")).sendKeys("ada@example.com");
    driver.findElement(By.id("flight-passenger-phone")).sendKeys("+15550100");
    driver.findElement(By.cssSelector("[data-testid='flight-continue-to-payment']")).click();

    // Step 4 — payment
    driver.findElement(By.id("flight-card-number")).sendKeys("4111111111111111");
    driver.findElement(By.id("flight-expiry")).sendKeys("12/30");
    driver.findElement(By.id("flight-cvv")).sendKeys("123");
    driver.findElement(By.id("flight-book")).click();

    String msg = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.id("flight-booking-success"))).getText();
    assert msg.contains("Booking Confirmed");

    driver.quit();
  }
}

Every interactive element on this page exposes a stable id and/or data-testid so your scripts don't depend on brittle positions or styling.

Elementiddata-testidPlaywright locatorSelenium locator
Step 1 · From cityflight-fromflight-fromgetByTestId('flight-from').selectOption('New York')new Select(driver.findElement(By.id("flight-from")))
Step 1 · To cityflight-toflight-togetByTestId('flight-to').selectOption('London')new Select(driver.findElement(By.id("flight-to")))
Step 1 · Departure dateflight-departure-dateflight-departure-dategetByTestId('flight-departure-date').fill('2026-08-01')By.id("flight-departure-date")
Step 1 · Return date (round-trip only)flight-return-dateflight-return-dategetByTestId('flight-return-date')By.id("flight-return-date")
Step 1 · Passengersflight-passengersflight-passengersgetByTestId('flight-passengers').fill('2')By.id("flight-passengers")
Step 1 · Travel classflight-classflight-classgetByTestId('flight-class').selectOption('Business')new Select(driver.findElement(By.id("flight-class")))
Step 1 · One-way checkboxflight-one-wayflight-one-waygetByTestId('flight-one-way')By.id("flight-one-way")
Step 1 · Search buttonflight-searchflight-searchgetByTestId('flight-search')By.id("flight-search")
Step 2 · Sort dropdownflight-sortflight-sortgetByTestId('flight-sort').selectOption('price-asc')new Select(driver.findElement(By.id("flight-sort")))
Step 2 · Airline filterflight-filter-airlineflight-filter-airlinegetByTestId('flight-filter-airline').selectOption('BlueJet')new Select(driver.findElement(By.id("flight-filter-airline")))
Step 2 · Non-stop filterflight-filter-nonstopflight-filter-nonstopgetByTestId('flight-filter-nonstop').check()By.id("flight-filter-nonstop")
Step 2 · A flight rowflight-result-<num>getByTestId('flight-result-GW100')By.cssSelector("[data-testid='flight-result-GW100']")
Step 2 · Select a flightflight-select-<num>getByTestId('flight-select-GW100')By.cssSelector("[data-testid='flight-select-GW100']")
Step 2 · Continue buttonflight-continue-to-passengersgetByTestId('flight-continue-to-passengers')By.cssSelector("[data-testid='flight-continue-to-passengers']")
Step 3 · Passenger nameflight-passenger-nameflight-passenger-namegetByTestId('flight-passenger-name')By.id("flight-passenger-name")
Step 3 · Passenger emailflight-passenger-emailflight-passenger-emailgetByTestId('flight-passenger-email')By.id("flight-passenger-email")
Step 3 · Passenger phoneflight-passenger-phoneflight-passenger-phonegetByTestId('flight-passenger-phone')By.id("flight-passenger-phone")
Step 3 · Continue to paymentflight-continue-to-paymentgetByTestId('flight-continue-to-payment')By.cssSelector("[data-testid='flight-continue-to-payment']")
Step 4 · Total priceflight-totalgetByTestId('flight-total')By.cssSelector("[data-testid='flight-total']")
Step 4 · Card numberflight-card-numberflight-card-numbergetByTestId('flight-card-number')By.id("flight-card-number")
Step 4 · Expiry dateflight-expiryflight-expirygetByTestId('flight-expiry')By.id("flight-expiry")
Step 4 · CVVflight-cvvflight-cvvgetByTestId('flight-cvv')By.id("flight-cvv")
Step 4 · Pay & Confirmflight-bookflight-bookgetByTestId('flight-book')By.id("flight-book")
Step 5 · Confirmation headingflight-booking-successflight-booking-successgetByTestId('flight-booking-success')By.id("flight-booking-success")
Step 5 · Booking reference (PNR)flight-pnrgetByTestId('flight-pnr')By.cssSelector("[data-testid='flight-pnr']")

Use these as a checklist to build your automation suite. Download them as a Markdown file to keep alongside your test project.

IDScenarioStepsExpected Result
TC01One-way booking, happy path
  1. Search a one-way trip
  2. Select a flight, continue
  3. Enter passenger details
  4. Pay & confirm
A "Booking Confirmed!" screen with a booking reference (PNR) is shown.
TC02Round-trip booking
  1. Leave One Way unticked
  2. Search
  3. Select a departure AND a return flight
  4. Complete passenger + payment
Both flights appear in the confirmation; total reflects both fares.
TC03Return date only for round trips
  1. Toggle the One Way checkbox
The Return Date field shows when One Way is unticked and hides when ticked.
TC04Search validation
  1. Leave From/To empty
  2. Click Search Flights
Inline validation errors appear for the missing fields.
TC05Same origin and destination
  1. Select the same city for From and To
  2. Search
A validation error prevents searching identical cities.
TC06Sort results by price
  1. On the results step, choose "Price: Low to High"
Flights re-order from cheapest to most expensive.
TC07Filter non-stop only
  1. Tick the "Non-stop only" filter
Only non-stop flights remain in the list.
TC08Continue disabled until selected
  1. On results, before selecting a flight
The "Continue to passenger details" button is disabled until the required flight(s) are chosen.
TC09Passenger validation
  1. On passenger details, submit with an invalid email
An email validation error is shown and the step does not advance.
TC10Total reflects passengers
  1. Set passengers to 2
  2. Reach the payment step
The total equals the selected fare(s) × 2.