package services import ( "context" "testing" "time" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/driver/sqlite" "gorm.io/gorm" "veza-backend-api/internal/models" "veza-backend-api/internal/repositories" ) func setupTestRoomService(t *testing.T) (*RoomService, *gorm.DB) { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) require.NoError(t, err) // Enable foreign keys db.Exec("PRAGMA foreign_keys = ON") err = db.AutoMigrate(&models.User{}, &models.Room{}, &models.RoomMember{}, &models.ChatMessage{}) require.NoError(t, err) logger := zap.NewNop() roomRepo := repositories.NewRoomRepository(db) messageRepo := repositories.NewChatMessageRepository(db) service := NewRoomService(roomRepo, messageRepo, logger) return service, db } func createTestUserForRoom(t *testing.T, db *gorm.DB, username string) *models.User { user := &models.User{ ID: uuid.New(), Username: username, Email: username + "@example.com", PasswordHash: "hash", IsActive: true, } err := db.Create(user).Error require.NoError(t, err) return user } func TestRoomService_CreateRoom(t *testing.T) { service, db := setupTestRoomService(t) user := createTestUserForRoom(t, db, "user1") req := CreateRoomRequest{ Name: "Test Room", Type: "public", IsPrivate: false, } room, err := service.CreateRoom(context.Background(), user.ID, req) assert.NoError(t, err) assert.NotNil(t, room) assert.Equal(t, req.Name, room.Name) assert.Contains(t, room.Participants, user.ID) // Verify room created in DB var createdRoom models.Room err = db.First(&createdRoom, "id = ?", room.ID).Error assert.NoError(t, err) assert.Equal(t, room.ID, createdRoom.ID) } func TestRoomService_GetUserRooms(t *testing.T) { service, db := setupTestRoomService(t) user1 := createTestUserForRoom(t, db, "user1") user2 := createTestUserForRoom(t, db, "user2") roomReq1 := CreateRoomRequest{Name: "Room 1", Type: "public", IsPrivate: false} roomReq2 := CreateRoomRequest{Name: "Room 2", Type: "private", IsPrivate: true} room1, err := service.CreateRoom(context.Background(), user1.ID, roomReq1) require.NoError(t, err) room2, err := service.CreateRoom(context.Background(), user2.ID, roomReq2) require.NoError(t, err) // User 1 joins room 2 err = service.AddMember(context.Background(), room2.ID, user1.ID) assert.NoError(t, err) rooms, err := service.GetUserRooms(context.Background(), user1.ID) assert.NoError(t, err) assert.Len(t, rooms, 2) // Should contain Room 1 and Room 2 // Check content var foundRoom1, foundRoom2 bool for _, r := range rooms { if r.ID == room1.ID { foundRoom1 = true } if r.ID == room2.ID { foundRoom2 = true } } assert.True(t, foundRoom1) assert.True(t, foundRoom2) } func TestRoomService_GetRoomHistory(t *testing.T) { service, db := setupTestRoomService(t) user := createTestUserForRoom(t, db, "user1") // Create a room roomReq := CreateRoomRequest{Name: "History Room", Type: "public", IsPrivate: false} room, err := service.CreateRoom(context.Background(), user.ID, roomReq) require.NoError(t, err) // Add messages to DB msgs := []models.ChatMessage{ {ID: uuid.New(), ConversationID: room.ID, SenderID: user.ID, Content: "Hello 1", CreatedAt: time.Now().Add(-2 * time.Minute)}, {ID: uuid.New(), ConversationID: room.ID, SenderID: user.ID, Content: "Hello 2", CreatedAt: time.Now().Add(-1 * time.Minute)}, {ID: uuid.New(), ConversationID: room.ID, SenderID: user.ID, Content: "Hello 3", CreatedAt: time.Now()}, } for _, msg := range msgs { db.Create(&msg) } history, err := service.GetRoomHistory(context.Background(), room.ID, 10, 0) assert.NoError(t, err) assert.Len(t, history, 3) assert.Equal(t, "Hello 3", history[0].Content) // ordered by created_at DESC history, err = service.GetRoomHistory(context.Background(), room.ID, 1, 1) // limit 1, offset 1 assert.NoError(t, err) assert.Len(t, history, 1) assert.Equal(t, "Hello 2", history[0].Content) } func TestRoomService_GetRoom_Success(t *testing.T) { service, db := setupTestRoomService(t) user := createTestUserForRoom(t, db, "user1") req := CreateRoomRequest{Name: "Single Room", Type: "public", IsPrivate: false} createdRoom, err := service.CreateRoom(context.Background(), user.ID, req) require.NoError(t, err) retrievedRoom, err := service.GetRoom(context.Background(), createdRoom.ID) assert.NoError(t, err) require.NotNil(t, retrievedRoom) assert.Equal(t, createdRoom.ID, retrievedRoom.ID) assert.Equal(t, "Single Room", retrievedRoom.Name) } func TestRoomService_GetRoom_NotFound(t *testing.T) { service, _ := setupTestRoomService(t) _, err := service.GetRoom(context.Background(), uuid.New()) assert.Error(t, err) // GORM RecordNotFound might be wrapped or returned as error // Implementation returns fmt.Errorf("failed to get room: %w", err) // So we assume it errors out. } func TestRoomService_AddMember_Success(t *testing.T) { service, db := setupTestRoomService(t) user1 := createTestUserForRoom(t, db, "user1") user2 := createTestUserForRoom(t, db, "user2") roomReq := CreateRoomRequest{Name: "Member Room", Type: "public", IsPrivate: false} room, err := service.CreateRoom(context.Background(), user1.ID, roomReq) require.NoError(t, err) err = service.AddMember(context.Background(), room.ID, user2.ID) assert.NoError(t, err) // Verify members in DB var members []models.RoomMember db.Where("room_id = ?", room.ID).Find(&members) assert.Len(t, members, 2) // Owner + New Member var foundUser2 bool for _, m := range members { if m.UserID == user2.ID { foundUser2 = true } } assert.True(t, foundUser2) }