# Test Coverage Analysis Report

> **Snapshot: 2025-12-12.** For current coverage run `npm test -- --coverage`.

**Date**: 2025-12-12
**Analyzer**: Claude Code
**Application**: AMSOIL Dealer Landing Pages (DLP)

---

## Executive Summary

The AMSOIL DLP application currently has **36.7% overall line coverage** across 225 test files. While certain modules demonstrate excellent testing practices (CMS publisher at 99%, email services at 100%), critical business-critical flows remain completely untested. This analysis identifies three high-priority areas requiring immediate attention and provides actionable implementation plans.

### Coverage Metrics

| Metric         | Total | Covered | Coverage % |
| -------------- | ----- | ------- | ---------- |
| **Lines**      | 5,547 | 2,035   | **36.68%** |
| **Statements** | 5,807 | 2,110   | **36.33%** |
| **Functions**  | 842   | 257     | **30.52%** |
| **Branches**   | 3,501 | 1,260   | **35.98%** |

---

## Current Testing Landscape

### Well-Tested Modules ✅

These areas demonstrate excellent testing practices:

1. **CMS Publishing System** (99.09% coverage)
   - `lib/cms/publisher.ts` - 111/111 lines covered
   - Comprehensive component rendering tests
   - Edge case validation

2. **Email Services** (100% coverage)
   - `lib/email/index.ts`, `lib/email/providers/*`
   - SMTP and Resend provider implementations
   - Error handling and fallback logic

3. **Domain & Validation Logic** (100% coverage)
   - `lib/custom-domain-validation.ts`
   - `lib/subdomain-validation.ts`
   - `lib/email-utils.ts`
   - `lib/domain-assignment.ts`

4. **Registration Helpers** (95.65% coverage)
   - `lib/registration-helpers.ts` - 66/69 lines covered
   - Transaction handling and error cases

5. **ISR Revalidation** (100% coverage)
   - `lib/isr-revalidation.ts`
   - Cache invalidation logic

### Testing Infrastructure ✅

- **Framework**: Jest with Next.js integration
- **Environment**: jsdom for React component testing
- **Coverage Collection**: Configured for `app/` and `lib/` directories
- **Test Organization**: Co-located `__tests__` directories
- **Total Test Files**: 225

---

## Top 3 Areas with Critical Coverage Gaps

### 🔴 #1: Authentication & Authorization System (0% coverage)

**Severity**: CRITICAL
**Business Impact**: Complete security failure risk
**Technical Debt**: HIGH

#### Untested Components

1. **OAuth Authentication Flow** (`lib/auth.ts` - 413 lines)
   - Google OAuth provider configuration
   - Apple OAuth JWT generation with ES256 signing
   - User creation and account linking logic
   - JWT token generation with Prisma user ID mapping
   - Session callback with impersonation support

2. **Middleware & Access Control** (`middleware.ts` - 255 lines)
   - Subdomain extraction and routing
   - Custom domain lookup with timeout handling
   - CSRF protection validation
   - Protected route enforcement
   - Admin role verification
   - JWT token validation error handling

3. **CSRF Protection** (`lib/csrf.ts` - 162 lines, 14.58% coverage)
   - Origin header validation
   - Subdomain pattern matching
   - Referer fallback logic
   - Higher-order function wrapper

4. **Admin Authorization** (`lib/admin-auth.ts` - 44 lines)
   - Admin role verification
   - Permission checks
   - Impersonation authorization

#### Why This Is Dangerous

1. **Security Vulnerabilities**:
   - OAuth callback hijacking could allow account takeover
   - CSRF protection bugs could enable unauthorized state changes
   - Middleware bypasses could expose admin functionality
   - JWT manipulation could escalate privileges

2. **Silent Failures**:
   - Apple OAuth JWT generation uses ES256 signing - any key format error fails silently
   - Middleware timeout on custom domain lookup could cause routing failures
   - Token expiration edge cases are unhandled

3. **Database Integrity**:
   - Account linking logic could create orphaned records
   - Email normalization inconsistencies could prevent login
   - Race conditions in user creation are untested

#### Regression Scenarios Without Tests

| Scenario                   | Current Risk                          | Impact                               |
| -------------------------- | ------------------------------------- | ------------------------------------ |
| Apple private key rotation | JWT generation fails silently         | All Apple OAuth logins break         |
| NEXTAUTH_SECRET rotation   | Invalid tokens not handled gracefully | All users logged out, session errors |
| Subdomain regex change     | Middleware routing breaks             | Dealer sites inaccessible            |
| CSRF origin list update    | Legitimate requests blocked           | Feature downtime                     |
| Impersonation token expiry | Expired sessions not detected         | Security vulnerability               |

---

### 🔴 #2: Stripe Integration & Revenue Flow (0% coverage)

**Severity**: CRITICAL
**Business Impact**: Revenue loss, data corruption
**Technical Debt**: HIGH

#### Untested Components

1. **Stripe Webhook Handler** (`app/api/webhooks/stripe/route.ts` - 383 lines)
   - Signature verification
   - Event deduplication logic
   - `checkout.session.completed` - Creates dealer accounts
   - `customer.subscription.updated` - Updates tier and status
   - `customer.subscription.deleted` - Cancels accounts
   - `invoice.payment_failed` - Grace period logic
   - Rate limiting (600 req/min)

2. **Checkout Session Creation** (`app/api/checkout/create-session/route.ts` - 183 lines)
   - User authentication verification
   - Duplicate account prevention
   - Plan validation and price ID mapping
   - Stripe session creation with metadata
   - Status-based redirect logic

3. **Stripe Webhook Handlers** (`lib/stripe-webhook-handlers.ts` - 68.35% coverage)
   - `createDealerFromCheckout` - Partial coverage
   - Tier mapping from Stripe price IDs
   - Email normalization for Stripe data
   - Idempotency handling

4. **Subscription Portal** (`app/api/subscription/portal/route.ts` - 37 lines)
   - Completely untested

#### Why This Is Dangerous

1. **Revenue Impact**:
   - Webhook signature verification failure = payment not processed
   - Event deduplication bugs = duplicate charges or accounts
   - Subscription tier mapping errors = wrong features enabled

2. **Data Corruption**:
   - Dealer creation race conditions could create orphaned accounts
   - Status mapping errors could suspend active paying customers
   - Failed webhook processing could leave accounts in inconsistent state

3. **Operational Chaos**:
   - Unhandled Stripe API errors could block all registrations
   - Grace period logic errors could prematurely suspend accounts
   - Cancellation handling bugs could prevent reactivation

#### Regression Scenarios Without Tests

| Scenario                     | Current Risk                 | Impact                          |
| ---------------------------- | ---------------------------- | ------------------------------- |
| Stripe price ID change       | Tier mapping breaks          | New subscriptions fail          |
| Webhook secret rotation      | Signature verification fails | All webhooks rejected           |
| Duplicate webhook delivery   | Idempotency fails            | Duplicate dealer records        |
| Subscription status change   | Status mapping error         | Active users suspended          |
| Payment retry logic          | Grace period miscalculated   | Premature cancellations         |
| Customer email normalization | Email mismatch               | User can't login after checkout |

