<!-- Powered by BMAD-CORE™ -->

# Acceptance Test-Driven Development (ATDD)

**Workflow ID**: `.bmad/bmm/testarch/atdd`
**Version**: 4.0 (BMad v6)

---

## Overview

Generates failing acceptance tests BEFORE implementation following TDD's red-green-refactor cycle. This workflow creates comprehensive test coverage at appropriate levels (E2E, API, Component) with supporting infrastructure (fixtures, factories, mocks) and provides an implementation checklist to guide development.

**Core Principle**: Tests fail first (red phase), then guide development to green, then enable confident refactoring.

---

## Preflight Requirements

**Critical:** Verify these requirements before proceeding. If any fail, HALT and notify the user.

- ✅ Story approved with clear acceptance criteria
- ✅ Development sandbox/environment ready
- ✅ Framework scaffolding exists (run `framework` workflow if missing)
- ✅ Test framework configuration available (playwright.config.ts or cypress.config.ts)

---

## Step 1: Load Story Context and Requirements

### Actions

1. **Read Story Markdown**
   - Load story file from `{story_file}` variable
   - Extract acceptance criteria (all testable requirements)
   - Identify affected systems and components
   - Note any technical constraints or dependencies

2. **Load Framework Configuration**
   - Read framework config (playwright.config.ts or cypress.config.ts)
   - Identify test directory structure
   - Check existing fixture patterns
   - Note test runner capabilities

3. **Load Existing Test Patterns**
   - Search `{test_dir}` for similar tests
   - Identify reusable fixtures and helpers
   - Check data factory patterns
   - Note naming conventions

4. **Load Knowledge Base Fragments**

   **Critical:** Consult `{project-root}/.bmad/bmm/testarch/tea-index.csv` to load:
   - `fixture-architecture.md` - Test fixture patterns with auto-cleanup (pure function → fixture → mergeTests composition, 406 lines, 5 examples)
   - `data-factories.md` - Factory patterns using faker (override patterns, nested factories, API seeding, 498 lines, 5 examples)
   - `component-tdd.md` - Component test strategies (red-green-refactor, provider isolation, accessibility, visual regression, 480 lines, 4 examples)
   - `network-first.md` - Route interception patterns (intercept before navigate, HAR capture, deterministic waiting, 489 lines, 5 examples)
   - `test-quality.md` - Test design principles (deterministic tests, isolated with cleanup, explicit assertions, length limits, execution time optimization, 658 lines, 5 examples)
   - `test-healing-patterns.md` - Common failure patterns and healing strategies (stale selectors, race conditions, dynamic data, network errors, hard waits, 648 lines, 5 examples)
   - `selector-resilience.md` - Selector best practices (data-testid > ARIA > text > CSS hierarchy, dynamic patterns, anti-patterns, 541 lines, 4 examples)
   - `timing-debugging.md` - Race condition prevention and async debugging (network-first, deterministic waiting, anti-patterns, 370 lines, 3 examples)

**Halt Condition:** If story has no acceptance criteria or framework is missing, HALT with message: "ATDD requires clear acceptance criteria and test framework setup"

---

## Step 1.5: Generation Mode Selection (NEW - Phase 2.5)

### Actions

1. **Detect Generation Mode**

   Determine mode based on scenario complexity:

   **AI Generation Mode (DEFAULT)**:
   - Clear acceptance criteria with standard patterns
   - Uses: AI-generated tests from requirements
   - Appropriate for: CRUD, auth, navigation, API tests
   - Fastest approach

   **Recording Mode (OPTIONAL - Complex UI)**:
   - Complex UI interactions (drag-drop, wizards, multi-page flows)
   - Uses: Interactive test recording with Playwright MCP
   - Appropriate for: Visual workflows, unclear requirements
   - Only if config.tea_use_mcp_enhancements is true AND MCP available

