Modern QA2026Test Patterns for AI-Driven Browser Automation
Log inJoin

Course01 Agent Skills for Browser Automation⊞ Tile viewNew!

Cutting-edge · Chapter 01

Test Patterns for AI-Driven Browser Automation

Updated Aug 2026

A note on how to read the examples: the Playwright CLI is ref-driven. The agent takes a snapshot (a YAML accessibility summary saved to disk), reads it to find elements like textbox "Email" [ref=e3], and then acts by ref. In the examples below, assume refs come from the most recent snapshot — the comments show what the agent saw there. Every action auto-waits for actionability (same Playwright engine underneath), so you will see far fewer explicit waits than in 2025-era CLI scripts.

Pattern 1: Navigate-Act-Verify (NAV)

The fundamental test pattern. Every browser test follows this structure:

Navigate → Act → Verify

Example: Login Test

# NAVIGATE
playwright-cli open https://app.example.com/login
playwright-cli snapshot
# → textbox "Email" [ref=e3], textbox "Password" [ref=e4], button "Sign in" [ref=e5]

# ACT
playwright-cli fill e3 "user@test.com"
playwright-cli fill e4 "secret123"
playwright-cli click e5

# VERIFY
playwright-cli snapshot
# → Agent checks the YAML: heading "Dashboard" present? PASS

Agent's Role

The agent decides:

  • What URL to navigate to
  • Which ref to act on (resolved from the snapshot by role and accessible name)
  • What text to type
  • How to verify success (snapshot contents, eval "location.href" for URL changes, element presence)

Pattern 2: Form Validation Testing

Test that forms reject invalid input correctly.

Example: Registration Form

# Test: empty form submission
playwright-cli goto https://app.example.com/register
playwright-cli snapshot
# → textbox "Email" [ref=e3], textbox "Password" [ref=e4], button "Create account" [ref=e5]
playwright-cli click e5                    # Submit empty form
playwright-cli snapshot
# → Agent verifies alerts in YAML: "Email is required", "Password is required"

# Test: invalid email
playwright-cli fill e3 "not-an-email"
playwright-cli click e5
playwright-cli snapshot
# → Agent verifies: "Please enter a valid email"

# Test: weak password
playwright-cli fill e3 "valid@test.com"
playwright-cli fill e4 "123"
playwright-cli click e5
playwright-cli snapshot
# → Agent verifies: "Password must be at least 8 characters"

# Test: valid submission
playwright-cli fill e3 "valid@test.com"
playwright-cli fill e4 "StrongP@ss123"
playwright-cli click e5
playwright-cli snapshot
# → Agent verifies: "Registration successful"

Agent's Added Value

The agent can generate test cases from the form structure:

  • Read the snapshot to enumerate every field, its role, and its accessible name
  • Generate boundary-value tests automatically
  • Verify error messages match expected UX copy

(For a whole suite of such cases, this is exactly the planner → generator hand-off from the Test Agents chapter — the agent explores, writes a Markdown plan, and generated .spec.ts files do the repetitive execution.)

Pattern 3: Multi-Page Flow

Tests that span multiple page navigations.

Example: E-Commerce Checkout

# Browse products
playwright-cli open https://shop.example.com
playwright-cli snapshot
# → link "Blue Widget" [ref=e7], price text "$29.99"
playwright-cli click e7

# Add to cart
playwright-cli snapshot
# → button "Add to cart" [ref=e12]
playwright-cli click e12
playwright-cli snapshot
# → Agent verifies: cart badge shows "1"

# Go to cart
playwright-cli goto https://shop.example.com/cart
playwright-cli snapshot
# → Agent verifies: "Blue Widget", total "$29.99"; button "Checkout" [ref=e9]

# Checkout
playwright-cli click e9
playwright-cli snapshot
# → textbox "Card number" [ref=e14], textbox "Expiry" [ref=e15],
#   textbox "CVV" [ref=e16], button "Pay now" [ref=e17]
playwright-cli fill e14 "4111111111111111"
playwright-cli fill e15 "12/29"
playwright-cli fill e16 "123"
playwright-cli click e17
playwright-cli snapshot
# → Agent captures: "Order #12345"

Key Considerations

  • State carries between pages (cart contents, session cookies) — a named session holds it
  • Refs do not carry between pages — re-snapshot after every navigation
  • Screenshot at each page for a debugging trail (files on disk; free until read)

Pattern 4: Data Extraction and Verification

Extract structured data from the page and verify against expected values.

Example: Dashboard Metrics

playwright-cli goto https://app.example.com/dashboard
playwright-cli eval "JSON.stringify({
  revenue: document.querySelector('.metric-revenue').textContent,
  users: document.querySelector('.metric-users').textContent,
  orders: document.querySelector('.metric-orders').textContent
})"
# → {"revenue": "$45,230", "users": "1,234", "orders": "567"}

Example: Table Data

playwright-cli goto https://app.example.com/users
playwright-cli eval "JSON.stringify(
  [...document.querySelectorAll('table tbody tr')].map(row => ({
    name: row.cells[0].textContent,
    email: row.cells[1].textContent,
    role: row.cells[2].textContent
  }))
)"
# → [{"name": "Alice", "email": "alice@test.com", "role": "Admin"}, ...]

eval is the escape hatch: when you need data rather than interaction, one JavaScript expression beats parsing a snapshot. (Inside eval you write ordinary DOM selectors — refs are for CLI interaction commands.)

