# Jomblo E-commerce Platform - Testing Guide

## Overview

This document provides comprehensive guidance on testing the Jomblo e-commerce platform, including setup, execution, and maintenance of the test suite.

## Test Architecture

### Test Pyramid Structure

```
┌─────────────────────────────────────┐
│           E2E Tests                 │  ← 5% - Full user journeys
│    (Playwright + Custom Scenarios)  │
├─────────────────────────────────────┤
│        Integration Tests            │  ← 25% - Component interactions
│   (API endpoints, DB operations)    │
├─────────────────────────────────────┤
│         Unit Tests                  │  ← 70% - Individual functions
│   (Components, utilities, schemas)  │
└─────────────────────────────────────┘
```

### Test Categories

1. **Unit Tests** (`*.test.ts`, `*.test.tsx`)
   - Individual function testing
   - Component rendering tests
   - Schema validation tests
   - Utility function tests

2. **Integration Tests** (`*.integration.test.ts`)
   - Database operations
   - API endpoint testing
   - Cross-module interactions

3. **Security Tests** (`*.security.test.ts`)
   - Authentication/authorization
   - Input validation
   - Rate limiting
   - CSRF protection

4. **Performance Tests** (`*.performance.test.ts`)
   - Load testing
   - Memory usage
   - Response time validation

5. **E2E Tests** (`e2e/*.spec.ts`)
   - Full user journeys
   - Cross-browser testing
   - Real-world scenarios

## Test Setup

### Prerequisites

```bash
# Install dependencies
pnpm install

# Set up test environment
cp .env.example .env.test
# Configure test database and Redis
```

### Test Database Configuration

```bash
# Create test database
createdb jomblo_test

# Run migrations on test database
pnpm run db:migrate -- --database-url $TEST_DATABASE_URL

# Seed test data
pnpm run db:seed -- --database-url $TEST_DATABASE_URL
```

### Environment Variables

Required for testing:

```bash
# Database
TEST_DATABASE_URL="postgresql://user:pass@localhost:5432/jomblo_test"
TEST_DATABASE_HOST="localhost"
TEST_DATABASE_USER="user"
TEST_DATABASE_PASSWORD="pass"
TEST_DATABASE_NAME="jomblo_test"

# Redis
REDIS_URL="redis://localhost:6379"
TEST_REDIS_URL="redis://localhost:6380"

# Stripe
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_WEBHOOK_SECRET="whsec_..."

# Authentication
NEXTAUTH_SECRET="test-secret"
NEXTAUTH_URL="http://localhost:3000"
```

## Running Tests

### Quick Start

```bash
# Run all tests
ppnpm run test:all

# Run comprehensive test suite
ppnpm run test:comprehensive

# Run specific test categories
ppnpm run test:unit
ppnpm run test:integration
ppnpm run test:security
ppnpm run test:performance
```

### Individual Test Execution

```bash
# Run specific test file
pnpm vitest run path/to/test.ts

# Run tests matching pattern
pnpm vitest run --grep "authentication"

# Run tests in watch mode
pnpm vitest

# Run with coverage
pnpm vitest run --coverage

# Run with UI
pnpm vitest --ui
```

### E2E Testing

```bash
# Run all E2E tests
pnpmpnpm run test:e2e

# Run E2E tests with UI
ppnpm run test:e2e:ui

# Run specific E2E test
pnpm playwright test path/to/test.spec.ts

# Run E2E tests in specific browser
pnpm playwright test --project=chromium
```

## Test Organization

### Directory Structure

