managarten/docs/TESTING_IMPLEMENTATION_GUIDE.md
Wuesteon ad495b2044 📝 docs: restructure CLAUDE.md and documentation (74% reduction)
Optimize CLAUDE.md based on industry best practices from HN and HumanLayer:

Changes:
- Trim CLAUDE.md from 678 to 176 lines (74% reduction, 5.7KB)
- Add "Critical Gotchas" section for common AI mistakes
- Add verification signature (🏗️ ManaCore Monorepo)
- Create docs/README.md navigation hub with "I want to..." index
- Delete 5 outdated audit files (ENV_AUDIT_*, DEPENDENCY_ALIGNMENT)
- Archive 7 analysis/historical docs to docs/archive/
- Keep authentication docs separate per request (.claude/guidelines/)

Benefits:
- Better AI instruction adherence (within ~150-200 line budget)
- Progressive disclosure via signposting to detailed docs
- Cleaner navigation with topic-based organization
- Reduced maintenance burden (stale docs archived)

Backup: CLAUDE.md.backup preserves original 678-line version
Change log: docs/archive/RESTRUCTURE_2025-12-16.md
2025-12-16 17:37:19 +01:00

646 lines
12 KiB
Markdown

# Testing Implementation Guide
**Quick Start Guide for Adding Tests to the Manacore Monorepo**
## Table of Contents
- [Quick Start](#quick-start)
- [Adding Tests to NestJS Backend](#adding-tests-to-nestjs-backend)
- [Adding Tests to React Native Mobile](#adding-tests-to-react-native-mobile)
- [Adding Tests to SvelteKit Web](#adding-tests-to-sveltekit-web)
- [Adding Tests to Shared Packages](#adding-tests-to-shared-packages)
- [Running Tests Locally](#running-tests-locally)
- [Coverage Reports](#coverage-reports)
- [Troubleshooting](#troubleshooting)
## Quick Start
### Prerequisites
```bash
# Ensure you have the correct versions
node --version # Should be 20+
pnpm --version # Should be 9.15.0
```
### Install Dependencies
```bash
# From monorepo root
pnpm install
```
### Run All Tests
```bash
# Run tests for all projects
pnpm test
# Run tests for specific project
pnpm --filter @maerchenzauber/backend test
pnpm --filter @memoro/mobile test
pnpm --filter @uload/web test:unit
```
## Adding Tests to NestJS Backend
### 1. Install Testing Dependencies (if not already installed)
```bash
cd apps/YOUR_PROJECT/apps/backend
pnpm add -D @nestjs/testing jest ts-jest @types/jest supertest @types/supertest
```
### 2. Create Jest Configuration
Create `jest.config.js` in your backend directory:
```javascript
const baseConfig = require('@manacore/test-config/jest-backend');
module.exports = {
...baseConfig,
// Project-specific overrides if needed
};
```
Or inline in `package.json`:
```json
{
"jest": {
"preset": "@manacore/test-config/jest-backend"
}
}
```
### 3. Add Test Scripts to package.json
```json
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand"
}
}
```
### 4. Create Your First Test
```typescript
// src/example/__tests__/example.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { ExampleService } from '../example.service';
describe('ExampleService', () => {
let service: ExampleService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ExampleService],
}).compile();
service = module.get<ExampleService>(ExampleService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
```
### 5. Run Tests
```bash
pnpm test
pnpm test:cov # With coverage
```
## Adding Tests to React Native Mobile
### 1. Install Testing Dependencies
```bash
cd apps/YOUR_PROJECT/apps/mobile
pnpm add -D jest jest-expo @testing-library/react-native @testing-library/jest-native
```
### 2. Create Jest Configuration
Create `jest.config.js`:
```javascript
module.exports = {
preset: '@manacore/test-config/jest-mobile',
// Project-specific overrides
};
```
### 3. Create Setup File
Create `jest.setup.js`:
```javascript
import '@testing-library/jest-native/extend-expect';
// Mock Expo modules
jest.mock('expo-secure-store', () => ({
getItemAsync: jest.fn(),
setItemAsync: jest.fn(),
deleteItemAsync: jest.fn(),
}));
jest.mock('expo-font', () => ({
loadAsync: jest.fn(),
isLoaded: jest.fn(() => true),
}));
// Global test setup
global.fetch = jest.fn();
```
### 4. Add Test Scripts to package.json
```json
{
"scripts": {
"test": "jest --watchAll",
"test:ci": "jest --ci --coverage --watchAll=false",
"test:cov": "jest --coverage --watchAll=false"
}
}
```
### 5. Create Your First Component Test
```typescript
// src/components/Button/__tests__/Button.test.tsx
import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import { Button } from '../Button';
describe('Button', () => {
it('should render', () => {
const { getByText } = render(<Button>Click Me</Button>);
expect(getByText('Click Me')).toBeTruthy();
});
it('should call onPress', () => {
const onPress = jest.fn();
const { getByText } = render(<Button onPress={onPress}>Click</Button>);
fireEvent.press(getByText('Click'));
expect(onPress).toHaveBeenCalled();
});
});
```
### 6. Run Tests
```bash
pnpm test
```
## Adding Tests to SvelteKit Web
### 1. Install Testing Dependencies
```bash
cd apps/YOUR_PROJECT/apps/web
pnpm add -D vitest @vitest/coverage-v8 @testing-library/svelte jsdom
pnpm add -D @playwright/test # For E2E tests
```
### 2. Create Vitest Configuration
Create `vitest.config.ts`:
```typescript
import { defineConfig, mergeConfig } from 'vitest/config';
import svelteConfig from '@manacore/test-config/vitest-svelte';
import { sveltekit } from '@sveltejs/kit/vite';
export default mergeConfig(
svelteConfig,
defineConfig({
plugins: [sveltekit()],
test: {
// Project-specific overrides
},
})
);
```
### 3. Create Vitest Setup File
Create `vitest.setup.ts`:
```typescript
import { expect, afterEach } from 'vitest';
import { cleanup } from '@testing-library/svelte';
// Cleanup after each test
afterEach(() => {
cleanup();
});
```
### 4. Create Playwright Configuration (E2E)
Create `playwright.config.ts`:
```typescript
import { defineConfig } from '@playwright/test';
import baseConfig from '@manacore/test-config/playwright';
export default defineConfig({
...baseConfig,
use: {
...baseConfig.use,
baseURL: 'http://localhost:5173',
},
webServer: {
command: 'pnpm run build && pnpm run preview',
port: 5173,
},
});
```
### 5. Add Test Scripts to package.json
```json
{
"scripts": {
"test": "pnpm run test:unit && pnpm run test:e2e",
"test:unit": "vitest run",
"test:unit:watch": "vitest",
"test:unit:cov": "vitest run --coverage",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui"
}
}
```
### 6. Create Your First Component Test
```typescript
// src/lib/components/Button/__tests__/Button.test.ts
import { render, screen } from '@testing-library/svelte';
import { describe, it, expect, vi } from 'vitest';
import Button from '../Button.svelte';
describe('Button', () => {
it('should render', () => {
render(Button, { props: { children: 'Click Me' } });
expect(screen.getByText('Click Me')).toBeTruthy();
});
it('should call onclick', async () => {
const onclick = vi.fn();
render(Button, { props: { onclick, children: 'Click' } });
await screen.getByText('Click').click();
expect(onclick).toHaveBeenCalled();
});
});
```
### 7. Create Your First E2E Test
```typescript
// e2e/homepage.spec.ts
import { test, expect } from '@playwright/test';
test('homepage loads successfully', async ({ page }) => {
await page.goto('/');
await expect(page.locator('h1')).toBeVisible();
});
```
### 8. Run Tests
```bash
pnpm test:unit # Unit tests
pnpm test:e2e # E2E tests
pnpm test:unit:cov # With coverage
```
## Adding Tests to Shared Packages
### 1. Install Vitest
```bash
cd packages/YOUR_PACKAGE
pnpm add -D vitest @vitest/coverage-v8
```
### 2. Create Vitest Configuration
Create `vitest.config.ts`:
```typescript
import { defineConfig, mergeConfig } from 'vitest/config';
import baseConfig from '@manacore/test-config/vitest-base';
export default mergeConfig(
baseConfig,
defineConfig({
test: {
// Package-specific config
},
})
);
```
### 3. Add Test Scripts to package.json
```json
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:cov": "vitest run --coverage"
}
}
```
### 4. Create Your First Utility Test
```typescript
// src/__tests__/format.test.ts
import { describe, it, expect } from 'vitest';
import { formatDate, truncate } from '../format';
describe('formatDate', () => {
it('should format date correctly', () => {
const date = new Date('2024-01-15T12:00:00Z');
expect(formatDate(date, 'yyyy-MM-dd')).toBe('2024-01-15');
});
});
describe('truncate', () => {
it('should truncate long strings', () => {
expect(truncate('Very long text', 10)).toBe('Very long…');
});
});
```
### 5. Run Tests
```bash
pnpm test
pnpm test:cov
```
## Running Tests Locally
### Individual Project Tests
```bash
# Backend
pnpm --filter @maerchenzauber/backend test
# Mobile
pnpm --filter @memoro/mobile test
# Web (unit tests)
pnpm --filter @uload/web test:unit
# Web (E2E tests)
pnpm --filter @uload/web test:e2e
# Shared package
pnpm --filter @manacore/shared-utils test
```
### All Tests for a Project
```bash
# Run all tests for maerchenzauber
pnpm --filter maerchenzauber... test
```
### Watch Mode
```bash
# Backend (Jest)
pnpm --filter @maerchenzauber/backend test:watch
# Mobile (Jest)
pnpm --filter @memoro/mobile test
# Web (Vitest)
pnpm --filter @uload/web test:unit:watch
```
### With Coverage
```bash
# Backend
pnpm --filter @maerchenzauber/backend test:cov
# Mobile
pnpm --filter @memoro/mobile test:cov
# Web
pnpm --filter @uload/web test:unit:cov
# View HTML report
open apps/YOUR_PROJECT/apps/backend/coverage/index.html
```
## Coverage Reports
### View Coverage Locally
```bash
# Generate coverage
pnpm test:cov
# Open HTML report
open coverage/index.html
```
### Coverage Thresholds
All projects have these default thresholds:
- **Lines**: 80%
- **Functions**: 80%
- **Branches**: 80%
- **Statements**: 80%
To override for your project:
**Jest (Backend/Mobile)**:
```javascript
module.exports = {
preset: '@manacore/test-config/jest-backend',
coverageThresholds: {
global: {
lines: 90, // Higher threshold
},
},
};
```
**Vitest (Web/Shared)**:
```typescript
export default defineConfig({
test: {
coverage: {
thresholds: {
lines: 90,
},
},
},
});
```
### CI/CD Coverage
- Coverage reports are automatically uploaded to Codecov on PR/push to main
- Coverage badges available at `https://codecov.io/gh/YOUR_ORG/YOUR_REPO`
- PR comments show coverage diff
## Troubleshooting
### Common Issues
#### "Cannot find module" errors
```bash
# Clear caches
pnpm store prune
pnpm install --force
# Backend: Clear Jest cache
pnpm --filter @YOUR_PROJECT/backend test --clearCache
# Mobile: Clear Metro cache
cd apps/YOUR_PROJECT/apps/mobile
rm -rf node_modules/.cache
```
#### Transform errors in React Native
Make sure `transformIgnorePatterns` in `jest.config.js` includes all necessary packages:
```javascript
transformIgnorePatterns: [
'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@manacore/.*)',
];
```
#### Svelte component tests fail
Ensure you have the correct Vite plugin:
```typescript
import { sveltekit } from '@sveltejs/kit/vite';
export default defineConfig({
plugins: [sveltekit()],
});
```
#### Playwright browser not installed
```bash
pnpm --filter @YOUR_PROJECT/web exec playwright install chromium
```
#### Tests timeout
Increase timeout in config:
```typescript
// Vitest
export default defineConfig({
test: {
testTimeout: 30000, // 30 seconds
},
});
// Jest
module.exports = {
testTimeout: 30000,
};
```
#### Coverage not generating
```bash
# Jest: Ensure collectCoverageFrom is set
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!**/*.d.ts',
],
# Vitest: Ensure include is set
coverage: {
include: ['src/**/*.{js,ts,svelte}'],
}
```
### Getting Help
1. Check existing tests in the project for patterns
2. Review [docs/TESTING.md](./TESTING.md) for detailed strategies
3. Check example tests in [docs/test-examples/](./test-examples/)
4. Review CI logs for failure details
5. Ask in team chat for project-specific guidance
## Next Steps
1. **Start with critical paths**: Auth, payments, data integrity
2. **Add tests incrementally**: Don't try to test everything at once
3. **Follow TDD when possible**: Write tests before code
4. **Review coverage**: Aim for 80% minimum, 100% for critical code
5. **Keep tests fast**: Unit tests < 100ms, integration < 1s
6. **Update this guide**: Add project-specific tips as you learn
## Resources
- [Full Testing Strategy](./TESTING.md)
- [Test Examples](./test-examples/)
- [Jest Documentation](https://jestjs.io/)
- [Vitest Documentation](https://vitest.dev/)
- [Playwright Documentation](https://playwright.dev/)
- [Testing Library](https://testing-library.com/)
---
**Quick Reference Commands**
```bash
# Run all tests
pnpm test
# Run specific project tests
pnpm --filter @PROJECT/APP test
# Run with coverage
pnpm --filter @PROJECT/APP test:cov
# Run in watch mode
pnpm --filter @PROJECT/APP test:watch
# Run E2E tests
pnpm --filter @PROJECT/web test:e2e
# Type check
pnpm type-check
# Lint
pnpm lint
# Format
pnpm format
```