Delete vehicles/external/nhtsa/ directory (3 files), remove VPICVariable and VPICResponse from platform models. Update all documentation to reflect Gemini VIN decode via OCR service architecture. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8.4 KiB
Testing Guide
Comprehensive testing strategy for MotoVaultPro Modified Feature Capsule architecture.
Testing Philosophy
Each feature capsule contains complete, isolated test suites with no cross-feature dependencies.
Test Structure
Per Feature Organization
backend/src/features/[name]/tests/
├── fixtures/ # Test data
├── unit/ # Isolated unit tests
│ ├── [name].service.test.ts
│ └── [external].client.test.ts
└── integration/ # Full API tests
└── [name].integration.test.ts
Docker Testing Workflow
Backend Testing
# Enter backend container shell
make shell-backend
# Inside container:
# Test all features
npm test
# Test single feature (complete isolation)
npm test -- --testPathPattern=src/features/vehicles
# Test specific test type
npm test -- --testPathPattern=src/features/vehicles/tests/unit
npm test -- --testPathPattern=src/features/vehicles/tests/integration
# Test with coverage
npm test -- --testPathPattern=src/features/vehicles --coverage
# Watch mode
npm run test:watch
Frontend Testing
# From project root, run tests in frontend container
docker compose exec mvp-frontend npm test
# Watch mode
docker compose exec mvp-frontend npm run test:watch
# With coverage
docker compose exec mvp-frontend npm test -- --coverage
Test Environment Setup
- Container-Based: All tests run inside Docker containers
- Database: Uses the development database in the stack (
motovaultpro) - Mock External APIs: No real API calls during testing (where implemented)
- Cleanup: Prefer transactions/cleanup per test; see feature tests for patterns
Test Types
Unit Tests
Location: features/[name]/tests/unit/
Purpose: Test business logic in isolation
Mocking: All external dependencies mocked
Example: vehicles.service.test.ts
- Tests VIN validation logic
- Tests vehicle creation with mocked OCR service responses
- Tests caching behavior with mocked Redis
- Tests error handling paths
Integration Tests
Location: features/[name]/tests/integration/
Purpose: Test complete API workflows
Database: Real test database with transactions
Example: vehicles.integration.test.ts
- Tests complete POST /api/vehicles workflow
- Tests authentication middleware
- Tests database persistence
- Tests error responses
Test Data
Location: Inline within test files Purpose: Test-specific mock data Format: TypeScript objects defined in test files
Tests use inline mock data rather than external fixture files. Example pattern:
const mockVehicle = {
vin: "1HGBH41JXMN109186",
nickname: "Test Honda",
color: "Blue"
};
const mockPlatformResponse = {
make: "Honda",
model: "Civic",
year: 2021
};
Testing Commands Reference
Development Testing
# Enter backend container
make shell-backend
# Run all tests
npm test
# Run specific feature
npm test -- --testPathPattern=src/features/vehicles
npm test -- --testPathPattern=src/features/fuel-logs
npm test -- --testPathPattern=src/features/maintenance
npm test -- --testPathPattern=src/features/stations
# Run with file watching
npm run test:watch
# Run single test file
npm test -- vehicles.service.test.ts
# Run tests matching pattern
npm test -- --testNamePattern="VIN validation"
# Frontend tests (Jest)
docker compose exec mvp-frontend npm test
Coverage Reports
# Generate coverage for specific feature
npm test -- --testPathPattern=src/features/vehicles --coverage
# View coverage report
# Inside the container, open using your OS tooling,
# or copy the report out of the container as needed
Container Management
# Restart containers with fresh database
make rebuild
# View test logs
make logs-backend
# Clean all test data
make clean && make start
Test Configuration
Jest Configuration
- Backend:
backend/jest.config.js - Frontend:
frontend/jest.config.ts- React + TypeScript via
ts-jest - jsdom environment
- Testing Library setup in
frontend/setupTests.ts
- React + TypeScript via
Database Testing
- DB: Same as development (
motovaultpro) within Docker - Transactions: Recommended pattern is one transaction per test
- Isolation: Keep tests independent; avoid shared state
- Seeding: Use feature-level fixtures when needed
Coverage and Availability
All 15 features have test suites with unit and/or integration tests:
admin- Unit + integration testsauth- Unit + integration testsbackup- Unit + integration testsdocuments- Unit + integration testsfuel-logs- Unit + integration testsmaintenance- Unit + integration testsnotifications- Unit + integration testsonboarding- Unit testsplatform- Unit + integration testsstations- Unit + integration tests (including community stations)terms-agreement- Unit testsuser-export- Unit testsuser-preferences- Unit testsuser-profile- Unit + integration testsvehicles- Unit + integration tests
Mock Strategy
- External APIs: Completely mocked (OCR service, Google Maps)
- Database: Real database with transactions
- Redis: Mocked for unit tests, real for integration
- Auth: Mocked JWT tokens for protected endpoints
Test Data Management
Inline Mock Data Strategy
// In test files - define mock data inline
const mockVehicle = {
vin: '1HGBH41JXMN109186',
nickname: 'Test Honda',
year: 2021,
make: 'Honda',
model: 'Civic'
};
describe('Vehicle Service', () => {
it('should create vehicle', async () => {
const result = await vehicleService.create(mockVehicle, 'user123');
expect(result.make).toBe('Honda');
});
});
Database Seeding
beforeEach(async () => {
// Clean slate for each test
await db.query('TRUNCATE TABLE vehicles CASCADE');
// Insert test-specific data
await db.query('INSERT INTO vehicles ...', testData);
});
Debugging Tests
Debug Single Test
# Run specific test with debugging
npm test -- --testNamePattern="should create vehicle" --verbose
# Debug integration test
npm test -- features/vehicles/tests/integration --detectOpenHandles
Common Issues
Container Connection Issues
# Check container health
make logs-backend
# Restart with fresh state
make rebuild
Database Connection Issues
# Check postgres container
docker compose logs postgres
# Reset database
make clean && make start
Test Timeout Issues
# Increase timeout in jest config
# Or debug hanging connections
npm test -- --detectOpenHandles
Continuous Integration
Pre-commit Testing
All tests must pass before commits:
# Backend: Enter shell and run tests
make shell-backend
npm run lint
npm test
# Frontend: Run tests from project root
docker compose exec mvp-frontend npm run lint
docker compose exec mvp-frontend npm test
Feature Development Workflow
- Write tests first: TDD approach preferred
- Run tests continuously: Use
npm run test:watch - Test in containers: Always verify with
docker compose exec mvp-backend npm test - Check coverage: Ensure new code is covered
- Integration last: Run full test suite before PR
Test Performance
Parallel Execution
- Jest runs tests in parallel by default
- Feature isolation allows true parallel testing
- No shared state between feature tests
Test Speed Optimization
- Unit tests: Fast (< 1 second per test)
- Integration tests: Medium (< 5 seconds per test)
- Full suite: Target < 30 seconds total
Database Optimization
- Use transactions for rollback (faster than truncate)
- Minimal fixture data
- Avoid complex joins in test setup
Error Testing Strategy
Expected Error Cases
describe('Error Handling', () => {
it('should handle invalid VIN', async () => {
await expect(
vehicleService.create({ vin: 'INVALID' }, 'user123')
).rejects.toThrow('Invalid VIN format');
});
it('should handle OCR service failure', async () => {
mockOcrClient.decodeVin.mockRejectedValue(new Error('API down'));
const result = await vehicleService.create(validVehicle, 'user123');
expect(result.make).toBeNull(); // Graceful degradation
});
});
External Service Failures
- Mock API failures to test error handling
- Test timeout scenarios
- Test network connectivity issues
- Verify graceful degradation paths