PracticeQAAutomation logoPracticeQAAutomation
Pw

TypeScript · @playwright/test

Advertising with Playwright

A 5-step campaign wizard — objective, audience with location autocomplete, budget & bidding, creative with character counters and a live preview — then launch and pause/resume.

App under test

📣 AdPulse

URL
/apps/ads
Login
not required
Min budget
$5/day · $100 lifetime
Review time
~3 seconds

Scenarios to automate

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

  1. 1

    Step validation

    Beginner

    wizard-next on an empty step shows step-errors and error-* for that step only.

  2. 2

    Autocomplete chips

    Intermediate

    Type in location-input, pick location-option-*, then remove a chip with remove-location-*.

  3. 3

    Dependent fields

    Intermediate

    bid-strategy “Cost cap” reveals cost-cap-amount; unticking run-continuously reveals run-duration.

  4. 4

    Character counters

    Intermediate

    headline-count tracks 0/40 and input stops at 40 characters (maxlength).

  5. 5

    Live preview

    Intermediate

    preview-headline and preview-cta mirror the creative fields as you type.

  6. 6

    Edit from review

    Advanced

    edit-step-2 jumps back to Audience; values are preserved when returning to Review.

  7. 7

    Async status

    Advanced

    A launched campaign shows “In review”, then flips to “Active” ~3s later.

  8. 8

    Toggle switches

    Beginner

    Flip toggle-<id> (role=switch) and assert aria-checked and the status badge.

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
adpulse.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 · getByPlaceholder ×1 · CSS ×4 · XPath ×1 · getByTestId ×14
test('creates and launches a campaign', async ({ page }) => {
  await page.goto('/apps/ads');
  await page.getByTestId('create-campaign').click();
  await expect(page).toHaveURL(/\/apps\/ads\/new/);
  await page.getByTestId('objective-traffic').click();
  await page.getByLabel('Campaign name').fill('Diwali Sale');
  await page.getByTestId('wizard-next').click();

  // Audience
  await page.getByRole('combobox', { name: 'Min age' }).selectOption('25');
  await page.locator('#age-max').selectOption('45');
  await page.getByLabel('Locations').fill('Mum');
  await page.locator('xpath=//button[normalize-space()="Mumbai, India"]').click();
  await page.getByRole('checkbox', { name: 'Online shopping' }).check();
  await expect(page.getByTestId('audience-reach')).toContainText('people');
  await page.getByTestId('wizard-next').click();

  // Budget
  await page.getByTestId('budget-type-daily').click();
  await page.locator('#budget-amount').fill('50');
  await page.getByTestId('wizard-next').click();

  // Creative with live preview
  await page.getByLabel('Headline').fill('Big Diwali Sale up to 50% off');
  await page.locator('#ad-description').fill('Lights, gifts and more at festive prices.');
  await page.getByPlaceholder('https://', { exact: true }).fill('https://example.com/diwali');
  await page.getByRole('combobox', { name: 'Call to action' }).selectOption('shop-now');
  await expect(page.getByTestId('preview-headline')).toContainText('Big Diwali Sale');
  await expect(page.getByTestId('preview-cta')).toContainText('Shop now');
  await page.getByTestId('wizard-next').click();
  await expect(page.getByTestId('review-name')).toContainText('Diwali Sale');
  await page.locator('#accept-ad-policy').check();
  await page.getByTestId('launch-campaign').click();
  await expect(page.getByTestId('campaign-launched')).toBeVisible();
  await expect(page.getByTestId('campaigns-table')).toContainText('Diwali Sale');
});

Practicing another tool?