Testing & Debugging¶
This guide covers running tests, debugging, and the pre-commit hook system.
Running Tests¶
Web Unit Tests (Vitest)¶
pnpm --filter @meisterbill/web test:unit # Run web tests
pnpm --filter @meisterbill/web test:unit --run # Run without watch mode
Test Count: 143 passing tests (1 skipped)
Framework: Vitest
Location: apps/web/test/unit/
API Tests (Jest)¶
pnpm --filter @meisterbill/api test # Run API tests
Test Count: 397 passing tests
Framework: Jest
Location: apps/api/src/**/*.test.ts
Schema Tests (Vitest)¶
pnpm --filter @meisterbill/schemas test # Run schema tests
Test Count: 414 passing tests
Framework: Vitest
Location: schemas/src/**/*.test.ts
E2E Tests (Playwright)¶
pnpm exec playwright test # Run all E2E tests
pnpm exec playwright test --project=chromium # Run only Chromium tests
pnpm exec playwright test --ui # Run with UI mode
pnpm exec playwright test signin.spec.ts # Run specific test file
pnpm exec playwright test --debug # Debug mode
Framework: Playwright
Browsers: Chromium, Firefox, WebKit
Location: tests/e2e/web/
Architecture: - Tests run against real API and WEB servers (no mocking) - API server starts on port 3002 - WEB server starts on port 5174 - Tests use actual Supabase database - Playwright webServer automatically starts/stops servers
Prerequisites:
docker compose up -d # Start gotenberg (PDF) and mailpit (SMTP) services
Test Files:
- signin.spec.ts - Authentication tests (login, validation, error handling)
- signup.spec.ts - Registration tests (sign up, validation, duplicate emails)
- test-helpers.ts - Shared utilities (generateTestEmail())
Test Data: Tests use unique generated emails to avoid conflicts:
import { generateTestEmail } from './test-helpers';
const email = generateTestEmail('signup'); // signup.1234567890.1234@test.meister-bill.com
Debugging:
- HTML report: pnpm exec playwright show-report
- Screenshots saved in test-results/ on failure
- Use --headed flag to see browser window
- Use --debug for step-by-step debugging
See tests/e2e/README.md for complete documentation.
Pre-commit Hook¶
A git pre-commit hook automatically runs all unit tests before allowing commits.
Location: .git/hooks/pre-commit
Tests Run:
- Web unit tests (@meisterbill/web)
- API tests (@meisterbill/api)
- Schema tests (@meisterbill/schemas)
Behavior: - Commit is aborted if any tests fail - Ensures only tested code is committed to the repository
The hook is installed automatically and will run on every git commit.
Test File Organization¶
Web Tests¶
apps/web/
├── test/unit/
│ ├── CookieBanner.spec.ts
│ ├── CustomerHelper.spec.ts
│ ├── Formater.spec.ts
│ ├── image-processing.spec.ts
│ ├── useAuth.spec.ts
│ ├── useInvoiceStatusMachine.spec.ts
│ └── plugins/
│ └── AuthInit.spec.ts
└── pages/
└── **/__tests__/
└── *.test.ts
API Tests¶
apps/api/src/
├── routes/
│ ├── addresses.test.ts
│ ├── auth.test.ts
│ ├── brands.test.ts
│ ├── credit-notes.test.ts
│ ├── founder-deal.test.ts
│ ├── payments.test.ts
│ ├── projects.test.ts
│ └── ...
├── services/
│ ├── EmailService.test.ts
│ └── CommitSummarizationService.test.ts
└── utils/
└── documentNumber.test.ts
Schema Tests¶
schemas/src/
├── AccountSchema.test.ts
├── AddressFormatters.test.ts
├── AddressSchema.test.ts
├── BreadcrumbSchema.test.ts
├── CurrencyCodeSchema.test.ts
├── CustomerSchema.test.ts
├── DocumentItemSchema.test.ts
├── DocumentSchema.test.ts
├── EventSchema.test.ts
├── ServiceProviderSchema.test.ts
├── TaxCalculationSchema.test.ts
├── TaxNumberSchema.test.ts
└── forms/
├── NewPasswordSchema.test.ts
└── SignUpSchema.test.ts
Debugging¶
Console Logging¶
Use console.debug for JavaScript debugging (not console.log):
console.debug('User logged in:', userId);
console.debug('Invoice state:', invoice);
This follows the project convention defined in CLAUDE.md.
API Hot Reloading¶
The API server has hot reloading enabled. No need to restart after changes.
Web Hot Reloading¶
The web server also has hot reloading. Changes are reflected immediately.
Testing Specific Files¶
# Web - test specific file
pnpm --filter @meisterbill/web test:unit CustomerHelper.spec.ts
# API - test specific file pattern
pnpm --filter @meisterbill/api test addresses
# Schemas - test specific file
pnpm --filter @meisterbill/schemas test AddressFormatters
Common Test Scenarios¶
Testing Event Bus¶
Example from apps/web/test/unit/plugins/AuthInit.spec.ts:
import { eventBus } from '~/composables/useEventBus';
it('emits auth.login.success event', () => {
const handler = vi.fn();
eventBus.on('auth.login.success', handler);
// Trigger login
await login({ email, password });
expect(handler).toHaveBeenCalledWith(expect.objectContaining({
userId: 'test-user-id',
}));
});
Testing State Machines¶
Example from apps/web/test/unit/useInvoiceStatusMachine.spec.ts:
import { useInvoiceStatusMachine } from '~/composables/useInvoiceStatusMachine';
it('transitions from draft to finalized', () => {
const { canTransitionTo, getValidNextStatuses } = useInvoiceStatusMachine();
expect(canTransitionTo('draft', 'finalized')).toBe(true);
expect(getValidNextStatuses('draft')).toContain('finalized');
});
Testing API Routes¶
Example from apps/api/src/routes/auth.test.ts:
import { app } from '../index';
describe('POST /auth/signup', () => {
it('creates a new user', async () => {
const res = await app.request('/auth/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'test@example.com',
password: 'SecurePass123!',
terms_accepted: true,
}),
});
expect(res.status).toBe(201);
});
});
Test Coverage Goals¶
- Critical paths: 100% coverage
- Business logic: 90%+ coverage
- UI components: 70%+ coverage
- Overall: 80%+ coverage target
Continuous Integration¶
All tests run automatically in CI/CD before deployment. Tests are defined in the .gitea/workflows/deploy.yml file.
See Also¶
- Development Setup - Initial setup
- Schema Validation - Working with Zod schemas
- Event Bus Architecture - Testing event subscribers