le-app/directus/integration-testing.md

62 lines
5.5 KiB
Markdown
Raw Permalink Normal View History

# Proposed disposable Directus integration testing
No tests described here have been implemented or run. This is a future design that must never target production.
## Environment
Use a dedicated Compose project with:
- A version-pinned Directus image matching production (currently 12.1.1), not the production `latest` deployment reference.
- A disposable MySQL database matching the production database family.
- Ephemeral uploads and a test-only extensions mount populated only when production extensions have been reviewed and are needed.
- Random per-run signing secrets and test-only static credentials.
- A loopback-only port and an unmistakable test public URL.
- Mail captured by a local sink; no external delivery.
- No production database, network, credentials, host mounts, or URLs.
Provision schema and access configuration from reviewed test fixtures derived from `schema.yaml` and the sanitized role/policy exports. Do not apply the production snapshot automatically until a reviewed fixture process accounts for system collections and version compatibility.
## Test identities
Create only synthetic records:
- Registration Bot with Registration policy and a test-only static credential.
- Supporter Bot with Supporter policy if cross-feature checks need it.
- A normal Users-role account with both Users policies.
- An administrator used only for fixture setup/teardown, never by application requests.
Have the test harness assert each identity's effective permissions before auth scenarios. This catches a valid credential attached to the wrong role/policy.
## Required scenarios
| Area | Cases and assertions |
| --- | --- |
| Registration | Valid account creates an active, login-capable Users-role account; app cookies have expected flags; omitted/default role behavior is explicit; whitespace in passwords is preserved. |
| Duplicate accounts | Duplicate email and duplicate username return the same non-enumerating conflict; mixed case behavior is recorded; failed pre-check cannot turn into a permission disclosure. |
| Email login | Correct credentials succeed; incorrect password and unknown account have indistinguishable responses; rate-limit behavior is isolated per test process. |
| Username login | Registration credential resolves username using only permitted fields; correct credentials succeed; unknown username is generic; missing/mis-scoped credential fails clearly without exposing Directus internals. |
| Current user | `/users/me` and application wrappers return only expected fields; another user's private fields cannot be queried; middleware validation accepts a valid token and rejects expired/revoked tokens. |
| Refresh | Once implemented, valid refresh rotates/returns expected tokens and cookies; expired/revoked/reused tokens fail; the endpoint never accepts an access token in place of refresh. Until then, assert/document that no application refresh endpoint exists. |
| Logout | Once strengthened, clears all auth state and invokes Directus revocation as designed. Until then, characterize the current local-only `ma_at` clearing and retained refresh cookie as a known failing contract. |
| Profile changes | Own first/last name and location succeed; email requires recent reauth; username update is denied; other-user updates are denied; the recent-auth marker expires and is single-use. |
| Password changes | Correct current password succeeds; incorrect current password fails; minimum length is enforced; username identifier path works; external-provider behavior is tested if enabled; existing token/session behavior is explicitly asserted. |
| Avatar changes | Allowed image succeeds into the test folder and links to self; bad type/signature/size fails; other-user linking and unauthorized folder behavior fail; partial upload cleanup behavior is characterized. |
| Least privilege | Registration identity can read only required role/user fields and create only permitted user fields; cannot update/delete users, read unrelated collections, administer settings, or access the Data Studio. Test whether exported sensitive read fields can be narrowed. |
## Permission-focused negative tests
- Remove Registration `directus_users.read`: username resolution and duplicate checks should fail predictably while the effect on create is separately asserted.
- Remove Registration `directus_users.create`: signup must fail without leaking permission internals.
- Attach the static credential to the wrong role to prove deployment validation catches it.
- Attempt to override role, status, policy, ID, and authentication data through the public app payload; the server must ignore or reject every override.
- Verify Users updates are limited to `id=$CURRENT_USER` and permitted fields.
- Exercise the exported `user_rigs` `%CURRENT_USER` update filter and record actual Directus 12.1.1 behavior.
## Harness and lifecycle
Run tests from outside the Next.js process against its HTTP interface, with a smaller Directus-level suite for permission diagnostics. Wait for both MySQL and Directus health, seed fixtures idempotently, run serial auth tests where rate limiting or cookie state matters, then destroy containers and volumes.
Log method, path template, status, Directus error code, and synthetic fixture ID only. Redact credentials and cookie values at the logging boundary. Never snapshot response bodies containing private profile fields.
CI should fail if the configured Directus version differs from the fixture version, a required permission assertion changes, a sensitive environment name lacks a test placeholder, or teardown leaves the disposable project running.