```
tests/
├── setup/                    # Test utilities and setup
│   ├── database.ts          # Database test utilities
│   ├── fixtures/            # Test data factories
│   └── utils.ts             # Common test utilities
├── factories/               # Data factories
│   ├── user.ts              # User factory
│   ├── product.ts           # Product factory
│   ├── customer.ts          # Customer factory
│   └── order.ts             # Order factory
├── components/              # Component tests
│   ├── auth/               # Authentication components
│   ├── cart/               # Cart components
│   └── shared/             # Shared components
├── lib/                    # Library tests
│   ├── db.test.ts          # Database library
│   ├── redis-client.test.ts # Redis client
│   ├── stripe.test.ts      # Stripe integration
│   └── auth-logic.test.ts  # Authentication logic
├── actions/                # Action tests
│   ├── login.test.ts       # Login action
│   ├── checkout.test.ts    # Checkout action
│   └── cart.test.ts        # Cart actions
├── schemas/                # Schema tests
│   └── api.test.ts         # API schema validation
├── e2e/                    # End-to-end tests
│   ├── auth-flow.spec.ts   # Authentication flow
│   ├── checkout-flow.spec.ts # Checkout flow
│   └── user-journeys/      # User journey tests
├── security/               # Security tests
│   ├── csrf.test.ts        # CSRF protection
│   ├── xss.test.ts         # XSS prevention
│   └── rate-limiting.test.ts # Rate limiting
├── performance/            # Performance tests
│   ├── load.test.ts        # Load testing
│   └── memory.test.ts      # Memory usage
└── run-tests.ts            # Test runner script
```

### Test Naming Conventions

- **Unit tests**: `filename.test.ts` or `filename.test.tsx`
- **Integration tests**: `filename.integration.test.ts`
- **Security tests**: `filename.security.test.ts`
- **Performance tests**: `filename.performance.test.ts`
- **E2E tests**: `filename.spec.ts`

## Test Patterns

### Unit Test Pattern

```typescript
import { describe, it, expect } from "vitest";
import { myFunction } from "@/lib/my-function";

describe("MyFunction", () => {
  it("should return expected result", () => {
    const result = myFunction("input");
    expect(result).toBe("expected");
  });

  it("should handle edge cases", () => {
    expect(() => myFunction("")).toThrow();
  });
});
```

### Component Test Pattern

```typescript
import { render, screen } from "@testing-library/react";
import { MyComponent } from "@/components/my-component";

describe("MyComponent", () => {
  it("should render correctly", () => {
    render(<MyComponent />);
    expect(screen.getByText("Hello")).toBeInTheDocument();
  });
});
```

### Database Test Pattern

```typescript
import { testDb } from "@/tests/setup/database";

describe("Database Operations", () => {
  beforeAll(async () => {
    await testDb.setupTestDb();
  });

  afterAll(async () => {
    await testDb.cleanupTestDb();
  });

  it("should create record", async () => {
    const result = await createRecord(testData);
    expect(result.id).toBeDefined();
  });
});
```

### E2E Test Pattern

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

test("user can complete checkout flow", async ({ page }) => {
  await page.goto("/products");
  await page.click('[data-testid="add-to-cart"]');
  await page.click('[data-testid="checkout"]');
  
  await expect(page).toHaveURL("/checkout");
});
```

## Test Data Management

### Factories

Use factories to generate consistent test data:

```typescript
import { createUser } from "@/tests/factories/user";

const user = createUser({
  email: "test@example.com",
  name: "Test User"
});
```

### Fixtures

Use fixtures for complex test data:

```typescript
// tests/fixtures/products.ts
export const mockProducts = [
  {
    id: "prod_1",
    name: "Test Product",
    price: 19.99,
    // ...
  }
];
```

### Database Seeding

```typescript
// Seed test data
await testDb.seedTestData();

// Clean up between tests
beforeEach(async () => {
  await testDb.truncateTables();
});
```

## Mocking Strategies

### API Mocking

```typescript
import { vi } from "vitest";

vi.mock("@/lib/api", () => ({
  fetchData: vi.fn().mockResolvedValue(mockData)
}));
```

### Database Mocking

```typescript
vi.mock("@/lib/db", () => ({
  db: {
    query: vi.fn().mockResolvedValue(mockResult)
  }
}));
```

### External Service Mocking

```typescript
vi.mock("stripe", () => ({
  checkout: {
    sessions: {
      create: vi.fn().mockResolvedValue(mockSession)
    }
  }
}));
```

## Test Coverage

### Coverage Goals

- **Overall Coverage**: 80%
- **Core Libraries**: 90%
- **API Endpoints**: 85%
- **Components**: 75%
- **Critical Paths**: 95%

### Coverage Reports

```bash
# Generate coverage report
pnpm run test:coverage

# View coverage in browser
open coverage/lcov-report/index.html
```

### Coverage Configuration

Coverage thresholds are defined in `vitest.config.ts`:

```typescript
coverage: {
  thresholds: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80,
    }
  }
}
```

## Continuous Integration

### GitHub Actions

Tests are automatically run on:

- Pull requests
- Push to main branch
- Scheduled runs (daily)

### CI Configuration

```yaml
# .github/workflows/test.yml
- name: Run tests
  run: pnpm run test:all

