|
| 1 | +# End-to-End Testing |
| 2 | + |
| 3 | +The repo ships Playwright-driven smoke tests at |
| 4 | +[tests/e2e/test_smoke.py](../tests/e2e/test_smoke.py). Two tests drive a real |
| 5 | +Chromium browser through the core flows: |
| 6 | + |
| 7 | +* **`test_login_and_browse_smoke`** — landing → Keycloak login → dashboard → |
| 8 | + products browse → logout. Minimal regression guard. |
| 9 | +* **`test_products_crud_smoke`** — same login + a full create / edit / delete |
| 10 | + round-trip against the products module. |
| 11 | + |
| 12 | +End-to-end tests are gated behind the `e2e` pytest marker (declared in |
| 13 | +[pyproject.toml](../pyproject.toml)) and are **excluded from the default |
| 14 | +`make test` run**. They only execute under `make test-e2e`. |
| 15 | + |
| 16 | +## Prerequisites |
| 17 | + |
| 18 | +One-time setup on the machine that will run the tests: |
| 19 | + |
| 20 | +```bash |
| 21 | +uv sync --all-packages |
| 22 | +uv run playwright install chromium |
| 23 | +``` |
| 24 | + |
| 25 | +Then bring up the full stack (in a separate terminal, leave it running): |
| 26 | + |
| 27 | +```bash |
| 28 | +make docker-up # Keycloak + Postgres |
| 29 | +make migrate # apply Alembic migrations |
| 30 | +make dev # FastAPI on :8000 + Vite on :5173 |
| 31 | +``` |
| 32 | + |
| 33 | +## Running |
| 34 | + |
| 35 | +```bash |
| 36 | +make test-e2e |
| 37 | +``` |
| 38 | + |
| 39 | +Or directly: |
| 40 | + |
| 41 | +```bash |
| 42 | +uv run pytest -m e2e tests/e2e |
| 43 | +``` |
| 44 | + |
| 45 | +## Configuration |
| 46 | + |
| 47 | +The test reads three environment variables (all optional): |
| 48 | + |
| 49 | +| Variable | Default | Notes | |
| 50 | +| -------------- | ------------------------- | ------------------------------------------------------------------ | |
| 51 | +| `E2E_BASE_URL` | `http://localhost:8000` | Where the FastAPI host is listening. | |
| 52 | +| `E2E_USERNAME` | `admin` | Keycloak username. The seeded `admin` user has role `admin`. | |
| 53 | +| `E2E_PASSWORD` | `admin` | Keycloak password for the above user. | |
| 54 | + |
| 55 | +Seeded Keycloak users live in [keycloak/realm-export.json](../keycloak/realm-export.json). |
| 56 | +The defaults match the `admin`/`admin` user out of the box. |
| 57 | + |
| 58 | +## What the smoke tests cover |
| 59 | + |
| 60 | +**`test_login_and_browse_smoke`** |
| 61 | + |
| 62 | +1. Landing page renders (`/`) with the "Get Started" CTA. |
| 63 | +2. Keycloak OIDC login round-trip. |
| 64 | +3. Dashboard (`/dashboard/`) renders — proves session cookie + AuthMiddleware + |
| 65 | + Inertia resolver + AuthenticatedLayout. |
| 66 | +4. Products browse (`/products/`) renders — proves module pages resolve. |
| 67 | +5. Logout returns the user to the public landing page. |
| 68 | + |
| 69 | +**`test_products_crud_smoke`** |
| 70 | + |
| 71 | +1. Login as admin. |
| 72 | +2. Create a timestamped product via the Create form. |
| 73 | +3. Edit its name and verify the new name appears in the list. |
| 74 | +4. Delete it through the confirm dialog and verify the row disappears. |
| 75 | + |
| 76 | +The CRUD test relies on the Keycloak `simple-module-app` client shipping a |
| 77 | +`realm roles` protocol mapper that emits `realm_access.roles` into userinfo |
| 78 | +(see [keycloak/realm-export.json](../keycloak/realm-export.json)); without |
| 79 | +that, `RequiresPermission("products.create")` returns 403. |
| 80 | + |
| 81 | +These are **not** pixel-perfect regression tests — the goal is to catch broad |
| 82 | +breakage in the auth + render + CRUD spine. |
| 83 | + |
| 84 | +## Debugging |
| 85 | + |
| 86 | +To see what the browser is doing, run headed with the Playwright trace |
| 87 | +viewer: |
| 88 | + |
| 89 | +```bash |
| 90 | +uv run pytest -m e2e tests/e2e --headed --slowmo 250 |
| 91 | +``` |
| 92 | + |
| 93 | +Add `--tracing on` to capture a trace for post-mortem inspection via |
| 94 | +`playwright show-trace`. |
0 commit comments