193 lines
5.8 KiB
Go
193 lines
5.8 KiB
Go
package handlers
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"veza-backend-api/internal/services"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// MockRoomService implements RoomServiceInterface for testing
|
|
type MockRoomService struct {
|
|
CreateRoomFunc func(ctx context.Context, userID uuid.UUID, req services.CreateRoomRequest) (*services.RoomResponse, error)
|
|
GetUserRoomsFunc func(ctx context.Context, userID uuid.UUID) ([]*services.RoomResponse, error)
|
|
GetRoomFunc func(ctx context.Context, roomID uuid.UUID) (*services.RoomResponse, error)
|
|
UpdateRoomFunc func(ctx context.Context, roomID uuid.UUID, userID uuid.UUID, req services.UpdateRoomRequest) (*services.RoomResponse, error)
|
|
AddMemberFunc func(ctx context.Context, roomID, userID uuid.UUID) error
|
|
RemoveMemberFunc func(ctx context.Context, roomID, userID uuid.UUID) error
|
|
GetRoomHistoryFunc func(ctx context.Context, roomID uuid.UUID, limit, offset int) ([]services.ChatMessageResponse, error)
|
|
GetRoomHistoryWithCursorFunc func(ctx context.Context, roomID uuid.UUID, limit int, cursor string) (*services.RoomHistoryWithCursorResult, error)
|
|
DeleteRoomFunc func(ctx context.Context, roomID uuid.UUID, userID uuid.UUID) error
|
|
}
|
|
|
|
func (m *MockRoomService) CreateRoom(ctx context.Context, userID uuid.UUID, req services.CreateRoomRequest) (*services.RoomResponse, error) {
|
|
if m.CreateRoomFunc != nil {
|
|
return m.CreateRoomFunc(ctx, userID, req)
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockRoomService) GetUserRooms(ctx context.Context, userID uuid.UUID) ([]*services.RoomResponse, error) {
|
|
if m.GetUserRoomsFunc != nil {
|
|
return m.GetUserRoomsFunc(ctx, userID)
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockRoomService) GetRoom(ctx context.Context, roomID uuid.UUID) (*services.RoomResponse, error) {
|
|
if m.GetRoomFunc != nil {
|
|
return m.GetRoomFunc(ctx, roomID)
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockRoomService) AddMember(ctx context.Context, roomID, userID uuid.UUID) error {
|
|
if m.AddMemberFunc != nil {
|
|
return m.AddMemberFunc(ctx, roomID, userID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *MockRoomService) GetRoomHistory(ctx context.Context, roomID uuid.UUID, limit, offset int) ([]services.ChatMessageResponse, error) {
|
|
if m.GetRoomHistoryFunc != nil {
|
|
return m.GetRoomHistoryFunc(ctx, roomID, limit, offset)
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockRoomService) GetRoomHistoryWithCursor(ctx context.Context, roomID uuid.UUID, limit int, cursor string) (*services.RoomHistoryWithCursorResult, error) {
|
|
if m.GetRoomHistoryWithCursorFunc != nil {
|
|
return m.GetRoomHistoryWithCursorFunc(ctx, roomID, limit, cursor)
|
|
}
|
|
return &services.RoomHistoryWithCursorResult{Messages: nil, NextCursor: ""}, nil
|
|
}
|
|
|
|
func (m *MockRoomService) UpdateRoom(ctx context.Context, roomID uuid.UUID, userID uuid.UUID, req services.UpdateRoomRequest) (*services.RoomResponse, error) {
|
|
if m.UpdateRoomFunc != nil {
|
|
return m.UpdateRoomFunc(ctx, roomID, userID, req)
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockRoomService) RemoveMember(ctx context.Context, roomID, userID uuid.UUID) error {
|
|
if m.RemoveMemberFunc != nil {
|
|
return m.RemoveMemberFunc(ctx, roomID, userID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *MockRoomService) DeleteRoom(ctx context.Context, roomID uuid.UUID, userID uuid.UUID) error {
|
|
if m.DeleteRoomFunc != nil {
|
|
return m.DeleteRoomFunc(ctx, roomID, userID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestRoomHandler_CreateRoom(t *testing.T) {
|
|
// Setup
|
|
gin.SetMode(gin.TestMode)
|
|
logger := zap.NewNop()
|
|
|
|
userID := uuid.New()
|
|
|
|
tests := []struct {
|
|
name string
|
|
setupMock func() *MockRoomService
|
|
requestBody interface{}
|
|
setupContext func(*gin.Context)
|
|
expectedStatus int
|
|
}{
|
|
{
|
|
name: "Success",
|
|
setupMock: func() *MockRoomService {
|
|
return &MockRoomService{
|
|
CreateRoomFunc: func(ctx context.Context, uid uuid.UUID, req services.CreateRoomRequest) (*services.RoomResponse, error) {
|
|
return &services.RoomResponse{
|
|
ID: uuid.New(),
|
|
Name: req.Name,
|
|
Type: req.Type,
|
|
}, nil
|
|
},
|
|
}
|
|
},
|
|
requestBody: services.CreateRoomRequest{
|
|
Name: "General",
|
|
Type: "public",
|
|
},
|
|
setupContext: func(c *gin.Context) {
|
|
c.Set("user_id", userID)
|
|
},
|
|
expectedStatus: http.StatusCreated,
|
|
},
|
|
{
|
|
name: "Unauthorized",
|
|
setupMock: func() *MockRoomService {
|
|
return &MockRoomService{}
|
|
},
|
|
requestBody: services.CreateRoomRequest{Name: "Test"},
|
|
setupContext: func(c *gin.Context) {
|
|
// No user_id set
|
|
},
|
|
expectedStatus: http.StatusUnauthorized,
|
|
},
|
|
{
|
|
name: "Invalid Payload",
|
|
setupMock: func() *MockRoomService {
|
|
return &MockRoomService{}
|
|
},
|
|
requestBody: "invalid-json", // String instead of struct
|
|
setupContext: func(c *gin.Context) {
|
|
c.Set("user_id", userID)
|
|
},
|
|
expectedStatus: http.StatusBadRequest,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
mockService := tt.setupMock()
|
|
handler := NewRoomHandler(mockService, logger)
|
|
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
|
|
// Setup request
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/conversations", nil)
|
|
if body, ok := tt.requestBody.(string); ok && body == "invalid-json" {
|
|
c.Request.Body = &closingBuffer{bytes.NewBufferString("invalid-json")}
|
|
} else {
|
|
jsonBytes, _ := json.Marshal(tt.requestBody)
|
|
c.Request.Body = &closingBuffer{bytes.NewBuffer(jsonBytes)}
|
|
}
|
|
c.Request.Header.Set("Content-Type", "application/json")
|
|
|
|
// Setup context (auth)
|
|
tt.setupContext(c)
|
|
|
|
// Execute
|
|
handler.CreateRoom(c)
|
|
|
|
// Assert
|
|
if w.Code != tt.expectedStatus {
|
|
t.Errorf("Expected status %d, got %d. Body: %s", tt.expectedStatus, w.Code, w.Body.String())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// closingBuffer helps to mock ReadCloser
|
|
type closingBuffer struct {
|
|
*bytes.Buffer
|
|
}
|
|
|
|
func (cb *closingBuffer) Close() error {
|
|
return nil
|
|
}
|