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:

  1. Record browser interactions: Capture clicks, inputs, navigation, and assertions
  2. Infer user intent: Understand why actions were taken, not just what was done
  3. Generate robust selectors: Create stable element selectors that survive refactors
  4. Synthesize test code: Produce idiomatic code for Playwright, Cypress, or Selenium
  5. Add intelligent assertions: Determine what to verify based on workflow context
  6. 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:

  1. Records user interactions through Chrome MCP
  2. Infers intent and groups related actions
  3. Generates stable selectors for each element
  4. Produces test code in multiple frameworks
  5. Adds appropriate assertions and waits
  6. Supports editing and refinement of generated tests

3.2 Functional Requirements

  1. 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
  2. Intent Analysis
    • Group related actions into test steps
    • Identify workflow patterns (login, search, checkout)
    • Determine appropriate test names
    • Suggest test boundaries
  3. Selector Generation
    • Prefer test IDs when available
    • Fall back through selector hierarchy
    • Validate selector uniqueness
    • Generate multiple selector options
  4. Assertion Generation
    • Add URL verification after navigation
    • Include element visibility checks
    • Verify expected text content
    • Support custom assertion insertion
  5. Code Generation
    • Output Playwright (default)
    • Support Cypress and Selenium
    • Generate TypeScript or JavaScript
    • Include proper imports and setup
  6. 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

  1. Security: Replace hardcoded password with environment variable Example: process.env.TEST_PASSWORD

  2. Data: Consider using test fixtures for credentials Example: test.use({ storageState: โ€˜auth.jsonโ€™ })

  3. Edge cases: Consider adding tests for:

    • Invalid credentials
    • Empty fields
    • Account lockout

Would you like me to:

  1. Generate the additional edge case tests?
  2. Convert to Cypress or Selenium format?
  3. Create a Page Object Model structure?
  4. 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:

  1. Implement start/stop recording commands
  2. Capture screenshots at key moments
  3. Track URL changes
  4. 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:

  1. Analyze GIF frames for action detection
  2. Correlate with read_page DOM snapshots
  3. Build action timeline with timestamps
  4. 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:

  1. Implement selector extraction
  2. Rank selectors by stability
  3. Validate uniqueness
  4. Generate framework-specific syntax

Checkpoint: Each action has robust selector attached.

Phase 4: Intent Inference (Week 3)

Goal: Understand workflow purpose using Claude.

Tasks:

  1. Implement pattern matching rules
  2. Use Claude to analyze action sequences
  3. Generate meaningful test names
  4. Identify assertion opportunities

Checkpoint: Actions grouped into logical test steps.

Phase 5: Code Generation (Week 3-4)

Goal: Output idiomatic test code.

Tasks:

  1. Build code templates for Playwright
  2. Add Cypress and Selenium support
  3. Include proper imports and setup
  4. Generate assertions and waits

Checkpoint: Generated code runs successfully.

Phase 6: Refinement (Week 4+)

Goal: Polish and extend capabilities.

Tasks:

  1. Support parameterization
  2. Generate edge case tests
  3. Add page object model option
  4. 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

  1. Syntax check: Run linter on generated code
  2. Execution test: Run generated test on same page
  3. Stability test: Run 10 times without flakes
  4. 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

  1. 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'
    };
    
  2. Edge Case Tests:
    • Empty cart checkout (should be blocked)
    • Invalid address (validation error)
    • Out of stock item
    • Multiple items in cart
  3. Page Object Model: For maintainability, consider:
    class CheckoutPage {
      async fillShippingAddress(address) { ... }
      async selectShippingMethod(method) { ... }
      async placeOrder() { ... }
    }
    
  4. Visual Regression: Add screenshot comparisons at key steps

================================================================================

Would you like me to:

  1. Generate the edge case tests?
  2. Convert to Cypress format?
  3. Create Page Object Model structure?
  4. 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:

  1. Semantic Understanding: โ€œClick at (234, 567)โ€ becomes โ€œClick Sign In buttonโ€
  2. Selector Stability: Generated IDs become test IDs or role selectors
  3. Intent Grouping: 15 low-level events become 5 meaningful steps
  4. Assertion Inference: โ€œI see the dashboardโ€ becomes expect(page).toHaveURL('/dashboard')
  5. 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:

  1. Action Detection: How do you know when a user action occurred? Click? Input? Navigation?

  2. Noise Filtering: How do you distinguish intentional actions from incidental mouse movements?

  3. Selector Priority: In what order should you try different selector strategies?

  4. Assertion Timing: When in the workflow should assertions be added?

  5. Multi-Framework: How do you structure code to output different test frameworks?

  6. 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:

  1. Which events are โ€œactionsโ€ vs โ€œnavigationโ€?
  2. How do you know the animation completed?
  3. Whatโ€™s the meaningful selector for โ€œSettingsโ€ option?
  4. What assertion should verify the toggle worked?
  5. How would you handle the modal dismissal?
  6. 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:

  1. โ€œHow do you generate stable selectors that survive refactors?โ€
    • Expected: Selector hierarchy, test IDs, role-based selectors
    • Bonus: Discuss uniqueness validation, fallback strategies
  2. โ€œWhatโ€™s your strategy for handling dynamic IDs or content?โ€
    • Expected: Avoid generated IDs, use semantic selectors
    • Bonus: Discuss data-testid patterns, selector composition
  3. โ€œHow do you differentiate between navigation and actions?โ€
    • Expected: URL changes, DOM mutations, explicit user gestures
    • Bonus: Discuss action grouping algorithms
  4. โ€œHow would you handle tests that require authenticated state?โ€
    • Expected: Storage state, session fixtures, API authentication
    • Bonus: Discuss Playwrightโ€™s storageState feature
  5. โ€œ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:

  1. What is the user trying to accomplish?
  2. What would be a good test name?
  3. 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.