Files
RenewCMS/features/cancel_pending_registration.qa.md

77 lines
5.0 KiB
Markdown

# QA procedure: cancel_pending_registration
Package: `test` (black-box), extending `test/user_test.go` (`mockUserRepo`) and following the
router/handler wiring pattern already used in `test/account_verification_http_test.go`.
## Test infrastructure reused, none new needed
`mockUserRepo` already supports deleting an entry (used by the existing `DeleteUserUseCase` tests
in `test/use_case_baseline_test.go`) and returning `user.ErrUserNotFound` from `Get` once a user is
gone. No new mock methods are required; `CancelRegistrationUseCase` only calls `Get` and `Delete`,
both of which `mockUserRepo` already implements.
## Setup shared by every case
1. Call `validator.InitValidator()` once.
2. Use-case-level checks build `useCases.NewCancelRegistrationUseCase(repo)` where `repo` is a
`mockUserRepo` pre-populated directly via `repo.users[id] = user.User{...}`.
3. HTTP-level checks wire `mockUserRepo`, `useCases.NewCancelRegistrationUseCase(repo)` and the
other existing use cases into `auth.NewHandler(...)` (extended with the new
`CancelRegistrationUseCase` parameter) with a test `jwtauth.New("HS256", []byte("test-secret"),
nil)`. Mount `DELETE /v1/auth/register` on a fresh `chi.NewRouter()` wrapped in
`jwtauth.Verifier(token)` then `jwtauth.Authenticator(token)`, mirroring the protected group
`api/router.go` adds inside `NewAuthRouter` (the same group `POST /v1/auth/verify` already sits
in). Mint jwt cookies with `token.Encode(map[string]any{"user_id": uint32(7)})` for the
valid-token cases.
## Use-case-level checks (no HTTP)
4. Repo has user id 3, `IsVerified: false`. Call `CancelRegistration(3)`. Assert `err == nil`.
Assert `repo.users` no longer has key 3 (or `repo.Get(3)` returns `user.ErrUserNotFound`).
5. Repo has user id 3, `IsVerified: true`. Call `CancelRegistration(3)`. Assert
`errors.Is(err, user.ErrAlreadyVerified)`. Assert the repo still has user id 3 with
`IsVerified: true`.
6. Repo has no user with id 42. Call `CancelRegistration(42)`. Assert
`errors.Is(err, user.ErrUserNotFound)`.
## HTTP-level checks (fakes, per the shared setup above)
7. Seed `mockUserRepo` with user id 7, username "alice", email "alice@example.com",
`IsVerified: false`. Mint a valid jwt cookie for user id 7. `DELETE /v1/auth/register` with that
cookie → assert status `200`, response body decodes to a JSON object with a `message` field,
the response has a `Set-Cookie` header for `jwt` with `MaxAge < 0` (or an `Expires` in the past)
and an empty `Value` (parse with `http.ParseSetCookie`, mirroring
`secureAttributeFromResponse` in `test/runtime_settings_injection_http_test.go`), and
`repo.Get(7)` now returns `user.ErrUserNotFound`.
8. Re-registration after cancel: repeat case 7's cancel call on the same router/repo, then
`POST /v1/auth/register` with `{"username":"alice","password":"hunter2example12","email":"alice@example.com"}`
→ assert status `200`, a `jwt` `Set-Cookie` header is present with a non-empty value, and the
newly created user's id (read back via `repo.GetByUsername("alice")` or the use case) is
different from `7`.
9. Seed `mockUserRepo` with user id 7, username "alice", email "alice@example.com",
`IsVerified: true`. Mint a valid jwt cookie for user id 7. `DELETE /v1/auth/register` with that
cookie → assert status `403`, body exactly the `apperr.AlreadyVerifiedErrorMessage` constant,
no `Set-Cookie` header for `jwt` is present in the response, and `repo.Get(7)` still returns the
user with `IsVerified: true`.
10. Table-driven over three "no valid user_id" cases, each against a fresh seed of user id 7,
`IsVerified: false`, and asserting status `401`, a response body equal to
`apperr.UnauthorizedErrorMessage`, no `jwt` `Set-Cookie` header in the response, and
`repo.Get(7)` still succeeding afterward:
- mint the jwt with `token.Encode(map[string]any{"role": "user"})` (no `user_id` key at all);
- mint the jwt with `token.Encode(map[string]any{"user_id": "seven"})` (string, not a number);
- mint the jwt with `token.Encode(map[string]any{"user_id": uint32(999)})` (well-formed but no
such user in the repo).
11. A request with no `jwt` cookie at all against the same router → assert status `401` (produced
by `jwtauth.Authenticator` itself, before the handler runs); do not assert an exact body for
this case, and assert `repo.Get(7)` still succeeds afterward.
## Manual verification (not exercised by the Go test)
- The SPA-visible "cancel registration" affordance (wherever it is surfaced to a logged-in,
unverified user, e.g. on the pending-verification screen) actually calling
`DELETE /v1/auth/register` and redirecting to a logged-out state on success is out of scope for
this slice's automated test and should be checked by hand against a running dev build.
- End-to-end confirmation against the real SQLite file that the row is physically gone (not just
hidden by a soft-delete) is already covered at the repository level by
`features/unverified_users_and_reregistration.feature` and is not re-verified here.