You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

714 lines
20 KiB

```json
{
"coaching_level": "standard",
"socratic_max_questions": 2,
"verbosity": "normal",
"timebox_minutes": null,
"format_enforcement": "strict"
}
```
# Unit Testing & Mocks — Universal Development Guide
**Author**: Matthew Raymer
**Date**: 2025-08-21T09:40Z
**Status**: 🎯 **ACTIVE** - Comprehensive testing standards
## Overview
This guide establishes **unified unit testing and mocking standards** for Vue
and React projects, ensuring consistent, maintainable test patterns using
Vitest, JSDOM, and component testing utilities. All tests follow F.I.R.S.T.
principles with comprehensive mock implementations.
## Scope and Goals
**Scope**: Applies to all unit tests, mock implementations, and testing
infrastructure in any project workspace.
**Goal**: One consistent testing approach with comprehensive mock coverage,
100% test coverage for simple components, and maintainable test patterns.
## Non‑Negotiables (DO THIS)
- **MUST** use Vitest + JSDOM for unit testing; **DO NOT** use Jest or other
frameworks
- **MUST** implement comprehensive mock levels (Simple, Standard, Complex) for
all components
- **MUST** achieve 100% line coverage for simple components (<100 lines)
- **MUST** follow F.I.R.S.T. principles: Fast, Independent, Repeatable,
Self-validating, Timely
- **MUST** use centralized test utilities from `src/test/utils/`
## Testing Infrastructure
### **Core Technologies**
- **Vitest**: Fast unit testing framework with Vue/React support
- **JSDOM**: Browser-like environment for Node.js testing
- **@vue/test-utils**: Vue component testing utilities
- **TypeScript**: Full type safety for tests and mocks
### **Configuration Files**
- `vitest.config.ts` - Vitest configuration with JSDOM environment
- `src/test/setup.ts` - Global test configuration and mocks
- `src/test/utils/` - Centralized testing utilities
### **Global Mocks**
```typescript
// Required browser API mocks
ResizeObserver, IntersectionObserver, localStorage, sessionStorage,
matchMedia, console methods (reduced noise)
```
## Mock Implementation Standards
### **Mock Architecture Levels**
#### **1. Simple Mock (Basic Testing)**
```typescript
// Minimal interface compliance
class ComponentSimpleMock {
// Essential props and methods only
// Basic computed properties
// No complex behavior
}
```
#### **2. Standard Mock (Integration Testing)**
```typescript
// Full interface compliance
class ComponentStandardMock {
// All props, methods, computed properties
// Realistic behavior simulation
// Helper methods for test scenarios
}
```
#### **3. Complex Mock (Advanced Testing)**
```typescript
// Enhanced testing capabilities
class ComponentComplexMock extends ComponentStandardMock {
// Mock event listeners
// Performance testing hooks
// Error scenario simulation
// Accessibility testing support
}
```
### **Mock Component Structure**
Each mock component provides:
- Same interface as original component
- Simplified behavior for testing
- Helper methods for test scenarios
- Computed properties for state validation
### **Enhanced Mock Architecture Validation** ✅ **NEW**
The three-tier mock architecture (Simple/Standard/Complex) has been successfully
validated through real-world implementation:
#### **Tier 1: Simple Mock**
```typescript
class ComponentSimpleMock {
// Basic interface compliance
// Minimal implementation for simple tests
// Fast execution for high-volume testing
}
```
#### **Tier 2: Standard Mock**
```typescript
class ComponentStandardMock {
// Full interface implementation
// Realistic behavior simulation
// Helper methods for common scenarios
}
```
#### **Tier 3: Complex Mock**
```typescript
class ComponentComplexMock {
// Enhanced testing capabilities
// Validation and error simulation
// Advanced state management
// Performance testing support
}
```
#### **Factory Function Pattern**
```typescript
// Specialized factory functions for common use cases
export const createComponentMock = () =>
new ComponentStandardMock({ type: 'default' })
export const createSpecializedMock = () =>
new ComponentComplexMock({
options: { filter: 'active', sort: 'name' }
})
```
### **Mock Usage Examples**
```typescript
export default class ComponentMock {
// Props simulation
props: ComponentProps
// Computed properties
get computedProp(): boolean {
return this.props.condition
}
// Mock methods
mockMethod(): void {
// Simulate behavior
}
// Helper methods
getCssClasses(): string[] {
return ['base-class', 'conditional-class']
}
}
```
## Test Patterns
### **Component Testing Template**
```typescript
import { mount } from '@vue/test-utils'
import { createComponentWrapper } from '@/test/utils/componentTestUtils'
describe('ComponentName', () => {
let wrapper: VueWrapper<any>
const mountComponent = (props = {}) => {
return mount(ComponentName, {
props: { ...defaultProps, ...props }
})
}
beforeEach(() => {
wrapper = mountComponent()
})
afterEach(() => {
wrapper?.unmount()
})
describe('Component Rendering', () => {
it('should render correctly', () => {
expect(wrapper.exists()).toBe(true)
})
})
})
```
### **Mock Integration Testing**
```typescript
import ComponentMock from '@/test/__mocks__/Component.mock'
it('should work with mock component', () => {
const mock = new ComponentMock()
expect(mock.shouldShow).toBe(true)
})
```
### **Event Testing**
```typescript
it('should emit event when triggered', async () => {
await wrapper.find('button').trigger('click')
expect(wrapper.emitted('event-name')).toBeTruthy()
})
```
### **Prop Validation**
```typescript
it('should accept all required props', () => {
wrapper = mountComponent()
expect(wrapper.vm.propName).toBeDefined()
})
```
## Test Categories
### **Required Coverage Areas**
1. **Component Rendering** - Existence, structure, conditional rendering
2. **Component Styling** - CSS classes, responsive design, framework
integration
3. **Component Props** - Required/optional prop handling, type validation
4. **User Interactions** - Click events, form inputs, keyboard navigation
5. **Component Methods** - Method existence, functionality, return values
6. **Edge Cases** - Empty/null props, rapid interactions, state changes
7. **Error Handling** - Invalid props, malformed data, graceful degradation
8. **Accessibility** - Semantic HTML, ARIA attributes, keyboard navigation
9. **Performance** - Render time, memory leaks, rapid re-renders
10. **Integration** - Parent-child interaction, dependency injection
### **Error Handling Testing**
```typescript
const invalidPropCombinations = [
null, undefined, 'invalid', 0, -1, {}, [],
() => {}, NaN, Infinity
]
invalidPropCombinations.forEach(invalidProp => {
it(`should handle invalid prop: ${invalidProp}`, () => {
wrapper = mountComponent({ prop: invalidProp })
expect(wrapper.exists()).toBe(true)
// Verify graceful handling
})
})
```
## Centralized Test Utilities
### **Component Testing Utilities**
```typescript
import {
createComponentWrapper,
createTestDataFactory,
testLifecycleEvents,
testComputedProperties,
testWatchers,
testPerformance,
testAccessibility,
testErrorHandling
} from '@/test/utils/componentTestUtils'
// Component wrapper factory
const wrapperFactory = createComponentWrapper(
Component,
defaultProps,
globalOptions
)
// Test data factory
const createTestProps = createTestDataFactory({
prop1: 'default',
prop2: true
})
```
### **Test Data Factories**
```typescript
import {
createMockContact,
createMockProject,
createMockUser
} from '@/test/factories/contactFactory'
const testContact = createMockContact({
id: 'test-1',
name: 'Test User'
})
```
## Coverage Standards
### **Coverage Standards by Component Complexity**
| Component Complexity | Line Coverage | Branch Coverage | Function Coverage |
|---------------------|---------------|-----------------|-------------------|
| **Simple (<100 lines)** | 100% | 100% | 100% |
| **Medium (100-300 lines)** | 95% | 90% | 100% |
| **Complex (300+ lines)** | 90% | 85% | 100% |
### **Current Coverage Status**
- **Simple Components**: Ready for implementation
- **Medium Components**: Ready for expansion
- **Complex Components**: Ready for expansion
- **Overall Coverage**: Varies by project implementation
### **Test Infrastructure Requirements**
- **Test Framework**: Vitest + JSDOM recommended
- **Component Testing**: Vue Test Utils integration
- **Mock Architecture**: Three-tier system (Simple/Standard/Complex)
- **Test Categories**: 10 comprehensive categories
- **Coverage Goals**: 100% for simple components, 90%+ for complex
## Testing Philosophy
### **Defensive Programming Validation**
- **Real-world edge case protection** against invalid API responses
- **System stability assurance** preventing cascading failures
- **Production readiness** ensuring graceful error handling
### **Comprehensive Error Scenarios**
- **Invalid input testing** with 10+ different invalid prop combinations
- **Malformed data testing** with various corrupted data structures
- **Extreme value testing** with boundary conditions and edge cases
- **Concurrent error testing** with rapid state changes
### **Benefits Beyond Coverage**
1. **Defensive Programming Validation** - Components handle unexpected data
gracefully
2. **Real-World Resilience** - Tested against actual failure scenarios
3. **Developer Confidence** - Safe to refactor and extend components
4. **Production Stability** - Reduced support tickets and user complaints
## Advanced Testing Patterns
### **Performance Testing** ✅ **NEW**
- Render time benchmarks
- Memory leak detection
- Rapid re-render efficiency
- Component cleanup validation
#### **Advanced Performance Testing Patterns**
```typescript
// Memory leak detection
it('should not cause memory leaks during prop changes', async () => {
const initialMemory = (performance as any).memory?.usedJSHeapSize || 0
for (let i = 0; i < 100; i++) {
await wrapper.setProps({
queryParams: { iteration: i.toString() }
})
}
const finalMemory = (performance as any).memory?.usedJSHeapSize || 0
const memoryIncrease = finalMemory - initialMemory
// Memory increase should be reasonable (less than 10MB)
expect(memoryIncrease).toBeLessThan(10 * 1024 * 1024)
})
// Rapid re-render efficiency
it('should handle rapid re-renders efficiently', async () => {
const start = performance.now()
for (let i = 0; i < 50; i++) {
await wrapper.setProps({
entityType: i % 2 === 0 ? 'type1' : 'type2',
queryParams: { index: i.toString() }
})
}
const end = performance.now()
expect(end - start).toBeLessThan(500) // 500ms threshold for 50 updates
})
```
### **Snapshot Testing** ✅ **NEW**
- DOM structure validation
- CSS class regression detection
- Accessibility attribute consistency
- Visual structure verification
#### **Snapshot Testing Implementation**
```typescript
describe('Snapshot Testing', () => {
it('should maintain consistent DOM structure', () => {
expect(wrapper.html()).toMatchSnapshot()
})
it('should maintain consistent structure with different props', () => {
wrapper = mountComponent({ type: 'alternative' })
expect(wrapper.html()).toMatchSnapshot()
})
it('should maintain consistent structure with query params', () => {
wrapper = mountComponent({
queryParams: { filter: 'active', sort: 'name' }
})
expect(wrapper.html()).toMatchSnapshot()
})
})
```
### **Mock Integration Testing** ✅ **NEW**
- Mock component validation
- Factory function testing
- Mock behavior verification
- Integration with testing utilities
#### **Mock Integration Testing Patterns**
```typescript
describe('Mock Integration Testing', () => {
it('should work with simple mock', () => {
const mock = new ComponentSimpleMock()
expect(mock.navigationRoute).toEqual({
name: 'default',
query: {}
})
})
it('should work with standard mock', () => {
const mock = new ComponentStandardMock({
type: 'special',
name: 'test'
})
expect(mock.getType()).toBe('special')
expect(mock.getName()).toBe('test')
})
it('should work with complex mock', () => {
const mock = new ComponentComplexMock({
type: 'advanced',
options: { filter: 'active' }
})
expect(mock.isValidState()).toBe(true)
expect(mock.getValidationErrors()).toEqual([])
})
it('should work with factory functions', () => {
const defaultMock = createComponentMock()
const specializedMock = createSpecializedMock()
expect(defaultMock.getType()).toBe('default')
expect(specializedMock.getOptions()).toHaveProperty('filter')
})
})
```
## Project Implementation Tracking
### **Setting Up Project-Specific Tracking**
Each project should maintain its own tracking file to monitor testing progress
and coverage metrics. This keeps the universal MDC clean while providing a
template for project implementation.
#### **Recommended Project Tracking Structure**
```tree
src/test/
├── README.md # Testing documentation
├── PROJECT_COVERAGE_TRACKING.md # Project-specific progress tracking
├── __mocks__/ # Mock implementations
├── utils/ # Test utilities
└── [test files]
```
#### **Project Tracking File Template**
Create a `PROJECT_COVERAGE_TRACKING.md` file with:
- **Current Coverage Status**: Component-by-component breakdown
- **Implementation Progress**: Phase completion status
- **Test Infrastructure Status**: Framework setup and metrics
- **Next Steps**: Immediate priorities and long-term goals
- **Lessons Learned**: Project-specific insights and best practices
#### **Example Project Tracking Sections**
```markdown
# [Project Name] Testing Coverage Tracking
## Current Coverage Status
- Simple Components: X/Y at 100% coverage
- Medium Components: X/Y ready for expansion
- Complex Components: X/Y planned
## Implementation Progress
- Phase 1: Simple Components ✅ COMPLETE
- Phase 2: Medium Components 🔄 IN PROGRESS
- Phase 3: Complex Components 🔄 PLANNED
## Test Infrastructure Status
- Total Tests: X tests passing
- Test Files: X files
- Mock Files: X implementations
- Overall Coverage: X% (focused on simple components)
```
### **Integration with Universal MDC**
- **MDC provides**: Testing patterns, mock architecture, best practices
- **Project tracking provides**: Implementation status, coverage metrics,
progress
- **Separation ensures**: MDC remains reusable, project data stays local
- **Template approach**: Other projects can copy and adapt the structure
### **Benefits of This Approach**
1. **Universal Reusability**: MDC works for any project
2. **Project Visibility**: Clear tracking of implementation progress
3. **Template Reuse**: Easy to set up tracking in new projects
4. **Clean Separation**: No project data polluting universal guidance
5. **Scalability**: Multiple projects can use the same MDC
## Best Practices
### **Test Organization**
1. **Group related tests** using `describe` blocks
2. **Use descriptive test names** that explain the scenario
3. **Keep tests focused** on one specific behavior
4. **Use helper functions** for common setup
### **Mock Design**
1. **Maintain interface compatibility** with original components
2. **Provide helper methods** for common test scenarios
3. **Include computed properties** for state validation
4. **Document mock behavior** clearly
### **Coverage Goals**
1. **100% line coverage** for simple components
2. **100% branch coverage** for conditional logic
3. **100% function coverage** for all methods
4. **Edge case coverage** for error scenarios
### **Lessons Learned from Implementation** ✅ **NEW**
#### **1. Performance Testing Best Practices**
- **Memory leak detection**: Use `performance.memory.usedJSHeapSize` for
memory profiling
- **Render time benchmarking**: Set realistic thresholds (100ms for single
render, 500ms for 50 updates)
- **Rapid re-render testing**: Test with 50+ prop changes to ensure
stability
#### **2. Snapshot Testing Implementation**
- **DOM structure validation**: Use `toMatchSnapshot()` for consistent
structure verification
- **Prop variation testing**: Test snapshots with different prop combinations
- **Regression prevention**: Snapshots catch unexpected DOM changes
#### **3. Mock Integration Validation**
- **Mock self-testing**: Test that mocks work correctly with testing
utilities
- **Factory function testing**: Validate specialized factory functions
- **Mock behavior verification**: Ensure mocks simulate real component
behavior
#### **4. Edge Case Coverage**
- **Null/undefined handling**: Test with `null as any` and `undefined`
props
- **Extreme values**: Test with very long strings and large numbers
- **Rapid changes**: Test with rapid prop changes to ensure stability
#### **5. Accessibility Testing**
- **Semantic structure**: Verify proper HTML elements and hierarchy
- **Component attributes**: Check component-specific attributes
- **Text content**: Validate text content and trimming
## Future Improvements
### **Implemented Enhancements**
1. ✅ **Error handling** - Component error states and exception handling
2. ✅ **Performance testing** - Render time benchmarks and memory leak
detection
3. ✅ **Integration testing** - Parent-child component interaction and
dependency injection
4. ✅ **Snapshot testing** - DOM structure validation and CSS class
regression detection
5. ✅ **Accessibility compliance** - ARIA attributes and semantic structure
validation
### **Future Enhancements**
1. **Visual regression testing** - Automated UI consistency checks
2. **Cross-browser compatibility** testing
3. **Service layer integration** testing
4. **End-to-end component** testing
5. **Advanced performance** profiling
### **Coverage Expansion**
1. **Medium complexity components** (100-300 lines)
2. **Complex components** (300+ lines)
3. **Service layer testing**
4. **Utility function testing**
5. **API integration testing**
## Troubleshooting
### **Common Issues**
1. **Import errors**: Check path aliases in `vitest.config.ts`
2. **Mock not found**: Verify mock file exists and exports correctly
3. **Test failures**: Check for timing issues with async operations
4. **Coverage gaps**: Add tests for uncovered code paths
### **Debug Tips**
1. **Use `console.log`** in tests for debugging
2. **Check test output** for detailed error messages
3. **Verify component props** are being passed correctly
4. **Test one assertion at a time** to isolate issues
---
**Status**: Active testing standards
**Priority**: High
**Estimated Effort**: Ongoing reference
**Dependencies**: Vitest, JSDOM, Vue Test Utils
**Stakeholders**: Development team, QA team
## Competence Hooks
- *Why this works*: Three-tier mock architecture provides flexibility,
comprehensive test categories ensure thorough coverage, performance testing
catches real-world issues early
- *Common pitfalls*: Not testing mocks themselves, missing edge case
coverage, ignoring performance implications
- *Next skill unlock*: Implement medium complexity component testing with
established patterns
- *Teach-back*: Explain how the three-tier mock architecture supports
different testing needs
## Collaboration Hooks
- **Reviewers**: Testing team, component developers, architecture team
- **Sign-off checklist**: All simple components at 100% coverage, mock
utilities documented, test patterns established, coverage expansion plan
approved
## Assumptions & Limits
- Assumes Vue/React component architecture
- Requires Vitest + JSDOM testing environment
- Mock complexity scales with component complexity
- Performance testing requires browser-like environment
## References
- [Vitest Documentation](https://vitest.dev/)
- [Vue Test Utils](https://test-utils.vuejs.org/)
- [JSDOM](https://github.com/jsdom/jsdom)
- [Testing Best Practices](https://testing-library.com/docs/guiding-principles)
- **Sign-off checklist**: All simple components at 100% coverage, mock
utilities documented, test patterns established, coverage expansion plan
approved