2. **AI Generation Mode (DEFAULT - Continue to Step 2)**

   For standard scenarios:
   - Continue with existing workflow (Step 2: Select Test Levels and Strategy)
   - AI generates tests based on acceptance criteria from Step 1
   - Use knowledge base patterns for test structure

3. **Recording Mode (OPTIONAL - Complex UI Only)**

   For complex UI scenarios AND config.tea_use_mcp_enhancements is true:

   **A. Check MCP Availability**

   If Playwright MCP tools are available in your IDE:
   - Use MCP recording mode (Step 3.B)

   If MCP unavailable:
   - Fallback to AI generation mode (silent, automatic)
   - Continue to Step 2

   **B. Interactive Test Recording (MCP-Based)**

   Use Playwright MCP test-generator tools:

   **Setup:**

   ```
   1. Use generator_setup_page to initialize recording session
   2. Navigate to application starting URL (from story context)
   3. Ready to record user interactions
   ```

   **Recording Process (Per Acceptance Criterion):**

   ```
   4. Read acceptance criterion from story
   5. Manually execute test scenario using browser_* tools:
      - browser_navigate: Navigate to pages
      - browser_click: Click buttons, links, elements
      - browser_type: Fill form fields
      - browser_select: Select dropdown options
      - browser_check: Check/uncheck checkboxes
   6. Add verification steps using browser_verify_* tools:
      - browser_verify_text: Verify text content
      - browser_verify_visible: Verify element visibility
      - browser_verify_url: Verify URL navigation
   7. Capture interaction log with generator_read_log
   8. Generate test file with generator_write_test
   9. Repeat for next acceptance criterion
   ```

   **Post-Recording Enhancement:**

   ```
   10. Review generated test code
   11. Enhance with knowledge base patterns:
       - Add Given-When-Then comments
       - Replace recorded selectors with data-testid (if needed)
       - Add network-first interception (from network-first.md)
       - Add fixtures for auth/data setup (from fixture-architecture.md)
       - Use factories for test data (from data-factories.md)
   12. Verify tests fail (missing implementation)
   13. Continue to Step 4 (Build Data Infrastructure)
   ```

   **When to Use Recording Mode:**
   - ✅ Complex UI interactions (drag-drop, multi-step forms, wizards)
   - ✅ Visual workflows (modals, dialogs, animations)
   - ✅ Unclear requirements (exploratory, discovering expected behavior)
   - ✅ Multi-page flows (checkout, registration, onboarding)
   - ❌ NOT for simple CRUD (AI generation faster)
   - ❌ NOT for API-only tests (no UI to record)

   **When to Use AI Generation (Default):**
   - ✅ Clear acceptance criteria available
   - ✅ Standard patterns (login, CRUD, navigation)
   - ✅ Need many tests quickly
   - ✅ API/backend tests (no UI interaction)

4. **Proceed to Test Level Selection**

   After mode selection:
   - AI Generation: Continue to Step 2 (Select Test Levels and Strategy)
   - Recording: Skip to Step 4 (Build Data Infrastructure) - tests already generated

---

## Step 2: Select Test Levels and Strategy

### Actions

1. **Analyze Acceptance Criteria**

   For each acceptance criterion, determine:
   - Does it require full user journey? → E2E test
   - Does it test business logic/API contract? → API test
   - Does it validate UI component behavior? → Component test
   - Can it be unit tested? → Unit test

2. **Apply Test Level Selection Framework**

   **Knowledge Base Reference**: `test-levels-framework.md`

   **E2E (End-to-End)**:
   - Critical user journeys (login, checkout, core workflow)
   - Multi-system integration
   - User-facing acceptance criteria
   - **Characteristics**: High confidence, slow execution, brittle

   **API (Integration)**:
   - Business logic validation
   - Service contracts
   - Data transformations
   - **Characteristics**: Fast feedback, good balance, stable

   **Component**:
   - UI component behavior (buttons, forms, modals)
   - Interaction testing
   - Visual regression
   - **Characteristics**: Fast, isolated, granular

   **Unit**:
   - Pure business logic
   - Edge cases
   - Error handling
   - **Characteristics**: Fastest, most granular

