PracticeQAAutomation logoPracticeQAAutomation
Pw

TypeScript · @playwright/test

Hospitality with Playwright

Search a destination, filter by stars, price and amenities, pick a room with add-ons, enter guest details, pay and manage the reservation.

App under test

🏨 StayEase

URL
/apps/hotel
Login
not required
Taxes
12%
Card
any 16 digits

Scenarios to automate

Work top to bottom — each one adds a new technique.

  1. 1

    Search validation

    Beginner

    Search with no destination or date shows error-city and error-checkin.

  2. 2

    Steppers & date chips

    Beginner

    nights-inc / guests-inc change the summary; pick checkin-day by index.

  3. 3

    Filters & sorting

    Intermediate

    Combine star-*, max-price (range), amenity-* and sort; assert result-count and price order.

  4. 4

    Room capacity

    Intermediate

    With 3+ guests the Standard room is disabled and shows room-standard-capacity.

  5. 5

    Live price summary

    Intermediate

    addon-* checkboxes update price-addons, price-taxes and price-total.

  6. 6

    Checkout validation

    Intermediate

    Submit empty to get form-errors and error-* per field; Pay at hotel hides card fields.

  7. 7

    Async confirmation

    Advanced

    confirm-booking shows a processing overlay (~1.5s) before booking-confirmed.

  8. 8

    Cancel with reason

    Advanced

    cancel-<id> opens cancel-modal; a reason is required before confirm-cancel.

Sample Playwright suite

A working starting point that finds elements every way Playwright can — by role, label, text, id, name, CSS, XPath and data-testid — so you practice them all. Pick your language, switch to data-testid only to compare, or try your own in the Locator Playground.

Language
stayease.spec.ts
import { test, expect } from '@playwright/test';

// playwright.config.ts → use: { baseURL: 'https://www.practiceqaautomation.com' }
// Locators in this suite: getByRole ×3 · getByLabel ×4 · getByPlaceholder ×1 · CSS ×5 · XPath ×3 · getByTestId ×10
test('books a hotel end to end', async ({ page }) => {
  await page.goto('/apps/hotel');
  await page.getByRole('combobox', { name: 'Destination' }).selectOption('goa');
  await page.getByTestId('checkin-day').nth(2).click();
  await page.getByTestId('nights-inc').click();
  await page.locator('xpath=//button[normalize-space()="Search hotels"]').click();
  await expect(page).toHaveURL(/\/apps\/hotel\/results/);

  // Filter to 5-star stays, cheapest first
  await page.locator('#star-5').check();
  await page.getByRole('combobox', { name: 'Sort by' }).selectOption('price-asc');
  await expect(page.getByTestId('result-count')).toContainText('2 properties');
  await page.getByTestId('view-rooms-g1').click();
  await expect(page).toHaveURL(/\/apps\/hotel\/hotel\/g1/);
  await expect(page.getByTestId('hotel-title')).toContainText('Palm Grove Resort');
  await page.getByTestId('select-room-deluxe').click();
  await page.locator('#addon-breakfast').check();
  await expect(page.getByTestId('price-total')).toBeVisible();
  await page.locator('xpath=//button[normalize-space()="Continue to booking"]').click();

  // Guest details and card payment
  await page.getByLabel('First name').fill('Ada');
  await page.getByLabel('Last name').fill('Lovelace');
  await page.getByLabel('Email').fill('ada@example.com');
  await page.locator('#guest-phone').fill('5551234567');
  await page.getByRole('combobox', { name: 'Estimated arrival' }).selectOption('14:00 – 16:00');
  await page.getByTestId('pay-now').click();
  await page.getByLabel('Card number').fill('4242424242424242');
  await page.getByPlaceholder('MM/YY', { exact: true }).fill('1230');
  await page.locator('#card-cvv').fill('123');
  await page.locator('#accept-policy').check();
  await page.locator('xpath=//button[normalize-space()="Confirm booking"]').click();
  await expect(page.getByTestId('booking-confirmed')).toBeVisible();
  await expect(page.getByTestId('reservation-id')).toContainText('SE-');
  await expect(page.getByTestId('confirmed-room')).toContainText('Deluxe Room');
});

Practicing another tool?