5.0 KiB
5.0 KiB
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
- Call
validator.InitValidator()once. - Use-case-level checks build
useCases.NewCancelRegistrationUseCase(repo)whererepois amockUserRepopre-populated directly viarepo.users[id] = user.User{...}. - HTTP-level checks wire
mockUserRepo,useCases.NewCancelRegistrationUseCase(repo)and the other existing use cases intoauth.NewHandler(...)(extended with the newCancelRegistrationUseCaseparameter) with a testjwtauth.New("HS256", []byte("test-secret"), nil). MountDELETE /v1/auth/registeron a freshchi.NewRouter()wrapped injwtauth.Verifier(token)thenjwtauth.Authenticator(token), mirroring the protected groupapi/router.goadds insideNewAuthRouter(the same groupPOST /v1/auth/verifyalready sits in). Mint jwt cookies withtoken.Encode(map[string]any{"user_id": uint32(7)})for the valid-token cases.
Use-case-level checks (no HTTP)
- Repo has user id 3,
IsVerified: false. CallCancelRegistration(3). Asserterr == nil. Assertrepo.usersno longer has key 3 (orrepo.Get(3)returnsuser.ErrUserNotFound). - Repo has user id 3,
IsVerified: true. CallCancelRegistration(3). Asserterrors.Is(err, user.ErrAlreadyVerified). Assert the repo still has user id 3 withIsVerified: true. - Repo has no user with id 42. Call
CancelRegistration(42). Asserterrors.Is(err, user.ErrUserNotFound).
HTTP-level checks (fakes, per the shared setup above)
- Seed
mockUserRepowith user id 7, username "alice", email "alice@example.com",IsVerified: false. Mint a valid jwt cookie for user id 7.DELETE /v1/auth/registerwith that cookie → assert status200, response body decodes to a JSON object with amessagefield, the response has aSet-Cookieheader forjwtwithMaxAge < 0(or anExpiresin the past) and an emptyValue(parse withhttp.ParseSetCookie, mirroringsecureAttributeFromResponseintest/runtime_settings_injection_http_test.go), andrepo.Get(7)now returnsuser.ErrUserNotFound. - Re-registration after cancel: repeat case 7's cancel call on the same router/repo, then
POST /v1/auth/registerwith{"username":"alice","password":"hunter2example12","email":"alice@example.com"}→ assert status200, ajwtSet-Cookieheader is present with a non-empty value, and the newly created user's id (read back viarepo.GetByUsername("alice")or the use case) is different from7. - Seed
mockUserRepowith user id 7, username "alice", email "alice@example.com",IsVerified: true. Mint a valid jwt cookie for user id 7.DELETE /v1/auth/registerwith that cookie → assert status403, body exactly theapperr.AlreadyVerifiedErrorMessageconstant, noSet-Cookieheader forjwtis present in the response, andrepo.Get(7)still returns the user withIsVerified: true. - Table-driven over three "no valid user_id" cases, each against a fresh seed of user id 7,
IsVerified: false, and asserting status401, a response body equal toapperr.UnauthorizedErrorMessage, nojwtSet-Cookieheader in the response, andrepo.Get(7)still succeeding afterward:- mint the jwt with
token.Encode(map[string]any{"role": "user"})(nouser_idkey 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).
- mint the jwt with
- A request with no
jwtcookie at all against the same router → assert status401(produced byjwtauth.Authenticatoritself, before the handler runs); do not assert an exact body for this case, and assertrepo.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/registerand 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.featureand is not re-verified here.