Files
adopt-a-street/TESTING.md
William Valentin 742d1cac56 docs: comprehensive CouchDB migration documentation update
- Updated AGENTS.md with CouchDB references throughout
- Updated TESTING.md to reflect CouchDB testing utilities
- Updated TESTING_QUICK_START.md with CouchDB terminology
- Updated TEST_IMPLEMENTATION_SUMMARY.md for CouchDB architecture
- Updated IMPLEMENTATION_SUMMARY.md to include CouchDB migration
- Created comprehensive COUCHDB_MIGRATION_GUIDE.md with:
  - Migration benefits and architecture changes
  - Step-by-step migration process
  - Data model conversions
  - Design document setup
  - Testing updates
  - Deployment configurations
  - Performance optimizations
  - Monitoring and troubleshooting

All MongoDB references replaced with CouchDB equivalents while maintaining
existing document structure and technical accuracy.

🤖 Generated with AI Assistant

Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
2025-11-03 10:30:24 -08:00

582 lines
14 KiB
Markdown

# Testing Documentation
Comprehensive testing infrastructure for the Adopt-a-Street application.
## Table of Contents
1. [Overview](#overview)
2. [Backend Testing](#backend-testing)
3. [Frontend Testing](#frontend-testing)
4. [Running Tests](#running-tests)
5. [Coverage Reports](#coverage-reports)
6. [Test Structure](#test-structure)
7. [Best Practices](#best-practices)
8. [Troubleshooting](#troubleshooting)
## Overview
The Adopt-a-Street application uses a comprehensive testing strategy covering both backend and frontend:
- **Backend**: Jest + Supertest + CouchDB testing utilities
- **Frontend**: React Testing Library + Jest + MSW (Mock Service Worker)
- **Current Coverage**:
- Backend: ~55% statement coverage (109 passing tests)
- Frontend: MSW infrastructure in place with component tests
## Backend Testing
### Test Infrastructure
The backend uses:
- **Jest**: Test runner and assertion library
- **Supertest**: HTTP assertions for API endpoint testing
- **CouchDB Testing Utilities**: In-memory CouchDB for isolated testing
- **Cross-env**: Environment variable management
### Setup Files
#### `backend/jest.config.js`
```javascript
module.exports = {
testEnvironment: 'node',
coverageDirectory: 'coverage',
collectCoverageFrom: [
'routes/**/*.js',
'middleware/**/*.js',
'models/**/*.js',
'!**/node_modules/**',
'!**/coverage/**'
],
testMatch: [
'**/__tests__/**/*.test.js',
'**/?(*.)+(spec|test).js'
],
coverageThreshold: {
global: {
branches: 70,
functions: 70,
lines: 70,
statements: 70
}
},
setupFilesAfterEnv: ['<rootDir>/__tests__/setup.js'],
testTimeout: 30000,
verbose: true
};
```
#### `backend/__tests__/setup.js`
Sets up CouchDB testing utilities for all tests:
- Creates in-memory CouchDB instance before all tests
- Clears documents after each test
- Closes connections after all tests
- Suppresses console logs during tests
### Test Files
#### Route Tests (`__tests__/routes/`)
- `auth.test.js` - Authentication endpoints (register, login, get user)
- `streets.test.js` - Street CRUD operations and adoption
- `tasks.test.js` - Task management operations
- `posts.test.js` - Social feed post operations
- `events.test.js` - Community event management
- `rewards.test.js` - Points and rewards system
- `reports.test.js` - Street condition reporting
#### Model Tests (`__tests__/models/`)
- `User.test.js` - User model validation and relationships
- `Street.test.js` - Street model with GeoJSON location
- `Task.test.js` - Task model validation
- `Post.test.js` - Post model with likes and comments
#### Middleware Tests (`__tests__/middleware/`)
- `auth.test.js` - JWT authentication middleware
#### Test Helpers (`__tests__/utils/`)
`testHelpers.js` provides utilities for:
- Creating test users with JWT tokens
- Creating test streets, tasks, posts, events, rewards, reports
- Database cleanup utilities
### Example Backend Test
```javascript
const request = require('supertest');
const express = require('express');
const authRoutes = require('../../routes/auth');
const { createTestUser } = require('../utils/testHelpers');
const app = express();
app.use(express.json());
app.use('/api/auth', authRoutes);
describe('Auth Routes', () => {
it('should register a new user', async () => {
const response = await request(app)
.post('/api/auth/register')
.send({
name: 'John Doe',
email: 'john@example.com',
password: 'password123',
})
.expect(200);
expect(response.body).toHaveProperty('token');
});
});
```
## Frontend Testing
### Test Infrastructure
The frontend uses:
- **React Testing Library**: Component testing utilities
- **Jest**: Test runner (via react-scripts)
- **MSW (Mock Service Worker)**: API mocking
- **@testing-library/user-event**: User interaction simulation
### Setup Files
#### `frontend/src/setupTests.js`
- Configures Jest-DOM matchers
- Sets up MSW server for API mocking
- Mocks localStorage and window.matchMedia
- Suppresses expected console warnings
#### `frontend/src/mocks/handlers.js`
Defines MSW handlers for all API endpoints:
- Authentication (register, login, get user)
- Streets (list, adopt)
- Tasks (list, create, complete)
- Posts (list, create, like)
- Events (list, create, RSVP)
- Rewards (list, redeem)
- Users (get, update)
### Test Files
#### Component Tests (`src/components/__tests__/`)
- `Login.test.js` - Login form validation and submission
- `Register.test.js` - Registration form validation
- `ErrorBoundary.test.js` - Error handling component
#### Integration Tests (`src/__tests__/`)
- `auth-flow.integration.test.js` - Complete authentication flows
### Example Frontend Test
```javascript
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import Login from '../Login';
import { AuthContext } from '../../context/AuthContext';
describe('Login Component', () => {
it('should render login form', () => {
render(
<BrowserRouter>
<AuthContext.Provider value={mockContext}>
<Login />
</AuthContext.Provider>
</BrowserRouter>
);
expect(screen.getByPlaceholderText(/email/i)).toBeInTheDocument();
expect(screen.getByPlaceholderText(/password/i)).toBeInTheDocument();
});
});
```
## Running Tests
### Backend Tests
```bash
cd backend
# Run all tests
bun test
# Run tests in watch mode
bun run test:watch
# Run tests with coverage
bun run test:coverage
# Run tests with verbose output
bun run test:verbose
```
### Frontend Tests
```bash
cd frontend
# Run all tests (interactive watch mode)
bun test
# Run tests with coverage
bun run test:coverage
# Run tests in watch mode
bun run test:watch
```
### Run All Tests
From the project root:
```bash
# Backend
cd backend && bun test
# Frontend
cd frontend && bun test
```
## Coverage Reports
### Backend Coverage
Current coverage (as of last run):
```
-----------------------|---------|----------|---------|---------|
File | % Stmts | % Branch | % Funcs | % Lines |
-----------------------|---------|----------|---------|---------|
All files | 54.75 | 32.23 | 62.66 | 54.85 |
middleware | 40.24 | 21.05 | 45.45 | 39.5 |
auth.js | 100 | 100 | 100 | 100 |
models | 82.5 | 66.66 | 50 | 82.5 |
routes | 45.84 | 22.61 | 60.97 | 46.07 |
-----------------------|---------|----------|---------|---------|
```
**Test Results**: 109 passing, 67 failing (schema mismatches)
Key Coverage Areas:
- ✅ Auth middleware: 100% coverage
- ✅ Model validators: 82.5% coverage
- ⚠️ Routes: 45.84% coverage (room for improvement)
- ⚠️ Other middleware: 40.24% coverage
### Frontend Coverage
Coverage configuration in `package.json`:
```json
{
"coverageThreshold": {
"global": {
"branches": 50,
"functions": 60,
"lines": 60,
"statements": 60
}
}
}
```
Coverage reports are generated in:
- Backend: `backend/coverage/`
- Frontend: `frontend/coverage/`
To view HTML coverage reports:
```bash
# Backend
cd backend && bun test -- --coverage
open coverage/lcov-report/index.html
# Frontend
cd frontend && bun run test:coverage
open coverage/lcov-report/index.html
```
## Test Structure
### Backend Test Organization
```
backend/
├── __tests__/
│ ├── setup.js # Global test setup
│ ├── middleware/
│ │ └── auth.test.js # Middleware tests
│ ├── models/
│ │ ├── User.test.js # Model tests
│ │ ├── Street.test.js
│ │ ├── Task.test.js
│ │ └── Post.test.js
│ ├── routes/
│ │ ├── auth.test.js # Route tests
│ │ ├── streets.test.js
│ │ ├── tasks.test.js
│ │ ├── posts.test.js
│ │ ├── events.test.js
│ │ ├── rewards.test.js
│ │ └── reports.test.js
│ └── utils/
│ └── testHelpers.js # Test utilities
└── jest.config.js # Jest configuration
```
### Frontend Test Organization
```
frontend/src/
├── setupTests.js # Global test setup
├── mocks/
│ ├── handlers.js # MSW API handlers
│ └── server.js # MSW server setup
├── __tests__/
│ └── auth-flow.integration.test.js # Integration tests
└── components/
└── __tests__/
├── Login.test.js # Component tests
├── Register.test.js
└── ErrorBoundary.test.js
```
## Best Practices
### Backend Testing
1. **Use Test Helpers**: Leverage `testHelpers.js` for consistent test data creation
2. **Isolate Tests**: Each test should be independent and not rely on other tests
3. **Mock External Services**: Mock Cloudinary, Stripe, and other external APIs
4. **Test Error Cases**: Don't just test happy paths, test error handling
5. **Use Descriptive Names**: Test names should clearly describe what they test
6. **Clean Up**: The test setup automatically cleans up between tests
### Frontend Testing
1. **Test User Behavior**: Focus on how users interact with components
2. **Use MSW for API Mocking**: Don't mock axios directly, use MSW handlers
3. **Test Accessibility**: Use semantic queries (getByRole, getByLabelText)
4. **Avoid Implementation Details**: Test what users see, not component internals
5. **Use waitFor for Async**: Always use waitFor for asynchronous operations
6. **Mock External Libraries**: Mock Leaflet, Socket.IO, and other heavy libraries
### Writing New Tests
#### Backend Route Test Template
```javascript
const request = require('supertest');
const express = require('express');
const yourRoute = require('../../routes/your-route');
const { createTestUser } = require('../utils/testHelpers');
const app = express();
app.use(express.json());
app.use('/api/your-route', yourRoute);
describe('Your Route', () => {
describe('GET /api/your-route', () => {
it('should do something', async () => {
const { token } = await createTestUser();
const response = await request(app)
.get('/api/your-route')
.set('x-auth-token', token)
.expect(200);
expect(response.body).toMatchObject({ /* expected shape */ });
});
});
});
```
#### Frontend Component Test Template
```javascript
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import YourComponent from '../YourComponent';
describe('YourComponent', () => {
it('should render and work', async () => {
render(<YourComponent />);
const button = screen.getByRole('button', { name: /submit/i });
fireEvent.click(button);
await waitFor(() => {
expect(screen.getByText(/success/i)).toBeInTheDocument();
});
});
});
```
## Troubleshooting
### Common Issues
#### CouchDB Testing Timeout
If tests timeout with CouchDB testing utilities:
```bash
# Increase timeout in jest.config.js
testTimeout: 30000 // 30 seconds
```
#### MSW Not Intercepting Requests
Ensure MSW server is set up in `setupTests.js`:
```javascript
import { server } from './mocks/server';
beforeAll(() => server.listen({ onUnhandledRequest: 'warn' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
```
#### React Router Errors in Tests
Wrap components with BrowserRouter:
```javascript
import { BrowserRouter } from 'react-router-dom';
render(
<BrowserRouter>
<YourComponent />
</BrowserRouter>
);
```
#### Auth Context Not Found
Provide AuthContext in tests:
```javascript
import { AuthContext } from '../../context/AuthContext';
const mockAuthContext = {
auth: { isAuthenticated: false, loading: false, user: null },
login: jest.fn(),
};
render(
<AuthContext.Provider value={mockAuthContext}>
<YourComponent />
</AuthContext.Provider>
);
```
#### Leaflet Map Errors
Mock react-leaflet in tests:
```javascript
jest.mock('react-leaflet', () => ({
MapContainer: ({ children }) => <div data-testid="map">{children}</div>,
TileLayer: () => null,
Marker: () => null,
Popup: () => null,
}));
```
### Performance Tips
1. **Run specific test files**:
```bash
bun test -- auth.test.js
```
2. **Run tests matching pattern**:
```bash
bun test -- --testNamePattern="login"
```
3. **Skip tests during development**:
```javascript
describe.skip('Skip this suite', () => { /* ... */ });
it.skip('Skip this test', () => { /* ... */ });
```
4. **Run only specific tests**:
```javascript
describe.only('Run only this suite', () => { /* ... */ });
it.only('Run only this test', () => { /* ... */ });
```
## Future Improvements
### Backend
- [ ] Increase route coverage to 70%+
- [ ] Add tests for Socket.IO events
- [ ] Add tests for file upload (Multer)
- [ ] Add tests for AI route
- [ ] Add tests for payments route
- [ ] Add performance/load tests
- [ ] Add E2E tests with real database
### Frontend
- [ ] Add tests for all remaining components:
- MapView
- TaskList
- SocialFeed
- Events
- Profile
- Premium
- Rewards
- [ ] Add integration tests for complete user flows
- [ ] Add accessibility tests (jest-axe)
- [ ] Add visual regression tests (Percy/Chromatic)
- [ ] Add E2E tests (Playwright/Cypress)
- [ ] Increase coverage to 60%+
## CI/CD Integration
To integrate tests into CI/CD pipeline:
### GitHub Actions Example
```yaml
name: Tests
on: [push, pull_request]
jobs:
backend-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: cd backend && bun install
- run: cd backend && bun test -- --coverage
frontend-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: cd frontend && bun install
- run: cd frontend && bun run test:coverage
```
## Resources
- [Jest Documentation](https://jestjs.io/)
- [React Testing Library](https://testing-library.com/react)
- [Supertest](https://github.com/visionmedia/supertest)
- [MSW Documentation](https://mswjs.io/)
- [CouchDB Testing Utilities](https://github.com/apache/couchdb/tree/main/test)
- [Testing Best Practices](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)