The Automation Demo Site

See all projects here

1. The Automation Tester's Canvas

1.1 Basic Interactable Elements

Text Inputs

How to automate
CSS: [data-testid="input-text"]
XPath: //input[@data-testid="input-text"]
Action: sendKeys("testuser")
Assert: value attribute equals "testuser"
                        

Checkboxes & Radio Buttons

Preferences
Plan Selection
How to automate
CSS: [data-testid="chk-terms"]
XPath: //input[@data-testid="radio-plan-pro"]
Action: click()
Assert: checked property is true
Radio: Only one in group can be selected
                        

Buttons & Links

Documentation Link External Link
How to automate
CSS: [data-testid="btn-primary"]
XPath: //button[@data-testid="btn-primary"]
Action: click()
Assert: enabled state, href attribute for links
Note: Check disabled attribute for btn-secondary
                        

Images

Company Logo
How to automate
CSS: [data-testid="img-logo"]
XPath: //img[@data-testid="img-logo"]
Assert: alt attribute, src attribute, isDisplayed()
Accessibility: Always verify alt text presence
                        

1.3 Data Components

Form with Validation

How to automate
CSS: [data-testid="form-login"]
Action: Fill inputs, click submit
Wait: [data-testid="spinner"] visible (1200ms fixed)
Then: [data-testid="spinner"] hidden
Assert: [data-testid="alert-success"] visible
Error case: [data-testid="alert-error"] visible
Sync: Explicit wait for spinner → alert transition
                        

Table Traversal

Name Role Salary
Alice Engineer $95,000
Bob Designer $85,000
Carol Manager $110,000
How to automate
CSS: [data-testid="table-employees"]
Find row: //tr[@data-row="Bob"]
Find cell: //tr[@data-row="Bob"]//td[@data-col="salary"]
Assert: Text content "$85,000"
Count rows: tbody tr (expect 3)
Traverse: thead th for headers, tbody tr for data
                        

Lists

Unordered List
  • Write test cases
  • Execute automation suite
  • Review results
Ordered List
  1. Identify element
  2. Perform action
  3. Assert outcome
How to automate
CSS: [data-testid="list-todos"] li
XPath: //ul[@data-testid="list-todos"]/li
Count: Assert 3 items
Order: Verify sequence by index or data-testid
Text: Assert specific item text content
                        

1.4 Advanced Inputs

Select Dropdown

Selected: None

How to automate
CSS: [data-testid="select-country"]
Action: Select by visible text "Canada"
        Select by value "ca"
        Select by index 2
Assert: Selected option text or value
Output: [data-testid="select-country-output"]
                        

Date Picker – Method A (Direct Input)

How to automate
CSS: [data-testid="date-input"]
Action: sendKeys("2025-10-16")
Assert: value attribute, feedback message
Validation: Strict format YYYY-MM-DD
Error: Invalid format shows error message
                        

Date Picker – Method B (UI Picker)

Selected: None

How to automate
CSS: [data-testid="date-open"]
Action: click() to open picker
Wait: [data-testid="date-picker"] visible
Navigate: [data-testid="date-next"] for next month
Select day: [data-day="15"] button
Assert: [data-testid="date-selected-output"] text
Deterministic: Fixed start date, predictable navigation
                        

Slider

50
How to automate
CSS: [data-testid="slider-volume"]
Action: Set value attribute to "75"
        Or use keyboard (Arrow keys)
Assert: value attribute, output text
Output: [data-testid="slider-volume-output"]
                        

Drag and Drop

Source
  • Item 1
  • Item 2
  • Item 3
Target

Keyboard: Select item, press Move button

How to automate
CSS: [data-testid="drag-source-item-1"]
Action: dragAndDrop(source, target)
        Or use Actions API
Target: [data-testid="drop-target-list"]
Assert: Item moved from source to target
Keyboard fallback: Select + Move button
Verify: Count items in both lists
                        

1.5 File Handling

Standard File Input

No file selected

How to automate
CSS: [data-testid="file-input-visible"]
Action: sendKeys("/path/to/file.txt")
Assert: files[0].name property
Output: [data-testid="file-visible-output"]
Note: No OS dialog; direct path assignment
                        

Hidden File Input (Custom Button)

No file selected

