Architect independently reclaimed this task after my fix landed and rewrote the same doc with more precise per-file test descriptions and a more specific gap list -- genuinely better in places (caught real detail I'd summarized loosely) but its own investigation also introduced one factual error (claimed 18 tests in test_auth_age_gate.py; verified via pytest --collect-only, it's 17) and dropped two things worth keeping: the exact commit hash for reproducibility, and the Client export section (it never looked at the export step). Merged: kept the architect's richer per-file coverage descriptions and gap analysis, restored the verified counts/commit hash/export section/ --quit gotcha from my original. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7.0 KiB
Test Inventory
What automated coverage actually exists, what it actually verifies, and what
doesn't have coverage yet. Keep this current as tests are added — it's the
thing a Package Checkpoint review (see docs/testing/README.md) reads first
to know what "run the tests" actually checked.
Run everything below in one shot with scripts/run_checkpoint_tests.py.
Last verified against main: 2026-08-20 (commit 927f9bd) — full PC1
checkpoint run, fresh clone, migrations + pytest + all 4 Godot smoke tests +
both platform exports, all clean.
Backend — backend/tests/ (pytest)
Run: cd backend && python -m pytest -v (needs DATABASE_URL pointed at a
reachable Postgres — see the runner script).
Current total: 68 tests, all passing on a clean main checkout.
| File | Tests | What it covers |
|---|---|---|
test_auth_age_gate.py |
17 | calculate_age() date-math correctness (exact boundary, leap years, birthday-not-yet-this-year) + RegisterRequest date-of-birth validation (parametrized valid/invalid date rejection). Backs the 18+ registration gate (PR #23). |
test_gltf_metadata.py |
21 | glTF/GLB binary + JSON parsing: magic-byte detection, chunk-padding handling, mesh/animation/texture-reference metadata extraction, malformed-input rejection. Backs the asset-import pipeline (PR #27). |
test_auth_endpoints.py |
11 | Integration tests for POST /api/auth/register and POST /api/auth/login against the real FastAPI app + real Postgres. Covers: successful register (201), duplicate username (409), duplicate email (409), underage rejection (400), invalid date format (422), exact-18 registration, successful login with correct credentials (200), wrong password (401), nonexistent user (401), form-encoded login (OAuth2), and JWT validity of returned tokens. |
test_refresh_endpoint.py |
8 | Integration tests for POST /api/auth/refresh. Covers: successful refresh (200, new access token, same refresh token returned), refresh produces different access tokens on repeated calls, invalid refresh token (401), empty body (422), missing field (422), refresh token from login also works, returned access token is valid JWT decodable with public key, access_token_expires_minutes in response. |
test_refresh_token_jti.py |
6 | Unit tests for refresh token uniqueness (jti claim) and model column length. Covers: two calls with same sub produce different tokens (jti uniqueness), jti is valid UUID, rapid repeated calls all produce unique jtis, jti survives decode, RefreshToken.token column is String(512), column type is String. |
test_auth_expired_token.py |
5 | Integration tests for expired-token rejection across auth endpoints. Covers: expired access JWT rejected by GET /api/auth/me (401), garbage access token rejected by /me (401), missing bearer token returns 401, expired refresh token (DB expires_at in past) rejected by /refresh (401), expired refresh JWT (past exp claim) rejected before DB lookup (401). |
What these are, honestly: a mix of pure unit tests (test_auth_age_gate.py,
test_gltf_metadata.py, test_refresh_token_jti.py) and real integration tests
(test_auth_endpoints.py, test_refresh_endpoint.py, test_auth_expired_token.py)
that hit the FastAPI app against a real Postgres database via TestClient.
The integration tests exercise the full stack: Pydantic validation → DB →
JWT → response. The suite is also re-runnable without manual cleanup —
backend/tests/conftest.py has a session-scoped autouse fixture that
truncates all app tables once before the suite runs.
Known coverage gaps (real gaps, not placeholders — nothing enforces filling these yet):
- No endpoint tests for
GET /api/worlds,GET /api/assets/*, or any world/asset CRUD routes — only auth endpoints have integration coverage (GET /api/worldsis covered indirectly via the Godot smoke tests below). - No tests for the moderation schema/migration beyond "the migration runs."
- No tests for the
GET /api/auth/meendpoint's response body (only its auth-header validation is covered via expired-token tests). - No tests for session management (create/validate/revoke sessions).
Godot client — scripts/smoke_test_*.gd
4 smoke tests merged into main. Each needs a live backend —
AGP_API_BASE_URL env var, falling back to the
application/agp/api_base_url project setting (default
http://127.0.0.1:8000) if unset.
| File | What it covers |
|---|---|
smoke_test_api.gd |
Exercises ApiClient.health_check() against a live backend. Verifies the real HTTP request path (HTTPRequest node lifecycle, JSON parse, result-dictionary contract). Exits 1 on failure. |
smoke_test_auth.gd |
Tests the full auth flow via ApiClient autoload: register unique user (201), duplicate username (409), under-18 registration (400), correct login (200), wrong password (401), nonexistent user (401). |
smoke_test_e2e.gd |
End-to-end flow: health check → register → login → worlds list. Verifies the full request chain with a fresh user, including token storage and get_worlds() with auth header. |
smoke_test_world_list.gd |
Instantiates world_list.tscn as a real scene, adds to tree (catches @onready node-path bugs), waits for _refresh_worlds() to complete, confirms the screen reaches a real end state (world cards, empty-list message, or error label — not stuck loading). |
Run (once, to build the class cache): godot --headless --path . --import,
then for each smoke test: godot --headless --path . --script res://scripts/smoke_test_<name>.gd — no --quit, it kills these before
their awaited HTTP calls finish.
Known gaps:
- No smoke tests for the main menu scene (
main_menu.tscn). - No smoke tests for chunk loading/streaming (
chunk.gd,chunk_scene.gd). - No smoke tests for dynamic/static object nodes.
- All smoke tests require a live backend; no offline/unit smoke tests exist.
smoke_test_world_list.gdis the only one that exercises a real.tscnscene instantiation — others only test theApiClientautoload.get_me()(GET /auth/me) is implemented inscripts/api_client.gdbut has no smoke coverage yet.
Client export
scripts/build.sh produces real Linux (agp-game.x86_64) and Windows
(agp-game.exe) binaries via --export-release. Verified 2026-08-20: both
exports complete clean from a fresh checkout and produce valid binaries
(confirmed via file — real ELF64/PE32+, not empty or truncated). Neither
export is exercised by an automated GUI test (headless Godot can't drive a
window) — actually launching and clicking through the exported binary is a
manual step, see docs/checkpoints/PC1.md for playtest instructions.
What "full coverage" should eventually mean here
Not defined precisely yet — the honest target as of 2026-08-20 is "integration tests for every endpoint + smoke tests for every major scene." As real integration/endpoint tests get added, update the tables above rather than letting this doc drift stale; a wrong inventory is worse than no inventory.