PracticeQAAutomation logoPracticeQAAutomation
Pw

TypeScript · @playwright/test

Automotive with Playwright

Configure a car — trim, colour swatches that recolour an SVG preview, wheels, interior and option packs — with live ex-showroom and on-road pricing, a trim comparison, then book a test drive.

App under test

🚘 AutoDrive

URL
/apps/auto
On-road
ex-showroom + 12%
Dealers
closed Sundays
Prices
fictional

Scenarios to automate

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

  1. 1

    Swatch state

    Beginner

    color-* buttons are role=radio with aria-checked; car-preview's data-color matches the chosen hex.

  2. 2

    SVG attributes

    Intermediate

    Changing wheels-* updates data-wheels on car-preview (and the wheel radius).

  3. 3

    Price maths

    Intermediate

    price-options sums colour, wheels, interior and packs; price-on-road = ex-showroom × 1.12.

  4. 4

    Compare modal

    Beginner

    compare-trims opens trim-compare-table with one column per trim.

  5. 5

    Save & carry over

    Intermediate

    save-config shows a CFG- code; the test-drive page shows the same code and price.

  6. 6

    Test-drive validation

    Intermediate

    Missing dealer, day, time, bad phone or unticked has-licence each show error-*.

  7. 7

    Disabled Sundays

    Beginner

    Pick the first enabled drive-day chip with :not([disabled]).

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
autodrive.spec.ts
import { test, expect } from '@playwright/test';

// playwright.config.ts → use: { baseURL: 'https://www.practiceqaautomation.com' }
// Locators in this suite: getByRole ×3 · getByLabel ×3 · CSS ×3 · XPath ×3 · getByTestId ×11
test('configures a car and books a test drive', async ({ page }) => {
  await page.goto('/apps/auto');
  await page.getByTestId('configure-aero').click();
  await page.getByTestId('trim-vx').click();
  await page.getByTestId('color-red').click();
  await expect(page.getByTestId('selected-color-name')).toContainText('Racing Red');
  await page.getByTestId('wheels-18').click();
  await page.getByTestId('interior-leather').click();
  await page.locator('#package-tech').check();
  await expect(page.getByTestId('price-ex-showroom')).toContainText('₹9,27,000');
  await expect(page.getByTestId('price-on-road')).toContainText('₹10,38,240');
  await page.getByRole('button', { name: 'Compare trims' }).click();
  await expect(page.getByTestId('trim-compare-table')).toBeVisible();
  await page.getByRole('button', { name: 'Close' }).click();
  await page.locator('xpath=//button[normalize-space()="Save configuration"]').click();
  await expect(page.getByTestId('config-saved')).toContainText('CFG-');
  await page.locator('xpath=//button[normalize-space()="Book a test drive"]').click();
  await expect(page).toHaveURL(/\/apps\/auto\/test-drive/);
  await page.getByLabel('Dealer').selectOption('pune-baner');
  await page.locator('[data-testid="drive-day"]:not([disabled])').first().click();
  await page.getByLabel('Time').selectOption('11:30');
  await page.locator('#driver-name').fill('Amir Khan');
  await page.getByLabel('Phone').fill('9876543210');
  await page.locator('#driver-email').fill('amir@example.com');
  await page.getByRole('checkbox', { name: 'I hold a valid driving licence' }).check();
  await page.locator('xpath=//button[normalize-space()="Confirm test drive"]').click();
  await expect(page.getByTestId('test-drive-confirmed')).toContainText('TD-');
});

Practicing another tool?