- docs: SCOPE_CONTROL, CONTRIBUTING, README, .github templates - frontend: DeveloperDashboardView, Player components, MSW handlers, auth, reactQuerySync - backend: playback_analytics, playlist_service, testutils, integration README Excluded (artifacts): .auth, playwright-report, test-results, storybook_audit_detailed.json
118 lines
3.1 KiB
Go
118 lines
3.1 KiB
Go
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)
|
|
}
|