Project 32: E2E Workflow Recorder - Test Case Generator
Project 32: E2E Workflow Recorder - Test Case Generator
Build a system where Claude observes you interacting with a website, records your actions, understands the intent behind them, and generates reusable test code in Playwright, Cypress, or Selenium format.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Expert |
| Time Estimate | 1 month+ |
| Language | TypeScript (Alternatives: JavaScript, Python) |
| Prerequisites | All previous browser projects, testing frameworks knowledge |
| Key Topics | Test recording, code generation, selector strategies, intent inference |
| Main Book | โxUnit Test Patternsโ by Gerard Meszaros |
1. Learning Objectives
By completing this project, you will:
- Record browser interactions: Capture clicks, inputs, navigation, and assertions
- Infer user intent: Understand why actions were taken, not just what was done
- Generate robust selectors: Create stable element selectors that survive refactors
- Synthesize test code: Produce idiomatic code for Playwright, Cypress, or Selenium
- Add intelligent assertions: Determine what to verify based on workflow context
- Handle async patterns: Generate proper waits and timeout handling
2. Theoretical Foundation
2.1 From Actions to Tests
The fundamental challenge: raw actions donโt make good tests.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Action Recording vs Test Generation โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Raw Recording: Intelligent Test: โ
โ โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โ
โ โ
โ click(234, 567) page.getByRole('button', โ
โ { name: 'Sign In' }).click() โ
โ โ
โ type("john@example.com") page.getByLabel('Email') โ
โ .fill('john@example.com') โ
โ โ
โ wait(3000) await expect(page) โ
โ .toHaveURL('/dashboard') โ
โ โ
โ click(456, 789) await expect( โ
โ page.getByTestId('welcome') โ
โ ).toBeVisible() โ
โ โ
โ Problems with raw: Benefits of intelligent: โ
โ - Coordinates are fragile - Semantic selectors โ
โ - No verification of success - Built-in assertions โ
โ - Arbitrary waits - Smart waiting โ
โ - Not readable/maintainable - Clear intent โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
2.2 Selector Strategy Hierarchy
Different selector strategies have different stability characteristics:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Selector Stability Pyramid โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ MOST STABLE โ
โ โฒ โ
โ /โ\ โ
โ / โ \ โ
โ / โ \ โ
โ / โ \ โ
โ / โ \ 1. Test IDs โ
โ / โ \ [data-testid="login-btn"] โ
โ / โ \ Explicit, stable, purpose-built โ
โ / โ \ โ
โ / โ \ โ
โ / โ \ 2. Semantic/Role โ
โ / โ \ getByRole('button', โ
โ / โ \ { name: 'Sign In' }) โ
โ / โ \ Accessibility-based โ
โ / โ \ โ
โ / โ \ 3. Text Content โ
โ / โ \ getByText('Submit') โ
โ / โ \ User-visible, readable โ
โ / โ \ โ
โ / โ \ 4. Stable Classes โ
โ / โ \ .login-button โ
โ / โ \ Meaningful names โ
โ / โ \ โ
โ / โ \ 5. Structural โ
โ / โ \ div > button โ
โ / โ \ DOM hierarchy โ
โ /โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\ โ
โ โผ โ
โ LEAST STABLE โ
โ โ
โ NEVER USE: โ
โ - Coordinates (click at 234, 567) โ
โ - Generated IDs (id="react-node-a7f3c2") โ
โ - Deep structural paths (div > div > div > span > button) โ
โ - Index-based (button:nth-child(3)) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
2.3 Intent Inference Patterns
Claudeโs unique capability: understanding why, not just what.
| Observed Actions | Inferred Intent | Generated Test |
|---|---|---|
| Navigate to /login, fill email, fill password, click button | โLogin flowโ | Test: โshould login successfullyโ |
| Fill search box, click search, click result | โSearch and selectโ | Test: โshould find item via searchโ |
| Click item, click add to cart, navigate to cart | โAdd to cart flowโ | Test: โshould add item to cartโ |
| Fill form, submit, see success message | โForm submissionโ | Test: โshould submit form successfullyโ |
2.4 Action Grouping Logic
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Action Grouping Algorithm โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Raw Events Timeline: โ
โ โโโโโโโโโโโโโโโโโโโโโ โ
โ t=0 navigate(/login) โ
โ t=1 click(email_input) โ
โ t=2 type(email_input, "user@example.com") โ
โ t=3 click(password_input) โ
โ t=4 type(password_input, "secret123") โ
โ t=5 click(submit_button) โ
โ t=6 wait(page_load) โ
โ t=7 url_changed(/dashboard) โ
โ โ
โ Grouping Rules: โ
โ โโโโโโโโโโโโโโโ โ
โ 1. Navigation events โ Start new test step โ
โ 2. Related inputs โ Group together (form filling) โ
โ 3. Submit/click โ End of action group โ
โ 4. URL change โ Verification point โ
โ 5. Visual check โ Assertion opportunity โ
โ โ
โ Grouped Actions: โ
โ โโโโโโโโโโโโโโโโ โ
โ Step 1: Navigate to login page โ
โ โโโ navigate(/login) โ
โ โ
โ Step 2: Fill login credentials โ
โ โโโ fill(email, "user@example.com") โ
โ โโโ fill(password, "secret123") โ
โ โ
โ Step 3: Submit and verify โ
โ โโโ click(submit) โ
โ โโโ assert(url == /dashboard) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
2.5 Test Framework Output Patterns
Generated code should be idiomatic for each framework:
Playwright:
import { test, expect } from '@playwright/test';
test.describe('Authentication', () => {
test('should login successfully', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('secret123');
await page.getByRole('button', { name: 'Sign In' }).click();
await expect(page).toHaveURL('/dashboard');
await expect(page.getByTestId('welcome-message')).toBeVisible();
});
});
Cypress:
describe('Authentication', () => {
it('should login successfully', () => {
cy.visit('/login');
cy.findByLabelText('Email').type('user@example.com');
cy.findByLabelText('Password').type('secret123');
cy.findByRole('button', { name: 'Sign In' }).click();
cy.url().should('include', '/dashboard');
cy.findByTestId('welcome-message').should('be.visible');
});
});
Selenium (Python):
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class TestAuthentication:
def test_login_successfully(self, driver):
driver.get('/login')
driver.find_element(By.XPATH, "//input[@aria-label='Email']").send_keys('user@example.com')
driver.find_element(By.XPATH, "//input[@aria-label='Password']").send_keys('secret123')
driver.find_element(By.XPATH, "//button[text()='Sign In']").click()
WebDriverWait(driver, 10).until(EC.url_contains('/dashboard'))
assert driver.find_element(By.CSS_SELECTOR, "[data-testid='welcome-message']").is_displayed()
3. Project Specification
3.1 What You Will Build
An intelligent test recorder that:
- Records user interactions through Chrome MCP
- Infers intent and groups related actions
- Generates stable selectors for each element
- Produces test code in multiple frameworks
- Adds appropriate assertions and waits
- Supports editing and refinement of generated tests
3.2 Functional Requirements
- Recording Mode
- Start/stop recording on demand
- Capture navigation, clicks, inputs, selections
- Record the DOM state at each interaction
- Support GIF recording for visual documentation
- Intent Analysis
- Group related actions into test steps
- Identify workflow patterns (login, search, checkout)
- Determine appropriate test names
- Suggest test boundaries
- Selector Generation
- Prefer test IDs when available
- Fall back through selector hierarchy
- Validate selector uniqueness
- Generate multiple selector options
- Assertion Generation
- Add URL verification after navigation
- Include element visibility checks
- Verify expected text content
- Support custom assertion insertion
- Code Generation
- Output Playwright (default)
- Support Cypress and Selenium
- Generate TypeScript or JavaScript
- Include proper imports and setup
- Workflow Refinement
- Edit generated tests
- Add parameterization
- Generate negative test cases
- Create page objects (stretch)
3.3 Example Workflow
You: Watch me test the login flow and generate Playwright tests
Claude: Recording started. I'll watch your actions and infer test intent.
[Using gif_creator to record the session...]
You perform actions:
1. Navigate to /login
2. Type "user@test.com" in email field
3. Type "password123" in password field
4. Click "Sign In" button
5. Wait for redirect to /dashboard
6. Click on username in header to verify logged in
Claude: Recording stopped. Analyzing your workflow...
================================================================================
WORKFLOW ANALYSIS & TEST GENERATION
================================================================================
RECORDED SESSION
----------------
GIF saved: ./recordings/login-flow-2024-12-22.gif
Duration: 12.4 seconds
Actions captured: 6
Page transitions: 1
ACTION TIMELINE
---------------
00:00 navigate("/login")
Intent: Start of login flow
02:30 fill(input[type="email"], "user@test.com")
Selector options:
[BEST] getByLabel('Email')
[ALT] getByPlaceholder('Enter your email')
[ALT] locator('input[type="email"]')
04:15 fill(input[type="password"], "password123")
Selector options:
[BEST] getByLabel('Password')
[ALT] locator('input[type="password"]')
06:00 click(button[type="submit"])
Selector options:
[BEST] getByRole('button', { name: 'Sign In' })
[ALT] getByTestId('login-submit')
[ALT] locator('button[type="submit"]')
08:30 page transition: /login โ /dashboard
Assertion: expect(page).toHaveURL('/dashboard')
10:00 click(header .user-menu)
Intent: Verification of logged-in state
Observation: User dropdown visible
INFERRED INTENT
---------------
Test Name: "should login with valid credentials"
Category: Authentication
Coverage: Happy path - successful login
Assertions inferred:
1. After login: URL should be /dashboard
2. After login: User menu should be visible
3. After login: Welcome message should contain username
GENERATED TEST (Playwright)
---------------------------
```typescript
import { test, expect } from '@playwright/test';
test.describe('Authentication', () => {
test('should login with valid credentials', async ({ page }) => {
// Navigate to login page
await page.goto('/login');
// Fill login credentials
await page.getByLabel('Email').fill('user@test.com');
await page.getByLabel('Password').fill('password123');
// Submit login form
await page.getByRole('button', { name: 'Sign In' }).click();
// Verify successful login
await expect(page).toHaveURL('/dashboard');
await expect(page.getByTestId('user-menu')).toBeVisible();
});
});
RECOMMENDATIONS
-
Security: Replace hardcoded password with environment variable Example: process.env.TEST_PASSWORD
-
Data: Consider using test fixtures for credentials Example: test.use({ storageState: โauth.jsonโ })
-
Edge cases: Consider adding tests for:
- Invalid credentials
- Empty fields
- Account lockout
Would you like me to:
- Generate the additional edge case tests?
- Convert to Cypress or Selenium format?
- Create a Page Object Model structure?
- Add error handling scenarios? ```
4. Solution Architecture
4.1 High-Level Design
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ E2E Workflow Recorder System โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Recording โโโโถโ Action โโโโถโ Intent โโโโถโ Code โ โ
โ โ Engine โ โ Analyzer โ โ Inferrer โ โ Generator โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ โ โ โ โ
โ โผ โผ โผ โผ โ
โ gif_creator DOM states Claude Playwright โ
โ read_page Grouping reasoning Cypress โ
โ computer Deduplication Naming Selenium โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Selector Generator โโ
โ โ โโ
โ โ Element โโโถ [Extractor] โโโถ [Ranker] โโโถ [Validator] โโโถ Best Selectorโโ
โ โ โโ
โ โ Extraction: Ranking: Validation: โโ
โ โ - data-testid - Stability score - Uniqueness check โโ
โ โ - aria-label - Readability - Dynamic ID filter โโ
โ โ - role + name - Framework support - Fragility analysis โโ
โ โ - text content - Maintenance cost โโ
โ โ - class names โโ
โ โ - structure path โโ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
4.2 Recording Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Recording Flow โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ User: "Start recording" โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. Initialize Recording โ โ
โ โ gif_creator(action: "start") โ โ
โ โ Take initial screenshot โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 2. User Performs Actions โ โ
โ โ (Claude observes via GIF frames) โ โ
โ โ โ โ
โ โ After each significant action: โ โ
โ โ - read_page() to capture DOM โ โ
โ โ - Record URL changes โ โ
โ โ - Note element interactions โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ User: "Stop recording" โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 3. Finalize Recording โ โ
โ โ gif_creator(action: "stop") โ โ
โ โ gif_creator(action: "export") โ โ
โ โ Take final screenshot โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 4. Analyze Recording โ โ
โ โ - Review GIF for actions โ โ
โ โ - Identify action sequence โ โ
โ โ - Infer user intent โ โ
โ โ - Generate test code โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
4.3 Selector Generation Algorithm
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Selector Generation Algorithm โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Input: Element reference from read_page (e.g., ref_42) โ
โ โ
โ Step 1: Extract All Possible Selectors โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ candidates = [] โ
โ โ
โ // Test ID (highest priority) โ
โ if element has data-testid: โ
โ candidates.push({ โ
โ type: 'testid', โ
โ selector: `[data-testid="${value}"]`, โ
โ playwright: `getByTestId('${value}')`, โ
โ stability: 10 โ
โ }) โ
โ โ
โ // Role-based (semantic) โ
โ if element has role (button, link, textbox, etc): โ
โ if element has accessible name: โ
โ candidates.push({ โ
โ type: 'role', โ
โ selector: `role=${role}[name="${name}"]`, โ
โ playwright: `getByRole('${role}', { name: '${name}' })`, โ
โ stability: 9 โ
โ }) โ
โ โ
โ // Label-based (forms) โ
โ if element is input and has label: โ
โ candidates.push({ โ
โ type: 'label', โ
โ selector: `label=${labelText}`, โ
โ playwright: `getByLabel('${labelText}')`, โ
โ stability: 8 โ
โ }) โ
โ โ
โ // Text-based โ
โ if element has visible text: โ
โ candidates.push({ โ
โ type: 'text', โ
โ selector: `text="${text}"`, โ
โ playwright: `getByText('${text}')`, โ
โ stability: 6 โ
โ }) โ
โ โ
โ // Class-based (if meaningful) โ
โ if element has non-generated class names: โ
โ candidates.push({ โ
โ type: 'class', โ
โ selector: `.${className}`, โ
โ playwright: `locator('.${className}')`, โ
โ stability: 4 โ
โ }) โ
โ โ
โ Step 2: Validate Uniqueness โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ for each candidate: โ
โ matches = querySelectorAll(candidate.selector) โ
โ if matches.length === 1: โ
โ candidate.unique = true โ
โ else: โ
โ candidate.unique = false โ
โ candidate.matches = matches.length โ
โ โ
โ Step 3: Filter and Rank โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ valid = candidates.filter(c => c.unique) โ
โ ranked = valid.sort((a, b) => b.stability - a.stability) โ
โ โ
โ Output: ranked[0] (best) plus alternatives โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
4.4 Intent Inference Logic
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Intent Inference Patterns โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Pattern Matching Rules: โ
โ โ
โ LOGIN FLOW โ
โ โโโโโโโโโโ โ
โ Indicators: โ
โ - URL contains: /login, /signin, /auth โ
โ - Fields: email/username + password โ
โ - Button: "Sign In", "Log In", "Submit" โ
โ - Redirect to: /dashboard, /home, /account โ
โ โ
โ Generated test name: "should login successfully" โ
โ Category: Authentication โ
โ โ
โ SIGNUP FLOW โ
โ โโโโโโโโโโโ โ
โ Indicators: โ
โ - URL contains: /signup, /register, /create-account โ
โ - Fields: email + password + confirm password โ
โ - Additional fields: name, terms checkbox โ
โ - Success: confirmation page or verify email message โ
โ โ
โ Generated test name: "should create new account" โ
โ Category: Registration โ
โ โ
โ SEARCH FLOW โ
โ โโโโโโโโโโโ โ
โ Indicators: โ
โ - Input with: search icon, placeholder "Search" โ
โ - Action: type + enter or click search button โ
โ - Result: list of items, "X results found" โ
โ โ
โ Generated test name: "should search and find results" โ
โ Category: Search โ
โ โ
โ CHECKOUT FLOW โ
โ โโโโโโโโโโโโโ โ
โ Indicators: โ
โ - Sequence: add to cart โ cart page โ checkout โ
โ - Fields: shipping address, payment info โ
โ - Buttons: "Add to Cart", "Checkout", "Place Order" โ
โ - Success: order confirmation, order number โ
โ โ
โ Generated test name: "should complete purchase" โ
โ Category: E-commerce โ
โ โ
โ FORM SUBMISSION โ
โ โโโโโโโโโโโโโโโ โ
โ Indicators: โ
โ - Multiple input fields โ
โ - Submit button โ
โ - Success message or redirect โ
โ โ
โ Generated test name: "should submit form successfully" โ
โ Category: Forms โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
5. Implementation Guide
5.1 Chrome MCP Tools for Recording
gif_creator - Record Sessions
// Start recording session
mcp__claude-in-chrome__gif_creator({
action: "start_recording",
tabId: 12345
})
// Take initial screenshot immediately after
mcp__claude-in-chrome__computer({
action: "screenshot",
tabId: 12345
})
// ... user performs actions ...
// Stop recording
mcp__claude-in-chrome__gif_creator({
action: "stop_recording",
tabId: 12345
})
// Export GIF with annotations
mcp__claude-in-chrome__gif_creator({
action: "export",
tabId: 12345,
download: true,
options: {
showClickIndicators: true,
showActionLabels: true,
showProgressBar: true,
showWatermark: true
}
})
read_page - Capture DOM State
// After each user action, capture element state
mcp__claude-in-chrome__read_page({
tabId: 12345,
filter: "interactive" // Focus on actionable elements
})
// Response includes elements like:
// button "Sign In" [ref_1]
// textbox "Email" [ref_2]
// checkbox "Remember me" [ref_3]
find - Locate Specific Elements
// Find elements user interacted with
mcp__claude-in-chrome__find({
tabId: 12345,
query: "submit button"
})
// Returns element references for selector extraction
5.2 Implementation Phases
Phase 1: Basic Recording (Week 1)
Goal: Capture user actions through GIF recording.
Tasks:
- Implement start/stop recording commands
- Capture screenshots at key moments
- Track URL changes
- Export GIF with action indicators
Checkpoint: GIF shows user interactions with click indicators.
Phase 2: Action Identification (Week 1-2)
Goal: Identify individual actions from recording.
Tasks:
- Analyze GIF frames for action detection
- Correlate with read_page DOM snapshots
- Build action timeline with timestamps
- Deduplicate redundant actions (hover, scroll)
Checkpoint: Generate list of discrete user actions.
Phase 3: Selector Generation (Week 2)
Goal: Generate stable selectors for each element.
Tasks:
- Implement selector extraction
- Rank selectors by stability
- Validate uniqueness
- Generate framework-specific syntax
Checkpoint: Each action has robust selector attached.
Phase 4: Intent Inference (Week 3)
Goal: Understand workflow purpose using Claude.
Tasks:
- Implement pattern matching rules
- Use Claude to analyze action sequences
- Generate meaningful test names
- Identify assertion opportunities
Checkpoint: Actions grouped into logical test steps.
Phase 5: Code Generation (Week 3-4)
Goal: Output idiomatic test code.
Tasks:
- Build code templates for Playwright
- Add Cypress and Selenium support
- Include proper imports and setup
- Generate assertions and waits
Checkpoint: Generated code runs successfully.
Phase 6: Refinement (Week 4+)
Goal: Polish and extend capabilities.
Tasks:
- Support parameterization
- Generate edge case tests
- Add page object model option
- Implement test editing
Checkpoint: Production-quality test generation.
6. Testing Strategy
6.1 Test Scenarios
| Scenario | Recording | Expected Output |
|---|---|---|
| Simple login | Fill form, submit | Login test with assertions |
| Multi-step wizard | Navigate 3 pages | Test with step comments |
| Search + select | Search, click result | Two-step test |
| Form with validation | Trigger error, fix | Error handling test |
| Dynamic content | Wait for async | Proper wait commands |
6.2 Generated Code Validation
- Syntax check: Run linter on generated code
- Execution test: Run generated test on same page
- Stability test: Run 10 times without flakes
- Readability: Human review of code quality
7. Common Pitfalls & Debugging
7.1 Frequent Issues
| Issue | Symptom | Solution |
|---|---|---|
| Generated ID | Selector breaks on reload | Use role/text selectors instead |
| Dynamic content | Test fails on timing | Add proper waits |
| Iframe content | Elements not found | Handle iframe context |
| Hover menus | Click target hidden | Add hover action before click |
| Animation timing | Screenshot mid-animation | Wait for stability |
7.2 Selector Debugging
// Verify selector uniqueness
mcp__claude-in-chrome__javascript_tool({
action: "javascript_exec",
text: `
const selector = '[data-testid="login-btn"]';
const matches = document.querySelectorAll(selector);
JSON.stringify({
selector: selector,
matchCount: matches.length,
matches: Array.from(matches).map(el => ({
tag: el.tagName,
text: el.textContent?.substring(0, 50)
}))
});
`,
tabId: 12345
})
8. Real World Outcome
When you complete this project, hereโs a complete recording and generation session:
You: Record me testing the checkout flow and generate Playwright tests
Claude: I'll start recording your checkout flow test.
[Starting GIF recording...]
[Initial screenshot captured]
Recording in progress... Perform your test actions.
---
[User performs actions over 45 seconds]
---
You: Stop recording
Claude: Recording stopped. Analyzing the workflow...
================================================================================
E2E WORKFLOW RECORDING ANALYSIS
================================================================================
RECORDING SUMMARY
-----------------
Duration: 45 seconds
Actions captured: 12
Page transitions: 3
GIF saved: ./recordings/checkout-2024-12-22-143500.gif
IDENTIFIED WORKFLOW: E-Commerce Checkout
----------------------------------------
Step 1: Browse to Product (0:00 - 0:08)
Actions:
- Navigate to /products
- Click product card "Wireless Headphones"
Element: Product card
[BEST] getByRole('article', { name: 'Wireless Headphones' })
[ALT] getByTestId('product-wh-001')
[ALT] locator('.product-card:has-text("Wireless")')
Step 2: Add to Cart (0:08 - 0:15)
Actions:
- Click "Add to Cart" button
- Wait for cart update notification
Element: Add to Cart button
[BEST] getByRole('button', { name: 'Add to Cart' })
[ALT] getByTestId('add-to-cart')
Assertion opportunity:
- Cart count should increase
- Success notification should appear
Step 3: Navigate to Cart (0:15 - 0:22)
Actions:
- Click cart icon in header
- Verify product in cart
Element: Cart icon
[BEST] getByLabel('Shopping Cart')
[ALT] getByTestId('cart-icon')
Assertion opportunity:
- URL should be /cart
- Product should be visible in cart
Step 4: Proceed to Checkout (0:22 - 0:35)
Actions:
- Click "Checkout" button
- Fill shipping address
- Select shipping method
Elements identified:
- Checkout button: getByRole('button', { name: 'Checkout' })
- Street field: getByLabel('Street Address')
- City field: getByLabel('City')
- Shipping method: getByRole('radio', { name: 'Standard' })
Step 5: Complete Order (0:35 - 0:45)
Actions:
- Click "Place Order" button
- Verify order confirmation
Assertion opportunity:
- URL should contain /order-confirmation
- Order number should be visible
INTENT ANALYSIS
---------------
Primary flow: Complete purchase of single item
Test category: E-commerce / Checkout
Coverage: Happy path with default shipping
Inferred assertions:
1. Product added to cart successfully
2. Cart shows correct item
3. Checkout form accepts valid data
4. Order confirmation displayed
GENERATED TEST (Playwright)
---------------------------
```typescript
import { test, expect } from '@playwright/test';
test.describe('E-commerce Checkout', () => {
test('should complete purchase of single item', async ({ page }) => {
// Step 1: Browse to product
await page.goto('/products');
await page.getByRole('article', { name: 'Wireless Headphones' }).click();
// Step 2: Add to cart
await page.getByRole('button', { name: 'Add to Cart' }).click();
// Verify item added
await expect(page.getByText('Added to cart')).toBeVisible();
// Step 3: Navigate to cart
await page.getByLabel('Shopping Cart').click();
await expect(page).toHaveURL('/cart');
// Verify product in cart
await expect(page.getByText('Wireless Headphones')).toBeVisible();
// Step 4: Proceed to checkout
await page.getByRole('button', { name: 'Checkout' }).click();
// Fill shipping address
await page.getByLabel('Street Address').fill('123 Test Street');
await page.getByLabel('City').fill('Test City');
await page.getByLabel('State').selectOption('California');
await page.getByLabel('ZIP Code').fill('90210');
// Select shipping method
await page.getByRole('radio', { name: 'Standard Shipping' }).check();
// Step 5: Complete order
await page.getByRole('button', { name: 'Place Order' }).click();
// Verify order confirmation
await expect(page).toHaveURL(/order-confirmation/);
await expect(page.getByTestId('order-number')).toBeVisible();
});
});
ADDITIONAL RECOMMENDATIONS
- Data Parameterization:
Consider extracting test data to fixtures:
const testProduct = 'Wireless Headphones'; const shippingAddress = { street: '123 Test Street', city: 'Test City', state: 'California', zip: '90210' }; - Edge Case Tests:
- Empty cart checkout (should be blocked)
- Invalid address (validation error)
- Out of stock item
- Multiple items in cart
- Page Object Model:
For maintainability, consider:
class CheckoutPage { async fillShippingAddress(address) { ... } async selectShippingMethod(method) { ... } async placeOrder() { ... } } - Visual Regression: Add screenshot comparisons at key steps
================================================================================
Would you like me to:
- Generate the edge case tests?
- Convert to Cypress format?
- Create Page Object Model structure?
- Add visual regression checkpoints? ```
9. The Core Question Youโre Answering
โHow do you go from recorded clicks to maintainable test code?โ
Raw action recording produces brittle tests. The transformation requires:
- Semantic Understanding: โClick at (234, 567)โ becomes โClick Sign In buttonโ
- Selector Stability: Generated IDs become test IDs or role selectors
- Intent Grouping: 15 low-level events become 5 meaningful steps
- Assertion Inference: โI see the dashboardโ becomes
expect(page).toHaveURL('/dashboard') - Wait Handling: โPause 3 secondsโ becomes proper await/expect patterns
Claudeโs reasoning capability enables all of these transformations.
10. Concepts You Must Understand First
Before starting this project, ensure you understand:
| Concept | Why It Matters | Where to Learn |
|---|---|---|
| Playwright/Cypress basics | Target output format | Official docs |
| Selector strategies | Core to stable tests | Testing Library docs |
| Async/await patterns | Test timing | MDN JavaScript |
| DOM events | Action recording | MDN - Event reference |
| Page Object Model | Advanced output | Selenium best practices |
| GIF recording | Visual documentation | Project 29 skills |
11. Questions to Guide Your Design
Work through these questions BEFORE implementing:
-
Action Detection: How do you know when a user action occurred? Click? Input? Navigation?
-
Noise Filtering: How do you distinguish intentional actions from incidental mouse movements?
-
Selector Priority: In what order should you try different selector strategies?
-
Assertion Timing: When in the workflow should assertions be added?
-
Multi-Framework: How do you structure code to output different test frameworks?
-
Parameterization: How do you identify values that should be extracted as variables?
12. Thinking Exercise
Before implementing, analyze this action sequence:
1. User clicks dropdown menu
2. Menu opens with animation (300ms)
3. User moves mouse through several options
4. User clicks "Settings"
5. Settings modal opens (fade in 200ms)
6. User toggles a switch to ON
7. User clicks outside modal
8. Modal closes
Questions to answer on paper:
- Which events are โactionsโ vs โnavigationโ?
- How do you know the animation completed?
- Whatโs the meaningful selector for โSettingsโ option?
- What assertion should verify the toggle worked?
- How would you handle the modal dismissal?
- Whatโs the generated test code for this sequence?
13. The Interview Questions Theyโll Ask
After completing this project, youโll be ready for:
- โHow do you generate stable selectors that survive refactors?โ
- Expected: Selector hierarchy, test IDs, role-based selectors
- Bonus: Discuss uniqueness validation, fallback strategies
- โWhatโs your strategy for handling dynamic IDs or content?โ
- Expected: Avoid generated IDs, use semantic selectors
- Bonus: Discuss data-testid patterns, selector composition
- โHow do you differentiate between navigation and actions?โ
- Expected: URL changes, DOM mutations, explicit user gestures
- Bonus: Discuss action grouping algorithms
- โHow would you handle tests that require authenticated state?โ
- Expected: Storage state, session fixtures, API authentication
- Bonus: Discuss Playwrightโs storageState feature
- โWhatโs the page object pattern and when would you use it?โ
- Expected: Encapsulation, reusability, maintenance
- Bonus: Discuss tradeoffs, when simple tests are better
14. Hints in Layers
If you get stuck, reveal hints progressively:
Hint 1: Recording Strategy
Use GIF recording as the primary capture mechanism:
// Start recording and take initial screenshot
gif_creator(action: "start_recording")
computer(action: "screenshot")
// User performs actions (tracked by GIF frames)
// Stop and export with action labels
gif_creator(action: "stop_recording")
gif_creator(action: "export", options: { showClickIndicators: true })
The GIF provides a visual timeline. Correlate with DOM snapshots from read_page.
Hint 2: Element Reference Tracking
When user interacts with an element, capture its reference:
// After observing a click action
mcp__claude-in-chrome__read_page({ tabId, filter: "interactive" })
// Find the clicked element in the accessibility tree
// Extract selectors from its properties:
// - data-testid attribute
// - role and accessible name
// - label text
// - visible text content
Store these for selector generation.
Hint 3: Selector Validation
Before using a selector, verify itโs unique:
mcp__claude-in-chrome__javascript_tool({
action: "javascript_exec",
text: `
const selector = "button:has-text('Submit')";
const matches = document.querySelectorAll(selector);
({ count: matches.length, unique: matches.length === 1 })
`,
tabId
})
If not unique, try more specific selectors.
Hint 4: Claude's Intent Inference
Show Claude the GIF and ask for analysis: โI recorded this user workflow. Watch the GIF and tell me:
- What is the user trying to accomplish?
- What would be a good test name?
- What assertions should verify success?โ
Claudeโs visual understanding provides the intent layer.
15. Books That Will Help
| Topic | Book | Chapter/Section |
|---|---|---|
| Test patterns | โxUnit Test Patternsโ by Gerard Meszaros | Ch. 11-12 |
| Selector strategies | โTesting JavaScript Applicationsโ by Lucas da Costa | Ch. 6 |
| Code generation | โDomain Specific Languagesโ by Martin Fowler | Ch. 8 |
| Playwright fundamentals | Playwright Official Docs | Getting Started |
| Page Object Model | โSelenium WebDriver 3 Practical Guideโ | Ch. 5 |
| Test architecture | โGrowing Object-Oriented Softwareโ by Freeman & Pryce | Ch. 5-6 |
16. Extensions & Challenges
16.1 Beginner Extensions
- Multiple output formats: Add WebDriverIO, TestCafe
- Test organization: Generate describe/context blocks
- Comment generation: Add explanatory comments
16.2 Intermediate Extensions
- Page Object Model: Generate POM structure automatically
- Data-driven tests: Extract data tables from recordings
- Negative tests: Generate error case tests
16.3 Advanced Extensions
- Self-healing selectors: Fallback if primary fails
- Visual assertions: Add screenshot comparisons
- API correlation: Match UI actions to API calls
17. Learning Milestones
Track your progress through these checkpoints:
| Milestone | Description | Verification |
|---|---|---|
| 1. Basic recording | GIF captures user actions | Click indicators visible |
| 2. Action identification | List discrete actions | Timeline matches user flow |
| 3. Selector generation | Stable selectors created | Selectors work on reload |
| 4. Intent inference | Meaningful test names | Names describe workflow |
| 5. Code generation | Runnable test code | Generated test passes |
| 6. Multi-framework | Playwright + Cypress | Both outputs work |
This guide was expanded from CLAUDE_CODE_MASTERY_40_PROJECTS.md. For the complete learning path, see the project index.