mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 01:21:09 +02:00
12 KiB
12 KiB
Testing Implementation Guide
Quick Start Guide for Adding Tests to the Manacore Monorepo
Table of Contents
- Quick Start
- Adding Tests to NestJS Backend
- Adding Tests to React Native Mobile
- Adding Tests to SvelteKit Web
- Adding Tests to Shared Packages
- Running Tests Locally
- Coverage Reports
- Troubleshooting
Quick Start
Prerequisites
# Ensure you have the correct versions
node --version # Should be 20+
pnpm --version # Should be 9.15.0
Install Dependencies
# From monorepo root
pnpm install
Run All Tests
# 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)
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:
const baseConfig = require('@manacore/test-config/jest-backend');
module.exports = {
...baseConfig,
// Project-specific overrides if needed
};
Or inline in package.json:
{
"jest": {
"preset": "@manacore/test-config/jest-backend"
}
}
3. Add Test Scripts to package.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
// 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
pnpm test
pnpm test:cov # With coverage
Adding Tests to React Native Mobile
1. Install Testing Dependencies
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:
module.exports = {
preset: '@manacore/test-config/jest-mobile',
// Project-specific overrides
};
3. Create Setup File
Create jest.setup.js:
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
{
"scripts": {
"test": "jest --watchAll",
"test:ci": "jest --ci --coverage --watchAll=false",
"test:cov": "jest --coverage --watchAll=false"
}
}
5. Create Your First Component Test
// 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
pnpm test
Adding Tests to SvelteKit Web
1. Install Testing Dependencies
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:
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:
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:
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
{
"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
// 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
// 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
pnpm test:unit # Unit tests
pnpm test:e2e # E2E tests
pnpm test:unit:cov # With coverage
Adding Tests to Shared Packages
1. Install Vitest
cd packages/YOUR_PACKAGE
pnpm add -D vitest @vitest/coverage-v8
2. Create Vitest Configuration
Create vitest.config.ts:
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
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:cov": "vitest run --coverage"
}
}
4. Create Your First Utility Test
// 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
pnpm test
pnpm test:cov
Running Tests Locally
Individual Project Tests
# 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
# Run all tests for maerchenzauber
pnpm --filter maerchenzauber... test
Watch Mode
# 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
# 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
# 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):
module.exports = {
preset: '@manacore/test-config/jest-backend',
coverageThresholds: {
global: {
lines: 90, // Higher threshold
},
},
};
Vitest (Web/Shared):
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
# 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:
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:
import { sveltekit } from '@sveltejs/kit/vite';
export default defineConfig({
plugins: [sveltekit()],
});
Playwright browser not installed
pnpm --filter @YOUR_PROJECT/web exec playwright install chromium
Tests timeout
Increase timeout in config:
// Vitest
export default defineConfig({
test: {
testTimeout: 30000, // 30 seconds
},
});
// Jest
module.exports = {
testTimeout: 30000,
};
Coverage not generating
# Jest: Ensure collectCoverageFrom is set
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!**/*.d.ts',
],
# Vitest: Ensure include is set
coverage: {
include: ['src/**/*.{js,ts,svelte}'],
}
Getting Help
- Check existing tests in the project for patterns
- Review docs/TESTING.md for detailed strategies
- Check example tests in docs/test-examples/
- Review CI logs for failure details
- Ask in team chat for project-specific guidance
Next Steps
- Start with critical paths: Auth, payments, data integrity
- Add tests incrementally: Don't try to test everything at once
- Follow TDD when possible: Write tests before code
- Review coverage: Aim for 80% minimum, 100% for critical code
- Keep tests fast: Unit tests < 100ms, integration < 1s
- Update this guide: Add project-specific tips as you learn
Resources
- Full Testing Strategy
- Test Examples
- Jest Documentation
- Vitest Documentation
- Playwright Documentation
- Testing Library
Quick Reference Commands
# 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