3. **Avoid Duplicate Coverage**

   Don't test same behavior at multiple levels unless necessary:
   - Use E2E for critical happy path only
   - Use API tests for complex business logic variations
   - Use component tests for UI interaction edge cases
   - Use unit tests for pure logic edge cases

4. **Prioritize Tests**

   If test-design document exists, align with priority levels:
   - P0 scenarios → Must cover in failing tests
   - P1 scenarios → Should cover if time permits
   - P2/P3 scenarios → Optional for this iteration

**Decision Point:** Set `primary_level` variable to main test level for this story (typically E2E or API)

---

## Step 3: Generate Failing Tests

### Actions

1. **Create Test File Structure**

   ```
   tests/
   ├── e2e/
   │   └── {feature-name}.spec.ts        # E2E acceptance tests
   ├── api/
   │   └── {feature-name}.api.spec.ts    # API contract tests
   ├── component/
   │   └── {ComponentName}.test.tsx      # Component tests
   └── support/
       ├── fixtures/                      # Test fixtures
       ├── factories/                     # Data factories
       └── helpers/                       # Utility functions
   ```

2. **Write Failing E2E Tests (If Applicable)**

   **Use Given-When-Then format:**

   ```typescript
   import { test, expect } from '@playwright/test';

   test.describe('User Login', () => {
     test('should display error for invalid credentials', async ({ page }) => {
       // GIVEN: User is on login page
       await page.goto('/login');

       // WHEN: User submits invalid credentials
       await page.fill('[data-testid="email-input"]', 'invalid@example.com');
       await page.fill('[data-testid="password-input"]', 'wrongpassword');
       await page.click('[data-testid="login-button"]');

       // THEN: Error message is displayed
       await expect(page.locator('[data-testid="error-message"]')).toHaveText('Invalid email or password');
     });
   });
   ```

   **Critical patterns:**
   - One assertion per test (atomic tests)
   - Explicit waits (no hard waits/sleeps)
   - Network-first approach (route interception before navigation)
   - data-testid selectors for stability
   - Clear Given-When-Then structure

3. **Apply Network-First Pattern**

   **Knowledge Base Reference**: `network-first.md`

   ```typescript
   test('should load user dashboard after login', async ({ page }) => {
     // CRITICAL: Intercept routes BEFORE navigation
     await page.route('**/api/user', (route) =>
       route.fulfill({
         status: 200,
         body: JSON.stringify({ id: 1, name: 'Test User' }),
       }),
     );

     // NOW navigate
     await page.goto('/dashboard');

     await expect(page.locator('[data-testid="user-name"]')).toHaveText('Test User');
   });
   ```

4. **Write Failing API Tests (If Applicable)**

   ```typescript
   import { test, expect } from '@playwright/test';

   test.describe('User API', () => {
     test('POST /api/users - should create new user', async ({ request }) => {
       // GIVEN: Valid user data
       const userData = {
         email: 'newuser@example.com',
         name: 'New User',
       };

       // WHEN: Creating user via API
       const response = await request.post('/api/users', {
         data: userData,
       });

       // THEN: User is created successfully
       expect(response.status()).toBe(201);
       const body = await response.json();
       expect(body).toMatchObject({
         email: userData.email,
         name: userData.name,
         id: expect.any(Number),
       });
     });
   });
   ```

5. **Write Failing Component Tests (If Applicable)**

   **Knowledge Base Reference**: `component-tdd.md`

   ```typescript
   import { test, expect } from '@playwright/experimental-ct-react';
   import { LoginForm } from './LoginForm';

   test.describe('LoginForm Component', () => {
     test('should disable submit button when fields are empty', async ({ mount }) => {
       // GIVEN: LoginForm is mounted
       const component = await mount(<LoginForm />);

       // WHEN: Form is initially rendered
       const submitButton = component.locator('button[type="submit"]');

       // THEN: Submit button is disabled
       await expect(submitButton).toBeDisabled();
     });
   });
   ```

