todo/internal/todo/handler/update_test.go

123 lines
2.9 KiB
Go

package handler
import (
"bytes"
"context"
"encoding/json"
"log/slog"
"errors"
"net/http"
"net/http/httptest"
"testing"
"gitea.michaelthomson.dev/mthomson/habits/internal/todo/service"
)
type MockTodoUpdater struct {
UpdateTodoFunc func(ctx context.Context, todo service.Todo) error
}
func (tg *MockTodoUpdater) UpdateTodo(ctx context.Context, todo service.Todo) error {
return tg.UpdateTodoFunc(ctx, todo)
}
func TestUpdateTodo(t *testing.T) {
logger := slog.Default()
t.Run("update todo", func(t *testing.T) {
updateTodoRequest := UpdateTodoRequest{Name: "clean dishes", Done: false}
service := MockTodoUpdater{
UpdateTodoFunc: func(ctx context.Context, todo service.Todo) error {
return nil
},
}
handler := HandleTodoUpdate(logger, &service)
requestBody, err := json.Marshal(updateTodoRequest)
if err != nil {
t.Fatalf("Failed to marshal request %+v: %v", updateTodoRequest, err)
}
req := httptest.NewRequest(http.MethodPut, "/todo/1", bytes.NewBuffer(requestBody))
res := httptest.NewRecorder()
req.SetPathValue("id", "1")
handler(res, req)
if res.Code != http.StatusOK {
t.Errorf("did not get correct status, got %d, want %d", res.Code, http.StatusOK)
}
})
t.Run("returns 400 with bad json", func(t *testing.T) {
handler := HandleTodoUpdate(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.MethodPut, "/todo/1", bytes.NewBuffer(requestBody))
res := httptest.NewRecorder()
handler(res, req)
if res.Code != http.StatusBadRequest {
t.Errorf("did not get correct status, got %d, want %d", res.Code, http.StatusOK)
}
})
t.Run("returns 400 with bad id", func(t *testing.T) {
handler := HandleTodoUpdate(logger, nil)
req := httptest.NewRequest(http.MethodPut, "/todo/hello", nil)
res := httptest.NewRecorder()
req.SetPathValue("id", "hello")
handler(res, req)
if res.Code != http.StatusBadRequest {
t.Errorf("did not get correct status, got %d, want %d", res.Code, http.StatusOK)
}
})
t.Run("returns 500 arbitrary errors", func(t *testing.T) {
updateTodoRequest := UpdateTodoRequest{Name: "clean dishes", Done: false}
service := MockTodoUpdater{
UpdateTodoFunc: func(ctx context.Context, todo service.Todo) error {
return errors.New("foo bar")
},
}
handler := HandleTodoUpdate(logger, &service)
requestBody, err := json.Marshal(updateTodoRequest)
if err != nil {
t.Fatalf("Failed to marshal request %+v: %v", updateTodoRequest, err)
}
req := httptest.NewRequest(http.MethodPost, "/todo/1", bytes.NewBuffer(requestBody))
res := httptest.NewRecorder()
req.SetPathValue("id", "1")
handler(res, req)
if res.Code != http.StatusInternalServerError {
t.Errorf("did not get correct status, got %d, want %d", res.Code, http.StatusOK)
}
})
}