2026-01-06 07:15:18 +00:00
|
|
|
package repository
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"backend/pkg/chat/domain/chat"
|
|
|
|
|
"backend/pkg/chat/domain/entity"
|
|
|
|
|
"backend/pkg/chat/domain/repository"
|
|
|
|
|
"backend/pkg/library/cassandra"
|
|
|
|
|
"context"
|
|
|
|
|
"strconv"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/gocql/gocql"
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
// 全局變量:所有測試共享的資源(與 message_test.go 共享)
|
|
|
|
|
roomTestRepo repository.RoomRepository
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// ensureRoomRepository 確保 Room Repository 已初始化
|
|
|
|
|
func ensureRoomRepository(t *testing.T) {
|
|
|
|
|
if roomTestRepo == nil {
|
|
|
|
|
if testDB == nil {
|
|
|
|
|
t.Fatal("testDB is not initialized. Make sure TestMain in message_test.go runs first.")
|
|
|
|
|
}
|
|
|
|
|
var err error
|
|
|
|
|
roomTestRepo, err = NewRoomRepository(testDB, "test_keyspace")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("Failed to create room repository: %v", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clearRoomData 清空所有 room 相關表的數據
|
|
|
|
|
func clearRoomData(t *testing.T) {
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
tables := []string{"user_room", "room_member", "room"}
|
|
|
|
|
for _, table := range tables {
|
|
|
|
|
truncateStmt := "TRUNCATE test_keyspace." + table
|
|
|
|
|
if err := testDB.GetSession().Query(truncateStmt, nil).WithContext(ctx).Exec(); err != nil {
|
|
|
|
|
t.Fatalf("Failed to truncate %s table: %v", table, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 等待數據清空
|
|
|
|
|
time.Sleep(50 * time.Millisecond)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== Room Interface 測試 ====================
|
|
|
|
|
|
|
|
|
|
func TestNewRoomRepository(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
assert.NotNil(t, roomTestRepo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_Create(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
room *entity.Room
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "successful create",
|
|
|
|
|
room: &entity.Room{
|
|
|
|
|
Name: "Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
},
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "create with auto timestamp",
|
|
|
|
|
room: &entity.Room{
|
|
|
|
|
Name: "Auto Timestamp Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
},
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
err := roomTestRepo.Create(ctx, tt.room)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
// 驗證 RoomID 和時間戳是否被自動設置
|
|
|
|
|
assert.NotZero(t, tt.room.RoomID)
|
|
|
|
|
assert.NotZero(t, tt.room.CreatedAt)
|
|
|
|
|
assert.NotZero(t, tt.room.UpdatedAt)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_RoomGet(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Get Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
roomIDStr := room.RoomID.String()
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
roomID string
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "get existing room",
|
|
|
|
|
roomID: roomIDStr,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "get non-existent room",
|
|
|
|
|
roomID: gocql.TimeUUID().String(),
|
|
|
|
|
wantErr: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "get with invalid UUID",
|
|
|
|
|
roomID: "invalid-uuid",
|
|
|
|
|
wantErr: true,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
result, err := roomTestRepo.RoomGet(ctx, tt.roomID)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
assert.Nil(t, result)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.NotNil(t, result)
|
|
|
|
|
assert.Equal(t, room.Name, result.Name)
|
|
|
|
|
assert.Equal(t, room.Status, result.Status)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_RoomUpdate(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Original Name",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
originalCreatedAt := room.CreatedAt
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 更新房間
|
|
|
|
|
room.Name = "Updated Name"
|
|
|
|
|
room.Status = "archived"
|
|
|
|
|
err := roomTestRepo.RoomUpdate(ctx, room)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
// 驗證更新
|
|
|
|
|
updated, err := roomTestRepo.RoomGet(ctx, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, "Updated Name", updated.Name)
|
|
|
|
|
assert.Equal(t, "archived", updated.Status)
|
2026-01-07 02:47:37 +00:00
|
|
|
assert.Equal(t, originalCreatedAt, updated.CreatedAt) // CreatedAt 不應該改變
|
2026-01-06 07:15:18 +00:00
|
|
|
assert.Greater(t, updated.UpdatedAt, originalCreatedAt) // UpdatedAt 應該更新
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_RoomDelete(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Delete Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
roomIDStr := room.RoomID.String()
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 刪除房間
|
|
|
|
|
err := roomTestRepo.RoomDelete(ctx, roomIDStr)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
// 驗證房間已被刪除
|
|
|
|
|
_, err = roomTestRepo.RoomGet(ctx, roomIDStr)
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
assert.True(t, cassandra.IsNotFound(err))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_RoomList(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建多個測試房間
|
|
|
|
|
rooms := make([]*entity.Room, 5)
|
|
|
|
|
for i := 0; i < 5; i++ {
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Room " + strconv.Itoa(i),
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
rooms[i] = room
|
|
|
|
|
time.Sleep(10 * time.Millisecond) // 確保時間戳不同
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
param repository.ListRoomsReq
|
|
|
|
|
wantLen int
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "list all rooms",
|
|
|
|
|
param: repository.ListRoomsReq{
|
|
|
|
|
PageSize: 10,
|
|
|
|
|
},
|
|
|
|
|
wantLen: 5,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "list with status filter",
|
|
|
|
|
param: repository.ListRoomsReq{
|
|
|
|
|
Status: "active",
|
|
|
|
|
PageSize: 10,
|
|
|
|
|
},
|
|
|
|
|
wantLen: 5,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "list with page size limit",
|
|
|
|
|
param: repository.ListRoomsReq{
|
|
|
|
|
PageSize: 2,
|
|
|
|
|
},
|
|
|
|
|
wantLen: 2,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
result, err := roomTestRepo.RoomList(ctx, tt.param)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.Len(t, result, tt.wantLen)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_RoomCount(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
for i := 0; i < 3; i++ {
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Count Room " + strconv.Itoa(i),
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 創建一個 archived 房間
|
|
|
|
|
archivedRoom := &entity.Room{
|
|
|
|
|
Name: "Archived Room",
|
|
|
|
|
Status: "archived",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, archivedRoom))
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
param repository.CountRoomsReq
|
|
|
|
|
want int64
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
2026-01-07 02:47:37 +00:00
|
|
|
name: "count all rooms",
|
2026-01-06 07:15:18 +00:00
|
|
|
param: repository.CountRoomsReq{},
|
|
|
|
|
want: 4,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "count active rooms",
|
|
|
|
|
param: repository.CountRoomsReq{
|
|
|
|
|
Status: "active",
|
|
|
|
|
},
|
|
|
|
|
want: 3,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "count archived rooms",
|
|
|
|
|
param: repository.CountRoomsReq{
|
|
|
|
|
Status: "archived",
|
|
|
|
|
},
|
|
|
|
|
want: 1,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
count, err := roomTestRepo.RoomCount(ctx, tt.param)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.Equal(t, tt.want, count)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_RoomExists(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Exists Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
roomIDStr := room.RoomID.String()
|
|
|
|
|
nonExistentID := gocql.TimeUUID().String()
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
roomID string
|
|
|
|
|
want bool
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "existing room",
|
|
|
|
|
roomID: roomIDStr,
|
|
|
|
|
want: true,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "non-existent room",
|
|
|
|
|
roomID: nonExistentID,
|
|
|
|
|
want: false,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
exists, err := roomTestRepo.RoomExists(ctx, tt.roomID)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.Equal(t, tt.want, exists)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_RoomGetByID(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建多個測試房間
|
|
|
|
|
rooms := make([]*entity.Room, 3)
|
|
|
|
|
roomIDs := make([]string, 3)
|
|
|
|
|
for i := 0; i < 3; i++ {
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Room " + strconv.Itoa(i),
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
rooms[i] = room
|
|
|
|
|
roomIDs[i] = room.RoomID.String()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
roomIDs []string
|
|
|
|
|
wantLen int
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "get multiple rooms",
|
|
|
|
|
roomIDs: roomIDs,
|
|
|
|
|
wantLen: 3,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "get empty list",
|
|
|
|
|
roomIDs: []string{},
|
|
|
|
|
wantLen: 0,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "get with non-existent ID",
|
|
|
|
|
roomIDs: []string{roomIDs[0], gocql.TimeUUID().String()},
|
|
|
|
|
wantLen: 1, // 只返回存在的房間
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
result, err := roomTestRepo.RoomGetByID(ctx, tt.roomIDs)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.Len(t, result, tt.wantLen)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== Member Interface 測試 ====================
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_Insert(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Member Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
member *entity.RoomMember
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "successful insert",
|
|
|
|
|
member: &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: "user-1",
|
|
|
|
|
Role: chat.RoomRoleMember.String(),
|
|
|
|
|
},
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "insert with auto role",
|
|
|
|
|
member: &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: "user-2",
|
|
|
|
|
},
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "insert with admin role",
|
|
|
|
|
member: &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: "user-3",
|
|
|
|
|
Role: chat.RoomRoleAdmin.String(),
|
|
|
|
|
},
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
err := roomTestRepo.Insert(ctx, tt.member)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
// 驗證 JoinedAt 是否被自動設置
|
|
|
|
|
assert.NotZero(t, tt.member.JoinedAt)
|
|
|
|
|
// 驗證 Role 是否被自動設置(如果為空)
|
|
|
|
|
if tt.member.Role == "" {
|
|
|
|
|
assert.Equal(t, chat.RoomRoleMember.String(), tt.member.Role)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 驗證 user_room 表也被更新
|
|
|
|
|
userRooms, err := roomTestRepo.GetUserRooms(ctx, tt.member.UID)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Greater(t, len(userRooms), 0)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_Get(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間和成員
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Get Member Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
member := &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: "user-1",
|
|
|
|
|
Role: chat.RoomRoleAdmin.String(),
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
roomID string
|
|
|
|
|
uid string
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "get existing member",
|
|
|
|
|
roomID: room.RoomID.String(),
|
|
|
|
|
uid: "user-1",
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "get non-existent member",
|
|
|
|
|
roomID: room.RoomID.String(),
|
|
|
|
|
uid: "non-existent-user",
|
|
|
|
|
wantErr: true,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
result, err := roomTestRepo.Get(ctx, tt.roomID, tt.uid)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
assert.Nil(t, result)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.NotNil(t, result)
|
|
|
|
|
assert.Equal(t, member.UID, result.UID)
|
|
|
|
|
assert.Equal(t, member.Role, result.Role)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_AllMembers(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "All Members Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
// 插入多個成員
|
|
|
|
|
members := []*entity.RoomMember{
|
|
|
|
|
{RoomID: room.RoomID, UID: "user-1", Role: chat.RoomRoleMember.String()},
|
|
|
|
|
{RoomID: room.RoomID, UID: "user-2", Role: chat.RoomRoleAdmin.String()},
|
|
|
|
|
{RoomID: room.RoomID, UID: "user-3", Role: chat.RoomRoleMember.String()},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, member := range members {
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 查詢所有成員
|
|
|
|
|
result, err := roomTestRepo.AllMembers(ctx, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Len(t, result, 3)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_UpdateRole(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間和成員
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Update Role Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
member := &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: "user-1",
|
|
|
|
|
Role: chat.RoomRoleMember.String(),
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 更新角色
|
|
|
|
|
member.Role = chat.RoomRoleAdmin.String()
|
|
|
|
|
err := roomTestRepo.UpdateRole(ctx, member)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
// 驗證更新
|
|
|
|
|
updated, err := roomTestRepo.Get(ctx, room.RoomID.String(), "user-1")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, chat.RoomRoleAdmin.String(), updated.Role)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_DeleteMember(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間和成員
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Delete Member Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
member := &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: "user-1",
|
|
|
|
|
Role: chat.RoomRoleMember.String(),
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 刪除成員
|
|
|
|
|
err := roomTestRepo.DeleteMember(ctx, room.RoomID.String(), "user-1")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
// 驗證成員已被刪除
|
|
|
|
|
_, err = roomTestRepo.Get(ctx, room.RoomID.String(), "user-1")
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
assert.True(t, cassandra.IsNotFound(err))
|
|
|
|
|
|
|
|
|
|
// 驗證 user_room 表也被刪除
|
|
|
|
|
userRooms, err := roomTestRepo.GetUserRooms(ctx, "user-1")
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Len(t, userRooms, 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_DeleteRoom(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Delete Room Test",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
// 插入多個成員
|
|
|
|
|
members := []*entity.RoomMember{
|
|
|
|
|
{RoomID: room.RoomID, UID: "user-1", Role: chat.RoomRoleMember.String()},
|
|
|
|
|
{RoomID: room.RoomID, UID: "user-2", Role: chat.RoomRoleAdmin.String()},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, member := range members {
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 刪除整個房間
|
|
|
|
|
err := roomTestRepo.DeleteRoom(ctx, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
// 驗證所有成員已被刪除
|
|
|
|
|
allMembers, err := roomTestRepo.AllMembers(ctx, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Len(t, allMembers, 0)
|
|
|
|
|
|
|
|
|
|
// 驗證 user_room 表中的關聯也被刪除
|
|
|
|
|
for _, member := range members {
|
|
|
|
|
userRooms, err := roomTestRepo.GetUserRooms(ctx, member.UID)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
// 驗證該用戶的 user_room 記錄中不包含這個房間
|
|
|
|
|
found := false
|
|
|
|
|
for _, ur := range userRooms {
|
|
|
|
|
if ur.RoomID == room.RoomID {
|
|
|
|
|
found = true
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert.False(t, found, "user_room should not contain deleted room")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_Count(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Count Members Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
// 插入多個成員
|
|
|
|
|
for i := 0; i < 5; i++ {
|
|
|
|
|
member := &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: "user-" + strconv.Itoa(i),
|
|
|
|
|
Role: chat.RoomRoleMember.String(),
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 計算成員數
|
|
|
|
|
count, err := roomTestRepo.Count(ctx, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, int64(5), count)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== User Interface 測試 ====================
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_GetUserRooms(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建多個測試房間
|
|
|
|
|
rooms := make([]*entity.Room, 3)
|
|
|
|
|
for i := 0; i < 3; i++ {
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "User Room " + strconv.Itoa(i),
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
rooms[i] = room
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 將用戶加入多個房間
|
|
|
|
|
uid := "user-1"
|
|
|
|
|
for _, room := range rooms {
|
|
|
|
|
member := &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: uid,
|
|
|
|
|
Role: chat.RoomRoleMember.String(),
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 查詢用戶所在的所有房間
|
|
|
|
|
userRooms, err := roomTestRepo.GetUserRooms(ctx, uid)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Len(t, userRooms, 3)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_CountUserRooms(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
rooms := make([]*entity.Room, 5)
|
|
|
|
|
for i := 0; i < 5; i++ {
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Count User Room " + strconv.Itoa(i),
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
rooms[i] = room
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 將用戶加入多個房間
|
|
|
|
|
uid := "user-1"
|
|
|
|
|
for _, room := range rooms {
|
|
|
|
|
member := &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: uid,
|
|
|
|
|
Role: chat.RoomRoleMember.String(),
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 計算用戶所在的房間數
|
|
|
|
|
count, err := roomTestRepo.CountUserRooms(ctx, uid)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, int64(5), count)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_IsUserInRoom(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建測試房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Is User In Room Test",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
// 插入成員
|
|
|
|
|
member := &entity.RoomMember{
|
|
|
|
|
RoomID: room.RoomID,
|
|
|
|
|
UID: "user-1",
|
|
|
|
|
Role: chat.RoomRoleMember.String(),
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
uid string
|
|
|
|
|
roomID string
|
|
|
|
|
want bool
|
|
|
|
|
wantErr bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "user in room",
|
|
|
|
|
uid: "user-1",
|
|
|
|
|
roomID: room.RoomID.String(),
|
|
|
|
|
want: true,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "user not in room",
|
|
|
|
|
uid: "user-2",
|
|
|
|
|
roomID: room.RoomID.String(),
|
|
|
|
|
want: false,
|
|
|
|
|
wantErr: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
result, err := roomTestRepo.IsUserInRoom(ctx, tt.uid, tt.roomID)
|
|
|
|
|
if tt.wantErr {
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
} else {
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.Equal(t, tt.want, result)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 整合測試 ====================
|
|
|
|
|
|
|
|
|
|
func TestRoomRepository_Integration(t *testing.T) {
|
|
|
|
|
ensureRoomRepository(t)
|
|
|
|
|
clearRoomData(t)
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
// 創建房間
|
|
|
|
|
room := &entity.Room{
|
|
|
|
|
Name: "Integration Test Room",
|
|
|
|
|
Status: "active",
|
|
|
|
|
}
|
|
|
|
|
require.NoError(t, roomTestRepo.Create(ctx, room))
|
|
|
|
|
|
|
|
|
|
// 添加多個成員
|
|
|
|
|
members := []*entity.RoomMember{
|
|
|
|
|
{RoomID: room.RoomID, UID: "user-1", Role: chat.RoomRoleOwner.String()},
|
|
|
|
|
{RoomID: room.RoomID, UID: "user-2", Role: chat.RoomRoleAdmin.String()},
|
|
|
|
|
{RoomID: room.RoomID, UID: "user-3", Role: chat.RoomRoleMember.String()},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, member := range members {
|
|
|
|
|
require.NoError(t, roomTestRepo.Insert(ctx, member))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待數據寫入
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
// 驗證房間存在
|
|
|
|
|
exists, err := roomTestRepo.RoomExists(ctx, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.True(t, exists)
|
|
|
|
|
|
|
|
|
|
// 驗證成員數量
|
|
|
|
|
count, err := roomTestRepo.Count(ctx, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, int64(3), count)
|
|
|
|
|
|
|
|
|
|
// 驗證所有成員
|
|
|
|
|
allMembers, err := roomTestRepo.AllMembers(ctx, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Len(t, allMembers, 3)
|
|
|
|
|
|
|
|
|
|
// 驗證用戶所在的房間
|
|
|
|
|
for _, member := range members {
|
|
|
|
|
userRooms, err := roomTestRepo.GetUserRooms(ctx, member.UID)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Greater(t, len(userRooms), 0)
|
|
|
|
|
|
|
|
|
|
inRoom, err := roomTestRepo.IsUserInRoom(ctx, member.UID, room.RoomID.String())
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.True(t, inRoom)
|
|
|
|
|
}
|
|
|
|
|
}
|