6. **Verify Tests Fail Initially**

   **Critical verification:**
   - Run tests locally to confirm they fail
   - Failure should be due to missing implementation, not test errors
   - Failure messages should be clear and actionable
   - All tests must be in RED phase before sharing with DEV

**Important:** Tests MUST fail initially. If a test passes before implementation, it's not a valid acceptance test.

---

## Step 4: Build Data Infrastructure

### Actions

1. **Create Data Factories**

   **Knowledge Base Reference**: `data-factories.md`

   ```typescript
   // tests/support/factories/user.factory.ts
   import { faker } from '@faker-js/faker';

   export const createUser = (overrides = {}) => ({
     id: faker.number.int(),
     email: faker.internet.email(),
     name: faker.person.fullName(),
     createdAt: faker.date.recent().toISOString(),
     ...overrides,
   });

   export const createUsers = (count: number) => Array.from({ length: count }, () => createUser());
   ```

   **Factory principles:**
   - Use faker for random data (no hardcoded values)
   - Support overrides for specific scenarios
   - Generate complete valid objects
   - Include helper functions for bulk creation

2. **Create Test Fixtures**

   **Knowledge Base Reference**: `fixture-architecture.md`

   ```typescript
   // tests/support/fixtures/auth.fixture.ts
   import { test as base } from '@playwright/test';

   export const test = base.extend({
     authenticatedUser: async ({ page }, use) => {
       // Setup: Create and authenticate user
       const user = await createUser();
       await page.goto('/login');
       await page.fill('[data-testid="email"]', user.email);
       await page.fill('[data-testid="password"]', 'password123');
       await page.click('[data-testid="login-button"]');
       await page.waitForURL('/dashboard');

       // Provide to test
       await use(user);

       // Cleanup: Delete user
       await deleteUser(user.id);
     },
   });
   ```

   **Fixture principles:**
   - Auto-cleanup (always delete created data)
   - Composable (fixtures can use other fixtures)
   - Isolated (each test gets fresh data)
   - Type-safe

3. **Document Mock Requirements**

   If external services need mocking, document requirements:

   ```markdown
   ### Mock Requirements for DEV Team

   **Payment Gateway Mock**:

   - Endpoint: `POST /api/payments`
   - Success response: `{ status: 'success', transactionId: '123' }`
   - Failure response: `{ status: 'failed', error: 'Insufficient funds' }`

   **Email Service Mock**:

   - Should not send real emails in test environment
   - Log email contents for verification
   ```

4. **List Required data-testid Attributes**

   ```markdown
   ### Required data-testid Attributes

   **Login Page**:

   - `email-input` - Email input field
   - `password-input` - Password input field
   - `login-button` - Submit button
   - `error-message` - Error message container

   **Dashboard Page**:

   - `user-name` - User name display
   - `logout-button` - Logout button
   ```

---

## Step 5: Create Implementation Checklist

### Actions

1. **Map Tests to Implementation Tasks**

   For each failing test, create corresponding implementation task:

   ```markdown
   ## Implementation Checklist

   ### Epic X - User Authentication

   #### Test: User Login with Valid Credentials

   - [ ] Create `/login` route
   - [ ] Implement login form component
   - [ ] Add email/password validation
   - [ ] Integrate authentication API
   - [ ] Add `data-testid` attributes: `email-input`, `password-input`, `login-button`
   - [ ] Implement error handling
   - [ ] Run test: `npm run test:e2e -- login.spec.ts`
   - [ ] ✅ Test passes (green phase)

   #### Test: Display Error for Invalid Credentials

   - [ ] Add error state management
   - [ ] Display error message UI
   - [ ] Add `data-testid="error-message"`
   - [ ] Run test: `npm run test:e2e -- login.spec.ts`
   - [ ] ✅ Test passes (green phase)
   ```

