package helper import ( "encoding/json" "net/http" "net/http/httptest" "testing" ) func TestRespondWithError(t *testing.T) { testCases := []struct { name string statusCode int message string }{ {"Bad Request", http.StatusBadRequest, "Invalid input"}, {"Unauthorized", http.StatusUnauthorized, "Not authenticated"}, {"Forbidden", http.StatusForbidden, "Access denied"}, {"Not Found", http.StatusNotFound, "Resource not found"}, {"Internal Error", http.StatusInternalServerError, "Server error"}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { recorder := httptest.NewRecorder() RespondWithError(recorder, tc.statusCode, tc.message) // Check status code if recorder.Code != tc.statusCode { t.Errorf("Expected status code %d, got %d", tc.statusCode, recorder.Code) } // Check content type contentType := recorder.Header().Get("Content-Type") if contentType != "application/json" { t.Errorf("Expected Content-Type 'application/json', got '%s'", contentType) } // Parse response body var response map[string]string err := json.Unmarshal(recorder.Body.Bytes(), &response) if err != nil { t.Fatalf("Failed to parse response: %v", err) } // Check error message if response["error"] != tc.message { t.Errorf("Expected error message '%s', got '%s'", tc.message, response["error"]) } }) } } func TestRespondWithMessage(t *testing.T) { testCases := []string{ "Operation successful", "User created", "Email sent", "Task completed", } for _, message := range testCases { t.Run(message, func(t *testing.T) { recorder := httptest.NewRecorder() RespondWithMessage(recorder, message) // Check status code (should default to 200) if recorder.Code != http.StatusOK { t.Errorf("Expected status code %d, got %d", http.StatusOK, recorder.Code) } // Parse response body var response map[string]string err := json.Unmarshal(recorder.Body.Bytes(), &response) if err != nil { t.Fatalf("Failed to parse response: %v", err) } // Check message if response["message"] != message { t.Errorf("Expected message '%s', got '%s'", message, response["message"]) } }) } } func TestRespondWithJSON(t *testing.T) { testCases := []struct { name string statusCode int data interface{} }{ { name: "Simple object", statusCode: http.StatusOK, data: map[string]string{"key": "value"}, }, { name: "Array", statusCode: http.StatusOK, data: []string{"item1", "item2", "item3"}, }, { name: "Nested object", statusCode: http.StatusCreated, data: map[string]interface{}{ "user": map[string]string{ "name": "John", "email": "john@example.com", }, "status": "active", }, }, { name: "Number", statusCode: http.StatusOK, data: map[string]int{"count": 42}, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { recorder := httptest.NewRecorder() RespondWithJSON(recorder, tc.statusCode, tc.data) // Check status code if recorder.Code != tc.statusCode { t.Errorf("Expected status code %d, got %d", tc.statusCode, recorder.Code) } // Check content type contentType := recorder.Header().Get("Content-Type") if contentType != "application/json" { t.Errorf("Expected Content-Type 'application/json', got '%s'", contentType) } // Verify response can be parsed as JSON var response interface{} err := json.Unmarshal(recorder.Body.Bytes(), &response) if err != nil { t.Fatalf("Failed to parse response as JSON: %v", err) } }) } } func TestRespondWithErrorEmptyMessage(t *testing.T) { recorder := httptest.NewRecorder() RespondWithError(recorder, http.StatusBadRequest, "") var response map[string]string err := json.Unmarshal(recorder.Body.Bytes(), &response) if err != nil { t.Fatalf("Failed to parse response: %v", err) } if _, exists := response["error"]; !exists { t.Error("Response should contain 'error' key even with empty message") } } func TestRespondWithJSONNilData(t *testing.T) { recorder := httptest.NewRecorder() RespondWithJSON(recorder, http.StatusOK, nil) if recorder.Code != http.StatusOK { t.Errorf("Expected status code %d, got %d", http.StatusOK, recorder.Code) } body := recorder.Body.String() if body != "null\n" { t.Errorf("Expected 'null', got '%s'", body) } } func TestRespondWithErrorStatusCodes(t *testing.T) { statusCodes := []int{ http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden, http.StatusNotFound, http.StatusMethodNotAllowed, http.StatusConflict, http.StatusUnprocessableEntity, http.StatusTooManyRequests, http.StatusInternalServerError, http.StatusServiceUnavailable, } for _, code := range statusCodes { t.Run(http.StatusText(code), func(t *testing.T) { recorder := httptest.NewRecorder() RespondWithError(recorder, code, "Test error") if recorder.Code != code { t.Errorf("Expected status code %d, got %d", code, recorder.Code) } }) } } func TestRespondWithJSONComplex(t *testing.T) { type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` Roles []string `json:"roles"` IsActive bool `json:"is_active"` } user := User{ ID: 123, Name: "Test User", Email: "test@example.com", Roles: []string{"admin", "user"}, IsActive: true, } recorder := httptest.NewRecorder() RespondWithJSON(recorder, http.StatusOK, user) var decoded User err := json.Unmarshal(recorder.Body.Bytes(), &decoded) if err != nil { t.Fatalf("Failed to decode response: %v", err) } if decoded.ID != user.ID { t.Errorf("Expected ID %d, got %d", user.ID, decoded.ID) } if decoded.Name != user.Name { t.Errorf("Expected Name '%s', got '%s'", user.Name, decoded.Name) } if decoded.Email != user.Email { t.Errorf("Expected Email '%s', got '%s'", user.Email, decoded.Email) } if len(decoded.Roles) != len(user.Roles) { t.Errorf("Expected %d roles, got %d", len(user.Roles), len(decoded.Roles)) } if decoded.IsActive != user.IsActive { t.Errorf("Expected IsActive %v, got %v", user.IsActive, decoded.IsActive) } } func TestRespondWithJSONArray(t *testing.T) { data := []map[string]string{ {"id": "1", "name": "Item 1"}, {"id": "2", "name": "Item 2"}, {"id": "3", "name": "Item 3"}, } recorder := httptest.NewRecorder() RespondWithJSON(recorder, http.StatusOK, data) var decoded []map[string]string err := json.Unmarshal(recorder.Body.Bytes(), &decoded) if err != nil { t.Fatalf("Failed to decode response: %v", err) } if len(decoded) != len(data) { t.Errorf("Expected %d items, got %d", len(data), len(decoded)) } } func TestResponseHeadersSet(t *testing.T) { recorder := httptest.NewRecorder() RespondWithJSON(recorder, http.StatusOK, map[string]string{"test": "data"}) // Verify Content-Type is set contentType := recorder.Header().Get("Content-Type") if contentType == "" { t.Error("Content-Type header should be set") } if contentType != "application/json" { t.Errorf("Expected Content-Type 'application/json', got '%s'", contentType) } } func BenchmarkRespondWithError(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { recorder := httptest.NewRecorder() RespondWithError(recorder, http.StatusBadRequest, "Test error") } } func BenchmarkRespondWithMessage(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { recorder := httptest.NewRecorder() RespondWithMessage(recorder, "Test message") } } func BenchmarkRespondWithJSON(b *testing.B) { data := map[string]interface{}{ "id": 123, "name": "Test", "email": "test@example.com", } b.ResetTimer() for i := 0; i < b.N; i++ { recorder := httptest.NewRecorder() RespondWithJSON(recorder, http.StatusOK, data) } }