2025-12-03 19:29:37 +00:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"net/http"
|
|
|
|
|
"net/http/httptest"
|
|
|
|
|
"testing"
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
"veza-backend-api/internal/models"
|
|
|
|
|
"veza-backend-api/internal/services"
|
|
|
|
|
|
2025-12-03 19:29:37 +00:00
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2026-01-03 17:48:45 +00:00
|
|
|
"github.com/stretchr/testify/mock"
|
2025-12-03 19:29:37 +00:00
|
|
|
"go.uber.org/zap"
|
|
|
|
|
)
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// MockChatServiceForChatHandler mocks ChatService
|
|
|
|
|
type MockChatServiceForChatHandler struct {
|
|
|
|
|
mock.Mock
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
func (m *MockChatServiceForChatHandler) GenerateToken(userID uuid.UUID, username string) (*services.ChatTokenResponse, error) {
|
|
|
|
|
args := m.Called(userID, username)
|
|
|
|
|
if args.Get(0) == nil {
|
|
|
|
|
return nil, args.Error(1)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
2026-01-03 17:48:45 +00:00
|
|
|
return args.Get(0).(*services.ChatTokenResponse), args.Error(1)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
func (m *MockChatServiceForChatHandler) GetStats(ctx context.Context) (*services.ChatStats, error) {
|
|
|
|
|
args := m.Called(ctx)
|
|
|
|
|
if args.Get(0) == nil {
|
|
|
|
|
return nil, args.Error(1)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
2026-01-03 17:48:45 +00:00
|
|
|
return args.Get(0).(*services.ChatStats), args.Error(1)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
2026-01-03 17:48:45 +00:00
|
|
|
|
|
|
|
|
// MockUserServiceForChatHandler mocks UserService
|
|
|
|
|
type MockUserServiceForChatHandler struct {
|
|
|
|
|
mock.Mock
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
func (m *MockUserServiceForChatHandler) GetByID(userID uuid.UUID) (*models.User, error) {
|
|
|
|
|
args := m.Called(userID)
|
|
|
|
|
if args.Get(0) == nil {
|
|
|
|
|
return nil, args.Error(1)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
2026-01-03 17:48:45 +00:00
|
|
|
return args.Get(0).(*models.User), args.Error(1)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
func setupTestChatRouter(mockChatService *MockChatServiceForChatHandler, mockUserService *MockUserServiceForChatHandler) *gin.Engine {
|
2025-12-03 19:29:37 +00:00
|
|
|
gin.SetMode(gin.TestMode)
|
2026-01-03 17:48:45 +00:00
|
|
|
router := gin.New()
|
2025-12-03 19:29:37 +00:00
|
|
|
|
|
|
|
|
logger := zap.NewNop()
|
2026-01-03 17:48:45 +00:00
|
|
|
handler := NewChatHandlerWithInterface(mockChatService, mockUserService, logger)
|
|
|
|
|
|
|
|
|
|
api := router.Group("/api/v1/chat")
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-03 19:29:37 +00:00
|
|
|
c.Next()
|
|
|
|
|
})
|
2026-01-03 17:48:45 +00:00
|
|
|
{
|
|
|
|
|
api.GET("/token", handler.GetToken)
|
|
|
|
|
api.GET("/stats", handler.GetStats)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
return router
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestChatHandler_GetToken_Success(t *testing.T) {
|
2026-01-03 17:48:45 +00:00
|
|
|
// Setup
|
|
|
|
|
mockChatService := new(MockChatServiceForChatHandler)
|
|
|
|
|
mockUserService := new(MockUserServiceForChatHandler)
|
|
|
|
|
router := setupTestChatRouter(mockChatService, mockUserService)
|
|
|
|
|
|
|
|
|
|
userID := uuid.New()
|
|
|
|
|
username := "testuser"
|
|
|
|
|
expectedToken := &services.ChatTokenResponse{
|
|
|
|
|
Token: "test-token-123",
|
|
|
|
|
}
|
2025-12-03 19:29:37 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
user := &models.User{
|
|
|
|
|
ID: userID,
|
|
|
|
|
Username: username,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mockUserService.On("GetByID", userID).Return(user, nil)
|
|
|
|
|
mockChatService.On("GenerateToken", userID, username).Return(expectedToken, nil)
|
|
|
|
|
|
|
|
|
|
// Execute
|
|
|
|
|
req, _ := http.NewRequest("GET", "/api/v1/chat/token", nil)
|
|
|
|
|
req.Header.Set("X-User-ID", userID.String())
|
2025-12-03 19:29:37 +00:00
|
|
|
w := httptest.NewRecorder()
|
2026-01-03 17:48:45 +00:00
|
|
|
router.ServeHTTP(w, req)
|
2025-12-03 19:29:37 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Assert
|
2025-12-03 19:29:37 +00:00
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
2026-01-03 17:48:45 +00:00
|
|
|
mockChatService.AssertExpectations(t)
|
|
|
|
|
mockUserService.AssertExpectations(t)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestChatHandler_GetToken_Unauthorized(t *testing.T) {
|
2026-01-03 17:48:45 +00:00
|
|
|
// Setup
|
|
|
|
|
mockChatService := new(MockChatServiceForChatHandler)
|
|
|
|
|
mockUserService := new(MockUserServiceForChatHandler)
|
|
|
|
|
router := setupTestChatRouter(mockChatService, mockUserService)
|
2025-12-03 19:29:37 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Execute - No X-User-ID header
|
|
|
|
|
req, _ := http.NewRequest("GET", "/api/v1/chat/token", nil)
|
2025-12-03 19:29:37 +00:00
|
|
|
w := httptest.NewRecorder()
|
2026-01-03 17:48:45 +00:00
|
|
|
router.ServeHTTP(w, req)
|
2025-12-03 19:29:37 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Assert
|
2025-12-03 19:29:37 +00:00
|
|
|
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
2026-01-03 17:48:45 +00:00
|
|
|
mockChatService.AssertNotCalled(t, "GenerateToken")
|
|
|
|
|
mockUserService.AssertNotCalled(t, "GetByID")
|
2025-12-25 00:28:36 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
func TestChatHandler_GetToken_UserServiceError(t *testing.T) {
|
|
|
|
|
// Setup
|
|
|
|
|
mockChatService := new(MockChatServiceForChatHandler)
|
|
|
|
|
mockUserService := new(MockUserServiceForChatHandler)
|
|
|
|
|
router := setupTestChatRouter(mockChatService, mockUserService)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
|
|
|
|
userID := uuid.New()
|
2026-01-03 17:48:45 +00:00
|
|
|
expectedToken := &services.ChatTokenResponse{
|
|
|
|
|
Token: "test-token-123",
|
2025-12-25 00:28:36 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// UserService returns error, handler should use fallback username
|
|
|
|
|
mockUserService.On("GetByID", userID).Return(nil, assert.AnError)
|
|
|
|
|
mockChatService.On("GenerateToken", userID, mock.MatchedBy(func(username string) bool {
|
|
|
|
|
return username == "user_"+userID.String()
|
|
|
|
|
})).Return(expectedToken, nil)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Execute
|
|
|
|
|
req, _ := http.NewRequest("GET", "/api/v1/chat/token", nil)
|
|
|
|
|
req.Header.Set("X-User-ID", userID.String())
|
2025-12-25 00:28:36 +00:00
|
|
|
w := httptest.NewRecorder()
|
2026-01-03 17:48:45 +00:00
|
|
|
router.ServeHTTP(w, req)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Assert
|
2025-12-25 00:28:36 +00:00
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
2026-01-03 17:48:45 +00:00
|
|
|
mockChatService.AssertExpectations(t)
|
|
|
|
|
mockUserService.AssertExpectations(t)
|
2025-12-25 00:28:36 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
func TestChatHandler_GetToken_ChatServiceError(t *testing.T) {
|
|
|
|
|
// Setup
|
|
|
|
|
mockChatService := new(MockChatServiceForChatHandler)
|
|
|
|
|
mockUserService := new(MockUserServiceForChatHandler)
|
|
|
|
|
router := setupTestChatRouter(mockChatService, mockUserService)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
userID := uuid.New()
|
|
|
|
|
username := "testuser"
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
user := &models.User{
|
|
|
|
|
ID: userID,
|
|
|
|
|
Username: username,
|
|
|
|
|
}
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
mockUserService.On("GetByID", userID).Return(user, nil)
|
|
|
|
|
mockChatService.On("GenerateToken", userID, username).Return(nil, assert.AnError)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Execute
|
|
|
|
|
req, _ := http.NewRequest("GET", "/api/v1/chat/token", nil)
|
|
|
|
|
req.Header.Set("X-User-ID", userID.String())
|
2025-12-25 00:28:36 +00:00
|
|
|
w := httptest.NewRecorder()
|
2026-01-03 17:48:45 +00:00
|
|
|
router.ServeHTTP(w, req)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Assert
|
|
|
|
|
assert.Equal(t, http.StatusInternalServerError, w.Code)
|
|
|
|
|
mockChatService.AssertExpectations(t)
|
|
|
|
|
mockUserService.AssertExpectations(t)
|
2025-12-25 00:28:36 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
func TestChatHandler_GetStats_Success(t *testing.T) {
|
|
|
|
|
// Setup
|
|
|
|
|
mockChatService := new(MockChatServiceForChatHandler)
|
|
|
|
|
mockUserService := new(MockUserServiceForChatHandler)
|
|
|
|
|
router := setupTestChatRouter(mockChatService, mockUserService)
|
|
|
|
|
|
|
|
|
|
expectedStats := &services.ChatStats{
|
|
|
|
|
TotalMessages: 100,
|
|
|
|
|
ActiveUsers: 10,
|
|
|
|
|
}
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
mockChatService.On("GetStats", mock.Anything).Return(expectedStats, nil)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Execute
|
|
|
|
|
req, _ := http.NewRequest("GET", "/api/v1/chat/stats", nil)
|
2025-12-25 00:28:36 +00:00
|
|
|
w := httptest.NewRecorder()
|
2026-01-03 17:48:45 +00:00
|
|
|
router.ServeHTTP(w, req)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Assert
|
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
|
mockChatService.AssertExpectations(t)
|
2025-12-25 00:28:36 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
func TestChatHandler_GetStats_ServiceError(t *testing.T) {
|
|
|
|
|
// Setup
|
|
|
|
|
mockChatService := new(MockChatServiceForChatHandler)
|
|
|
|
|
mockUserService := new(MockUserServiceForChatHandler)
|
|
|
|
|
router := setupTestChatRouter(mockChatService, mockUserService)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
mockChatService.On("GetStats", mock.Anything).Return(nil, assert.AnError)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Execute
|
|
|
|
|
req, _ := http.NewRequest("GET", "/api/v1/chat/stats", nil)
|
2025-12-25 00:28:36 +00:00
|
|
|
w := httptest.NewRecorder()
|
2026-01-03 17:48:45 +00:00
|
|
|
router.ServeHTTP(w, req)
|
2025-12-25 00:28:36 +00:00
|
|
|
|
2026-01-03 17:48:45 +00:00
|
|
|
// Assert
|
|
|
|
|
assert.Equal(t, http.StatusInternalServerError, w.Code)
|
|
|
|
|
mockChatService.AssertExpectations(t)
|
2025-12-25 00:28:36 +00:00
|
|
|
}
|