51 lines
3.6 KiB
Markdown
51 lines
3.6 KiB
Markdown
# QA procedure: unverified_users_and_reregistration
|
|
|
|
Package: `test` (black-box), extending `test/user_test.go` (mockUserRepo) and reusing the
|
|
`openInMemoryDb(t)` helper from `test/not_found_errors_test.go`.
|
|
|
|
## Setup shared by every case
|
|
1. Call `validator.InitValidator()` once.
|
|
2. Repository-level checks use `openInMemoryDb(t)`, `db.AutoMigrate(&models.User{})`, and a real
|
|
`persistence.NewUserRepository(db)`.
|
|
3. HTTP-level checks use `mockUserRepo` (from `test/user_test.go`) wired into
|
|
`useCases.NewCreateUserUseCase(repo, &hashing.BcryptHasher{})`,
|
|
`useCases.NewListUsersUseCase(repo)`, `useCases.NewGetUserUseCase(repo)`,
|
|
`useCases.NewAuthenticateUserUseCase(repo, ...)`, and `auth.NewHandler(...)` with a test
|
|
`jwtauth.New("HS256", []byte("test-secret"), nil)`. Mount `POST /v1/auth/register` and
|
|
`POST /v1/auth/login` unprotected on a fresh `chi.NewRouter()`, mirroring `api/router.go`. No live
|
|
server.
|
|
|
|
## Repository-level checks (real persistence repository, in-memory SQLite, no HTTP)
|
|
4. On an empty repository, `Create` a user "alice"/"alice@example.com" with `PasswordResetCode: ""` and
|
|
`VerificationCode: "code-alice"` → assert `err == nil`. `Create` a second user "bob"/"bob@example.com"
|
|
with `PasswordResetCode: ""` and `VerificationCode: "code-bob"` → assert `err == nil` (regression: before
|
|
the fix this fails with a SQLite `UNIQUE constraint failed: users.password_reset_code` error). Then
|
|
`GetByUsername("alice")` and `GetByUsername("bob")` → assert `PasswordResetCode == ""` for both.
|
|
5. `Create` a user "alice" with `PasswordResetCode: "shared-code"`. `Create` a user "bob" with the same
|
|
`PasswordResetCode: "shared-code"` → assert `err != nil` (the unique constraint still applies to an
|
|
actual shared value). Assert `GetByUsername("bob")` returns `user.ErrUserNotFound` (the row was never
|
|
created).
|
|
6. `Create` a user "alice"/"alice@example.com", capture its id. `Delete(id)` → assert `err == nil`.
|
|
`Create` a new user with the same username "alice" and email "alice@example.com" (a different
|
|
password and verification code) → assert `err == nil` (regression: before the fix this fails with a
|
|
SQLite `UNIQUE constraint failed: users.username` error because the row was only soft-deleted). Assert
|
|
the new user's id differs from the deleted one. Assert `Get(deletedId)` returns `user.ErrUserNotFound`.
|
|
7. `Create` a user "alice"/"alice@example.com" and do **not** delete it. `Create` a second user with
|
|
username "alice" and a different email → assert `err != nil` (unchanged: still rejected while the row
|
|
is live).
|
|
|
|
## HTTP checks (fakes, per the shared setup above)
|
|
8. `POST /v1/auth/register` with `{"username":"alice","password":"hunter2example12","email":"alice@example.com"}`
|
|
against an empty `mockUserRepo` → assert status `200`, a `Set-Cookie: jwt=...` header present, body
|
|
decodes to `{"message":"User registered! HTTPonly jwt cookie created"}`.
|
|
9. `POST /v1/auth/register` again with `{"username":"bob","password":"hunter2example12","email":"bob@example.com"}`
|
|
(repo now holds unverified "alice") → assert status `200` and a `Set-Cookie: jwt=...` header present
|
|
(register stays allowed because no user is verified yet).
|
|
10. Assert `mockUserRepo.users` holds two entries, both `IsVerified == false` and both
|
|
`PasswordResetCode == ""`.
|
|
|
|
## Manual verification (not exercised by the Go test)
|
|
- None. `DeleteUser` has no HTTP route mounted today, so there is no SPA-visible delete-and-re-register
|
|
flow to check by hand, and `CreateUser` does not call the mailer, so there is no SMTP involvement in
|
|
this slice.
|