Files
Authentication/helper/response_test.go
T
2025-11-25 15:12:31 +08:00

313 lines
7.8 KiB
Go

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)
}
}