# Testing Guide

This document explains how to run and write tests for Brackt.com.

## Overview

We use two testing frameworks:
- **Vitest + React Testing Library** - Unit and component tests
- **Cypress** - End-to-end integration tests

## Running Tests

### Unit Tests

```bash
# Run tests in watch mode (interactive)
npm test

# Run tests once (CI mode)
npm run test:run

# Run tests with UI
npm run test:ui

# Run tests with coverage
npm run test:coverage
```

### E2E Tests

```bash
# Open Cypress interactive mode
npm run test:e2e

# Run Cypress headless (CI mode)
npm run test:e2e:headless

# Run all tests (unit + E2E)
npm run test:all
```

## Writing Tests

### Unit Tests

Unit tests go in `__tests__` directories next to the code they test:

```
app/
  lib/
    utils.ts
    __tests__/
      utils.test.ts
  models/
    league.ts
    __tests__/
      league.test.ts
```

Example unit test:

```typescript
import { describe, it, expect } from 'vitest';
import { myFunction } from '../myFunction';

describe('myFunction', () => {
  it('should do something', () => {
    const result = myFunction('input');
    expect(result).toBe('expected output');
  });
});
```

### Component Tests

Component tests also go in `__tests__` directories:

```
app/
  components/
    DraftGrid.tsx
    __tests__/
      DraftGrid.test.tsx
```

Example component test:

```typescript
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import { MyComponent } from '../MyComponent';

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

### E2E Tests

E2E tests go in the `cypress/e2e` directory:

```
cypress/
  e2e/
    league-creation.cy.ts
    league-settings.cy.ts
    draft-room.cy.ts
```

Example E2E test:

```typescript
describe('Feature Name', () => {
  it('should do something', () => {
    cy.visit('/some-page');
    cy.get('button').click();
    cy.findByText('Expected Text').should('exist');
  });
});
```

## Test Fixtures

Reusable test data is stored in `app/test/fixtures/`:

```typescript
// app/test/fixtures/league.ts
export const mockLeague = {
  id: 'league-1',
  name: 'Test League',
  // ...
};
```

Import and use in tests:

```typescript
import { mockLeague } from '~/test/fixtures/league';
```

## CI/CD Integration

Tests run automatically on:
- Every push to `main` or `develop`
- Every pull request

### GitHub Actions Workflow

1. **Test Job** - Runs unit tests with PostgreSQL service
2. **Typecheck Job** - Runs TypeScript type checking
3. **Build Job** - Builds Docker image (only on main branch)
4. **Deploy Job** - Deploys to server (only after all tests pass)

**Tests must pass before deployment!**

## Coverage

Coverage reports are generated automatically:
- HTML report: `coverage/index.html`
- JSON report: `coverage/coverage-final.json`

View coverage locally:

```bash
npm run test:coverage
open coverage/index.html
```

## Best Practices

### Unit Tests
- Test one thing per test
- Use descriptive test names
- Mock external dependencies
- Aim for 80%+ coverage

### Component Tests
- Test user interactions, not implementation
- Use `screen.getByRole()` when possible
- Test accessibility
- Keep tests focused

### E2E Tests
- Test critical user flows
- Use `data-testid` sparingly
- Prefer semantic queries
- Keep tests independent

## Debugging Tests

### Vitest
```bash
# Run specific test file
npm test -- path/to/test.test.ts

# Run tests matching pattern
npm test -- --grep "pattern"

# Debug in VS Code
# Add breakpoint and use "Debug Test" in test file
```

### Cypress
```bash
# Open Cypress UI for debugging
npm run test:e2e

# Run specific test file
npx cypress run --spec "cypress/e2e/specific-test.cy.ts"
```

## Common Issues

### Tests fail locally but pass in CI
- Check Node version matches CI (v20)
- Ensure database is running locally
- Check environment variables

### Cypress tests timeout
- Increase timeout in `cypress.config.ts`
- Check if app is running on correct port
- Verify selectors are correct

### Coverage not generating
- Ensure `@vitest/coverage-v8` is installed
- Check `vitest.config.ts` coverage settings
- Run with `npm run test:coverage`

## Additional Resources

- [Vitest Documentation](https://vitest.dev/)
- [React Testing Library](https://testing-library.com/react)
- [Cypress Documentation](https://docs.cypress.io/)
- [Testing Best Practices](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)
