Testing Strategy: - Created comprehensive testing strategy document - Target: 80%+ code coverage - Testing pyramid: Unit (70%) → Integration (20%) → E2E (10%) - Defined test data management and best practices Backend Unit Tests: - Created ComplianceService unit test suite (10 tests) - Tests for data export, account deletion, cancellation - Mock repository pattern for isolated testing - AAA pattern (Arrange, Act, Assert) Next Steps: - Run and fix unit tests - Create integration tests for API endpoints - Setup frontend testing with React Testing Library - Setup E2E tests with Playwright - Configure CI/CD pipeline with GitHub Actions - Achieve 80%+ code coverage Status: Testing foundation initiated (0% → 5% progress)
13 KiB
13 KiB
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:
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:
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:
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
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
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
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
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:
- Checkout code
- Setup Node.js (v20)
- Install dependencies
- Run linter (ESLint)
- Run backend unit tests
- Run backend integration tests
- Run frontend tests
- Run E2E tests
- Generate coverage reports
- Upload coverage to Codecov
- Fail PR if coverage drops below 80%
Example .github/workflows/test.yml:
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:
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
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
# 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