Skip to content

Testing

Backend Tests (pytest)

Unit tests run against api/ using FastAPI's TestClient with mocked SMTP — no running server needed.

bash
# Run all API tests
pytest tests/ -v

# Run a specific file
pytest tests/test_api_endpoints.py -v

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)

bash
npm run test:unit

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

bash
# Generate coverage report locally (text + lcov + html)
npm run test:unit:coverage

# Open HTML report
open coverage/index.html

For Python:

bash
pytest tests/ --cov=api --cov-report=term-missing

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.

bash
# Run a specific job
act -j unit
act -j api
act -j typecheck

# Run the full push workflow
act push

On first run, choose Medium when prompted for a runner image. Requires Docker to be running.

To pass secrets:

bash
# Create .secrets (already in .gitignore)
echo "EMAIL_ADDRESS=ci@example.com" >> .secrets
act -j api --secret-file .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)

bash
# Run against dev environment (default)
npm run test:e2e

# Run against a specific URL
BASE_URL=https://www.sven-relijveld.com npm run test:e2e

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

bash
# Install
uv tool install prek
prek install

# Run manually
prek run --all-files

# Run specific hooks
prek run black isort flake8 --all-files

Hooks enforce black + isort for Python and ESLint/Prettier for TypeScript.

Code Quality

bash
# Python
black api/ tests/
isort api/ tests/
flake8 api/ tests/

# TypeScript
npm run format
npm run lint

Troubleshooting

Playwright can't find the browser

bash
npx playwright install --with-deps chromium

pytest — module not found

bash
uv pip install -r api/requirements.txt

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.