92 lines
4.0 KiB
Markdown
92 lines
4.0 KiB
Markdown
# Tests
|
|
|
|
Deterministic and hermetic. Integration tests stand up a local mock
|
|
OIDC/OAuth2 server on an ephemeral port; no traffic to a real Gitea.
|
|
|
|
```bash
|
|
just test # full suite
|
|
python3 -m unittest discover -t . -s tests -p 'test_*.py' -v
|
|
bash tests/test_forge_auth_integration.sh
|
|
bash tests/test_setup_args.sh
|
|
bash tests/test_setup_deploy_flag.sh
|
|
bash tests/test_doctor.sh
|
|
bash tests/test_next_steps.sh
|
|
```
|
|
|
|
## Inventory
|
|
|
|
- **`test_forge_auth.py`**: `scripts/forge_auth.py` unit tests: PKCE
|
|
pair generation, HMAC state signing + CSRF rejection,
|
|
`ForgeAuthConfig.from_env` validation (loopback-only redirect,
|
|
missing port, missing env vars, `FORGE_GITEA_USERNAME`
|
|
propagation), `build_authorize_url` with `prompt=login` and
|
|
`login_hint`, `build_gitea_logout_url`, `AuthFile`
|
|
read/write/merge/`has_live_gitea_token`, `auth_store_path`
|
|
precedence, `run_logout`, `main()` dispatcher.
|
|
|
|
- **`test_git_credential_forge.py`**: `scripts/git-credential-forge.py`
|
|
unit tests: credential protocol I/O, host/scheme/port matching,
|
|
live-token fast-path, pass-through for missing store or non-matching
|
|
host, expired-token refresh, refresh-failure handling, `store` /
|
|
`erase` no-ops, `main()` dispatcher.
|
|
|
|
- **`test_forge_auth_integration.py`**: end-to-end Python integration
|
|
tests against `tests/mock_oidc_server.py`: full PKCE flow,
|
|
gateway-required schema on disk, idempotent re-login, refresh-token
|
|
rotation with server-side revocation, logout preserving
|
|
gateway-bearer fields.
|
|
|
|
- **`test_forge_auth_integration.sh`**: shell end-to-end: drives
|
|
`forge_auth.py login` against the mock server, installs the
|
|
credential helper into a sandboxed `$HOME`, and exercises
|
|
`git credential fill`. Covers URL matching, `github.com`
|
|
non-leakage, rotated-token pickup, `just logout` teardown, and the
|
|
username-mismatch guard (login fails, auth file untouched, Gitea
|
|
logout URL surfaced, authorise URL carries `prompt=login` +
|
|
`login_hint`).
|
|
|
|
- **`test_setup_args.sh`**: `scripts/setup.sh` coverage: argument
|
|
parsing, `--help`, `--headless` wiring to `forge_login.sh
|
|
--no-browser`, the `--headless + FORGE_SETUP_YES=1` hang guard,
|
|
live-token reuse, silent-refresh rescue, `prompt_choice` non-tty
|
|
stdout isolation.
|
|
|
|
- **`test_setup_deploy_flag.sh`**: `scripts/setup.sh --deploy`
|
|
coverage: `--deploy` is parsed and surfaced in `--help`,
|
|
`setup.sh` with `--deploy` swaps the manifest/recipe pair to
|
|
`operator_setup_steps.json` / `operator-setup`, non-interactive
|
|
runs either hand off or print the `just run-next-steps --manifest
|
|
operator_setup_steps.json --recipe operator-setup` follow-up
|
|
hint, and `next_steps.sh --run --manifest ... --recipe
|
|
operator-setup` execs the expected recipe in the orchestrator
|
|
checkout.
|
|
|
|
- **`test_doctor.sh`**: `scripts/doctor.sh`: miss-path under a
|
|
sandboxed PATH, asserts every `[miss]` line is followed by a `fix:`
|
|
line and the consolidated block is emitted.
|
|
|
|
- **`test_next_steps.sh`**: `scripts/next_steps.sh` contract:
|
|
operator manifest / recipe is the default,
|
|
`--manifest contributor_setup_steps.json --recipe contributor-setup`
|
|
swaps to the contributor runner, missing manifest warns and
|
|
points at the orchestrator README, `--headless` / `--yes` /
|
|
`--skip-optional` / `--only ID` forward verbatim to the selected
|
|
`just <recipe>`. Fixtures use generic step ids (the real manifests
|
|
ship with the orchestrator).
|
|
|
|
- **`mock_oidc_server.py`**: test fixture implementing
|
|
`/.well-known/openid-configuration`, `/login/oauth/authorize`,
|
|
`/login/oauth/access_token`, `/login/oauth/userinfo`. PKCE
|
|
verification on `authorization_code`; rotation + revocation on
|
|
`refresh_token`.
|
|
|
|
## Adding tests
|
|
|
|
- Python: drop `test_*.py` in this directory, use `unittest`, stdlib
|
|
only.
|
|
- Shell: executable, deterministic, non-interactive. Use ephemeral
|
|
ports via `python3 -c 'import socket; ...'` and sandbox `$HOME`
|
|
with `mktemp -d`. Stub external binaries (e.g. `just`, `git`) by
|
|
dropping a script into a temp `fakebin/` and prepending it to
|
|
`PATH`.
|