Files
2026-06-20 04:09:38 -04:00

200 lines
7.7 KiB
Markdown

# Backend API Test Guide
This directory contains the backend API test suite. The tests use pytest, FastAPI's `TestClient`, and an isolated in-memory SQLite database. The goal is to cover the business-critical API behaviour without relying on MySQL, SMTP, or a running browser.
## How To Run
From `backend/`:
```bash
pytest
pytest --cov=app --cov-report=term-missing
```
From the project root with Docker Compose running:
```bash
docker compose exec api pytest
docker compose exec api pytest --cov=app --cov-report=term-missing
```
## Shared Fixtures
### `conftest.py`
Sets up the test harness used by every module.
What it does:
- Provides safe default environment variables before the app imports settings.
- Creates an in-memory SQLite database and overrides FastAPI's `get_db` dependency.
- Recreates all tables for every test so tests cannot leak state into each other.
- Patches SQLite primary-key handling for models that use `BigInteger` ids in production.
- Provides `client` for unauthenticated requests and `auth_client` for administrator/operator requests.
- Provides reusable PPR payload and factory fixtures.
Why it exists:
- Keeps API tests fast, deterministic, and independent from Docker MySQL data.
- Lets tests exercise the real FastAPI routes, schemas, CRUD calls, and dependency overrides.
## Test Modules
### `test_app_health.py`
Covers the simplest application-level endpoints.
What it tests:
- `/` returns API metadata.
- `/health` reports a healthy application and database connection.
Why it matters:
- These tests catch broken app imports, router setup problems, and database dependency regressions early.
### `test_auth_api.py`
Covers authentication and admin user-management routes.
What it tests:
- Login rejects invalid credentials.
- Login returns a bearer token for a valid user.
- Admin users can create, list, update, and change passwords for users.
- Duplicate users and missing users return the expected errors.
Why it matters:
- Auth is the gatekeeper for most operational endpoints.
- The admin user flow is also a good end-to-end check of password hashing, token creation, CRUD, and journal side effects.
### `test_pprs_api.py`
Covers the core PPR lifecycle.
What it tests:
- PPR routes require authentication where appropriate.
- Authenticated users can create, read, update, patch, acknowledge, status-update, soft-delete, and audit PPRs.
- List filters work for status, dates, skip, and limit.
- Public PPR creation sends email and generates secure edit tokens.
- Public edit and cancel token flows work and reject invalid or processed requests.
- Activation creates an arrival and pending departure.
- Missing PPRs return 404.
- Invalid payloads return validation errors.
Why it matters:
- PPRs are the central workflow in the system.
- These tests protect the operational state transitions that drive tower/admin views and audit history.
### `test_public_api.py`
Covers public read-only board and lookup endpoints.
What it tests:
- Public arrivals and departures start empty.
- Today's PPRs, local flights, arrivals, and departures appear on public boards.
- Old or cancelled records are excluded.
- Public airport and aircraft lookups return seeded records.
- Short or invalid lookup queries return empty lists.
Why it matters:
- Public boards and lookup helpers are user-facing and unauthenticated.
- These tests check that the public API exposes useful operational information without requiring login.
### `test_flight_strip_apis.py`
Covers authenticated flight-strip style CRUD endpoints.
What it tests:
- Arrival lifecycle: create, list/filter, read, update, land, cancel, and not-found paths.
- Landing an arrival promotes a linked pending departure.
- Departure lifecycle: create, list/filter, update, takeoff/departure status, cancel, and not-found paths.
- Local flight lifecycle: create, list/filter, update, depart, land, special lists, cancel, and not-found paths.
- Overflight lifecycle: create, active/today lists, list/filter, update, mark inactive/QSY, cancel, and not-found paths.
- Movement records are created for real takeoff, landing, touch-and-go, and overflight events where relevant.
Why it matters:
- These endpoints represent day-to-day tower strip operations.
- They also exercise important CRUD side effects: status timestamps, movements, linked departures, and journal entries.
### `test_circuits_api.py`
Covers circuit/touch-and-go records.
What it tests:
- Circuits can be recorded for local flights.
- Circuits can be recorded for arrivals.
- Circuit list, lookup-by-flight, lookup-by-arrival, update, and delete work.
- Invalid circuit creation requests are rejected when neither or both parent ids are supplied.
- Missing circuits return 404.
- Recording a circuit creates a touch-and-go movement.
Why it matters:
- Circuit traffic is a distinct operational pattern and feeds movement logging.
- The parent-id validation prevents ambiguous audit/movement records.
### `test_movements_api.py`
Covers movement listing, context lookup, and bulk paper-strip logging.
What it tests:
- Movement list filters and single-record reads.
- Bulk movement context suggests matching PPRs and existing movements.
- Bulk logging can create and update PPR-linked arrivals.
- Bulk logging can create unmatched arrival and departure records.
- Bulk logging handles local flight strips with takeoff, landing, duration, and circuits.
- Bulk logging handles overflight strips and updates existing overflight records.
- Invalid bulk-log requests return helpful 400 errors.
Why it matters:
- Bulk movement logging is one of the densest workflows in the API.
- These tests protect the behaviour that translates paper-strip data into PPR, arrival, departure, local flight, overflight, movement, and journal records.
### `test_drone_requests_api.py`
Covers drone flight request workflows.
What it tests:
- Public drone request creation generates references/tokens and sends confirmation email.
- Public edit and cancel token flows work.
- Processed drone requests cannot be edited or cancelled publicly.
- Authenticated users can list, read, update, status-update, comment on, and audit drone requests.
- Missing records and invalid payloads return expected errors.
Why it matters:
- Drone requests are a newer workflow with public and authenticated surfaces.
- The tests protect email notification, public token, status, comment, and journal behaviour.
### `test_public_book_api.py`
Covers the optional public booking portal.
What it tests:
- Public booking rejects requests when disabled.
- Public local flight booking creates a public-submitted local flight.
- Public circuit recording creates a circuit and touch-and-go movement.
- Public departure and arrival booking create public-submitted records with pilot emails.
- Invalid public booking payloads return validation errors.
Why it matters:
- Public booking is controlled by configuration and should be safe to disable.
- When enabled, it creates operational records without authentication, so validation and submitted-via metadata matter.
### `test_journal_api.py`
Covers generic audit/journal endpoints.
What it tests:
- Journal search filters by date, entity type, entity id, and user.
- Invalid entity types are rejected.
- User journal and entity journal endpoints return entries and summary counts.
Why it matters:
- The journal is the audit trail across PPRs, flights, users, drone requests, and movements.
- These tests make sure audit entries remain queryable as the system grows.
## Current Scope
The suite intentionally focuses on API behaviour, local WebSocket broadcast behaviour, and database side effects. It does not deeply test:
- Full browser WebSocket lifecycle.
- Real SMTP delivery.
- Browser UI behaviour.
- Every branch of low-level validators or helper functions.
Those areas are better handled with focused unit tests or E2E tests later.