Files
2026-09-23 17:42:55 +08:00

269 lines
9.6 KiB
Go

package live
import (
"context"
"errors"
"testing"
bizlive "kra/internal/biz/live"
"github.com/glebarez/sqlite"
"gorm.io/gorm"
)
type catalogTestProvider struct{ db *gorm.DB }
func (p catalogTestProvider) DB() *gorm.DB { return p.db }
func openCatalogTestDB(t *testing.T) *gorm.DB {
t.Helper()
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{})
if err != nil {
t.Fatal(err)
}
if err = db.AutoMigrate(&categoryPO{}, &roomPO{}); err != nil {
t.Fatal(err)
}
if err = db.Exec(`CREATE TABLE sys_users (
id integer primary key,
username text,
nick_name text,
header_img text,
deleted_at datetime
)`).Error; err != nil {
t.Fatal(err)
}
return db
}
func TestCatalogRepoScansCategoryAndRoomFields(t *testing.T) {
db := openCatalogTestDB(t)
if err := db.Exec(`INSERT INTO sys_users(id, username, nick_name, header_img) VALUES (2, 'anchor', 'Anchor', 'avatar.png')`).Error; err != nil {
t.Fatal(err)
}
category := categoryPO{Name: "Games", Icon: "game.png", Sort: 1, Enabled: true}
if err := db.Create(&category).Error; err != nil {
t.Fatal(err)
}
room := roomPO{Name: "Test Room", CategoryID: category.ID, CoverURL: "cover.png", Intro: "intro", Sort: 2, AnchorUserID: 2, ReplayURL: "https://example.test/replay.mp4", Enabled: true}
if err := db.Create(&room).Error; err != nil {
t.Fatal(err)
}
repo := NewCatalogRepo(catalogTestProvider{db: db})
categories, total, err := repo.ListCategories(context.Background(), bizlive.CategoryFilter{}, bizlive.ListOptions{Limit: 10})
if err != nil {
t.Fatal(err)
}
if total != 1 || len(categories) != 1 || categories[0].ID != category.ID || categories[0].Name != category.Name || !categories[0].Enabled || categories[0].RoomCount != 1 {
t.Fatalf("category scan result total=%d categories=%+v", total, categories)
}
rooms, total, err := repo.ListRooms(context.Background(), bizlive.RoomFilter{}, bizlive.ListOptions{Limit: 10})
if err != nil {
t.Fatal(err)
}
if total != 1 || len(rooms) != 1 || rooms[0].ID != room.ID || rooms[0].Name != room.Name || rooms[0].CategoryName != category.Name || rooms[0].AnchorName != "Anchor" || !rooms[0].Enabled {
t.Fatalf("room list scan result total=%d rooms=%+v", total, rooms)
}
got, err := repo.GetRoom(context.Background(), room.ID)
if err != nil {
t.Fatal(err)
}
if got.ID != room.ID || got.Name != room.Name || got.AnchorUserID != 2 || got.AnchorAvatar != "avatar.png" || got.ReplayURL != room.ReplayURL || !got.Enabled {
t.Fatalf("room get scan result=%+v", got)
}
}
func TestCatalogRepoFiltersRoomsByCategoryEnabled(t *testing.T) {
db := openCatalogTestDB(t)
if err := db.Exec(`INSERT INTO sys_users(id, username, nick_name, header_img) VALUES (2, 'anchor', 'Anchor', 'avatar.png')`).Error; err != nil {
t.Fatal(err)
}
enabledCategory := categoryPO{Name: "Games", Enabled: true}
disabledCategory := categoryPO{Name: "Hidden", Enabled: false}
if err := db.Create(&enabledCategory).Error; err != nil {
t.Fatal(err)
}
if err := db.Create(&disabledCategory).Error; err != nil {
t.Fatal(err)
}
if err := db.Model(&disabledCategory).Update("enabled", false).Error; err != nil {
t.Fatal(err)
}
for _, room := range []*roomPO{
{Name: "Visible", CategoryID: enabledCategory.ID, CoverURL: "visible.png", AnchorUserID: 2, Enabled: true},
{Name: "Hidden", CategoryID: disabledCategory.ID, CoverURL: "hidden.png", AnchorUserID: 2, Enabled: true},
} {
if err := db.Create(room).Error; err != nil {
t.Fatal(err)
}
}
repo := NewCatalogRepo(catalogTestProvider{db: db})
enabled := true
rooms, total, err := repo.ListRooms(context.Background(), bizlive.RoomFilter{CategoryEnabled: &enabled}, bizlive.ListOptions{Limit: 10})
if err != nil {
t.Fatal(err)
}
if total != 1 || len(rooms) != 1 || rooms[0].Name != "Visible" {
t.Fatalf("enabled-category rooms total=%d rooms=%+v", total, rooms)
}
}
func TestCatalogRepoPublicVisibilityFiltersBeforePagination(t *testing.T) {
db := openCatalogTestDB(t)
if err := db.Exec(`INSERT INTO sys_users(id, username, nick_name, header_img) VALUES (2, 'anchor', 'Anchor', 'avatar.png')`).Error; err != nil {
t.Fatal(err)
}
visible := categoryPO{Name: "Visible", Enabled: true}
disabled := categoryPO{Name: "Disabled", Enabled: true}
deleted := categoryPO{Name: "Deleted", Enabled: true}
for _, category := range []*categoryPO{&visible, &disabled, &deleted} {
if err := db.Create(category).Error; err != nil {
t.Fatal(err)
}
}
if err := db.Model(&disabled).Update("enabled", false).Error; err != nil {
t.Fatal(err)
}
if err := db.Delete(&deleted).Error; err != nil {
t.Fatal(err)
}
rooms := []*roomPO{
{Name: "Offline Room", CategoryID: visible.ID, Enabled: true},
{Name: "Replay Room", CategoryID: visible.ID, Enabled: true, ReplayURL: "https://example.test/replay.mp4"},
{Name: "Disabled Room", CategoryID: visible.ID, Enabled: true},
{Name: "Disabled Category", CategoryID: disabled.ID, Enabled: true},
{Name: "Deleted Category", CategoryID: deleted.ID, Enabled: true},
{Name: "Missing Category", CategoryID: 999, Enabled: true},
{Name: "Deleted Room", CategoryID: visible.ID, Enabled: true},
}
for _, room := range rooms {
room.AnchorUserID = 2
room.CoverURL = "cover.png"
if err := db.Create(room).Error; err != nil {
t.Fatal(err)
}
}
if err := db.Model(rooms[2]).Update("enabled", false).Error; err != nil {
t.Fatal(err)
}
if err := db.Delete(rooms[6]).Error; err != nil {
t.Fatal(err)
}
repo := NewCatalogRepo(catalogTestProvider{db: db})
enabled := true
filter := bizlive.RoomFilter{Enabled: &enabled, CategoryEnabled: &enabled}
items, total, err := repo.ListRooms(context.Background(), filter, bizlive.ListOptions{Limit: 10, OrderBy: "id_asc"})
if err != nil {
t.Fatal(err)
}
if total != 2 || len(items) != 2 || items[0].ID != rooms[0].ID || items[1].ID != rooms[1].ID {
t.Fatalf("public candidates total=%d items=%+v", total, items)
}
if items[1].ReplayURL != rooms[1].ReplayURL {
t.Fatalf("replay URL=%q, want %q", items[1].ReplayURL, rooms[1].ReplayURL)
}
items, total, err = repo.ListRooms(context.Background(), filter, bizlive.ListOptions{Offset: 1, Limit: 1, OrderBy: "id_asc"})
if err != nil {
t.Fatal(err)
}
if total != 2 || len(items) != 1 || items[0].ID != rooms[1].ID {
t.Fatalf("public page total=%d items=%+v", total, items)
}
filter.CategoryID = disabled.ID
items, total, err = repo.ListRooms(context.Background(), filter, bizlive.ListOptions{Limit: 10})
if err != nil {
t.Fatal(err)
}
if total != 0 || len(items) != 0 {
t.Fatalf("disabled category returned rooms: total=%d items=%+v", total, items)
}
}
func TestCatalogRepoCreatePreservesExplicitEnabledState(t *testing.T) {
db := openCatalogTestDB(t)
// Existing installations still have the old database-level default.
for _, table := range []string{"live_categories", "live_rooms"} {
if err := db.Table(table).AutoMigrate(&struct {
Enabled bool `gorm:"default:true"`
}{}); err != nil {
t.Fatal(err)
}
}
if err := db.Exec(`INSERT INTO sys_users(id, username, nick_name, header_img) VALUES (2, 'anchor', 'Anchor', 'avatar.png')`).Error; err != nil {
t.Fatal(err)
}
repo := NewCatalogRepo(catalogTestProvider{db: db})
ctx := context.Background()
for _, enabled := range []bool{false, true} {
name := "Disabled"
if enabled {
name = "Enabled"
}
t.Run(name+" category", func(t *testing.T) {
created, err := repo.CreateCategory(ctx, &bizlive.Category{Name: name, Enabled: enabled})
if err != nil {
t.Fatal(err)
}
if created.Enabled != enabled {
t.Fatalf("created category enabled=%v, want %v", created.Enabled, enabled)
}
reloaded, err := repo.GetCategory(ctx, created.ID)
if err != nil || reloaded.Enabled != enabled {
t.Fatalf("reloaded category=%+v error=%v, want enabled=%v", reloaded, err, enabled)
}
})
}
enabled := true
categories, total, err := repo.ListCategories(ctx, bizlive.CategoryFilter{Enabled: &enabled}, bizlive.ListOptions{Limit: 10})
if err != nil {
t.Fatal(err)
}
if total != 1 || len(categories) != 1 || categories[0].Name != "Enabled" {
t.Fatalf("public categories include a disabled new category: total=%d categories=%+v", total, categories)
}
categoryID := categories[0].ID
streams := bizlive.NewStreamUsecase(NewStreamRepo())
rooms := bizlive.NewRoomUsecase(repo, streams)
for _, enabled := range []bool{false, true} {
name := "Disabled"
if enabled {
name = "Enabled"
}
t.Run(name+" room", func(t *testing.T) {
created, err := repo.CreateRoom(ctx, &bizlive.Room{
Name: name, CategoryID: categoryID, AnchorUserID: 2,
CoverURL: "cover.png", ReplayURL: "https://example.test/replay.mp4", Enabled: enabled,
})
if err != nil {
t.Fatal(err)
}
if created.Enabled != enabled {
t.Fatalf("created room enabled=%v, want %v", created.Enabled, enabled)
}
reloaded, err := repo.GetRoom(ctx, created.ID)
if err != nil || reloaded.Enabled != enabled {
t.Fatalf("reloaded room=%+v error=%v, want enabled=%v", reloaded, err, enabled)
}
public, err := rooms.GetPublic(ctx, created.ID)
if enabled {
if err != nil || public.Status != bizlive.RoomStatusOffline {
t.Fatalf("enabled offline public room=%+v error=%v", public, err)
}
} else if public != nil || !errors.Is(err, bizlive.ErrRoomDisabled) {
t.Fatalf("disabled new room passed public/publisher authorization: room=%+v error=%v", public, err)
}
})
}
public, total, err := repo.ListRooms(ctx, bizlive.RoomFilter{Enabled: &enabled, CategoryEnabled: &enabled}, bizlive.ListOptions{Limit: 10})
if err != nil {
t.Fatal(err)
}
if total != 1 || len(public) != 1 || public[0].Name != "Enabled" {
t.Fatalf("public list includes a disabled new room: total=%d rooms=%+v", total, public)
}
}