---

### 🔴 #3: Registration & Onboarding Flow (0% coverage)

**Severity**: HIGH
**Business Impact**: Customer acquisition failure
**Technical Debt**: MEDIUM

#### Untested Components

1. **Registration Completion** (`app/api/register/complete/route.ts` - 236 lines)
   - Stripe session verification
   - Dealer ownership validation
   - Subdomain availability checking
   - Data validation orchestration
   - Error handling for various failure modes

2. **Registration Pages** (All 0% coverage)
   - `/app/registration/onboarding/page.tsx`
   - `/app/registration/terms/page.tsx`
   - `/app/registration/welcome/page.tsx`

3. **Admin Impersonation API** (0% coverage, but lib has 79.31%)
   - `/app/api/admin/impersonate/start/route.ts` - 52 lines
   - `/app/api/admin/impersonate/end/route.ts` - 39 lines
   - Token injection and validation

#### Why This Is Problematic

1. **Customer Acquisition**:
   - Registration failures prevent revenue
   - Poor error messages frustrate users
   - Subdomain conflicts cause abandonment

2. **Support Burden**:
   - Unhandled edge cases require manual intervention
   - Session expiration not gracefully handled
   - No validation for malformed data from Stripe

3. **Admin Tooling**:
   - Impersonation bugs could lock admins in dealer sessions
   - Token expiration could leave admins unable to exit impersonation

#### Regression Scenarios Without Tests

| Scenario                 | Current Risk                         | Impact                           |
| ------------------------ | ------------------------------------ | -------------------------------- |
| Stripe session expired   | No graceful error handling           | User stuck on registration page  |
| Subdomain already taken  | Race condition in availability check | Registration fails after payment |
| Invalid dealer ownership | Security check bypassed              | Users could claim other accounts |
| Impersonation expiry     | Admin stuck as dealer                | Support intervention required    |
| Missing required fields  | Validation errors unclear            | User confusion, abandonment      |

---

## Additional High-Risk Untested Areas

### 4. Dashboard & Admin Features (0% coverage)

- All admin API routes: `/app/api/admin/*` - 0% coverage
- Stats/Analytics: `/app/api/stats/*` - 0% coverage (93 lines in dashboard route alone)
- Dealer settings: `/app/api/dealer/settings/route.ts` - 0% coverage
- Dashboard pages: All React components - 0% coverage

### 5. Content Management APIs (Partial coverage)

- CMS publish endpoint: 0% coverage (58 lines)
- Navigation API: 45-50% coverage (needs improvement)
- Links API: 0% coverage (78 lines)

### 6. Image Upload & Processing (0% coverage)

- `/app/api/upload/image/route.ts` - 44 lines
- `/app/api/upload/cloudflare/route.ts` - 35 lines
- Image cropping modal and editor components

---

## Implementation Roadmap

### Phase 1: Critical Security & Revenue (Weeks 1-2)

**Priority**: Immediate - Blocks production confidence

1. **Authentication System Tests**
   - OAuth flow integration tests with mock providers
   - Middleware routing test suite
   - CSRF protection unit tests
   - Session lifecycle tests

2. **Stripe Integration Tests**
   - Webhook signature verification tests
   - Event deduplication tests
   - All webhook event type handlers
   - Checkout session creation flow

### Phase 2: User Experience & Onboarding (Weeks 3-4)

**Priority**: High - Affects revenue

1. **Registration Flow Tests**
   - End-to-end registration with mocked Stripe
   - Subdomain conflict handling
   - Session validation
   - Error state handling

2. **Admin Impersonation Tests**
   - Token injection and validation
   - Expiration handling
   - Exit flow verification

### Phase 3: Feature Completeness (Weeks 5-6)

**Priority**: Medium - Reduces support burden

1. **Dashboard & Admin Tests**
   - Stats calculation accuracy
   - Admin dealer management
   - Settings updates

2. **Content Management Tests**
   - Publishing workflow
   - Navigation CRUD operations
   - Image upload validation

---

## TDD Methodology Analysis

### How TDD Would Have Prevented These Issues

#### 1. **Design-First Thinking**

Without TDD, the team built features implementation-first:

- **Example**: `lib/auth.ts` Apple OAuth JWT generation
  - No test for ES256 key format validation before implementation
  - Module-level `await` for key generation makes testing harder
  - Error handling added as afterthought (comments show warnings, not prevention)

**With TDD**: Test would have been written first:

```typescript
it('should reject invalid Apple private key format', async () => {
  process.env.APPLE_PRIVATE_KEY = 'invalid-key';
  await expect(generateAppleClientSecret()).rejects.toThrow('PKCS8 PEM format');
});
```

This would have forced:

- Validation logic before implementation
- Testable architecture (function instead of module-level code)
- Clear error messages

#### 2. **Regression Prevention**

Current code has TODOs and comments indicating known edge cases:

- **Example**: `app/api/webhooks/stripe/route.ts:128-133`
  ```typescript
  // TODO: Send welcome email to dealer
  // Email should include:
  // - Welcome message
  // - Subscription tier details
  ```

**With TDD**: This would be a failing test from day one:

```typescript
it('should send welcome email after successful checkout', async () => {
  const result = await handleCheckoutCompleted(mockSession);
  expect(mockEmailService.send).toHaveBeenCalledWith({
    to: 'dealer@example.com',
    template: 'welcome',
    data: expect.objectContaining({ tier: 'starter' }),
  });
});
```

This ensures the feature is never "forgotten" - the test fails until implemented.

#### 3. **Confident Refactoring**

Areas with good tests (CMS publisher, email service) have been safely refactored:

- **Example**: `lib/cms/publisher.ts` has 99% coverage
  - Can confidently optimize rendering logic
  - Component type changes are caught immediately
  - Unknown component warning is tested (line 131)

Areas without tests are frozen:

- **Example**: `middleware.ts` has complex subdomain extraction
  - Fear of breaking dealer routing prevents optimization
  - Custom domain lookup timeout is hardcoded (can't safely change)
  - CSRF logic is sacred - nobody dares touch it

#### 4. **Documentation Through Tests**

Well-tested code documents itself:

- **Example**: `lib/registration-helpers.test.ts` shows:
  - All valid registration states
  - Error conditions and messages
  - Database transaction rollback behavior
  - Subdomain validation rules

Untested code requires reading implementation:

- **Example**: Understanding `middleware.ts` requires:
  - Reading 255 lines of nested conditions
  - Tracing `extractSubdomain()` logic
  - Understanding custom domain lookup flow
  - Inferring CSRF validation rules

#### 5. **Integration Points**

Without TDD, integration assumptions go untested:

- **Example**: `app/api/register/complete/route.ts` assumes:
  - Stripe session customer ID matches dealer record
  - Session is always retrievable
  - Webhook has already created dealer record
  - No concurrent registration attempts

**With TDD**: Integration contract tests would verify:

```typescript
it('should reject registration if webhook has not created dealer', async () => {
  // Simulate: Checkout completed, but webhook delayed
  const response = await POST(mockRequest);
  expect(response.status).toBe(404);
  expect(await response.json()).toEqual({
    error: 'Dealer account not found',
  });
});
```

---

### How Lack of TDD Has Weakened the Application

#### 1. **Hidden Assumptions**

Code is full of implicit assumptions that only fail in production:

- **Middleware** assumes custom domain lookup completes within 2 seconds
  - What if the internal API is slow?
  - Current code: Times out, falls through to subdomain logic
  - Risk: Custom domain dealers get 404s during DB slowness

- **Stripe webhooks** assume deduplication prevents races
  - What if two webhooks arrive simultaneously?
  - Current code: Uses `findUnique` then `create` (race condition)
  - Risk: Could create duplicate dealer records

#### 2. **Error Paths Are Untested**

Happy path works, but error handling is fragile:

- **Example**: `lib/auth.ts:278-286` updates user name
  - Wrapped in try/catch with "non-critical error, continue sign-in"
  - Error is logged but never tested
  - If this fails repeatedly, logs fill up, but nobody notices
  - Could indicate a serious DB issue, but sign-in succeeds

- **Example**: `middleware.ts:198-216` handles invalid JWT
  - Clears 4 different cookie variations
  - Never tested if all are actually cleared
  - Could leave user in broken state with partial cookies

#### 3. **Combinatorial Explosion**

Complex state machines are untested:

- **Dealer Status States**: `registration_pending`, `active`, `payment_failed`, `suspended`, `cancelled`
- **Subscription States**: Stripe has 8+ states mapping to dealer states
- **Untested Transitions**:
  - `payment_failed` → `suspended` (after 3 retries)
  - `suspended` → `active` (after payment update)
  - `cancelled` → `active` (reactivation)

Without tests, these transitions could corrupt state:

- Grace period counter never resets?
- Reactivation doesn't restore feature flags?
- Cancellation doesn't clear subscription ID?

#### 4. **Security Through Obscurity**

Critical security logic is untested and thus unverified:

- **CSRF Protection**: Only 14.58% coverage
  - Origin matching logic is complex (exact + subdomain patterns)
  - What if regex has a bug and allows attacker domain?
  - What if environment variable parsing fails?
  - Current approach: Hope it works, discover in production

- **Admin Authorization**: 0% coverage
  - Impersonation token injection is untested
  - What if token validation has a bypass?
  - What if expiration check has timezone bug?
  - Current approach: Manual testing, fingers crossed

#### 5. **Technical Debt Compounds**

Areas without tests accumulate debt faster:

- **Example**: `app/api/webhooks/stripe/route.ts` has 3 TODOs
  - Send welcome email (line 128)
  - Send cancellation email (line 282)
  - Send payment failure email (line 362)

These are never implemented because:

1. No failing test to force completion
2. Fear of breaking existing logic
3. Unclear where to inject email service
4. Untested code is "working" - why risk changes?

**With TDD**: Each TODO would be a failing test, blocking PR merge until implemented.

---

## Test Quality Standards Going Forward

To prevent this situation from recurring, implement these practices:

### 1. Definition of Done Includes Tests

No PR is complete without:

- ✅ Unit tests for new functions/methods
- ✅ Integration tests for API endpoints
- ✅ Error path tests (not just happy path)
- ✅ Edge case tests (empty inputs, concurrent requests, etc.)

### 2. Coverage Gates

Enforce minimum coverage thresholds:

- **New Code**: 90% coverage required
- **Critical Paths**: 100% coverage required (auth, payments, security)
- **Overall**: Gradual increase to 80% over 6 months

### 3. TDD for Critical Features

Require TDD workflow for:

- Authentication & authorization
- Payment processing
- Data mutations
- Security features
- API contracts

### 4. Test First, Then Implement

**Red-Green-Refactor** discipline:

1. **Red**: Write failing test that describes desired behavior
2. **Green**: Write minimal code to make test pass
3. **Refactor**: Improve code while keeping tests green

### 5. Integration Test Coverage

Add end-to-end tests for critical user journeys:

- New dealer registration (OAuth → Checkout → Onboarding → Dashboard)
- Subscription management (Upgrade → Downgrade → Cancel → Reactivate)
- Admin impersonation (Start → Use dealer features → End)
- Custom domain setup (Add → Verify → Activate)

---

## Detailed Implementation Notes

### Area 1: Authentication & Authorization

**Estimated Effort**: 40 hours
**Priority**: P0 - Start immediately

#### Test Files to Create

1. **`lib/__tests__/auth.test.ts`** (20 hours)

   ```typescript
   describe('Apple OAuth Client Secret Generation', () => {
     it('should generate valid JWT with ES256 signature');
     it('should reject invalid private key format');
     it('should set 180 day expiration');
     it('should handle missing environment variables');
     it('should validate NEXTAUTH_URL is HTTPS');
   });

   describe('OAuth SignIn Callback', () => {
     it('should create new user on first sign-in');
     it('should link account for existing user');
     it('should update user name if changed');
     it('should handle email normalization');
     it('should reject missing email or account data');
     it('should handle database errors gracefully');
     it('should prevent duplicate account linking');
   });

   describe('JWT Callback', () => {
     it('should replace OAuth provider ID with Prisma user ID');
     it('should fetch user role from database');
     it('should handle missing user gracefully');
     it('should preserve impersonation metadata');
     it('should handle database errors without breaking session');
   });

   describe('Session Callback', () => {
     it('should include user ID and role');
     it('should include active impersonation info');
     it('should exclude expired impersonation info');
     it('should handle missing token data');
   });
   ```

   **Key Test Data**:
   - Mock Prisma client with jest.mock
   - Sample Apple private key (test key, not production)
   - OAuth provider response fixtures
   - Session token structures

2. **`__tests__/middleware.test.ts`** (Enhancement - 12 hours)

   **Current test exists but needs:**

   ```typescript
   describe('Custom Domain Routing', () => {
     it('should lookup custom domain via internal API');
     it('should handle lookup timeout gracefully');
     it('should rewrite to dealer subdomain route');
     it('should skip API routes');
   });

   describe('Subdomain Extraction', () => {
     it('should extract dealer subdomain correctly');
     it('should handle localhost development');
     it('should skip main domain subdomains');
     it('should ignore IP addresses');
     it('should handle ports correctly');
   });

   describe('CSRF Protection', () => {
     it('should validate origin header');
     it('should fall back to referer header');
     it('should block missing headers');
     it('should exempt webhooks and OAuth callbacks');
   });

   describe('Authentication Flow', () => {
     it('should allow public routes');
     it('should redirect unauthenticated to sign-in');
     it('should handle invalid JWT gracefully');
     it('should clear cookies on JWT error');
   });

   describe('Admin Authorization', () => {
     it('should require admin role for admin routes');
     it('should allow impersonation exit during impersonation');
     it('should return 403 for API, redirect for pages');
   });
   ```

3. **`lib/__tests__/csrf.test.ts`** (Enhancement - 8 hours)

   **Current test may exist but needs:**

   ```typescript
   describe('CSRF Validation', () => {
     it('should allow exact origin match');
     it('should allow subdomain pattern match');
     it('should block invalid origin');
     it('should handle missing origin with referer fallback');
     it('should block when both headers missing');
     it('should skip GET/HEAD/OPTIONS requests');
   });

   describe('Subdomain Pattern Matching', () => {
     it('should match exact base domain');
     it('should match wildcard subdomains');
     it('should respect protocol (http vs https)');
     it('should handle edge cases (www, nested subdomains)');
   });

   describe('withCsrfProtection HOC', () => {
     it('should pass through when validation succeeds');
     it('should return error when validation fails');
     it('should preserve request context');
   });
   ```

#### Testing Strategy

**Unit Tests**: Mock external dependencies

- Prisma: `jest.mock('@/lib/prisma')`
- NextAuth providers: Mock OAuth responses
- Crypto operations: Use test keys

**Integration Tests**: Test with real JWT operations

- Create actual JWT tokens
- Verify signature validation
- Test token expiration

**Mocking Approach**:

```typescript
// Mock Prisma
jest.mock('@/lib/prisma', () => ({
  prisma: {
    user: {
      findUnique: jest.fn(),
      create: jest.fn(),
      update: jest.fn(),
    },
    account: {
      create: jest.fn(),
    },
  },
}));

// Mock NextAuth providers
jest.mock('next-auth/providers/google', () => ({
  default: jest.fn(() => ({ id: 'google' })),
}));
```

#### Success Criteria

- ✅ All OAuth flows covered (Google, Apple)
- ✅ All middleware routing scenarios tested
- ✅ CSRF protection edge cases verified
- ✅ Error handling tested (DB failures, invalid tokens)
- ✅ Coverage > 90% for all auth modules

---

### Area 2: Stripe Integration & Revenue Flow

**Estimated Effort**: 50 hours
**Priority**: P0 - Start immediately

#### Test Files to Create

1. **`app/api/webhooks/stripe/__tests__/route.test.ts`** (25 hours)

   ```typescript
   describe('Stripe Webhook Handler', () => {
     describe('Signature Verification', () => {
       it('should verify valid signature');
       it('should reject invalid signature');
       it('should reject missing signature header');
       it('should handle malformed signatures');
     });

     describe('Event Deduplication', () => {
       it('should process new event');
       it('should skip already processed event');
       it('should handle concurrent duplicate events');
     });

     describe('Rate Limiting', () => {
       it('should allow within rate limit');
       it('should block when rate limit exceeded');
       it('should return rate limit headers');
     });

     describe('checkout.session.completed', () => {
       it('should create dealer for paid session');
       it('should skip unpaid session');
       it('should handle idempotent dealer creation');
       it('should retrieve line items for price ID');
       it('should log dealer creation');
     });

     describe('customer.subscription.updated', () => {
       it('should update subscription tier');
       it('should update dealer status based on subscription status');
       it('should handle unmapped subscription status gracefully');
       it('should update feature flags based on tier');
       it('should handle missing dealer');
       it('should log before/after state for audit');
     });

     describe('customer.subscription.deleted', () => {
       it('should cancel dealer account');
       it('should disable feature flags');
       it('should clear subscription ID');
       it('should handle missing dealer');
       it('should log cancellation details');
     });

     describe('invoice.payment_failed', () => {
       it('should mark as payment_failed on first failure');
       it('should suspend on final failure');
       it('should retrieve subscription for attempt count');
       it('should handle missing subscription gracefully');
       it('should log payment failure details');
     });

     describe('Unknown Event Types', () => {
       it('should log unhandled events');
       it('should return success for unknown types');
     });

     describe('Error Handling', () => {
       it('should handle database errors');
       it('should handle Stripe API errors');
       it('should return 500 on unexpected errors');
     });
   });
   ```

   **Key Test Data**:
   - Stripe webhook event fixtures (use real Stripe test data)
   - Valid/invalid signatures
   - Mock Stripe client
   - Database state fixtures

2. **`app/api/checkout/create-session/__tests__/route.test.ts`** (15 hours)

   ```typescript
   describe('Checkout Session Creation', () => {
     describe('Authentication', () => {
       it('should redirect unauthenticated to sign-in');
       it('should proceed for authenticated users');
     });

     describe('Duplicate Account Prevention', () => {
       it('should redirect active dealer to dashboard');
       it('should redirect pending dealer to onboarding');
       it('should redirect suspended dealer to dashboard with message');
       it('should allow new users without dealer');
     });

     describe('Plan Validation', () => {
       it('should accept valid plan names');
       it('should reject invalid plan names');
       it('should return 400 for missing plan');
     });

     describe('Stripe Session Creation', () => {
       it('should create session with correct price ID');
       it('should include user ID and email');
       it('should set correct success/cancel URLs');
       it('should require billing address');
       it('should enable phone collection');
       it('should handle Stripe API errors');
     });

     describe('Rate Limiting', () => {
       it('should allow within rate limit');
       it('should block excessive requests');
     });

     describe('Error Handling', () => {
       it('should handle missing price ID configuration');
       it('should handle Stripe session creation failure');
     });
   });
   ```

3. **`lib/__tests__/stripe-webhook-handlers.test.ts`** (Enhancement - 10 hours)

   **Current coverage: 68.35% - needs improvement**

   ```typescript
   describe('createDealerFromCheckout', () => {
     it('should create dealer with normalized email');
     it('should handle existing dealer idempotently');
     it('should extract tier from line items');
     it('should set feature flags based on tier');
     it('should create user if not exists');
     it('should link user to dealer');
     it('should handle missing customer email');
     it('should handle missing line items');
   });

   describe('getTierFromPriceId', () => {
     it('should map all valid price IDs to tiers');
     it('should return starter for unknown price ID');
     it('should handle missing environment variables');
   });
   ```

#### Testing Strategy

**Stripe Mocking**:

```typescript
// Use Stripe's official test helpers
import Stripe from 'stripe';

const mockStripe = {
  webhooks: {
    constructEvent: jest.fn(),
  },
  checkout: {
    sessions: {
      create: jest.fn(),
      retrieve: jest.fn(),
    },
  },
  subscriptions: {
    retrieve: jest.fn(),
  },
};

jest.mock('@/lib/stripe', () => ({
  getStripeClient: () => mockStripe,
}));
```

**Webhook Signature Testing**:

```typescript
// Generate valid test signatures
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY_TEST!, {
  apiVersion: '2023-10-16',
});

const signature = stripe.webhooks.generateTestHeaderString({
  payload: JSON.stringify(event),
  secret: process.env.STRIPE_WEBHOOK_SECRET_TEST!,
});
```

**Event Fixtures**: Use actual Stripe event JSON from webhook logs

#### Success Criteria

- ✅ All webhook event types tested
- ✅ Signature verification edge cases covered
- ✅ Idempotency verified with race condition tests
- ✅ All subscription status transitions tested
- ✅ Error handling for Stripe API failures
- ✅ Coverage > 95% for all Stripe integration code

---

### Area 3: Registration & Onboarding Flow

**Estimated Effort**: 30 hours
**Priority**: P1 - Start after Area 1 & 2

#### Test Files to Create

1. **`app/api/register/complete/__tests__/route.test.ts`** (20 hours)

   ```typescript
   describe('Registration Completion', () => {
     describe('Rate Limiting', () => {
       it('should allow within rate limit');
       it('should block excessive requests');
     });

     describe('Session Validation', () => {
       it('should require session ID');
       it('should verify session exists in Stripe');
       it('should verify session is paid');
       it('should reject unpaid session');
       it('should handle expired session');
       it('should handle invalid session ID');
     });

     describe('Dealer Ownership Validation', () => {
       it('should verify dealer exists');
       it('should verify customer ID matches');
       it('should reject mismatched customer IDs');
       it('should return 403 for ownership violation');
     });

     describe('Data Validation', () => {
       it('should validate required fields');
       it('should validate subdomain format');
       it('should validate state code');
       it('should validate zip code');
       it('should return validation errors');
     });

     describe('Registration Process', () => {
       it('should complete registration successfully');
       it('should set subdomain and domain');
       it('should activate dealer account');
       it('should return dealer info and redirect URL');
     });

     describe('Error Handling', () => {
       it('should handle dealer not found');
       it('should handle already completed registration');
       it('should handle subdomain unavailable');
       it('should handle database errors');
       it('should return appropriate status codes');
     });
   });
   ```

2. **`app/api/admin/impersonate/__tests__/start.test.ts`** (5 hours)

   ```typescript
   describe('Start Impersonation', () => {
     it('should require admin authentication');
     it('should inject impersonation metadata into token');
     it('should set expiration time');
     it('should return new session token');
     it('should reject non-admin users');
     it('should handle missing dealer ID');
     it('should handle invalid dealer ID');
   });
   ```

3. **`app/api/admin/impersonate/__tests__/end.test.ts`** (5 hours)
   ```typescript
   describe('End Impersonation', () => {
     it('should verify impersonation is active');
     it('should remove impersonation metadata');
     it('should restore original admin token');
     it('should handle already-ended impersonation');
     it('should handle expired impersonation');
   });
   ```

#### Testing Strategy

**Session Mocking**:

```typescript
// Mock NextAuth session
jest.mock('next-auth/next', () => ({
  getServerSession: jest.fn(),
}));

// Mock Stripe session retrieval
const mockStripeSession = {
  id: 'cs_test_123',
  payment_status: 'paid',
  customer: 'cus_test_123',
};
```

**Database State**:

```typescript
// Setup dealer in known state
beforeEach(async () => {
  await prisma.dealer.create({
    data: {
      id: 'dealer_test_123',
      stripeCustomerId: 'cus_test_123',
      status: 'registration_pending',
    },
  });
});
```

#### Success Criteria

- ✅ All registration validation paths tested
- ✅ Ownership verification edge cases covered
- ✅ Impersonation lifecycle fully tested
- ✅ Error messages validated
- ✅ Coverage > 90%

---

## AI-Assisted Test Development with Red-Green-Refactor TDD

### Overview: Leveraging AI for Superior Test Quality

AI coding assistants (like Claude Code, GitHub Copilot, or ChatGPT) can dramatically accelerate test writing **when guided correctly**. However, poorly-prompted AI generates brittle, meaningless tests that pass without verifying actual behavior. This section provides concrete strategies for using AI to write production-quality tests using the Red-Green-Refactor methodology.

**Key Principle**: AI should write tests that **describe behavior**, not implementation. Tests should survive refactoring.

---

### The Red-Green-Refactor TDD Cycle with AI

#### **RED Phase**: AI Writes the Failing Test First

**Human's Role**:

1. Define the behavior you want to test
2. Identify edge cases and error conditions
3. Specify exact assertions (not just "test should pass")

**AI's Role**:

1. Generate comprehensive test cases based on behavior description
2. Create proper mocking setup
3. Structure tests with clear arrange-act-assert pattern

**Example Prompt (Good)**:

```
Write a test for the Apple OAuth JWT generation function. The test should:

1. Verify it generates a valid JWT with:
   - ES256 algorithm
   - 180-day expiration
   - Correct audience (https://appleid.apple.com)
   - Correct issuer (APPLE_TEAM_ID)
   - Correct subject (APPLE_ID)

2. Test error cases:
   - Missing APPLE_PRIVATE_KEY environment variable
   - Invalid private key format (not PKCS8 PEM)
   - Missing APPLE_KEY_ID

3. Use real crypto operations (not mocks) to verify signature is valid

The test should fail right now because the function doesn't exist yet.
Focus on WHAT the function should do, not HOW it does it.
```

**Example Prompt (Bad)**:

```
Write tests for auth.ts
```

**Why Bad Prompt Fails**:

- Too vague - AI doesn't know what behaviors matter
- Will generate tests that just verify implementation exists
- No guidance on edge cases
- Results in 100% coverage with 0% actual verification

---

### What to Emphasize When Prompting AI

#### 1. **Behavior Over Implementation**

✅ **DO**: Test observable behavior

```typescript
// Good: Tests behavior
it('should reject login with invalid credentials', async () => {
  const result = await signIn({ email: 'test@example.com', password: 'wrong' });
  expect(result.success).toBe(false);
  expect(result.error).toBe('Invalid credentials');
});
```

❌ **DON'T**: Test implementation details

```typescript
// Bad: Tests internal implementation
it('should call bcrypt.compare with correct arguments', async () => {
  await signIn({ email: 'test@example.com', password: 'wrong' });
  expect(bcrypt.compare).toHaveBeenCalledWith('wrong', hashedPassword);
});
```

**Prompt Guidance**:

```
Focus on testing the PUBLIC API and observable outcomes, not internal function calls.
Test what the function DOES (return values, side effects, errors), not how it does it.
The test should pass even if we completely rewrite the implementation.
```

#### 2. **Edge Cases and Error Paths**

✅ **DO**: Explicitly list edge cases to test

```
Test the Stripe webhook handler with these scenarios:

Happy paths:
- checkout.session.completed with paid status creates dealer
- subscription.updated changes dealer tier and status

Error paths:
- Invalid signature returns 400
- Already-processed event is skipped (idempotency)
- Missing dealer for subscription update logs warning, returns 200
- Database error during dealer creation returns 500

Race conditions:
- Two webhooks with same event ID arrive simultaneously
- Webhook arrives before session is fully created in Stripe

Edge cases:
- Unmapped subscription status defaults to current dealer status
- Missing price ID defaults to starter tier
```

❌ **DON'T**: Ask AI to "test all cases"

```
Write tests that cover all edge cases for the webhook handler.
```

**Why This Fails**: AI will generate generic tests that don't reflect your actual business logic.

#### 3. **Exact Assertion Specifications**

✅ **DO**: Specify what assertions you expect

```
When testing dealer creation from checkout:

1. Assert dealer record has correct fields:
   - stripeCustomerId matches session.customer
   - subscriptionTier matches price ID mapping
   - status is 'registration_pending'
   - hasLeadForm is true for growth+ tiers, false for starter

2. Assert user is created if doesn't exist with:
   - Normalized email (lowercase, trimmed)
   - emailVerified set to current timestamp
   - name from session.customer_details.name

3. Assert audit log entry created with:
   - event: 'dealer_created'
   - metadata includes sessionId and tier
```

❌ **DON'T**: Use vague success criteria

```
Test that the dealer is created successfully.
```

#### 4. **Mock Boundaries and Real Data**

✅ **DO**: Be explicit about what to mock vs. use real

```
For the custom domain DNS verification test:

MOCK:
- Cloudflare API calls (use jest.mock)
- DNS lookup (use fake DNS responses)
- Database queries (use in-memory Prisma)

USE REAL:
- Domain validation regex
- Hostname parsing logic
- Error message generation

Provide realistic test data:
- Valid domains: www.example.com, dealer.mysite.com
- Invalid domains: -invalid.com, not a domain, http://example.com
- Edge cases: very-long-subdomain-name.example.com, example.co.uk
```

❌ **DON'T**: Let AI decide what to mock

```
Write tests for domain verification with appropriate mocks.
```

---

### What to Prevent in AI-Generated Tests

#### 1. **Tautological Tests** (Tests that can't fail)

❌ **Bad**:

```typescript
it('should return the result from the function', async () => {
  const result = await myFunction();
  expect(result).toBe(result); // This always passes!
});
```

**Prevention Prompt**:

```
CRITICAL: Every assertion must be able to FAIL if the implementation is wrong.
If I change the implementation to return garbage, the test should catch it.
Do not write assertions like `expect(result).toBeDefined()` unless undefined is a valid bug case.
```

#### 2. **Testing Mocks Instead of Behavior**

❌ **Bad**:

```typescript
it('should call Stripe API', async () => {
  await createCheckoutSession();
  expect(mockStripe.checkout.sessions.create).toHaveBeenCalled();
  // But did it return the right data? Did it handle errors?
});
```

✅ **Good**:

```typescript
it('should return checkout URL from Stripe session', async () => {
  mockStripe.checkout.sessions.create.mockResolvedValue({
    id: 'cs_123',
    url: 'https://checkout.stripe.com/cs_123',
  });

  const result = await createCheckoutSession('starter');

  expect(result.url).toBe('https://checkout.stripe.com/cs_123');
  expect(result.sessionId).toBe('cs_123');
});
```

**Prevention Prompt**:

```
Avoid testing that mocks were called.
Instead, set up mocks to return specific data, then verify the function returns the RIGHT data.
Focus on: Does the function return correct values? Does it handle errors properly?
```

#### 3. **Overly Coupled Tests**

❌ **Bad**:

```typescript
it('should process checkout', async () => {
  // Assumes exact order of operations
  await processCheckout();
  expect(validateSession).toHaveBeenCalledBefore(createDealer);
  expect(createDealer).toHaveBeenCalledBefore(sendEmail);
});
```

✅ **Good**:

```typescript
it('should create dealer after validating session', async () => {
  await processCheckout();

  // Verify end state, not order
  expect(mockPrisma.dealer.create).toHaveBeenCalledWith({
    data: expect.objectContaining({
      status: 'registration_pending',
      stripeCustomerId: 'cus_123',
    }),
  });
});
```

**Prevention Prompt**:

```
Do not test the ORDER of internal operations unless it's critical to correctness.
Test the OUTCOME: final state, return values, side effects.
The implementation should be free to reorder operations if the outcome is the same.
```

#### 4. **Magic Numbers Without Context**

❌ **Bad**:

```typescript
it('should handle rate limiting', async () => {
  for (let i = 0; i < 101; i++) {
    await makeRequest();
  }
  expect(lastResponse.status).toBe(429);
});
```

✅ **Good**:

```typescript
it('should block requests after rate limit is exceeded', async () => {
  const RATE_LIMIT = 100; // From RATE_LIMITS.CHECKOUT_CREATION

  // Make exactly RATE_LIMIT requests (should all succeed)
  for (let i = 0; i < RATE_LIMIT; i++) {
    const response = await makeRequest();
    expect(response.status).toBe(200);
  }

  // 101st request should be rate limited
  const blockedResponse = await makeRequest();
  expect(blockedResponse.status).toBe(429);
  expect(blockedResponse.body.error).toBe('Too many requests');
});
```

**Prevention Prompt**:

```
Use named constants instead of magic numbers.
Add comments explaining WHY a test value was chosen.
Make tests self-documenting - a developer should understand the test without reading the implementation.
```

---

### Red-Green-Refactor Workflow with AI

#### **Step 1: RED - Write Failing Test with AI**

**Human**: Describes desired behavior in detail

```
I need to add a feature to automatically suspend dealers after 3 failed payment attempts.

Current behavior: Dealers stay active even after payment failures.

Desired behavior:
- First payment failure: Status changes to 'payment_failed', dealer stays active
- Second failure: Status stays 'payment_failed', grace period counter increments
- Third failure: Status changes to 'suspended', dealer loses access

Write tests that verify this behavior using the Stripe webhook handler for invoice.payment_failed events.

The tests should fail right now because this logic doesn't exist.
```

**AI**: Generates comprehensive test suite

```typescript
describe('Payment Failure Grace Period', () => {
  it('should mark dealer as payment_failed on first failure', async () => {
    // Test implementation...
  });

  it('should remain payment_failed on second failure', async () => {
    // Test implementation...
  });

  it('should suspend dealer on third failure', async () => {
    // Test implementation...
  });

  it('should reset counter when payment succeeds', async () => {
    // Test implementation...
  });
});
```

**Human**: Reviews tests for accuracy

- Verify assertions match business requirements
- Check edge cases are covered
- Ensure error messages are tested

**Run Tests**: They should **FAIL** (RED phase complete)

---

#### **Step 2: GREEN - Implement Minimum Code to Pass**

**Human**: Asks AI to implement the feature

```
Now implement the grace period logic in the webhook handler to make these tests pass.

Requirements:
- Add 'paymentFailureCount' field to Dealer model
- Increment on each payment failure
- Reset to 0 on successful payment
- Change status based on count:
  - Count 1-2: 'payment_failed'
  - Count >= 3: 'suspended'

Keep it simple - we'll refactor later. Just make the tests green.
```

**AI**: Implements minimal solution

**Run Tests**: They should **PASS** (GREEN phase complete)

---

#### **Step 3: REFACTOR - Improve Code Quality**

**Human**: Asks AI to refactor while keeping tests green

```
The implementation works, but let's refactor:

1. Extract grace period logic into a separate function for reusability
2. Add constants for magic numbers (GRACE_PERIOD_ATTEMPTS = 3)
3. Improve error logging
4. Add TypeScript types for payment failure states

CRITICAL: Run tests after each change. All tests must stay green.
```

**AI**: Refactors in small steps

**Run Tests After Each Refactor**: Should stay **GREEN**

---

### Effective AI Prompting Patterns

#### Pattern 1: The "Behavior Specification" Prompt

```
Write tests for [FUNCTION/FEATURE] that verify:

GIVEN [initial state/context]
WHEN [action occurs]
THEN [expected outcome]

Include these test cases:
1. [Happy path scenario]
2. [Error case 1]
3. [Error case 2]
4. [Edge case 1]

Mock [external dependencies] but use real [internal logic].
Assert on [specific fields/values], not just that function completed.
```

#### Pattern 2: The "Edge Case Enumeration" Prompt

```
List all edge cases for [FEATURE] including:

Boundary conditions:
- Empty inputs
- Maximum length inputs
- Null/undefined values

Error conditions:
- Network failures
- Database errors
- Invalid data types

Race conditions:
- Concurrent operations
- Stale data
- Timing issues

Then write tests for each case with specific assertions.
```

#### Pattern 3: The "Error Message Validation" Prompt

```
For each error case in [FUNCTION], verify:

1. Correct HTTP status code is returned
2. Error message is user-friendly and actionable
3. Error is logged with appropriate severity level
4. Sensitive data is NOT included in error response
5. Database rollback occurs if transaction fails

Test should assert exact error message text to prevent regression.
```

#### Pattern 4: The "Integration Contract" Prompt

```
Test the integration between [SERVICE A] and [SERVICE B]:

Contract assumptions to verify:
- [SERVICE A] provides data in format X
- [SERVICE B] handles missing fields gracefully
- Errors from [SERVICE B] are propagated correctly
- Timeouts don't cause data corruption

Write tests that FAIL if the contract is violated.
```

---

### AI Test Review Checklist

Before accepting AI-generated tests, verify:

#### ✅ **Behavior Coverage**

- [ ] Tests describe WHAT the code does, not HOW
- [ ] Happy path is tested
- [ ] At least 3 error cases are tested
- [ ] Edge cases are covered (empty, null, boundary values)
- [ ] Race conditions are considered (if applicable)

#### ✅ **Assertion Quality**

- [ ] Every assertion can FAIL if implementation breaks
- [ ] Specific values are asserted (not just `.toBeDefined()`)
- [ ] Error messages are tested (exact text)
- [ ] Side effects are verified (database changes, API calls)
- [ ] Return values are completely validated

#### ✅ **Test Independence**

- [ ] Tests don't depend on execution order
- [ ] Each test sets up its own state
- [ ] Mocks are reset between tests
- [ ] No shared mutable state

#### ✅ **Readability**

- [ ] Test names clearly describe behavior
- [ ] Arrange-Act-Assert structure is clear
- [ ] Magic numbers have named constants
- [ ] Comments explain WHY, not WHAT

#### ✅ **Maintainability**

- [ ] Tests will survive refactoring
- [ ] Mocks are minimal (only external dependencies)
- [ ] Test data is realistic (not foo/bar/baz)
- [ ] Setup code is reusable (helpers/fixtures)

---

### Example: Good vs. Bad AI Test Generation

#### Scenario: Testing Stripe Webhook Signature Verification

❌ **Bad Prompt**:

```
Write tests for the webhook signature verification
```

❌ **Bad AI Output**:

```typescript
it('should verify signature', () => {
  const result = verifySignature(request);
  expect(result).toBe(true);
});

it('should handle invalid signature', () => {
  const result = verifySignature(invalidRequest);
  expect(result).toBe(false);
});
```

**Problems**:

- Doesn't test actual Stripe signature algorithm
- No setup for test data
- Doesn't verify error handling
- Too generic to catch real bugs

---

✅ **Good Prompt**:

```
Write tests for Stripe webhook signature verification using stripe.webhooks.constructEvent.

Test cases needed:

1. Valid signature:
   - Use Stripe's test helper to generate real signature
   - Verify event object is returned with correct type and data

2. Invalid signature:
   - Tampered payload
   - Wrong secret
   - Expired timestamp
   - Should throw error with message "Invalid signature"

3. Missing signature header:
   - Should throw error with message "Missing signature"

4. Malformed signature format:
   - Should throw error gracefully

Use actual Stripe library (not mocks) for signature generation.
Mock only the webhook secret from environment.
```

✅ **Good AI Output**:

```typescript
import Stripe from 'stripe';

describe('Stripe Webhook Signature Verification', () => {
  const webhookSecret = 'whsec_test_secret';
  const stripe = new Stripe(process.env.STRIPE_SECRET_KEY_TEST!);

  beforeEach(() => {
    process.env.STRIPE_WEBHOOK_SECRET = webhookSecret;
  });

  it('should verify valid signature and return event', () => {
    const payload = JSON.stringify({ type: 'checkout.session.completed' });
    const signature = stripe.webhooks.generateTestHeaderString({
      payload,
      secret: webhookSecret,
    });

    const event = stripe.webhooks.constructEvent(payload, signature, webhookSecret);

    expect(event.type).toBe('checkout.session.completed');
    expect(event.data.object).toBeDefined();
  });

  it('should reject tampered payload', () => {
    const payload = JSON.stringify({ type: 'checkout.session.completed' });
    const signature = stripe.webhooks.generateTestHeaderString({
      payload,
      secret: webhookSecret,
    });

    const tamperedPayload = payload + ' malicious data';

    expect(() => {
      stripe.webhooks.constructEvent(tamperedPayload, signature, webhookSecret);
    }).toThrow('Invalid signature');
  });

  it('should reject wrong secret', () => {
    const payload = JSON.stringify({ type: 'checkout.session.completed' });
    const signature = stripe.webhooks.generateTestHeaderString({
      payload,
      secret: 'wrong_secret',
    });

    expect(() => {
      stripe.webhooks.constructEvent(payload, signature, webhookSecret);
    }).toThrow();
  });

  it('should reject missing signature header', () => {
    const payload = JSON.stringify({ type: 'checkout.session.completed' });

    expect(() => {
      stripe.webhooks.constructEvent(payload, '', webhookSecret);
    }).toThrow('Missing signature');
  });
});
```

**Why This Is Good**:

- Uses real Stripe library for signature generation
- Tests actual security vulnerability scenarios
- Verifies exact error messages
- Would catch signature bypasses

---

### AI-Powered TDD Best Practices

#### 1. **Iterate in Small Steps**

Don't ask AI to write all tests at once. Instead:

```
Step 1: "Write tests for the happy path only"
[Review, adjust, run tests - RED]

Step 2: "Add tests for missing required fields errors"
[Review, run tests - still RED]

Step 3: "Now implement the validation logic to make tests pass"
[Run tests - GREEN]

Step 4: "Refactor validation into separate function, tests must stay green"
[Run tests - stays GREEN]
```

#### 2. **Use AI to Generate Test Data Factories**

```
Create a test data factory for Dealer objects with:
- Realistic default values
- Builder pattern for customization
- Faker.js for random but valid data
- Type-safe overrides

Example usage:
  const dealer = buildDealer({ status: 'active', tier: 'growth' });
```

This produces reusable, maintainable test fixtures.

#### 3. **Have AI Audit Existing Tests**

```
Review this test file and identify:
1. Tests that don't actually verify behavior
2. Brittle tests that will break during refactoring
3. Missing edge cases
4. Opportunities to reduce duplication

For each issue, explain WHY it's a problem and suggest a fix.
```

#### 4. **Generate Test Coverage Gap Analysis**

```
Given this function [paste code], identify test cases that are missing:
- Uncovered branches
- Error paths without tests
- Integration points not tested
- Race conditions not considered

For each gap, write a specific test case.
```

---

### Integration with Development Workflow

#### Daily TDD Workflow with AI

**Morning**:

```
1. Review yesterday's code with AI: "Audit these changes for missing tests"
2. Plan today's feature: "List test cases for [FEATURE]"
3. AI generates test suite
4. Review and adjust tests
5. Run tests - verify they FAIL (RED)
```

**During Development**:

```
6. Ask AI to implement feature: "Make these tests pass"
7. Run tests frequently - watch them turn GREEN
8. Refactor with AI: "Improve this code while keeping tests green"
9. Run tests after each refactor - ensure they stay GREEN
```

**Before Commit**:

```
10. AI review: "Are these tests brittle? Will they survive refactoring?"
11. Run full test suite
12. Check coverage report
13. Commit with confidence
```

#### Code Review with AI

**Reviewer prompts**:

```
Review this PR's tests for:
1. Do tests verify actual behavior or just implementation?
2. Are all error cases covered?
3. Will these tests catch regressions?
4. Are assertions specific enough?
5. Is test data realistic?

For each issue, suggest a better test case.
```

---

### Common Pitfalls and How to Avoid Them

#### Pitfall 1: "Coverage Theater"

**Problem**: AI generates tests that pass and give 100% coverage, but don't verify anything meaningful.

**Solution**:

```
Prompt: "After generating tests, show me how to intentionally break the implementation.
If the tests still pass when the code is broken, the tests are bad."
```

#### Pitfall 2: "Mock Hell"

**Problem**: AI mocks everything, testing only that mocks were called.

**Solution**:

```
Prompt: "Only mock EXTERNAL dependencies (database, APIs, filesystem).
Use REAL implementations for business logic, validation, and calculations.
If I can test it in-memory without network/disk, test it for real."
```

#### Pitfall 3: "Test Duplication"

**Problem**: AI generates 50 nearly-identical tests.

**Solution**:

```
Prompt: "Use parameterized tests (test.each) for similar cases with different inputs.
Example:
test.each([
  ['starter', false],
  ['growth', true],
  ['professional', true],
])('tier %s should have lead form access: %s', (tier, hasAccess) => {
  expect(hasLeadFormAccess(tier)).toBe(hasAccess);
});
```

#### Pitfall 4: "Flaky Tests"

**Problem**: AI-generated tests fail randomly due to timing or randomness.

**Solution**:

```
Prompt: "Avoid Date.now(), Math.random(), or setTimeout in tests.
Use fixed timestamps, seeded random generators, and fake timers.
Every test should be deterministic - same input = same output, always."
```

---

### Measuring AI Test Quality

Track these metrics to ensure AI is generating valuable tests:

| Metric                    | Target | How to Measure                                                 |
| ------------------------- | ------ | -------------------------------------------------------------- |
| **Mutation Score**        | >80%   | Run mutation testing (Stryker) - how many bugs do tests catch? |
| **Regression Detection**  | 100%   | When bugs are found, do existing tests catch them?             |
| **Refactor Safety**       | 100%   | Tests stay green during refactoring?                           |
| **Review Rejection Rate** | <10%   | How often are AI tests rejected in code review?                |
| **False Positive Rate**   | <5%    | How often do tests fail for wrong reasons?                     |

**If metrics are poor**: Your prompts need improvement. Add more constraints and examples.

---

## Recommended Next Steps

### Immediate Actions (This Week)

1. **Establish Coverage Baseline**
   - Run coverage report daily
   - Track trending metrics
   - Set up coverage CI checks

2. **Freeze Feature Development**
   - Dedicate 2 weeks to testing critical paths
   - No new features until Areas 1 & 2 are tested
   - All hands on deck for test writing

3. **Implement Coverage Gates**
   - Require 90% coverage for new PRs
   - Block merges below threshold
   - Review existing code for quick wins

### Short-Term (Next 2 Weeks)

1. **Complete Area 1: Auth & Security**
   - Assign 2 developers
   - Daily progress reviews
   - Pair programming for complex tests

2. **Complete Area 2: Stripe Integration**
   - Assign 2 developers
   - Use Stripe's test event fixtures
   - Validate with Stripe's webhook testing tool

3. **Document Testing Standards**
   - Write testing guidelines
   - Create test templates
   - Share best practices

### Medium-Term (Next 1-2 Months)

1. **Complete Area 3: Registration Flow**
   - Assign 1 developer
   - End-to-end testing with real Stripe test mode
   - User acceptance testing

2. **Tackle Remaining Gaps**
   - Dashboard features
   - Admin tooling
   - Image upload

3. **Establish TDD Culture**
   - Require TDD for all new features
   - Code review focus on tests
   - Celebrate test coverage improvements

### Long-Term (Next 3-6 Months)

1. **Reach 80% Overall Coverage**
   - Systematic backfilling
   - Prioritize by business impact
   - Retire legacy untested code

2. **Add End-to-End Tests**
   - Playwright or Cypress
   - Critical user journeys
   - Visual regression testing

3. **Continuous Improvement**
   - Quarterly testing retrospectives
   - Update standards based on learnings
   - Invest in testing infrastructure

---

## Conclusion

The AMSOIL DLP application has solid testing in isolated modules (CMS, email, validation) but **critical business flows are completely untested**. This creates significant risk:

- **Security**: Authentication and authorization vulnerabilities could enable account takeover
- **Revenue**: Stripe integration bugs could prevent payment processing or corrupt subscriptions
- **Customer Experience**: Registration failures block new customer acquisition

**The lack of TDD discipline has compounded this problem**:

- Features were built without tests, making them fragile
- Error handling was added as an afterthought
- Integration assumptions were never validated
- Refactoring became risky, freezing technical debt

**Recommended approach**:

1. **Immediate**: Implement tests for authentication and Stripe (Areas 1 & 2)
2. **Short-term**: Complete registration flow tests (Area 3)
3. **Long-term**: Adopt TDD for all new features, gradually backfill remaining gaps

This will transform the application from "hoping it works" to "knowing it works" through comprehensive, automated verification.

---

**Report prepared by**: Claude Code
**Date**: 2025-12-12
**Next review**: 2 weeks after implementation begins