How to automate
CSS: [data-testid="file-input-hidden"]
Strategy: Target hidden input directly
Action: sendKeys("/path/to/document.pdf")
Assert: files[0].name property
Output: [data-testid="file-hidden-output"]
Note: Bypass custom button; use hidden input
                        

2. Complex Architectures

2.1 Iframes

Single Iframe

How to automate
CSS: [data-testid="frame-parent"]
Action: driver.switchTo().frame(element)
Inside: [data-testid="btn-frame-action"]
Assert: [data-testid="frame-output"] text
Exit: driver.switchTo().defaultContent()
Note: Must switch context before interacting
                        

Nested Iframes

How to automate
CSS: [data-testid="frame-outer"]
Action: driver.switchTo().frame(outerFrame)
Then: driver.switchTo().frame(innerFrame)
Target: [data-testid="input-nested"]
Assert: Input is interactable
Exit: driver.switchTo().defaultContent()
Note: Switch to each frame in sequence
                        

2.2 Shadow DOM

Custom Web Component with Shadow Root

How to automate
CSS: [data-testid="shadow-host"]
Action: shadowRoot = element.shadowRoot (Selenium 4+)
        Or executeScript("return arguments[0].shadowRoot", el)
Inside: shadowRoot.querySelector('[data-testid="shadow-username"]')
Fill: sendKeys("testuser")
Submit: [data-testid="shadow-login"] button
Assert: [data-testid="shadow-result-output"] in main DOM
Note: Must pierce shadow boundary
                        

2.3 Canvas

Canvas Interaction & Visual Regression

Click a bar to see its value

How to automate
CSS: [data-testid="canvas-chart"]
Coordinate click: Actions.moveToElement(canvas, x, y).click()
Assert: [data-testid="canvas-click-output"] text changes
Visual check: [data-testid="btn-canvas-snapshot"]
Compare: Canvas pixels vs baseline image
Tolerance: Pixel diff threshold (e.g., 5%)
Output: [data-testid="canvas-diff-output"]
Note: Use screenshot comparison tools in real tests
                        

3. Common Automation Challenges

3.1 Locator Hierarchy & Best Practices

Locator Priority

This element demonstrates multiple locator strategies:

  • 1. data-testid (preferred): [data-testid="locator-demo"]
  • 2. id: #locator-demo
  • 3. name: [name="example"] (for inputs)
  • 4. CSS: .locator-example
  • 5. XPath: //div[@data-testid="locator-demo"]
Partial Match Strategies

Partial matches:

  • Starts with: [data-testid^="btn-submit"]
  • Ends with: [data-testid$="2025"]
  • Contains: [data-testid*="submit-form"]
  • XPath contains: //button[contains(@data-testid, "submit")]
How to automate
Priority order:
1. data-testid (stable, explicit)
2. id (unique, but may change)
3. name (for form elements)
4. Semantic CSS (role, type)
5. XPath (last resort, brittle)

Avoid: Generated classes, deep nesting, text-only
Use: Partial matches for dynamic IDs
                        

3.2 Synchronization & Explicit Waits

Explicit Wait Demo

How to automate
CSS: [data-testid="btn-trigger-async"]
Action: click()
Wait: [data-testid="async-spinner"] visible
Duration: 1200ms (fixed, deterministic)
Then wait: [data-testid="async-spinner"] hidden
Assert: [data-testid="async-result"] visible
Anti-pattern: Thread.sleep(2000) ❌
Best practice: WebDriverWait.until(visibilityOf(...)) ✓
                        

SPA Content Loading

How to automate
CSS: [data-testid="btn-load-content"]
Action: click()
Wait: [data-testid="spa-content"] visible (no hidden attr)
Assert: Text content present
Sync: Wait for specific element, not page load
Timeout: Configure explicit wait (e.g., 10s)
                        

3.3 Flakiness Lab & Retry Strategies

Controlled Retry Demo

This demo simulates a transient failure on first attempt.

Attempts: 0

How to automate
CSS: [data-testid="btn-flaky-action"]
First attempt: Shows error [data-testid="flaky-error"]
Retry: Click again
Second attempt: Shows success [data-testid="flaky-success"]
Strategy: Implement retry logic (max 3 attempts)
Assert: [data-testid="flaky-attempt-count"] increments
Best practice: Idempotent actions, clean state between retries