package handlers import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "go.uber.org/zap" ) // MockCSRFMiddleware mocks CSRFMiddleware type MockCSRFMiddleware struct { mock.Mock } func (m *MockCSRFMiddleware) GetToken(ctx context.Context, userID uuid.UUID) (string, error) { args := m.Called(ctx, userID) return args.String(0), args.Error(1) } func setupTestCSRFRouter(mockCSRFMiddleware *MockCSRFMiddleware) *gin.Engine { gin.SetMode(gin.TestMode) router := gin.New() logger := zap.NewNop() handler := NewCSRFHandlerWithInterface(mockCSRFMiddleware, logger) api := router.Group("/api/v1") api.Use(func(c *gin.Context) { userIDStr := c.GetHeader("X-User-ID") if userIDStr != "" { uid, err := uuid.Parse(userIDStr) if err == nil { c.Set("user_id", uid) } } c.Next() }) { api.GET("/csrf-token", handler.GetCSRFToken()) } return router } func TestCSRFHandler_GetCSRFToken_Success(t *testing.T) { // Setup mockCSRFMiddleware := new(MockCSRFMiddleware) router := setupTestCSRFRouter(mockCSRFMiddleware) userID := uuid.New() expectedToken := "test-csrf-token" mockCSRFMiddleware.On("GetToken", mock.Anything, userID).Return(expectedToken, nil) // Execute req, _ := http.NewRequest("GET", "/api/v1/csrf-token", nil) req.Header.Set("X-User-ID", userID.String()) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusOK, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.True(t, response["success"].(bool)) data := response["data"].(map[string]interface{}) assert.Equal(t, expectedToken, data["csrf_token"]) mockCSRFMiddleware.AssertExpectations(t) } func TestCSRFHandler_GetCSRFToken_Unauthorized(t *testing.T) { // Setup mockCSRFMiddleware := new(MockCSRFMiddleware) router := setupTestCSRFRouter(mockCSRFMiddleware) // Execute - No X-User-ID header (unauthenticated) req, _ := http.NewRequest("GET", "/api/v1/csrf-token", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert - When no user_id, handler returns public anonymous token (200) assert.Equal(t, http.StatusOK, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.True(t, response["success"].(bool)) data := response["data"].(map[string]interface{}) assert.Equal(t, "public-anonymous-token", data["csrf_token"]) mockCSRFMiddleware.AssertNotCalled(t, "GetToken") } func TestCSRFHandler_GetCSRFToken_ServiceError(t *testing.T) { // Setup mockCSRFMiddleware := new(MockCSRFMiddleware) router := setupTestCSRFRouter(mockCSRFMiddleware) userID := uuid.New() mockCSRFMiddleware.On("GetToken", mock.Anything, userID).Return("", assert.AnError) // Execute req, _ := http.NewRequest("GET", "/api/v1/csrf-token", nil) req.Header.Set("X-User-ID", userID.String()) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Assert assert.Equal(t, http.StatusInternalServerError, w.Code) mockCSRFMiddleware.AssertExpectations(t) }