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
Swatch state
Beginnercolor-* buttons are role=radio with aria-checked; car-preview's data-color matches the chosen hex.
- 2
SVG attributes
IntermediateChanging wheels-* updates data-wheels on car-preview (and the wheel radius).
- 3
Price maths
Intermediateprice-options sums colour, wheels, interior and packs; price-on-road = ex-showroom × 1.12.
- 4
Compare modal
Beginnercompare-trims opens trim-compare-table with one column per trim.
- 5
Save & carry over
Intermediatesave-config shows a CFG- code; the test-drive page shows the same code and price.
- 6
Test-drive validation
IntermediateMissing dealer, day, time, bad phone or unticked has-licence each show error-*.
- 7
Disabled Sundays
BeginnerPick 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.
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-');
});