Agent's Added Value

The agent can:

  • Parse the JSON output
  • Compare against expected values from a database or API
  • Identify discrepancies and report them meaningfully

Pattern 5: Async Operations (Uploads, Debounce)

For operations that don't complete immediately (AJAX calls, file uploads, etc.). Actions auto-wait for their target element, which covers most cases; for long-running operations, poll observable state via eval or re-snapshot.

Example: File Upload

playwright-cli goto https://app.example.com/upload
playwright-cli snapshot
# → button "Choose file" [ref=e6]
playwright-cli upload e6 ./fixtures/report.pdf

# Poll for completion instead of a blind sleep
playwright-cli eval "document.querySelector('.upload-status')?.textContent"
# → "Uploading… 47%"  → agent re-checks until:
# → "Upload complete"

Example: Search with Debounce

playwright-cli goto https://app.example.com/search
playwright-cli snapshot
# → searchbox "Search" [ref=e3]
playwright-cli fill e3 "test query"
playwright-cli snapshot
# → Agent verifies results region: "15 results found"
# (if results haven't rendered yet, the agent re-snapshots — judgment, not sleep())

Pattern 6: Multi-Session Testing

Tests that require multiple browser contexts — two users, two roles, two environments. Named sessions (-s=name) replace the tab juggling of older CLI tools: each session is an isolated browser context, and one agent orchestrates all of them.

Example: Admin Changes a Price, Customer Sees It

playwright-cli -s=admin open https://app.example.com/admin
playwright-cli -s=customer open https://app.example.com/shop
playwright-cli list                       # both sessions visible

# Admin updates the price
playwright-cli -s=admin snapshot          # → textbox "Price" [ref=e8], button "Save" [ref=e9]
playwright-cli -s=admin fill e8 "24.99"
playwright-cli -s=admin click e9

# Customer refreshes and verifies
playwright-cli -s=customer reload
playwright-cli -s=customer snapshot
# → Agent verifies: "$24.99"

Example: Compare Two Environments

playwright-cli -s=staging open https://staging.example.com
playwright-cli -s=prod open https://production.example.com
playwright-cli -s=staging eval "document.querySelector('.version').textContent"
playwright-cli -s=prod eval "document.querySelector('.version').textContent"
# Agent compares the two outputs

Pattern 7: Negative Testing

Verify that the application correctly rejects invalid operations.

Example: Unauthorized Access

# Try to access admin page without login
playwright-cli goto https://app.example.com/admin
playwright-cli eval "location.href"
# → Agent verifies: redirected to /login (not /admin)

playwright-cli snapshot
# → Agent verifies: heading "Please log in" (not admin content)

Example: Rate Limiting

# Rapid-fire requests (ref e5 = submit button from the current snapshot)
for i in $(seq 1 10); do
  playwright-cli click e5
  playwright-cli eval "document.querySelector('.response')?.textContent"
done
# Agent checks if rate limiting kicked in

Pattern 8: Visual Regression (Screenshot Comparison)

Use screenshots to detect visual changes.

# Capture baseline
playwright-cli goto https://app.example.com/dashboard
playwright-cli screenshot            # → path in .playwright-cli/; copy to baseline/

# ... after code change ...

# Capture current
playwright-cli goto https://app.example.com/dashboard
playwright-cli screenshot            # → copy to current/

# Agent compares screenshots (via vision or a pixel-diff tool)

Note the disk-first advantage here: screenshots never enter the model context unless the agent chooses to look. A pixel-diff tool can compare hundreds of PNG pairs for zero tokens; the agent only reads the images that actually differ.

Agent's Added Value

With vision capabilities, the agent can:

  • Identify specific visual differences
  • Classify changes as intentional vs regression
  • Describe what changed in natural language

Pattern 9: Error State Testing

Verify the application handles errors gracefully.

Example: Network Error

# Use eval to simulate offline mode
playwright-cli eval "window.navigator.__defineGetter__('onLine', () => false)"
playwright-cli click e11        # "Save" button ref from current snapshot
playwright-cli snapshot
# → Agent verifies: appropriate offline message shown

Example: Server Error

playwright-cli goto https://app.example.com/broken-page
playwright-cli snapshot
# → Agent checks: is there a user-friendly error page (not a raw 500 stack trace)?
playwright-cli screenshot

Anti-Patterns

Don't: Hard-Code Wait Times

# BAD
playwright-cli goto https://app.example.com
sleep 5  # Arbitrary wait
playwright-cli snapshot

# GOOD
playwright-cli goto https://app.example.com
playwright-cli snapshot      # actions auto-wait; for slow async state,
                             # poll via eval or re-snapshot with judgment

Don't: Act on Refs from a Stale Snapshot

# BAD: page navigated since the last snapshot
playwright-cli click e5      # e5 belonged to the previous page

# GOOD: re-snapshot after any navigation or major state change
playwright-cli snapshot
playwright-cli click e9      # ref from the current snapshot

Don't: Chain Commands Without Verification

# BAD: Assumes every step succeeds
playwright-cli goto url && playwright-cli click e3 && playwright-cli click e7

# GOOD: Verify each critical step
playwright-cli goto url
playwright-cli snapshot          # confirm expected elements exist
playwright-cli click e3
playwright-cli snapshot          # confirm the state actually changed
playwright-cli click e7