510 lines
16 KiB
Go
510 lines
16 KiB
Go
package repository
|
||
|
||
import (
|
||
"testing"
|
||
"time"
|
||
|
||
"github.com/stretchr/testify/assert"
|
||
"github.com/topfans/backend/pkg/database"
|
||
"github.com/topfans/backend/pkg/models"
|
||
"github.com/topfans/backend/services/galleryService/config"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// setupTestDB 设置测试数据库
|
||
func setupTestDB(t *testing.T) *gorm.DB {
|
||
dbConfig := database.Config{
|
||
Host: "localhost",
|
||
Port: 5432,
|
||
User: "haihuizhu",
|
||
Password: "admin",
|
||
DBName: "top-fans",
|
||
SSLMode: "disable",
|
||
TimeZone: "Asia/Shanghai",
|
||
}
|
||
|
||
if err := database.Init(dbConfig); err != nil {
|
||
t.Skipf("Skipping test: failed to connect to test database: %v", err)
|
||
}
|
||
|
||
db := database.GetDB()
|
||
|
||
// 迁移展馆相关表
|
||
if err := db.AutoMigrate(&models.BoothSlot{}, &models.Exhibition{}); err != nil {
|
||
t.Logf("Warning: Failed to migrate gallery tables (may already exist): %v", err)
|
||
}
|
||
|
||
// 测试开始前先清理一次,确保测试环境干净
|
||
cleanupTestDB(t, db)
|
||
|
||
return db
|
||
}
|
||
|
||
// cleanupTestDB 清理测试数据
|
||
func cleanupTestDB(t *testing.T, db *gorm.DB) {
|
||
// 清理测试数据(注意外键约束顺序)
|
||
// 先清理展品展示记录,再清理展位
|
||
db.Exec("DELETE FROM exhibitions WHERE occupier_uid IN (SELECT id FROM users WHERE mobile LIKE '199%')")
|
||
db.Exec("DELETE FROM booth_slots WHERE user_id IN (SELECT id FROM users WHERE mobile LIKE '199%')")
|
||
}
|
||
|
||
// createTestStar 创建测试用明星
|
||
func createTestStar(t *testing.T, db *gorm.DB, identityID string) *models.Star {
|
||
// 先检查是否已存在
|
||
var existingStar models.Star
|
||
if err := db.Where("identity_id = ?", identityID).First(&existingStar).Error; err == nil {
|
||
// 已存在,返回现有的
|
||
return &existingStar
|
||
}
|
||
|
||
// 不存在,创建新的
|
||
star := &models.Star{
|
||
Name: "测试明星-" + identityID,
|
||
IdentityID: identityID,
|
||
IsActive: true,
|
||
}
|
||
if err := db.Create(star).Error; err != nil {
|
||
t.Fatalf("Failed to create test star: %v", err)
|
||
}
|
||
return star
|
||
}
|
||
|
||
// createTestUser 创建测试用户
|
||
func createTestUser(t *testing.T, db *gorm.DB, mobile string) *models.User {
|
||
user := &models.User{
|
||
Mobile: mobile,
|
||
PasswordHash: "test_hash",
|
||
IsActive: true,
|
||
}
|
||
if err := db.Create(user).Error; err != nil {
|
||
t.Fatalf("Failed to create test user: %v", err)
|
||
}
|
||
return user
|
||
}
|
||
|
||
// createTestFanProfile 创建测试粉丝档案
|
||
func createTestFanProfile(t *testing.T, db *gorm.DB, userID, starID int64, nickname string) *models.FanProfile {
|
||
profile := &models.FanProfile{
|
||
UserID: userID,
|
||
StarID: starID,
|
||
Nickname: nickname,
|
||
Level: 1,
|
||
}
|
||
if err := db.Create(profile).Error; err != nil {
|
||
t.Fatalf("Failed to create test fan profile: %v", err)
|
||
}
|
||
return profile
|
||
}
|
||
|
||
// TestCreateInitialSlots 测试创建初始展位
|
||
func TestCreateInitialSlots(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_001")
|
||
user := createTestUser(t, db, "19900000001")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户001")
|
||
|
||
// 测试创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err, "创建初始展位应该成功")
|
||
|
||
// 验证展位数量
|
||
count, err := repo.GetSlotCount(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
assert.Equal(t, int64(config.GalleryRules.InitialSlotCount), count, "初始展位数量应该为3")
|
||
|
||
// 验证展位信息
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
assert.Len(t, slots, config.GalleryRules.InitialSlotCount, "展位列表长度应该为3")
|
||
|
||
// 验证展位属性
|
||
for i, slot := range slots {
|
||
assert.Equal(t, i+1, slot.SlotIndex, "展位序号应该从1开始")
|
||
assert.True(t, slot.IsEnabled, "初始展位应该已解锁")
|
||
assert.Equal(t, "public", slot.Visibility, "初始展位应该是公有的")
|
||
assert.Equal(t, "free", slot.UnlockType, "初始展位应该是免费的")
|
||
assert.Equal(t, 0, slot.UnlockValue, "初始展位解锁值应该为0")
|
||
}
|
||
}
|
||
|
||
// TestCreateInitialSlots_Idempotent 测试懒加载的幂等性(避免重复创建)
|
||
func TestCreateInitialSlots_Idempotent(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_002")
|
||
user := createTestUser(t, db, "19900000002")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户002")
|
||
|
||
// 第一次创建
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err, "第一次创建应该成功")
|
||
|
||
// 第二次创建(应该不会报错,也不会重复创建)
|
||
err = repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err, "第二次创建应该不报错(幂等性)")
|
||
|
||
// 验证展位数量仍然是3
|
||
count, err := repo.GetSlotCount(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
assert.Equal(t, int64(config.GalleryRules.InitialSlotCount), count, "展位数量应该仍然为3,不会重复创建")
|
||
}
|
||
|
||
// TestGetSlotsByUser 测试查询展位列表
|
||
func TestGetSlotsByUser(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_003")
|
||
user := createTestUser(t, db, "19900000003")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户003")
|
||
|
||
// 创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 查询展位列表
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
assert.Len(t, slots, config.GalleryRules.InitialSlotCount, "应该返回3个展位")
|
||
|
||
// 验证排序(按 slot_index 升序)
|
||
for i, slot := range slots {
|
||
assert.Equal(t, i+1, slot.SlotIndex, "展位应该按序号升序排列")
|
||
}
|
||
}
|
||
|
||
// TestGetSlotByID 测试根据ID获取展位
|
||
func TestGetSlotByID(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_004")
|
||
user := createTestUser(t, db, "19900000004")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户004")
|
||
|
||
// 创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 获取展位列表
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
assert.NotEmpty(t, slots)
|
||
|
||
// 根据ID获取第一个展位
|
||
firstSlot := slots[0]
|
||
slot, err := repo.GetSlotByID(firstSlot.SlotID)
|
||
assert.NoError(t, err)
|
||
assert.NotNil(t, slot)
|
||
assert.Equal(t, firstSlot.SlotID, slot.SlotID, "展位ID应该匹配")
|
||
assert.Equal(t, firstSlot.SlotIndex, slot.SlotIndex, "展位序号应该匹配")
|
||
|
||
// 测试获取不存在的展位
|
||
_, err = repo.GetSlotByID(999999)
|
||
assert.Error(t, err, "获取不存在的展位应该返回错误")
|
||
}
|
||
|
||
// TestCreateSlot 测试创建新展位(解锁)
|
||
func TestCreateSlot(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_005")
|
||
user := createTestUser(t, db, "19900000005")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户005")
|
||
|
||
// 创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 创建第4个展位(需要解锁)
|
||
hostProfileID := generateHostProfileID(user.ID, star.StarID)
|
||
newSlot := &models.BoothSlot{
|
||
HostProfileID: hostProfileID,
|
||
UserID: user.ID,
|
||
StarID: star.StarID,
|
||
SlotIndex: 4,
|
||
Visibility: "public",
|
||
IsEnabled: true,
|
||
UnlockType: "level",
|
||
UnlockValue: 5,
|
||
}
|
||
err = repo.CreateSlot(newSlot)
|
||
assert.NoError(t, err, "创建新展位应该成功")
|
||
|
||
// 验证展位数量
|
||
count, err := repo.GetSlotCount(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
assert.Equal(t, int64(4), count, "展位数量应该为4")
|
||
|
||
// 验证新展位信息
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
assert.Len(t, slots, 4, "展位列表长度应该为4")
|
||
|
||
lastSlot := slots[3]
|
||
assert.Equal(t, 4, lastSlot.SlotIndex, "新展位序号应该为4")
|
||
assert.True(t, lastSlot.IsEnabled, "新展位应该已解锁")
|
||
assert.Equal(t, "level", lastSlot.UnlockType, "解锁方式应该为等级")
|
||
assert.Equal(t, 5, lastSlot.UnlockValue, "解锁条件应该为等级5")
|
||
}
|
||
|
||
// TestCreateExhibition 测试创建展品展示记录
|
||
func TestCreateExhibition(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_006")
|
||
user := createTestUser(t, db, "19900000006")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户006")
|
||
|
||
// 创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 获取第一个展位
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
firstSlot := slots[0]
|
||
|
||
// 创建展品展示记录
|
||
now := time.Now().UnixMilli()
|
||
expireAt := now + config.GalleryRules.GrabSlotDuration*1000
|
||
exhibition := &models.Exhibition{
|
||
AssetID: 12345,
|
||
SlotID: firstSlot.SlotID,
|
||
HostProfileID: firstSlot.HostProfileID,
|
||
OccupierUID: user.ID,
|
||
OccupierStarID: star.StarID,
|
||
StartTime: now,
|
||
ExpireAt: expireAt,
|
||
}
|
||
err = repo.CreateExhibition(exhibition)
|
||
assert.NoError(t, err, "创建展品展示记录应该成功")
|
||
|
||
// 验证展品展示记录
|
||
fetchedExhibition, err := repo.GetExhibitionByAsset(12345)
|
||
assert.NoError(t, err)
|
||
assert.NotNil(t, fetchedExhibition)
|
||
assert.Equal(t, int64(12345), fetchedExhibition.AssetID, "资产ID应该匹配")
|
||
assert.Equal(t, firstSlot.SlotID, fetchedExhibition.SlotID, "展位ID应该匹配")
|
||
}
|
||
|
||
// TestGetExhibitionBySlot 测试根据展位ID获取展品展示记录
|
||
func TestGetExhibitionBySlot(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_007")
|
||
user := createTestUser(t, db, "19900000007")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户007")
|
||
|
||
// 创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 获取第一个展位
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
firstSlot := slots[0]
|
||
|
||
// 创建展品展示记录
|
||
now := time.Now().UnixMilli()
|
||
expireAt := now + config.GalleryRules.GrabSlotDuration*1000
|
||
exhibition := &models.Exhibition{
|
||
AssetID: 23456,
|
||
SlotID: firstSlot.SlotID,
|
||
HostProfileID: firstSlot.HostProfileID,
|
||
OccupierUID: user.ID,
|
||
OccupierStarID: star.StarID,
|
||
StartTime: now,
|
||
ExpireAt: expireAt,
|
||
}
|
||
err = repo.CreateExhibition(exhibition)
|
||
assert.NoError(t, err)
|
||
|
||
// 根据展位ID获取展品展示记录
|
||
fetchedExhibition, err := repo.GetExhibitionBySlot(firstSlot.SlotID)
|
||
assert.NoError(t, err)
|
||
assert.NotNil(t, fetchedExhibition)
|
||
assert.Equal(t, int64(23456), fetchedExhibition.AssetID, "资产ID应该匹配")
|
||
assert.Equal(t, firstSlot.SlotID, fetchedExhibition.SlotID, "展位ID应该匹配")
|
||
}
|
||
|
||
// TestDeleteExhibition 测试删除展品展示记录
|
||
func TestDeleteExhibition(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_008")
|
||
user := createTestUser(t, db, "19900000008")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户008")
|
||
|
||
// 创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 获取第一个展位
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
firstSlot := slots[0]
|
||
|
||
// 创建展品展示记录
|
||
now := time.Now().UnixMilli()
|
||
expireAt := now + config.GalleryRules.GrabSlotDuration*1000
|
||
exhibition := &models.Exhibition{
|
||
AssetID: 34567,
|
||
SlotID: firstSlot.SlotID,
|
||
HostProfileID: firstSlot.HostProfileID,
|
||
OccupierUID: user.ID,
|
||
OccupierStarID: star.StarID,
|
||
StartTime: now,
|
||
ExpireAt: expireAt,
|
||
}
|
||
err = repo.CreateExhibition(exhibition)
|
||
assert.NoError(t, err)
|
||
|
||
// 验证展品展示记录存在
|
||
fetchedExhibition, err := repo.GetExhibitionByAsset(34567)
|
||
assert.NoError(t, err)
|
||
assert.NotNil(t, fetchedExhibition)
|
||
|
||
// 删除展品展示记录
|
||
err = repo.DeleteExhibition(fetchedExhibition.ID)
|
||
assert.NoError(t, err, "删除展品展示记录应该成功")
|
||
|
||
// 验证展品展示记录已删除
|
||
fetchedExhibition, err = repo.GetExhibitionByAsset(34567)
|
||
assert.NoError(t, err)
|
||
assert.Nil(t, fetchedExhibition, "展品展示记录应该已被删除")
|
||
}
|
||
|
||
// TestDeleteExhibitionByAsset 测试根据资产ID删除展品展示记录
|
||
func TestDeleteExhibitionByAsset(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_009")
|
||
user := createTestUser(t, db, "19900000009")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户009")
|
||
|
||
// 创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 获取第一个展位
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
firstSlot := slots[0]
|
||
|
||
// 创建展品展示记录
|
||
now := time.Now().UnixMilli()
|
||
expireAt := now + config.GalleryRules.GrabSlotDuration*1000
|
||
exhibition := &models.Exhibition{
|
||
AssetID: 45678,
|
||
SlotID: firstSlot.SlotID,
|
||
HostProfileID: firstSlot.HostProfileID,
|
||
OccupierUID: user.ID,
|
||
OccupierStarID: star.StarID,
|
||
StartTime: now,
|
||
ExpireAt: expireAt,
|
||
}
|
||
err = repo.CreateExhibition(exhibition)
|
||
assert.NoError(t, err)
|
||
|
||
// 根据资产ID删除展品展示记录
|
||
err = repo.DeleteExhibitionByAsset(45678)
|
||
assert.NoError(t, err, "根据资产ID删除展品展示记录应该成功")
|
||
|
||
// 验证展品展示记录已删除
|
||
fetchedExhibition, err := repo.GetExhibitionByAsset(45678)
|
||
assert.NoError(t, err)
|
||
assert.Nil(t, fetchedExhibition, "展品展示记录应该已被删除")
|
||
}
|
||
|
||
// TestGetExpiredExhibitions 测试获取过期的展品展示记录
|
||
func TestGetExpiredExhibitions(t *testing.T) {
|
||
db := setupTestDB(t)
|
||
defer cleanupTestDB(t, db)
|
||
|
||
repo := NewGalleryRepository(db)
|
||
|
||
// 创建测试用户和明星
|
||
star := createTestStar(t, db, "test_gallery_010")
|
||
user := createTestUser(t, db, "19900000010")
|
||
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户010")
|
||
|
||
// 创建初始展位
|
||
err := repo.CreateInitialSlots(user.ID, star.StarID, user.ID*1000000+star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 获取展位
|
||
slots, err := repo.GetSlotsByUser(user.ID, star.StarID)
|
||
assert.NoError(t, err)
|
||
|
||
// 创建已过期的展品展示记录
|
||
now := time.Now().UnixMilli()
|
||
pastExpireTime := now - 1000*60*60 // 1小时前过期
|
||
expiredExhibition := &models.Exhibition{
|
||
AssetID: 56789,
|
||
SlotID: slots[0].SlotID,
|
||
HostProfileID: slots[0].HostProfileID,
|
||
OccupierUID: user.ID,
|
||
OccupierStarID: star.StarID,
|
||
StartTime: now - 1000*60*60*5, // 5小时前开始
|
||
ExpireAt: pastExpireTime,
|
||
}
|
||
err = repo.CreateExhibition(expiredExhibition)
|
||
assert.NoError(t, err)
|
||
|
||
// 创建未过期的展品展示记录
|
||
futureExpireTime := now + 1000*60*60 // 1小时后过期
|
||
validExhibition := &models.Exhibition{
|
||
AssetID: 67890,
|
||
SlotID: slots[1].SlotID,
|
||
HostProfileID: slots[1].HostProfileID,
|
||
OccupierUID: user.ID,
|
||
OccupierStarID: star.StarID,
|
||
StartTime: now,
|
||
ExpireAt: futureExpireTime,
|
||
}
|
||
err = repo.CreateExhibition(validExhibition)
|
||
assert.NoError(t, err)
|
||
|
||
// 获取过期的展品展示记录
|
||
expiredExhibitions, err := repo.GetExpiredExhibitions(now)
|
||
assert.NoError(t, err)
|
||
assert.Len(t, expiredExhibitions, 1, "应该只有1个过期的展品展示记录")
|
||
assert.Equal(t, int64(56789), expiredExhibitions[0].AssetID, "过期的展品资产ID应该为56789")
|
||
}
|