- name: Run E2E tests
  run: pnpm run test:e2e

- name: Generate coverage report
  run: pnpm run test:coverage
```

### Quality Gates

Tests must pass before merge:

- All unit tests pass
- Coverage meets thresholds
- E2E tests pass
- Security tests pass
- Performance tests meet SLA

## Debugging Tests

### Common Issues

1. **Database Connection**
   ```bash
   # Check database is running
   psql -h localhost -U user jomblo_test
   
   # Reset test database
   pnpm run db:migrate -- --database-url $TEST_DATABASE_URL
   ```

2. **Redis Connection**
   ```bash
   # Check Redis is running
   redis-cli ping
   
   # Clear Redis cache
   redis-cli flushall
   ```

3. **Test Isolation**
   ```typescript
   // Ensure proper cleanup
   beforeEach(async () => {
     await testDb.truncateTables();
   });
   ```

### Debug Commands

```bash
# Run single test with debug
npx vitest run --reporter=verbose path/to/test.ts

# Run with debugger
npx vitest run --inspect-brk

# Run E2E test with trace
npx playwright test --trace on path/to/test.spec.ts
```

## Performance Testing

### Load Testing

```typescript
// tests/performance/load.test.ts
describe("Load Testing", () => {
  it("should handle concurrent requests", async () => {
    const promises = Array.from({ length: 100 }, () =>
      fetch("/api/products")
    );
    
    const results = await Promise.all(promises);
    expect(results.every(r => r.ok)).toBe(true);
  });
});
```

### Memory Testing

```typescript
describe("Memory Usage", () => {
  it("should not leak memory", async () => {
    const initialMemory = process.memoryUsage();
    
    // Perform operations
    for (let i = 0; i < 1000; i++) {
      await performOperation();
    }
    
    // Force garbage collection
    if (global.gc) global.gc();
    
    const finalMemory = process.memoryUsage();
    expect(finalMemory.heapUsed).toBeLessThan(initialMemory.heapUsed * 1.1);
  });
});
```

## Security Testing

### Authentication Tests

```typescript
describe("Authentication Security", () => {
  it("should reject invalid tokens", async () => {
    const response = await request(app)
      .get("/api/protected")
      .set("Authorization", "Bearer invalid-token");
    
    expect(response.status).toBe(401);
  });
});
```

### Input Validation Tests

```typescript
describe("Input Validation", () => {
  it("should reject XSS attempts", async () => {
    const response = await request(app)
      .post("/api/users")
      .send({
        name: "<script>alert('xss')</script>",
        email: "test@example.com"
      });
    
    expect(response.status).toBe(400);
  });
});
```

## Best Practices

### Test Organization

1. **One test file per module/component**
2. **Clear, descriptive test names**
3. **Group related tests with describe blocks**
4. **Use proper setup/teardown**

### Test Quality

1. **Test one thing at a time**
2. **Use meaningful assertions**
3. **Avoid testing implementation details**
4. **Test edge cases and error conditions**

### Performance

1. **Keep tests fast (< 1s each)**
2. **Use mocks for external dependencies**
3. **Run tests in parallel when possible**
4. **Clean up resources properly**

### Maintenance

1. **Update tests when code changes**
2. **Remove obsolete tests**
3. **Refactor test code regularly**
4. **Review test coverage reports**

## Troubleshooting

### Common Errors

1. **"Test timeout"**
   - Increase timeout: `it("test", async () => {}, 10000)`
   - Check for infinite loops
   - Verify async/await usage

2. **"Database connection failed"**
   - Check test database URL
   - Verify database is running
   - Check credentials

3. **"Element not found"**
   - Verify selectors are correct
   - Check component rendering
   - Use debugging tools

### Getting Help

- Check test logs for detailed error messages
- Use test debugging tools
- Review similar test patterns
- Consult team members

## Conclusion

This testing guide provides comprehensive coverage of testing practices for the Jomblo e-commerce platform. Follow these guidelines to ensure high-quality, maintainable tests that provide confidence in the application's reliability and performance.

For questions or improvements to this guide, please create an issue or submit a pull request.