mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 23:01:09 +02:00
Applied formatting to 1487+ files using pnpm format:write - TypeScript/JavaScript files - Svelte components - Astro pages - JSON configs - Markdown docs 13 files still need manual review (Astro JSX comments)
369 lines
8.2 KiB
Markdown
369 lines
8.2 KiB
Markdown
# Test Examples
|
|
|
|
This directory contains comprehensive example test files demonstrating best practices for testing different app types in the Manacore monorepo.
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
test-examples/
|
|
├── backend/ # NestJS backend examples
|
|
│ ├── example.controller.spec.ts
|
|
│ └── example.service.spec.ts
|
|
├── mobile/ # React Native mobile examples
|
|
│ ├── ExampleComponent.test.tsx
|
|
│ └── authService.test.ts
|
|
├── web/ # SvelteKit web examples
|
|
│ ├── Button.test.ts
|
|
│ └── page.server.test.ts
|
|
├── shared/ # Shared package examples
|
|
│ └── format.test.ts
|
|
└── README.md
|
|
```
|
|
|
|
## Example Files Overview
|
|
|
|
### Backend Tests (NestJS)
|
|
|
|
#### `example.controller.spec.ts`
|
|
|
|
Demonstrates:
|
|
|
|
- Controller unit testing with mocked services
|
|
- Request/response handling
|
|
- Authentication/authorization testing
|
|
- Input validation
|
|
- Error handling
|
|
- CRUD operations
|
|
|
|
**Key Patterns**:
|
|
|
|
- Use `@nestjs/testing` TestingModule
|
|
- Mock all service dependencies
|
|
- Test both success and error paths
|
|
- Verify service method calls
|
|
|
|
#### `example.service.spec.ts`
|
|
|
|
Demonstrates:
|
|
|
|
- Service business logic testing
|
|
- Database operation mocking
|
|
- External API mocking
|
|
- Result pattern for error handling
|
|
- Data validation and sanitization
|
|
- Authorization checks
|
|
|
|
**Key Patterns**:
|
|
|
|
- Mock database and external services
|
|
- Test error handling thoroughly
|
|
- Verify data transformations
|
|
- Test edge cases and boundary conditions
|
|
|
|
### Mobile Tests (React Native)
|
|
|
|
#### `ExampleComponent.test.tsx`
|
|
|
|
Demonstrates:
|
|
|
|
- Component rendering
|
|
- User interactions (press, long press)
|
|
- State management
|
|
- Props validation
|
|
- Accessibility testing
|
|
- Performance testing
|
|
- Snapshot testing
|
|
|
|
**Key Patterns**:
|
|
|
|
- Use `@testing-library/react-native`
|
|
- Test user behavior, not implementation
|
|
- Verify accessibility props
|
|
- Test loading and error states
|
|
|
|
#### `authService.test.ts`
|
|
|
|
Demonstrates:
|
|
|
|
- Async service testing
|
|
- API call mocking with fetch
|
|
- Storage operations (SecureStore)
|
|
- Error handling (network, storage)
|
|
- Token management
|
|
- Integration with other services
|
|
|
|
**Key Patterns**:
|
|
|
|
- Mock global fetch
|
|
- Mock Expo modules (SecureStore)
|
|
- Test timeout scenarios
|
|
- Verify storage operations
|
|
|
|
### Web Tests (SvelteKit)
|
|
|
|
#### `Button.test.ts`
|
|
|
|
Demonstrates:
|
|
|
|
- Svelte 5 component testing
|
|
- Reactive state with runes ($state, $derived)
|
|
- User events
|
|
- Accessibility
|
|
- Variants and sizes
|
|
- Custom events
|
|
- Debouncing
|
|
|
|
**Key Patterns**:
|
|
|
|
- Use `@testing-library/svelte`
|
|
- Test Svelte 5 reactivity
|
|
- Verify accessibility attributes
|
|
- Test custom event dispatch
|
|
|
|
#### `page.server.test.ts`
|
|
|
|
Demonstrates:
|
|
|
|
- Server load function testing
|
|
- Form action testing
|
|
- Database mocking (PocketBase)
|
|
- Authentication checks
|
|
- Input validation and sanitization
|
|
- Authorization enforcement
|
|
- File upload handling
|
|
|
|
**Key Patterns**:
|
|
|
|
- Mock `locals` object
|
|
- Mock database client
|
|
- Test redirect behavior
|
|
- Verify authorization logic
|
|
- Sanitize user input
|
|
|
|
### Shared Package Tests
|
|
|
|
#### `format.test.ts`
|
|
|
|
Demonstrates:
|
|
|
|
- Pure function testing
|
|
- Parameterized tests (it.each)
|
|
- Edge case testing
|
|
- Boundary testing
|
|
- Property-based testing
|
|
- Security testing (XSS, SQL injection)
|
|
- Unicode and emoji handling
|
|
|
|
**Key Patterns**:
|
|
|
|
- Test with multiple inputs using `it.each`
|
|
- Cover edge cases thoroughly
|
|
- Test security vulnerabilities
|
|
- Verify type safety
|
|
|
|
## How to Use These Examples
|
|
|
|
### 1. Copy and Adapt
|
|
|
|
Copy the relevant example to your project and adapt it:
|
|
|
|
```bash
|
|
# Copy backend controller test
|
|
cp docs/test-examples/backend/example.controller.spec.ts \
|
|
apps/YOUR_PROJECT/apps/backend/src/your-module/__tests__/your.controller.spec.ts
|
|
|
|
# Update imports and names
|
|
```
|
|
|
|
### 2. Follow the Patterns
|
|
|
|
Each example demonstrates specific testing patterns:
|
|
|
|
- **AAA Pattern**: Arrange, Act, Assert
|
|
- **Descriptive Names**: Clear test descriptions
|
|
- **Mock Management**: Proper setup and cleanup
|
|
- **Error Testing**: Both happy and error paths
|
|
- **Edge Cases**: Boundary conditions and special cases
|
|
|
|
### 3. Customize for Your Needs
|
|
|
|
Adapt the examples to your specific requirements:
|
|
|
|
```typescript
|
|
// Example: Add project-specific mocks
|
|
jest.mock('@your-project/custom-service', () => ({
|
|
CustomService: {
|
|
doSomething: jest.fn(),
|
|
},
|
|
}));
|
|
```
|
|
|
|
### 4. Reference Best Practices
|
|
|
|
Each file includes comments explaining:
|
|
|
|
- Why specific patterns are used
|
|
- What to test and what not to test
|
|
- Common pitfalls to avoid
|
|
- Performance considerations
|
|
|
|
## Testing Principles Demonstrated
|
|
|
|
### 1. Test Behavior, Not Implementation
|
|
|
|
```typescript
|
|
// ✅ Good - Testing behavior
|
|
it('should display error message when login fails', async () => {
|
|
await userEvent.click(loginButton);
|
|
expect(screen.getByText('Invalid credentials')).toBeVisible();
|
|
});
|
|
|
|
// ❌ Bad - Testing implementation
|
|
it('should set isLoading to false after login', async () => {
|
|
await userEvent.click(loginButton);
|
|
expect(component.state.isLoading).toBe(false);
|
|
});
|
|
```
|
|
|
|
### 2. Isolation
|
|
|
|
Each test should be independent:
|
|
|
|
```typescript
|
|
beforeEach(() => {
|
|
jest.clearAllMocks(); // Clear mock call history
|
|
// Reset any state
|
|
});
|
|
```
|
|
|
|
### 3. Comprehensive Coverage
|
|
|
|
Cover all code paths:
|
|
|
|
```typescript
|
|
describe('createItem', () => {
|
|
it('should create successfully'); // Happy path
|
|
it('should handle validation errors'); // Error path
|
|
it('should handle database errors'); // Error path
|
|
it('should handle edge cases'); // Edge cases
|
|
});
|
|
```
|
|
|
|
### 4. Readable Tests
|
|
|
|
Make tests self-documenting:
|
|
|
|
```typescript
|
|
describe('User Authentication', () => {
|
|
describe('signIn', () => {
|
|
it('should sign in successfully with valid credentials', () => {
|
|
// Test implementation
|
|
});
|
|
|
|
it('should reject invalid email format', () => {
|
|
// Test implementation
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
## Common Test Scenarios
|
|
|
|
### Authentication Testing
|
|
|
|
```typescript
|
|
it('should require authentication', async () => {
|
|
mockEvent.locals = { user: null };
|
|
await expect(load(mockEvent)).rejects.toThrow('Redirect');
|
|
});
|
|
|
|
it('should allow access with valid token', async () => {
|
|
mockEvent.locals = { user: { id: '123' } };
|
|
const result = await load(mockEvent);
|
|
expect(result).toBeDefined();
|
|
});
|
|
```
|
|
|
|
### Form Validation
|
|
|
|
```typescript
|
|
it('should validate required fields', async () => {
|
|
const formData = new FormData();
|
|
formData.append('title', ''); // Invalid
|
|
|
|
const result = await actions.create(mockEvent);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('required');
|
|
});
|
|
```
|
|
|
|
### Error Handling
|
|
|
|
```typescript
|
|
it('should handle network errors gracefully', async () => {
|
|
(global.fetch as jest.Mock).mockRejectedValue(new Error('Network error'));
|
|
|
|
const result = await authService.signIn('test@example.com', 'password');
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Network');
|
|
});
|
|
```
|
|
|
|
### Async Operations
|
|
|
|
```typescript
|
|
it('should wait for async operation to complete', async () => {
|
|
const promise = service.fetchData();
|
|
|
|
await waitFor(() => {
|
|
expect(service.isLoading).toBe(false);
|
|
});
|
|
|
|
const result = await promise;
|
|
expect(result).toBeDefined();
|
|
});
|
|
```
|
|
|
|
## Testing Checklist
|
|
|
|
When writing tests, ensure you cover:
|
|
|
|
- [ ] Happy path (successful execution)
|
|
- [ ] Error paths (validation errors, API errors)
|
|
- [ ] Edge cases (empty inputs, null values, boundaries)
|
|
- [ ] Authentication/authorization
|
|
- [ ] Input sanitization
|
|
- [ ] Accessibility (for components)
|
|
- [ ] Loading states
|
|
- [ ] Error states
|
|
- [ ] Network failures (for API calls)
|
|
- [ ] Storage failures (for persistence)
|
|
|
|
## Additional Resources
|
|
|
|
- [Full Testing Strategy](../TESTING.md)
|
|
- [Implementation Guide](../TESTING_IMPLEMENTATION_GUIDE.md)
|
|
- [Shared Test Configurations](../../packages/test-config/)
|
|
- [Jest Documentation](https://jestjs.io/)
|
|
- [Vitest Documentation](https://vitest.dev/)
|
|
- [Testing Library](https://testing-library.com/)
|
|
- [Playwright](https://playwright.dev/)
|
|
|
|
## Contributing
|
|
|
|
When adding new examples:
|
|
|
|
1. Follow existing naming conventions
|
|
2. Add comprehensive comments
|
|
3. Demonstrate best practices
|
|
4. Cover edge cases
|
|
5. Update this README
|
|
|
|
## Questions?
|
|
|
|
- Check the [Testing Strategy](../TESTING.md) for overall approach
|
|
- Review [Implementation Guide](../TESTING_IMPLEMENTATION_GUIDE.md) for step-by-step instructions
|
|
- Look at existing tests in the project for patterns
|
|
- Ask in team chat for project-specific guidance
|