2. **Include Red-Green-Refactor Guidance**

   ```markdown
   ## Red-Green-Refactor Workflow

   **RED Phase** (Complete):

   - ✅ All tests written and failing
   - ✅ Fixtures and factories created
   - ✅ Mock requirements documented

   **GREEN Phase** (DEV Team):

   1. Pick one failing test
   2. Implement minimal code to make it pass
   3. Run test to verify green
   4. Move to next test
   5. Repeat until all tests pass

   **REFACTOR Phase** (DEV Team):

   1. All tests passing (green)
   2. Improve code quality
   3. Extract duplications
   4. Optimize performance
   5. Ensure tests still pass
   ```

3. **Add Execution Commands**

   ````markdown
   ## Running Tests

   ```bash
   # Run all failing tests
   npm run test:e2e

   # Run specific test file
   npm run test:e2e -- login.spec.ts

   # Run tests in headed mode (see browser)
   npm run test:e2e -- --headed

   # Debug specific test
   npm run test:e2e -- login.spec.ts --debug
   ```
   ````

   ```

   ```

---

## Step 6: Generate Deliverables

### Actions

1. **Create ATDD Checklist Document**

   Use template structure at `{installed_path}/atdd-checklist-template.md`:
   - Story summary
   - Acceptance criteria breakdown
   - Test files created (with paths)
   - Data factories created
   - Fixtures created
   - Mock requirements
   - Required data-testid attributes
   - Implementation checklist
   - Red-green-refactor workflow
   - Execution commands

2. **Verify All Tests Fail**

   Before finalizing:
   - Run full test suite locally
   - Confirm all tests in RED phase
   - Document expected failure messages
   - Ensure failures are due to missing implementation, not test bugs

3. **Write to Output File**

   Save to `{output_folder}/atdd-checklist-{story_id}.md`

---

## Important Notes

### Red-Green-Refactor Cycle

**RED Phase** (TEA responsibility):

- Write failing tests first
- Tests define expected behavior
- Tests must fail for right reason (missing implementation)

**GREEN Phase** (DEV responsibility):

- Implement minimal code to pass tests
- One test at a time
- Don't over-engineer

**REFACTOR Phase** (DEV responsibility):

- Improve code quality with confidence
- Tests provide safety net
- Extract duplications, optimize

### Given-When-Then Structure

**GIVEN** (Setup):

- Arrange test preconditions
- Create necessary data
- Navigate to starting point

**WHEN** (Action):

- Execute the behavior being tested
- Single action per test

**THEN** (Assertion):

- Verify expected outcome
- One assertion per test (atomic)

### Network-First Testing

**Critical pattern:**

```typescript
// ✅ CORRECT: Intercept BEFORE navigation
await page.route('**/api/data', handler);
await page.goto('/page');

// ❌ WRONG: Navigate then intercept (race condition)
await page.goto('/page');
await page.route('**/api/data', handler); // Too late!
```

### Data Factory Best Practices

**Use faker for all test data:**

```typescript
// ✅ CORRECT: Random data
email: faker.internet.email();

// ❌ WRONG: Hardcoded data (collisions, maintenance burden)
email: 'test@example.com';
```

**Auto-cleanup principle:**

- Every factory that creates data must provide cleanup
- Fixtures automatically cleanup in teardown
- No manual cleanup in test code

### One Assertion Per Test

**Atomic test design:**

```typescript
// ✅ CORRECT: One assertion
test('should display user name', async ({ page }) => {
  await expect(page.locator('[data-testid="user-name"]')).toHaveText('John');
});

// ❌ WRONG: Multiple assertions (not atomic)
test('should display user info', async ({ page }) => {
  await expect(page.locator('[data-testid="user-name"]')).toHaveText('John');
  await expect(page.locator('[data-testid="user-email"]')).toHaveText('john@example.com');
});
```

