Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
- Remove production Docker Compose files (docker-compose.production.yml, docker-compose.prod-simple.yml) - Remove production Dockerfiles (backend and frontend) - Move implementation docs to docs/implementation-docs/ directory - Remove test scripts (test-embeddings.js, test-voice-*.js/sh) - Update ecosystem.config.js with production environment variables (CORS, JWT secrets, database config) - Add database connection pooling configuration - Update CORS configuration for production domains (parentflowapp.com) - Fix frontend dev server port configuration (3005) - Add PWA web push implementation plan documentation - Simplify health check endpoints (remove MongoDB/Redis specific checks) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
527 lines
13 KiB
Markdown
527 lines
13 KiB
Markdown
# Testing Strategy - Maternal App
|
|
|
|
**Target Coverage:** 80%+ across all layers
|
|
**Testing Pyramid:** Unit (70%) → Integration (20%) → E2E (10%)
|
|
|
|
---
|
|
|
|
## 1. Backend Testing (NestJS)
|
|
|
|
### 1.1 Unit Tests (Target: 70% of tests)
|
|
|
|
**Tools:** Jest, @nestjs/testing
|
|
|
|
**What to Test:**
|
|
- **Services** (Business Logic)
|
|
- ComplianceService (data export, account deletion)
|
|
- AuthService (registration with COPPA validation, login, token management)
|
|
- ChildrenService (CRUD operations)
|
|
- TrackingService (activity creation, daily summary)
|
|
- AIService (chat, conversation memory)
|
|
- VoiceService (intent classification, entity extraction)
|
|
- EmbeddingsService (vector search, semantic memory)
|
|
|
|
- **Guards**
|
|
- JwtAuthGuard
|
|
- Public decorator
|
|
|
|
- **Pipes**
|
|
- ValidationPipe (DTO validation)
|
|
|
|
- **Utilities**
|
|
- Date calculations
|
|
- Age verification (COPPA compliance)
|
|
- Token generation
|
|
|
|
**Example Test Structure:**
|
|
```typescript
|
|
describe('ComplianceService', () => {
|
|
let service: ComplianceService;
|
|
let userRepository: Repository<User>;
|
|
|
|
beforeEach(async () => {
|
|
const module = await Test.createTestingModule({
|
|
providers: [
|
|
ComplianceService,
|
|
{ provide: getRepositoryToken(User), useClass: Repository },
|
|
],
|
|
}).compile();
|
|
|
|
service = module.get<ComplianceService>(ComplianceService);
|
|
});
|
|
|
|
it('should export user data with all entities', async () => {
|
|
// Test implementation
|
|
});
|
|
|
|
it('should schedule account deletion with 30-day grace period', async () => {
|
|
// Test implementation
|
|
});
|
|
});
|
|
```
|
|
|
|
### 1.2 Integration Tests (Target: 20% of tests)
|
|
|
|
**Tools:** Jest, Supertest, @nestjs/testing
|
|
|
|
**What to Test:**
|
|
- **API Endpoints** (Controller + Service + Database)
|
|
- POST /api/v1/compliance/data-export
|
|
- POST /api/v1/compliance/request-deletion
|
|
- POST /api/v1/auth/register (with COPPA validation)
|
|
- POST /api/v1/auth/login
|
|
- POST /api/v1/activities (tracking)
|
|
- POST /api/v1/ai/chat
|
|
|
|
- **Authentication Flows**
|
|
- Register → Login → Protected Route
|
|
- Register with COPPA (age 13-17)
|
|
- Register blocked (age < 13)
|
|
|
|
- **Database Operations**
|
|
- CRUD operations with real database
|
|
- Transaction rollbacks
|
|
- Cascade deletions
|
|
|
|
**Example Test Structure:**
|
|
```typescript
|
|
describe('ComplianceController (e2e)', () => {
|
|
let app: INestApplication;
|
|
let authToken: string;
|
|
|
|
beforeAll(async () => {
|
|
const moduleFixture = await Test.createTestingModule({
|
|
imports: [AppModule],
|
|
}).compile();
|
|
|
|
app = moduleFixture.createNestApplication();
|
|
await app.init();
|
|
});
|
|
|
|
it('/api/v1/compliance/data-export (GET)', () => {
|
|
return request(app.getHttpServer())
|
|
.get('/api/v1/compliance/data-export')
|
|
.set('Authorization', `Bearer ${authToken}`)
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body.data).toHaveProperty('user');
|
|
expect(res.body.data).toHaveProperty('children');
|
|
expect(res.body.data).toHaveProperty('activities');
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Frontend Testing (Next.js + React)
|
|
|
|
### 2.1 Unit Tests (Component Testing)
|
|
|
|
**Tools:** Jest, React Testing Library, @testing-library/user-event
|
|
|
|
**What to Test:**
|
|
- **Components**
|
|
- DataExport component (button click, download trigger)
|
|
- AccountDeletion component (dialog flow, deletion request)
|
|
- Registration form (COPPA age validation, form submission)
|
|
- Settings page (profile update, compliance sections)
|
|
- Tracking forms (feeding, sleep, diaper)
|
|
|
|
- **Redux Slices**
|
|
- authSlice (login, logout, token refresh)
|
|
- childrenSlice (CRUD operations)
|
|
- activitiesSlice (create, update, delete)
|
|
- offlineSlice (sync queue, conflict resolution)
|
|
|
|
- **API Clients**
|
|
- complianceApi (all methods)
|
|
- authApi, childrenApi, trackingApi
|
|
|
|
- **Utilities**
|
|
- Date formatting
|
|
- Age calculation
|
|
- Token storage
|
|
|
|
**Example Test Structure:**
|
|
```typescript
|
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
import { DataExport } from '@/components/settings/DataExport';
|
|
import { complianceApi } from '@/lib/api/compliance';
|
|
|
|
jest.mock('@/lib/api/compliance');
|
|
|
|
describe('DataExport Component', () => {
|
|
it('should download user data when button is clicked', async () => {
|
|
const mockDownload = jest.fn();
|
|
(complianceApi.downloadUserData as jest.Mock) = mockDownload;
|
|
|
|
render(<DataExport />);
|
|
|
|
const button = screen.getByText('Download My Data');
|
|
fireEvent.click(button);
|
|
|
|
await waitFor(() => {
|
|
expect(mockDownload).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
expect(screen.getByText('Your data has been downloaded successfully!')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should show error message on download failure', async () => {
|
|
(complianceApi.downloadUserData as jest.Mock).mockRejectedValue(
|
|
new Error('Network error')
|
|
);
|
|
|
|
render(<DataExport />);
|
|
fireEvent.click(screen.getByText('Download My Data'));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/Failed to export data/)).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
### 2.2 Integration Tests (API Interaction)
|
|
|
|
**What to Test:**
|
|
- Form submission with API calls
|
|
- Authentication flows
|
|
- Error handling and retry logic
|
|
- Optimistic updates with Redux
|
|
|
|
---
|
|
|
|
## 3. End-to-End Tests (Target: 10% of tests)
|
|
|
|
**Tools:** Playwright
|
|
|
|
**Critical User Journeys:**
|
|
|
|
### 3.1 Registration & COPPA Compliance
|
|
```typescript
|
|
test('User under 13 cannot register', async ({ page }) => {
|
|
await page.goto('/register');
|
|
await page.fill('[name="name"]', 'John Doe');
|
|
await page.fill('[name="email"]', 'john@example.com');
|
|
await page.fill('[name="dateOfBirth"]', '2015-01-01'); // 9 years old
|
|
await page.fill('[name="password"]', 'SecurePass123');
|
|
await page.fill('[name="confirmPassword"]', 'SecurePass123');
|
|
await page.check('[name="agreeToTerms"]');
|
|
await page.check('[name="agreeToPrivacy"]');
|
|
|
|
await page.click('button[type="submit"]');
|
|
|
|
await expect(page.locator('text=/Users under 13/')).toBeVisible();
|
|
});
|
|
|
|
test('User 13-17 requires parental consent', async ({ page }) => {
|
|
await page.goto('/register');
|
|
await page.fill('[name="dateOfBirth"]', '2010-01-01'); // 14 years old
|
|
|
|
// Parental email field should appear
|
|
await expect(page.locator('[name="parentalEmail"]')).toBeVisible();
|
|
await expect(page.locator('text=/parental consent/')).toBeVisible();
|
|
});
|
|
```
|
|
|
|
### 3.2 Account Deletion Flow
|
|
```typescript
|
|
test('User can request account deletion and cancel it', async ({ page }) => {
|
|
// Login
|
|
await login(page, 'user@example.com', 'password');
|
|
|
|
// Navigate to settings
|
|
await page.goto('/settings');
|
|
|
|
// Request deletion
|
|
await page.click('text=Delete My Account');
|
|
await page.fill('[name="reason"]', 'Testing deletion flow');
|
|
await page.click('button:has-text("Delete Account")');
|
|
|
|
// Verify deletion scheduled
|
|
await expect(page.locator('text=/Account deletion scheduled/')).toBeVisible();
|
|
|
|
// Cancel deletion
|
|
await page.click('text=Cancel Deletion Request');
|
|
await page.click('button:has-text("Cancel Deletion")');
|
|
|
|
// Verify cancellation
|
|
await expect(page.locator('text=/cancelled successfully/')).toBeVisible();
|
|
});
|
|
```
|
|
|
|
### 3.3 Data Export Flow
|
|
```typescript
|
|
test('User can export their data', async ({ page }) => {
|
|
await login(page, 'user@example.com', 'password');
|
|
await page.goto('/settings');
|
|
|
|
const [download] = await Promise.all([
|
|
page.waitForEvent('download'),
|
|
page.click('text=Download My Data')
|
|
]);
|
|
|
|
expect(download.suggestedFilename()).toMatch(/maternal-app-data-export.*\.json/);
|
|
});
|
|
```
|
|
|
|
### 3.4 Activity Tracking Flow
|
|
```typescript
|
|
test('User can track feeding activity', async ({ page }) => {
|
|
await login(page, 'user@example.com', 'password');
|
|
await page.goto('/track/feeding');
|
|
|
|
await page.selectOption('[name="childId"]', { index: 0 });
|
|
await page.fill('[name="amount"]', '120');
|
|
await page.selectOption('[name="unit"]', 'ml');
|
|
await page.click('button:has-text("Save")');
|
|
|
|
await expect(page.locator('text=/Activity saved/')).toBeVisible();
|
|
|
|
// Verify on dashboard
|
|
await page.goto('/');
|
|
await expect(page.locator('text=/Feeding/')).toBeVisible();
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Code Coverage Goals
|
|
|
|
### 4.1 Overall Targets
|
|
- **Total Coverage:** 80%+
|
|
- **Statements:** 80%+
|
|
- **Branches:** 75%+
|
|
- **Functions:** 80%+
|
|
- **Lines:** 80%+
|
|
|
|
### 4.2 Module-Specific Targets
|
|
|
|
**Backend:**
|
|
- Auth Module: 90%+ (critical security)
|
|
- Compliance Module: 95%+ (legal requirement)
|
|
- Tracking Module: 85%+
|
|
- AI Module: 80%+
|
|
- Voice Module: 80%+
|
|
|
|
**Frontend:**
|
|
- Compliance Components: 95%+
|
|
- Auth Components: 90%+
|
|
- Tracking Components: 85%+
|
|
- API Clients: 90%+
|
|
- Redux Slices: 85%+
|
|
|
|
---
|
|
|
|
## 5. CI/CD Integration
|
|
|
|
### 5.1 GitHub Actions Workflow
|
|
|
|
**Triggers:**
|
|
- Push to main branch
|
|
- Pull request to main
|
|
- Scheduled nightly runs
|
|
|
|
**Steps:**
|
|
1. Checkout code
|
|
2. Setup Node.js (v20)
|
|
3. Install dependencies
|
|
4. Run linter (ESLint)
|
|
5. Run backend unit tests
|
|
6. Run backend integration tests
|
|
7. Run frontend tests
|
|
8. Run E2E tests
|
|
9. Generate coverage reports
|
|
10. Upload coverage to Codecov
|
|
11. Fail PR if coverage drops below 80%
|
|
|
|
**Example `.github/workflows/test.yml`:**
|
|
```yaml
|
|
name: Test Suite
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
backend-tests:
|
|
runs-on: ubuntu-latest
|
|
services:
|
|
postgres:
|
|
image: postgres:15
|
|
env:
|
|
POSTGRES_PASSWORD: test
|
|
options: >-
|
|
--health-cmd pg_isready
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
- uses: actions/setup-node@v3
|
|
with:
|
|
node-version: '20'
|
|
- run: npm ci
|
|
- run: npm test -- --coverage
|
|
- uses: codecov/codecov-action@v3
|
|
|
|
frontend-tests:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
- uses: actions/setup-node@v3
|
|
- run: npm ci
|
|
- run: npm test -- --coverage
|
|
|
|
e2e-tests:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
- uses: actions/setup-node@v3
|
|
- run: npx playwright install --with-deps
|
|
- run: npm run test:e2e
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Test Data Management
|
|
|
|
### 6.1 Test Database
|
|
- Use separate test database
|
|
- Seed with test fixtures
|
|
- Clean between tests
|
|
|
|
### 6.2 Test Fixtures
|
|
- Create factory functions for test data
|
|
- Predefined users, children, activities
|
|
- COPPA-compliant test scenarios (various ages)
|
|
|
|
**Example:**
|
|
```typescript
|
|
export const testUsers = {
|
|
adult: {
|
|
name: 'Adult User',
|
|
email: 'adult@example.com',
|
|
dateOfBirth: '1990-01-01',
|
|
},
|
|
minor14: {
|
|
name: 'Teen User',
|
|
email: 'teen@example.com',
|
|
dateOfBirth: '2010-01-01',
|
|
parentalEmail: 'parent@example.com',
|
|
coppaConsentGiven: true,
|
|
},
|
|
child12: {
|
|
name: 'Child User',
|
|
email: 'child@example.com',
|
|
dateOfBirth: '2012-01-01', // Should be blocked
|
|
},
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Testing Best Practices
|
|
|
|
### 7.1 General Principles
|
|
- **AAA Pattern:** Arrange, Act, Assert
|
|
- **DRY:** Don't Repeat Yourself (use factories and helpers)
|
|
- **Fast:** Keep unit tests under 100ms
|
|
- **Isolated:** No dependencies between tests
|
|
- **Deterministic:** Same input = same output
|
|
|
|
### 7.2 Mocking Strategy
|
|
- Mock external services (Azure OpenAI, Mailgun, MinIO)
|
|
- Mock time-dependent functions
|
|
- Use in-memory database for unit tests
|
|
- Real database for integration tests
|
|
|
|
### 7.3 Naming Conventions
|
|
```typescript
|
|
describe('ServiceName', () => {
|
|
describe('methodName', () => {
|
|
it('should do something when condition', () => {
|
|
// Test
|
|
});
|
|
|
|
it('should throw error when invalid input', () => {
|
|
// Test
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Continuous Improvement
|
|
|
|
### 8.1 Metrics to Track
|
|
- Code coverage percentage
|
|
- Test execution time
|
|
- Flaky test rate
|
|
- Bug escape rate
|
|
|
|
### 8.2 Review Process
|
|
- All PRs must have tests
|
|
- Coverage must not decrease
|
|
- CI must pass before merge
|
|
|
|
---
|
|
|
|
## 9. Implementation Timeline
|
|
|
|
**Week 1:**
|
|
- ✅ Setup Jest for backend and frontend
|
|
- ✅ Create first unit tests (Compliance, Auth)
|
|
- ✅ Setup test database
|
|
|
|
**Week 2:**
|
|
- ✅ Create integration tests for critical endpoints
|
|
- ✅ Setup Playwright for E2E
|
|
- ✅ Create E2E tests for COPPA flows
|
|
|
|
**Week 3:**
|
|
- ✅ Expand coverage to 50%+
|
|
- ✅ Setup CI/CD pipeline
|
|
- ✅ Configure coverage reporting
|
|
|
|
**Week 4:**
|
|
- ✅ Reach 80%+ coverage
|
|
- ✅ Optimize test performance
|
|
- ✅ Documentation and training
|
|
|
|
---
|
|
|
|
## 10. Quick Start Commands
|
|
|
|
```bash
|
|
# Backend
|
|
cd maternal-app-backend
|
|
npm test # Run all tests
|
|
npm test -- --coverage # With coverage
|
|
npm test -- --watch # Watch mode
|
|
npm run test:e2e # Integration tests
|
|
|
|
# Frontend
|
|
cd maternal-web
|
|
npm test # Run all tests
|
|
npm test -- --coverage # With coverage
|
|
npm test -- --watch # Watch mode
|
|
npm run test:e2e # E2E with Playwright
|
|
|
|
# Coverage Reports
|
|
npm test -- --coverage --coverageReporters=html
|
|
# Open coverage/index.html in browser
|
|
```
|
|
|
|
---
|
|
|
|
## Status: IN PROGRESS
|
|
**Current Coverage:** 0%
|
|
**Target Coverage:** 80%+
|
|
**Estimated Completion:** 3-4 weeks
|