Testing¶
Backend Tests (pytest)¶
Unit tests run against api/ using FastAPI's TestClient with mocked SMTP — no running server needed.
Test files:
| File | Coverage |
|---|---|
tests/test_api_endpoints.py |
Health, contact form (success + demo + SMTP errors + dual delivery), CV status flag, projects, experience, skills, rate limiting |
tests/test_cv_download.py |
GET /api/download-cv — file serving, language fallback, 404 on missing file |
tests/test_cv_generation.py |
PATCH /api/cv/generate — feature flag, missing workspace/bun/template/build-script, subprocess timeout and non-zero exit, happy path, unknown lang fallback, App Config flag integration |
tests/test_cv_files_exist.py |
Disk-presence check: every CV_FILES entry resolves to a file in client/public/ |
tests/test_admin_endpoints.py |
Admin CRUD endpoints for projects, experience, skills — auth, validation, 404s |
tests/test_db_endpoints.py |
Database-backed GET endpoints — projects, experience, skills with seed data |
tests/test_feature_flags.py |
Feature flag endpoints — App Configuration integration, env var fallback |
Frontend Unit Tests (Vitest)¶
Tests run in a jsdom environment via Vitest. Test files in client/src/__tests__/ and server/__tests__/:
| File | Coverage |
|---|---|
useContactForm.test.ts |
Contact hook — validation, error mapping, success toast (25 tests) |
CVDownloadDialog.test.tsx |
Dialog trigger, language selection, window.open URLs, feature-flag show/hide, /api/cv/status fetch |
FeatureFlags.test.tsx |
Feature flags context — loading state, flag values, refresh behaviour |
server/__tests__/cv-paths.test.ts |
File-existence check for every path in CV_FILE_CONFIG (Node environment) |
Coverage Reporting¶
For Python:
In CI, both stacks upload coverage artifacts — unit-coverage (lcov) and api-coverage (XML) — retained for 14 days per run.
Local CI Simulation (act)¶
act runs GitHub Actions workflows locally in Docker, letting you validate CI changes before pushing.
On first run, choose Medium when prompted for a runner image. Requires Docker to be running.
To pass secrets:
Note: dorny/test-reporter contacts the GitHub API and will fail locally — this is non-blocking; the test output still runs.
E2E Tests (Playwright)¶
Playwright runs Chromium only. Test files in e2e/:
| File | Coverage |
|---|---|
contact.spec.ts |
Happy path, client-side validation, API 500 mock |
cv-download.spec.ts |
PDF download via window.open — handled via popup context |
navigation.spec.ts |
Page routing and anchor scroll |
responsive.spec.ts |
Mobile viewport checks |
projects.spec.ts |
Projects list loads, card navigation to detail page, no JS errors, home page projects link |
admin-uigen.spec.ts |
UIGen admin portal loads, action buttons present, lang dropdown options |
Reports are uploaded as GitHub artifacts on every CI run.
Pre-commit Hooks¶
Hooks enforce black + isort for Python and ESLint/Prettier for TypeScript.
Code Quality¶
Troubleshooting¶
Playwright can't find the browser¶
pytest — module not found¶
Next Steps¶
- Pipeline Overview — how tests run in CI (PR preview, post-deploy, scheduled smoke tests)
Page history
| Field | Value |
|---|---|
| Last updated | 2026-04-16 |
Changelog
| Date | PRs | Summary |
|---|---|---|
| 2026-03-20 | #81 | New page: extracted testing section from setup.md; covers pytest, Vitest, Playwright E2E, pre-commit hooks |
| 2026-04-16 | Expanded pytest coverage (cv/generate + cv/status + file-existence tests), added CVDownloadDialog Vitest test, added projects.spec.ts E2E spec, added coverage reporting and local CI simulation (act) sections. |