todo/internal/user/handler/register_test.go
Michael Thomson e55d419d44
All checks were successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
auth services, middleware, and other stuff
2025-05-22 13:55:43 -04:00

149 lines
3.6 KiB
Go

package handler
import (
"bytes"
"context"
"encoding/json"
"log/slog"
"errors"
"net/http"
"net/http/httptest"
"testing"
"gitea.michaelthomson.dev/mthomson/habits/internal/user/service"
"github.com/gofrs/uuid/v5"
)
type MockUserRegisterer struct {
RegisterUserFunc func(ctx context.Context, email string, password string) (uuid.UUID, error)
}
func (m *MockUserRegisterer) Register(ctx context.Context, email string, password string) (uuid.UUID, error) {
return m.RegisterUserFunc(ctx, email, password)
}
func TestCreateUser(t *testing.T) {
logger := slog.Default()
t.Run("create user", func(t *testing.T) {
createUserRequest := RegisterRequest{Email: "test@test.com", Password: "password"}
newUUID := NewUUID(t)
service := MockUserRegisterer{
RegisterUserFunc: func(ctx context.Context, email string, password string) (uuid.UUID, error) {
return newUUID, nil
},
}
handler := HandleRegisterUser(logger, &service)
requestBody, err := json.Marshal(createUserRequest)
if err != nil {
t.Fatalf("Failed to marshal request %+v: %v", createUserRequest, err)
}
req := httptest.NewRequest(http.MethodPost, "/register", bytes.NewBuffer(requestBody))
res := httptest.NewRecorder()
handler(res, req)
AssertStatusCodes(t, res.Code, http.StatusOK)
})
t.Run("returns 409 when user exists", func(t *testing.T) {
createUserRequest := RegisterRequest{Email: "test@test.com", Password: "password"}
newUUID := NewUUID(t)
service := MockUserRegisterer{
RegisterUserFunc: func(ctx context.Context, email string, password string) (uuid.UUID, error) {
return newUUID, service.ErrUserExists
},
}
handler := HandleRegisterUser(logger, &service)
requestBody, err := json.Marshal(createUserRequest)
if err != nil {
t.Fatalf("Failed to marshal request %+v: %v", createUserRequest, err)
}
req := httptest.NewRequest(http.MethodPost, "/register", bytes.NewBuffer(requestBody))
res := httptest.NewRecorder()
handler(res, req)
AssertStatusCodes(t, res.Code, http.StatusConflict)
})
t.Run("returns 400 with bad json", func(t *testing.T) {
handler := HandleRegisterUser(logger, nil)
badStruct := struct {
Foo string
}{
Foo: "bar",
}
requestBody, err := json.Marshal(badStruct)
if err != nil {
t.Fatalf("Failed to marshal request %+v: %v", badStruct, err)
}
req := httptest.NewRequest(http.MethodPost, "/register", bytes.NewBuffer(requestBody))
res := httptest.NewRecorder()
handler(res, req)
AssertStatusCodes(t, res.Code, http.StatusBadRequest)
})
t.Run("returns 500 arbitrary errors", func(t *testing.T) {
createUserRequest := RegisterRequest{Email: "test@test.com", Password: "password"}
newUUID := NewUUID(t)
service := MockUserRegisterer{
RegisterUserFunc: func(ctx context.Context, email string, password string) (uuid.UUID, error) {
return newUUID, errors.New("foo bar")
},
}
handler := HandleRegisterUser(logger, &service)
requestBody, err := json.Marshal(createUserRequest)
if err != nil {
t.Fatalf("Failed to marshal request %+v: %v", createUserRequest, err)
}
req := httptest.NewRequest(http.MethodPost, "/user", bytes.NewBuffer(requestBody))
res := httptest.NewRecorder()
handler(res, req)
AssertStatusCodes(t, res.Code, http.StatusInternalServerError)
})
}
func AssertStatusCodes(t testing.TB, got, want int) {
t.Helper()
if got != want {
t.Errorf("got status code: %v, want status code: %v", want, got)
}
}
func NewUUID(t testing.TB) uuid.UUID {
t.Helper()
uuid, err := uuid.NewV4()
if err != nil {
t.Errorf("error generation uuid: %v", err)
}
return uuid
}