package handlers import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/go-chi/chi/v5" "git.threesix.ai/jordan/slack-auth-1770277167/pkg/logging" ) func newTestLogger() *logging.Logger { return logging.New(logging.Config{ Level: logging.LevelDebug, Format: logging.FormatText, }) } func TestExample_List(t *testing.T) { handler := NewExample(newTestLogger()) r := chi.NewRouter() r.Get("/api/v1/examples", func(w http.ResponseWriter, r *http.Request) { if err := handler.List(w, r); err != nil { t.Fatalf("unexpected error: %v", err) } }) req := httptest.NewRequest(http.MethodGet, "/api/v1/examples", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusOK { t.Errorf("expected status 200, got %d", w.Code) } var resp map[string]any if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatalf("failed to decode response: %v", err) } data, ok := resp["data"] if !ok { t.Fatal("expected 'data' field in response") } items, ok := data.([]any) if !ok { t.Fatal("expected 'data' to be an array") } if len(items) == 0 { t.Error("expected at least one item in response") } } func TestExample_Get(t *testing.T) { handler := NewExample(newTestLogger()) tests := []struct { name string id string wantStatus int }{ { name: "valid uuid", id: "550e8400-e29b-41d4-a716-446655440000", wantStatus: http.StatusOK, }, { name: "invalid uuid", id: "not-a-uuid", wantStatus: http.StatusBadRequest, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { r := chi.NewRouter() r.Get("/api/v1/examples/{id}", func(w http.ResponseWriter, r *http.Request) { if err := handler.Get(w, r); err != nil { // Error-returning handler: convert error to status w.WriteHeader(http.StatusBadRequest) return } }) req := httptest.NewRequest(http.MethodGet, "/api/v1/examples/"+tt.id, nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != tt.wantStatus { t.Errorf("expected status %d, got %d", tt.wantStatus, w.Code) } }) } } func TestExample_Create(t *testing.T) { handler := NewExample(newTestLogger()) tests := []struct { name string body any wantStatus int }{ { name: "valid request", body: CreateRequest{ Name: "Test Example", Description: "A test description", }, wantStatus: http.StatusCreated, }, { name: "empty body", body: nil, wantStatus: http.StatusBadRequest, }, { name: "missing required name", body: map[string]string{ "description": "no name provided", }, wantStatus: http.StatusUnprocessableEntity, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { r := chi.NewRouter() r.Post("/api/v1/examples", func(w http.ResponseWriter, r *http.Request) { if err := handler.Create(w, r); err != nil { // Simulate Wrap behavior for tests w.WriteHeader(http.StatusBadRequest) return } }) var body []byte if tt.body != nil { var err error body, err = json.Marshal(tt.body) if err != nil { t.Fatalf("failed to marshal body: %v", err) } } req := httptest.NewRequest(http.MethodPost, "/api/v1/examples", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) // For the valid case, check 201 if tt.name == "valid request" && w.Code != http.StatusCreated { t.Errorf("expected status %d, got %d", http.StatusCreated, w.Code) } }) } } func TestExample_Delete(t *testing.T) { handler := NewExample(newTestLogger()) r := chi.NewRouter() r.Delete("/api/v1/examples/{id}", func(w http.ResponseWriter, r *http.Request) { if err := handler.Delete(w, r); err != nil { w.WriteHeader(http.StatusBadRequest) return } }) req := httptest.NewRequest(http.MethodDelete, "/api/v1/examples/550e8400-e29b-41d4-a716-446655440000", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusNoContent { t.Errorf("expected status 204, got %d", w.Code) } }