**Why?** If second assertion fails, you don't know if first is still valid.

### Component Test Strategy

**When to use component tests:**

- Complex UI interactions (drag-drop, keyboard nav)
- Form validation logic
- State management within component
- Visual edge cases

**When NOT to use:**

- Simple rendering (snapshot tests are sufficient)
- Integration with backend (use E2E or API tests)
- Full user journeys (use E2E tests)

### Knowledge Base Integration

**Core Fragments (Auto-loaded in Step 1):**

- `fixture-architecture.md` - Pure function → fixture → mergeTests patterns (406 lines, 5 examples)
- `data-factories.md` - Factory patterns with faker, overrides, API seeding (498 lines, 5 examples)
- `component-tdd.md` - Red-green-refactor, provider isolation, accessibility, visual regression (480 lines, 4 examples)
- `network-first.md` - Intercept before navigate, HAR capture, deterministic waiting (489 lines, 5 examples)
- `test-quality.md` - Deterministic tests, cleanup, explicit assertions, length/time limits (658 lines, 5 examples)
- `test-healing-patterns.md` - Common failure patterns: stale selectors, race conditions, dynamic data, network errors, hard waits (648 lines, 5 examples)
- `selector-resilience.md` - Selector hierarchy (data-testid > ARIA > text > CSS), dynamic patterns, anti-patterns (541 lines, 4 examples)
- `timing-debugging.md` - Race condition prevention, deterministic waiting, async debugging (370 lines, 3 examples)

**Reference for Test Level Selection:**

- `test-levels-framework.md` - E2E vs API vs Component vs Unit decision framework (467 lines, 4 examples)

**Manual Reference (Optional):**

- Use `tea-index.csv` to find additional specialized fragments as needed

---

## Output Summary

After completing this workflow, provide a summary:

```markdown
## ATDD Complete - Tests in RED Phase

**Story**: {story_id}
**Primary Test Level**: {primary_level}

**Failing Tests Created**:

- E2E tests: {e2e_count} tests in {e2e_files}
- API tests: {api_count} tests in {api_files}
- Component tests: {component_count} tests in {component_files}

**Supporting Infrastructure**:

- Data factories: {factory_count} factories created
- Fixtures: {fixture_count} fixtures with auto-cleanup
- Mock requirements: {mock_count} services documented

**Implementation Checklist**:

- Total tasks: {task_count}
- Estimated effort: {effort_estimate} hours

**Required data-testid Attributes**: {data_testid_count} attributes documented

**Next Steps for DEV Team**:

1. Run failing tests: `npm run test:e2e`
2. Review implementation checklist
3. Implement one test at a time (RED → GREEN)
4. Refactor with confidence (tests provide safety net)
5. Share progress in daily standup

**Output File**: {output_file}

**Knowledge Base References Applied**:

- Fixture architecture patterns
- Data factory patterns with faker
- Network-first route interception
- Component TDD strategies
- Test quality principles
```

---

## Validation

After completing all steps, verify:

- [ ] Story acceptance criteria analyzed and mapped to tests
- [ ] Appropriate test levels selected (E2E, API, Component)
- [ ] All tests written in Given-When-Then format
- [ ] All tests fail initially (RED phase verified)
- [ ] Network-first pattern applied (route interception before navigation)
- [ ] Data factories created with faker
- [ ] Fixtures created with auto-cleanup
- [ ] Mock requirements documented for DEV team
- [ ] Required data-testid attributes listed
- [ ] Implementation checklist created with clear tasks
- [ ] Red-green-refactor workflow documented
- [ ] Execution commands provided
- [ ] Output file created and formatted correctly

Refer to `checklist.md` for comprehensive validation criteria.
