* feat(task-104): Complete task 104 - Implement scope-up and scope-down CLI Commands - Added new CLI commands 'scope-up' and 'scope-down' with comma-separated ID support - Implemented strength levels (light/regular/heavy) and custom prompt functionality - Created core complexity adjustment logic with AI integration - Added MCP tool equivalents for integrated environments - Comprehensive error handling and task validation - Full test coverage with TDD approach - Updated task manager core and UI components Task 104: Implement 'scope-up' and 'scope-down' CLI Commands for Dynamic Task Complexity Adjustment - Complete implementation with CLI, MCP integration, and testing * chore: Add changeset for scope-up and scope-down features - Comprehensive user-facing description with usage examples - Key features and benefits explanation - CLI and MCP integration details - Real-world use cases for agile workflows * feat(extension): Add scope-up and scope-down to VS Code extension task details - Added useScopeUpTask and useScopeDownTask hooks in useTaskQueries.ts - Enhanced AIActionsSection with Task Complexity Adjustment section - Added strength selection (light/regular/heavy) and custom prompt support - Integrated scope buttons with proper loading states and error handling - Uses existing mcpRequest handler for scope_up_task and scope_down_task tools - Maintains consistent UI patterns with existing AI actions Extension now supports dynamic task complexity adjustment directly from task details view.
803 lines
21 KiB
Plaintext
803 lines
21 KiB
Plaintext
---
|
|
description:
|
|
globs:
|
|
alwaysApply: true
|
|
---
|
|
# Test Workflow & Development Process
|
|
|
|
## **Initial Testing Framework Setup**
|
|
|
|
Before implementing the TDD workflow, ensure your project has a proper testing framework configured. This section covers setup for different technology stacks.
|
|
|
|
### **Detecting Project Type & Framework Needs**
|
|
|
|
**AI Agent Assessment Checklist:**
|
|
1. **Language Detection**: Check for `package.json` (Node.js/JavaScript), `requirements.txt` (Python), `Cargo.toml` (Rust), etc.
|
|
2. **Existing Tests**: Look for test files (`.test.`, `.spec.`, `_test.`) or test directories
|
|
3. **Framework Detection**: Check for existing test runners in dependencies
|
|
4. **Project Structure**: Analyze directory structure for testing patterns
|
|
|
|
### **JavaScript/Node.js Projects (Jest Setup)**
|
|
|
|
#### **Prerequisites Check**
|
|
```bash
|
|
# Verify Node.js project
|
|
ls package.json # Should exist
|
|
|
|
# Check for existing testing setup
|
|
ls jest.config.js jest.config.ts # Check for Jest config
|
|
grep -E "(jest|vitest|mocha)" package.json # Check for test runners
|
|
```
|
|
|
|
#### **Jest Installation & Configuration**
|
|
|
|
**Step 1: Install Dependencies**
|
|
```bash
|
|
# Core Jest dependencies
|
|
npm install --save-dev jest
|
|
|
|
# TypeScript support (if using TypeScript)
|
|
npm install --save-dev ts-jest @types/jest
|
|
|
|
# Additional useful packages
|
|
npm install --save-dev supertest @types/supertest # For API testing
|
|
npm install --save-dev jest-watch-typeahead # Enhanced watch mode
|
|
```
|
|
|
|
**Step 2: Create Jest Configuration**
|
|
|
|
Create `jest.config.js` with the following production-ready configuration:
|
|
|
|
```javascript
|
|
/** @type {import('jest').Config} */
|
|
module.exports = {
|
|
// Use ts-jest preset for TypeScript support
|
|
preset: 'ts-jest',
|
|
|
|
// Test environment
|
|
testEnvironment: 'node',
|
|
|
|
// Roots for test discovery
|
|
roots: ['<rootDir>/src', '<rootDir>/tests'],
|
|
|
|
// Test file patterns
|
|
testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
|
|
|
|
// Transform files
|
|
transform: {
|
|
'^.+\\.ts$': [
|
|
'ts-jest',
|
|
{
|
|
tsconfig: {
|
|
target: 'es2020',
|
|
module: 'commonjs',
|
|
esModuleInterop: true,
|
|
allowSyntheticDefaultImports: true,
|
|
skipLibCheck: true,
|
|
strict: false,
|
|
noImplicitAny: false,
|
|
},
|
|
},
|
|
],
|
|
'^.+\\.js$': [
|
|
'ts-jest',
|
|
{
|
|
useESM: false,
|
|
tsconfig: {
|
|
target: 'es2020',
|
|
module: 'commonjs',
|
|
esModuleInterop: true,
|
|
allowSyntheticDefaultImports: true,
|
|
allowJs: true,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
|
|
// Module file extensions
|
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
|
|
|
// Transform ignore patterns - adjust for ES modules
|
|
transformIgnorePatterns: ['node_modules/(?!(your-es-module-deps|.*\\.mjs$))'],
|
|
|
|
// Coverage configuration
|
|
collectCoverage: true,
|
|
coverageDirectory: 'coverage',
|
|
coverageReporters: [
|
|
'text', // Console output
|
|
'text-summary', // Brief summary
|
|
'lcov', // For IDE integration
|
|
'html', // Detailed HTML report
|
|
],
|
|
|
|
// Files to collect coverage from
|
|
collectCoverageFrom: [
|
|
'src/**/*.ts',
|
|
'!src/**/*.d.ts',
|
|
'!src/**/*.test.ts',
|
|
'!src/**/index.ts', // Often just exports
|
|
'!src/generated/**', // Generated code
|
|
'!src/config/database.ts', // Database config (tested via integration)
|
|
],
|
|
|
|
// Coverage thresholds - TaskMaster standards
|
|
coverageThreshold: {
|
|
global: {
|
|
branches: 70,
|
|
functions: 80,
|
|
lines: 80,
|
|
statements: 80,
|
|
},
|
|
// Higher standards for critical business logic
|
|
'./src/utils/': {
|
|
branches: 85,
|
|
functions: 90,
|
|
lines: 90,
|
|
statements: 90,
|
|
},
|
|
'./src/middleware/': {
|
|
branches: 80,
|
|
functions: 85,
|
|
lines: 85,
|
|
statements: 85,
|
|
},
|
|
},
|
|
|
|
// Setup files
|
|
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
|
|
|
|
// Global teardown to prevent worker process leaks
|
|
globalTeardown: '<rootDir>/tests/teardown.ts',
|
|
|
|
// Module path mapping (if needed)
|
|
moduleNameMapper: {
|
|
'^@/(.*)$': '<rootDir>/src/$1',
|
|
},
|
|
|
|
// Clear mocks between tests
|
|
clearMocks: true,
|
|
|
|
// Restore mocks after each test
|
|
restoreMocks: true,
|
|
|
|
// Global test timeout
|
|
testTimeout: 10000,
|
|
|
|
// Projects for different test types
|
|
projects: [
|
|
// Unit tests - for pure functions only
|
|
{
|
|
displayName: 'unit',
|
|
testMatch: ['<rootDir>/src/**/*.test.ts'],
|
|
testPathIgnorePatterns: ['.*\\.integration\\.test\\.ts$', '/tests/'],
|
|
preset: 'ts-jest',
|
|
testEnvironment: 'node',
|
|
collectCoverageFrom: [
|
|
'src/**/*.ts',
|
|
'!src/**/*.d.ts',
|
|
'!src/**/*.test.ts',
|
|
'!src/**/*.integration.test.ts',
|
|
],
|
|
coverageThreshold: {
|
|
global: {
|
|
branches: 70,
|
|
functions: 80,
|
|
lines: 80,
|
|
statements: 80,
|
|
},
|
|
},
|
|
},
|
|
// Integration tests - real database/services
|
|
{
|
|
displayName: 'integration',
|
|
testMatch: [
|
|
'<rootDir>/src/**/*.integration.test.ts',
|
|
'<rootDir>/tests/integration/**/*.test.ts',
|
|
],
|
|
preset: 'ts-jest',
|
|
testEnvironment: 'node',
|
|
setupFilesAfterEnv: ['<rootDir>/tests/setup/integration.ts'],
|
|
testTimeout: 10000,
|
|
},
|
|
// E2E tests - full workflows
|
|
{
|
|
displayName: 'e2e',
|
|
testMatch: ['<rootDir>/tests/e2e/**/*.test.ts'],
|
|
preset: 'ts-jest',
|
|
testEnvironment: 'node',
|
|
setupFilesAfterEnv: ['<rootDir>/tests/setup/e2e.ts'],
|
|
testTimeout: 30000,
|
|
},
|
|
],
|
|
|
|
// Verbose output for better debugging
|
|
verbose: true,
|
|
|
|
// Run projects sequentially to avoid conflicts
|
|
maxWorkers: 1,
|
|
|
|
// Enable watch mode plugins
|
|
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
|
|
};
|
|
```
|
|
|
|
**Step 3: Update package.json Scripts**
|
|
|
|
Add these scripts to your `package.json`:
|
|
|
|
```json
|
|
{
|
|
"scripts": {
|
|
"test": "jest",
|
|
"test:watch": "jest --watch",
|
|
"test:coverage": "jest --coverage",
|
|
"test:unit": "jest --selectProjects unit",
|
|
"test:integration": "jest --selectProjects integration",
|
|
"test:e2e": "jest --selectProjects e2e",
|
|
"test:ci": "jest --ci --coverage --watchAll=false"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Step 4: Create Test Setup Files**
|
|
|
|
Create essential test setup files:
|
|
|
|
```typescript
|
|
// tests/setup.ts - Global setup
|
|
import { jest } from '@jest/globals';
|
|
|
|
// Global test configuration
|
|
beforeAll(() => {
|
|
// Set test timeout
|
|
jest.setTimeout(10000);
|
|
});
|
|
|
|
afterEach(() => {
|
|
// Clean up mocks after each test
|
|
jest.clearAllMocks();
|
|
});
|
|
```
|
|
|
|
```typescript
|
|
// tests/setup/integration.ts - Integration test setup
|
|
import { PrismaClient } from '@prisma/client';
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
beforeAll(async () => {
|
|
// Connect to test database
|
|
await prisma.$connect();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
// Cleanup and disconnect
|
|
await prisma.$disconnect();
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
// Clean test data before each test
|
|
// Add your cleanup logic here
|
|
});
|
|
```
|
|
|
|
```typescript
|
|
// tests/teardown.ts - Global teardown
|
|
export default async () => {
|
|
// Global cleanup after all tests
|
|
console.log('Global test teardown complete');
|
|
};
|
|
```
|
|
|
|
**Step 5: Create Initial Test Structure**
|
|
|
|
```bash
|
|
# Create test directories
|
|
mkdir -p tests/{setup,fixtures,unit,integration,e2e}
|
|
mkdir -p tests/unit/src/{utils,services,middleware}
|
|
|
|
# Create sample test fixtures
|
|
mkdir tests/fixtures
|
|
```
|
|
|
|
### **Generic Testing Framework Setup (Any Language)**
|
|
|
|
#### **Framework Selection Guide**
|
|
|
|
**Python Projects:**
|
|
- **pytest**: Recommended for most Python projects
|
|
- **unittest**: Built-in, suitable for simple projects
|
|
- **Coverage**: Use `coverage.py` for code coverage
|
|
|
|
```bash
|
|
# Python setup example
|
|
pip install pytest pytest-cov
|
|
echo "[tool:pytest]" > pytest.ini
|
|
echo "testpaths = tests" >> pytest.ini
|
|
echo "addopts = --cov=src --cov-report=html --cov-report=term" >> pytest.ini
|
|
```
|
|
|
|
**Go Projects:**
|
|
- **Built-in testing**: Use Go's built-in `testing` package
|
|
- **Coverage**: Built-in with `go test -cover`
|
|
|
|
```bash
|
|
# Go setup example
|
|
go mod init your-project
|
|
mkdir -p tests
|
|
# Tests are typically *_test.go files alongside source
|
|
```
|
|
|
|
**Rust Projects:**
|
|
- **Built-in testing**: Use Rust's built-in test framework
|
|
- **cargo-tarpaulin**: For coverage analysis
|
|
|
|
```bash
|
|
# Rust setup example
|
|
cargo new your-project
|
|
cd your-project
|
|
cargo install cargo-tarpaulin # For coverage
|
|
```
|
|
|
|
**Java Projects:**
|
|
- **JUnit 5**: Modern testing framework
|
|
- **Maven/Gradle**: Build tools with testing integration
|
|
|
|
```xml
|
|
<!-- Maven pom.xml example -->
|
|
<dependency>
|
|
<groupId>org.junit.jupiter</groupId>
|
|
<artifactId>junit-jupiter</artifactId>
|
|
<version>5.9.2</version>
|
|
<scope>test</scope>
|
|
</dependency>
|
|
```
|
|
|
|
#### **Universal Testing Principles**
|
|
|
|
**Coverage Standards (Adapt to Your Language):**
|
|
- **Global Minimum**: 70-80% line coverage
|
|
- **Critical Code**: 85-90% coverage
|
|
- **New Features**: Must meet or exceed standards
|
|
- **Legacy Code**: Gradual improvement strategy
|
|
|
|
**Test Organization:**
|
|
- **Unit Tests**: Fast, isolated, no external dependencies
|
|
- **Integration Tests**: Test component interactions
|
|
- **E2E Tests**: Test complete user workflows
|
|
- **Performance Tests**: Load and stress testing (if applicable)
|
|
|
|
**Naming Conventions:**
|
|
- **Test Files**: `*.test.*`, `*_test.*`, or language-specific patterns
|
|
- **Test Functions**: Descriptive names (e.g., `should_return_error_for_invalid_input`)
|
|
- **Test Directories**: Organized by test type and mirroring source structure
|
|
|
|
#### **TaskMaster Integration for Any Framework**
|
|
|
|
**Document Testing Setup in Subtasks:**
|
|
```bash
|
|
# Update subtask with testing framework setup
|
|
task-master update-subtask --id=X.Y --prompt="Testing framework setup:
|
|
- Installed [Framework Name] with coverage support
|
|
- Configured [Coverage Tool] with thresholds: 80% lines, 70% branches
|
|
- Created test directory structure: unit/, integration/, e2e/
|
|
- Added test scripts to build configuration
|
|
- All setup tests passing"
|
|
```
|
|
|
|
**Testing Framework Verification:**
|
|
```bash
|
|
# Verify setup works
|
|
[test-command] # e.g., npm test, pytest, go test, cargo test
|
|
|
|
# Check coverage reporting
|
|
[coverage-command] # e.g., npm run test:coverage
|
|
|
|
# Update task with verification
|
|
task-master update-subtask --id=X.Y --prompt="Testing framework verified:
|
|
- Sample tests running successfully
|
|
- Coverage reporting functional
|
|
- CI/CD integration ready
|
|
- Ready to begin TDD workflow"
|
|
```
|
|
|
|
## **Test-Driven Development (TDD) Integration**
|
|
|
|
### **Core TDD Cycle with Jest**
|
|
```bash
|
|
# 1. Start development with watch mode
|
|
npm run test:watch
|
|
|
|
# 2. Write failing test first
|
|
# Create test file: src/utils/newFeature.test.ts
|
|
# Write test that describes expected behavior
|
|
|
|
# 3. Implement minimum code to make test pass
|
|
# 4. Refactor while keeping tests green
|
|
# 5. Add edge cases and error scenarios
|
|
```
|
|
|
|
### **TDD Workflow Per Subtask**
|
|
```bash
|
|
# When starting a new subtask:
|
|
task-master set-status --id=4.1 --status=in-progress
|
|
|
|
# Begin TDD cycle:
|
|
npm run test:watch # Keep running during development
|
|
|
|
# Document TDD progress in subtask:
|
|
task-master update-subtask --id=4.1 --prompt="TDD Progress:
|
|
- Written 3 failing tests for core functionality
|
|
- Implemented basic feature, tests now passing
|
|
- Adding edge case tests for error handling"
|
|
|
|
# Complete subtask with test summary:
|
|
task-master update-subtask --id=4.1 --prompt="Implementation complete:
|
|
- Feature implemented with 8 unit tests
|
|
- Coverage: 95% statements, 88% branches
|
|
- All tests passing, TDD cycle complete"
|
|
```
|
|
|
|
## **Testing Commands & Usage**
|
|
|
|
### **Development Commands**
|
|
```bash
|
|
# Primary development command - use during coding
|
|
npm run test:watch # Watch mode with Jest
|
|
npm run test:watch -- --testNamePattern="auth" # Watch specific tests
|
|
|
|
# Targeted testing during development
|
|
npm run test:unit # Run only unit tests
|
|
npm run test:unit -- --coverage # Unit tests with coverage
|
|
|
|
# Integration testing when APIs are ready
|
|
npm run test:integration # Run integration tests
|
|
npm run test:integration -- --detectOpenHandles # Debug hanging tests
|
|
|
|
# End-to-end testing for workflows
|
|
npm run test:e2e # Run E2E tests
|
|
npm run test:e2e -- --timeout=30000 # Extended timeout for E2E
|
|
```
|
|
|
|
### **Quality Assurance Commands**
|
|
```bash
|
|
# Full test suite with coverage (before commits)
|
|
npm run test:coverage # Complete coverage analysis
|
|
|
|
# All tests (CI/CD pipeline)
|
|
npm test # Run all test projects
|
|
|
|
# Specific test file execution
|
|
npm test -- auth.test.ts # Run specific test file
|
|
npm test -- --testNamePattern="should handle errors" # Run specific tests
|
|
```
|
|
|
|
## **Test Implementation Patterns**
|
|
|
|
### **Unit Test Development**
|
|
```typescript
|
|
// ✅ DO: Follow established patterns from auth.test.ts
|
|
describe('FeatureName', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
// Setup mocks with proper typing
|
|
});
|
|
|
|
describe('functionName', () => {
|
|
it('should handle normal case', () => {
|
|
// Test implementation with specific assertions
|
|
});
|
|
|
|
it('should throw error for invalid input', async () => {
|
|
// Error scenario testing
|
|
await expect(functionName(invalidInput))
|
|
.rejects.toThrow('Specific error message');
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
### **Integration Test Development**
|
|
```typescript
|
|
// ✅ DO: Use supertest for API endpoint testing
|
|
import request from 'supertest';
|
|
import { app } from '../../src/app';
|
|
|
|
describe('POST /api/auth/register', () => {
|
|
beforeEach(async () => {
|
|
await integrationTestUtils.cleanupTestData();
|
|
});
|
|
|
|
it('should register user successfully', async () => {
|
|
const userData = createTestUser();
|
|
|
|
const response = await request(app)
|
|
.post('/api/auth/register')
|
|
.send(userData)
|
|
.expect(201);
|
|
|
|
expect(response.body).toMatchObject({
|
|
id: expect.any(String),
|
|
email: userData.email
|
|
});
|
|
|
|
// Verify database state
|
|
const user = await prisma.user.findUnique({
|
|
where: { email: userData.email }
|
|
});
|
|
expect(user).toBeTruthy();
|
|
});
|
|
});
|
|
```
|
|
|
|
### **E2E Test Development**
|
|
```typescript
|
|
// ✅ DO: Test complete user workflows
|
|
describe('User Authentication Flow', () => {
|
|
it('should complete registration → login → protected access', async () => {
|
|
// Step 1: Register
|
|
const userData = createTestUser();
|
|
await request(app)
|
|
.post('/api/auth/register')
|
|
.send(userData)
|
|
.expect(201);
|
|
|
|
// Step 2: Login
|
|
const loginResponse = await request(app)
|
|
.post('/api/auth/login')
|
|
.send({ email: userData.email, password: userData.password })
|
|
.expect(200);
|
|
|
|
const { token } = loginResponse.body;
|
|
|
|
// Step 3: Access protected resource
|
|
await request(app)
|
|
.get('/api/profile')
|
|
.set('Authorization', `Bearer ${token}`)
|
|
.expect(200);
|
|
}, 30000); // Extended timeout for E2E
|
|
});
|
|
```
|
|
|
|
## **Mocking & Test Utilities**
|
|
|
|
### **Established Mocking Patterns**
|
|
```typescript
|
|
// ✅ DO: Use established bcrypt mocking pattern
|
|
jest.mock('bcrypt');
|
|
import bcrypt from 'bcrypt';
|
|
const mockHash = bcrypt.hash as jest.MockedFunction<typeof bcrypt.hash>;
|
|
const mockCompare = bcrypt.compare as jest.MockedFunction<typeof bcrypt.compare>;
|
|
|
|
// ✅ DO: Use Prisma mocking for unit tests
|
|
jest.mock('@prisma/client', () => ({
|
|
PrismaClient: jest.fn().mockImplementation(() => ({
|
|
user: {
|
|
create: jest.fn(),
|
|
findUnique: jest.fn(),
|
|
},
|
|
$connect: jest.fn(),
|
|
$disconnect: jest.fn(),
|
|
})),
|
|
}));
|
|
```
|
|
|
|
### **Test Fixtures Usage**
|
|
```typescript
|
|
// ✅ DO: Use centralized test fixtures
|
|
import { createTestUser, adminUser, invalidUser } from '../fixtures/users';
|
|
|
|
describe('User Service', () => {
|
|
it('should handle admin user creation', async () => {
|
|
const userData = createTestUser(adminUser);
|
|
// Test implementation
|
|
});
|
|
|
|
it('should reject invalid user data', async () => {
|
|
const userData = createTestUser(invalidUser);
|
|
// Error testing
|
|
});
|
|
});
|
|
```
|
|
|
|
## **Coverage Standards & Monitoring**
|
|
|
|
### **Coverage Thresholds**
|
|
- **Global Standards**: 80% lines/functions, 70% branches
|
|
- **Critical Code**: 90% utils, 85% middleware
|
|
- **New Features**: Must meet or exceed global thresholds
|
|
- **Legacy Code**: Gradual improvement with each change
|
|
|
|
### **Coverage Reporting & Analysis**
|
|
```bash
|
|
# Generate coverage reports
|
|
npm run test:coverage
|
|
|
|
# View detailed HTML report
|
|
open coverage/lcov-report/index.html
|
|
|
|
# Coverage files generated:
|
|
# - coverage/lcov-report/index.html # Detailed HTML report
|
|
# - coverage/lcov.info # LCOV format for IDE integration
|
|
# - coverage/coverage-final.json # JSON format for tooling
|
|
```
|
|
|
|
### **Coverage Quality Checks**
|
|
```typescript
|
|
// ✅ DO: Test all code paths
|
|
describe('validateInput', () => {
|
|
it('should return true for valid input', () => {
|
|
expect(validateInput('valid')).toBe(true);
|
|
});
|
|
|
|
it('should return false for various invalid inputs', () => {
|
|
expect(validateInput('')).toBe(false); // Empty string
|
|
expect(validateInput(null)).toBe(false); // Null value
|
|
expect(validateInput(undefined)).toBe(false); // Undefined
|
|
});
|
|
|
|
it('should throw for unexpected input types', () => {
|
|
expect(() => validateInput(123)).toThrow('Invalid input type');
|
|
});
|
|
});
|
|
```
|
|
|
|
## **Testing During Development Phases**
|
|
|
|
### **Feature Development Phase**
|
|
```bash
|
|
# 1. Start feature development
|
|
task-master set-status --id=X.Y --status=in-progress
|
|
|
|
# 2. Begin TDD cycle
|
|
npm run test:watch
|
|
|
|
# 3. Document test progress in subtask
|
|
task-master update-subtask --id=X.Y --prompt="Test development:
|
|
- Created test file with 5 failing tests
|
|
- Implemented core functionality
|
|
- Tests passing, adding error scenarios"
|
|
|
|
# 4. Verify coverage before completion
|
|
npm run test:coverage
|
|
|
|
# 5. Update subtask with final test status
|
|
task-master update-subtask --id=X.Y --prompt="Testing complete:
|
|
- 12 unit tests with full coverage
|
|
- All edge cases and error scenarios covered
|
|
- Ready for integration testing"
|
|
```
|
|
|
|
### **Integration Testing Phase**
|
|
```bash
|
|
# After API endpoints are implemented
|
|
npm run test:integration
|
|
|
|
# Update integration test templates
|
|
# Replace placeholder tests with real endpoint calls
|
|
|
|
# Document integration test results
|
|
task-master update-subtask --id=X.Y --prompt="Integration tests:
|
|
- Updated auth endpoint tests
|
|
- Database integration verified
|
|
- All HTTP status codes and responses tested"
|
|
```
|
|
|
|
### **Pre-Commit Testing Phase**
|
|
```bash
|
|
# Before committing code
|
|
npm run test:coverage # Verify all tests pass with coverage
|
|
npm run test:unit # Quick unit test verification
|
|
npm run test:integration # Integration test verification (if applicable)
|
|
|
|
# Commit pattern for test updates
|
|
git add tests/ src/**/*.test.ts
|
|
git commit -m "test(task-X): Add comprehensive tests for Feature Y
|
|
|
|
- Unit tests with 95% coverage (exceeds 90% threshold)
|
|
- Integration tests for API endpoints
|
|
- Test fixtures for data generation
|
|
- Proper mocking patterns established
|
|
|
|
Task X: Feature Y - Testing complete"
|
|
```
|
|
|
|
## **Error Handling & Debugging**
|
|
|
|
### **Test Debugging Techniques**
|
|
```typescript
|
|
// ✅ DO: Use test utilities for debugging
|
|
import { testUtils } from '../setup';
|
|
|
|
it('should debug complex operation', () => {
|
|
testUtils.withConsole(() => {
|
|
// Console output visible only for this test
|
|
console.log('Debug info:', complexData);
|
|
service.complexOperation();
|
|
});
|
|
});
|
|
|
|
// ✅ DO: Use proper async debugging
|
|
it('should handle async operations', async () => {
|
|
const promise = service.asyncOperation();
|
|
|
|
// Test intermediate state
|
|
expect(service.isProcessing()).toBe(true);
|
|
|
|
const result = await promise;
|
|
expect(result).toBe('expected');
|
|
expect(service.isProcessing()).toBe(false);
|
|
});
|
|
```
|
|
|
|
### **Common Test Issues & Solutions**
|
|
```bash
|
|
# Hanging tests (common with database connections)
|
|
npm run test:integration -- --detectOpenHandles
|
|
|
|
# Memory leaks in tests
|
|
npm run test:unit -- --logHeapUsage
|
|
|
|
# Slow tests identification
|
|
npm run test:coverage -- --verbose
|
|
|
|
# Mock not working properly
|
|
# Check: mock is declared before imports
|
|
# Check: jest.clearAllMocks() in beforeEach
|
|
# Check: TypeScript typing is correct
|
|
```
|
|
|
|
## **Continuous Integration Integration**
|
|
|
|
### **CI/CD Pipeline Testing**
|
|
```yaml
|
|
# Example GitHub Actions integration
|
|
- name: Run tests
|
|
run: |
|
|
npm ci
|
|
npm run test:coverage
|
|
|
|
- name: Upload coverage reports
|
|
uses: codecov/codecov-action@v3
|
|
with:
|
|
file: ./coverage/lcov.info
|
|
```
|
|
|
|
### **Pre-commit Hooks**
|
|
```bash
|
|
# Setup pre-commit testing (recommended)
|
|
# In package.json scripts:
|
|
"pre-commit": "npm run test:unit && npm run test:integration"
|
|
|
|
# Husky integration example:
|
|
npx husky add .husky/pre-commit "npm run test:unit"
|
|
```
|
|
|
|
## **Test Maintenance & Evolution**
|
|
|
|
### **Adding Tests for New Features**
|
|
1. **Create test file** alongside source code or in `tests/unit/`
|
|
2. **Follow established patterns** from `src/utils/auth.test.ts`
|
|
3. **Use existing fixtures** from `tests/fixtures/`
|
|
4. **Apply proper mocking** patterns for dependencies
|
|
5. **Meet coverage thresholds** for the module
|
|
|
|
### **Updating Integration/E2E Tests**
|
|
1. **Update templates** in `tests/integration/` when APIs change
|
|
2. **Modify E2E workflows** in `tests/e2e/` for new user journeys
|
|
3. **Update test fixtures** for new data requirements
|
|
4. **Maintain database cleanup** utilities
|
|
|
|
### **Test Performance Optimization**
|
|
- **Parallel execution**: Jest runs tests in parallel by default
|
|
- **Test isolation**: Use proper setup/teardown for independence
|
|
- **Mock optimization**: Mock heavy dependencies appropriately
|
|
- **Database efficiency**: Use transaction rollbacks where possible
|
|
|
|
---
|
|
|
|
**Key References:**
|
|
- [Testing Standards](mdc:.cursor/rules/tests.mdc)
|
|
- [Git Workflow](mdc:.cursor/rules/git_workflow.mdc)
|
|
- [Development Workflow](mdc:.cursor/rules/dev_workflow.mdc)
|
|
- [Jest Configuration](mdc:jest.config.js) |