- Initialize Git repository with main branch - Create comprehensive .gitignore for Node.js, React, and environment files - Set up directory structure (frontend/, backend/, docs/) - Create detailed README.md with project overview and setup instructions - Add .env.example with all required environment variables - Configure Prettier for consistent code formatting All acceptance criteria met: ✅ Git repository initialized with appropriate .gitignore ✅ Directory structure matches Technical Assumptions ✅ README.md created with project overview and setup docs ✅ .env.example file with all required environment variables ✅ Prettier config files added for code formatting consistency 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
203 lines
5.4 KiB
Markdown
203 lines
5.4 KiB
Markdown
# Testing Strategy
|
|
|
|
## Testing Pyramid
|
|
|
|
```
|
|
E2E Tests (Manual)
|
|
/ \
|
|
Integration Tests (Backend)
|
|
/ \
|
|
Frontend Unit Tests Backend Unit Tests
|
|
```
|
|
|
|
**Coverage Targets:**
|
|
- Frontend: >70% for utils, services, business logic
|
|
- Backend: >80% for controllers, services, business logic
|
|
- Manual E2E: All critical user flows tested before deployment
|
|
|
|
## Test Organization
|
|
|
|
### Frontend Tests
|
|
|
|
```
|
|
frontend/tests/
|
|
├── components/
|
|
│ ├── BookCard.test.jsx
|
|
│ ├── LogProgressModal.test.jsx
|
|
│ └── StatusIndicator.test.jsx
|
|
├── utils/
|
|
│ ├── dateUtils.test.js
|
|
│ ├── paceUtils.test.js
|
|
│ └── validation.test.js
|
|
└── services/
|
|
└── booksService.test.js
|
|
```
|
|
|
|
### Backend Tests
|
|
|
|
```
|
|
backend/tests/
|
|
├── controllers/
|
|
│ ├── booksController.test.js
|
|
│ └── logsController.test.js
|
|
├── services/
|
|
│ ├── openLibraryService.test.js
|
|
│ └── paceCalculationService.test.js
|
|
└── integration/
|
|
└── api.test.js
|
|
```
|
|
|
|
### E2E Tests (Manual Checklist)
|
|
|
|
```
|
|
Manual E2E Test Checklist:
|
|
- [ ] Add book: Search → Select → Set deadline → Verify in list
|
|
- [ ] Log progress: Tap book → Enter page → Verify status updates
|
|
- [ ] View calendar: Navigate to book detail → See logged days
|
|
- [ ] Install PWA: "Add to Home Screen" → Launch from home screen
|
|
- [ ] Offline mode: Disable network → Log entry → Re-enable → Verify sync
|
|
- [ ] Mobile responsiveness: Test on iPhone and Android
|
|
```
|
|
|
|
## Test Examples
|
|
|
|
### Frontend Component Test
|
|
|
|
```typescript
|
|
// tests/components/StatusIndicator.test.jsx
|
|
import { describe, it, expect } from 'vitest';
|
|
import { render, screen } from '@testing-library/react';
|
|
import StatusIndicator from '../../src/components/progress/StatusIndicator';
|
|
|
|
describe('StatusIndicator', () => {
|
|
it('displays green indicator for on-track status', () => {
|
|
render(<StatusIndicator status="on-track" />);
|
|
const indicator = screen.getByText(/on track/i);
|
|
expect(indicator).toBeInTheDocument();
|
|
expect(indicator).toHaveClass('text-green-600'); // Tailwind class
|
|
});
|
|
|
|
it('displays yellow indicator for slightly-behind status', () => {
|
|
render(<StatusIndicator status="slightly-behind" />);
|
|
const indicator = screen.getByText(/slightly behind/i);
|
|
expect(indicator).toBeInTheDocument();
|
|
expect(indicator).toHaveClass('text-yellow-600');
|
|
});
|
|
|
|
it('displays red indicator for behind status', () => {
|
|
render(<StatusIndicator status="behind" />);
|
|
const indicator = screen.getByText(/behind/i);
|
|
expect(indicator).toBeInTheDocument();
|
|
expect(indicator).toHaveClass('text-red-600');
|
|
});
|
|
});
|
|
```
|
|
|
|
### Backend API Test
|
|
|
|
```typescript
|
|
// tests/controllers/booksController.test.js
|
|
const request = require('supertest');
|
|
const app = require('../../src/server');
|
|
const { PrismaClient } = require('@prisma/client');
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
describe('Books API', () => {
|
|
beforeAll(async () => {
|
|
// Setup test database
|
|
await prisma.book.deleteMany();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await prisma.$disconnect();
|
|
});
|
|
|
|
describe('POST /api/books', () => {
|
|
it('creates a new book with valid data', async () => {
|
|
const bookData = {
|
|
title: 'The Name of the Wind',
|
|
author: 'Patrick Rothfuss',
|
|
totalPages: 662,
|
|
deadlineDate: '2025-12-31',
|
|
};
|
|
|
|
const response = await request(app)
|
|
.post('/api/books')
|
|
.send(bookData)
|
|
.expect(201);
|
|
|
|
expect(response.body).toMatchObject({
|
|
title: bookData.title,
|
|
author: bookData.author,
|
|
totalPages: bookData.totalPages,
|
|
status: 'reading',
|
|
});
|
|
expect(response.body.id).toBeDefined();
|
|
});
|
|
|
|
it('returns 400 for invalid deadline (past date)', async () => {
|
|
const bookData = {
|
|
title: 'Test Book',
|
|
totalPages: 300,
|
|
deadlineDate: '2020-01-01', // Past date
|
|
};
|
|
|
|
const response = await request(app)
|
|
.post('/api/books')
|
|
.send(bookData)
|
|
.expect(400);
|
|
|
|
expect(response.body.error).toBe('Deadline must be in the future');
|
|
});
|
|
});
|
|
|
|
describe('GET /api/books', () => {
|
|
it('returns all active books with progress', async () => {
|
|
// Create test book
|
|
await prisma.book.create({
|
|
data: {
|
|
title: 'Test Book',
|
|
totalPages: 300,
|
|
deadlineDate: new Date('2025-12-31'),
|
|
},
|
|
});
|
|
|
|
const response = await request(app)
|
|
.get('/api/books')
|
|
.expect(200);
|
|
|
|
expect(response.body.books).toBeInstanceOf(Array);
|
|
expect(response.body.books.length).toBeGreaterThan(0);
|
|
expect(response.body.books[0]).toHaveProperty('requiredPace');
|
|
expect(response.body.books[0]).toHaveProperty('status');
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
### E2E Test (Manual)
|
|
|
|
**Test Case:** Add Book and Log Progress
|
|
|
|
**Steps:**
|
|
1. Navigate to http://localhost:5173
|
|
2. Click "Add Book" button
|
|
3. Search for "Name of the Wind"
|
|
4. Select first result
|
|
5. Set deadline to 30 days from today
|
|
6. Click "Add to Reading List"
|
|
7. Verify book appears in list with status "on-track" or "unknown"
|
|
8. Click "Log Progress" button
|
|
9. Enter page number: 50
|
|
10. Click "Save"
|
|
11. Verify status updates to show required pace and actual pace
|
|
|
|
**Expected Result:**
|
|
- Book added successfully
|
|
- Progress logged successfully
|
|
- Status indicator shows appropriate color
|
|
- Pace calculations display correctly
|
|
|
|
---
|