package live import ( "context" "errors" "testing" bizlive "kra/internal/biz/live" "kra/internal/service/dto" ) type roomCatalogStub struct { roomCatalogUsecase filter bizlive.RoomFilter options bizlive.ListOptions items []*bizlive.Room total int64 publicID uint item *bizlive.Room err error } func (s *roomCatalogStub) List(_ context.Context, filter bizlive.RoomFilter, options bizlive.ListOptions) ([]*bizlive.Room, int64, error) { s.filter, s.options = filter, options return s.items, s.total, s.err } func (s *roomCatalogStub) GetPublic(_ context.Context, id uint) (*bizlive.Room, error) { s.publicID = id return s.item, s.err } func TestListPublicRoomsPreservesOptionalStatusAndEnforcesVisibility(t *testing.T) { for _, status := range []string{"", bizlive.RoomStatusLive, bizlive.RoomStatusOffline, bizlive.RoomStatusDisabled} { t.Run("status="+status, func(t *testing.T) { rooms := &roomCatalogStub{ items: []*bizlive.Room{{ID: 7, Status: bizlive.RoomStatusOffline, ReplayURL: "https://example.test/replay.mp4"}}, total: 21, } service := &CatalogService{rooms: rooms} disabled := false result, total, err := service.ListPublicRooms(context.Background(), &dto.LiveRoomListRequest{ LiveListRequest: dto.LiveListRequest{Page: 2, PageSize: 20, OrderBy: "viewer_count_desc"}, Name: "Room", CategoryID: 3, Status: status, Enabled: &disabled, }) if err != nil { t.Fatal(err) } if rooms.filter.Status != status || rooms.filter.Name != "Room" || rooms.filter.CategoryID != 3 { t.Fatalf("public filter=%+v", rooms.filter) } if rooms.filter.Enabled == nil || !*rooms.filter.Enabled || rooms.filter.CategoryEnabled == nil || !*rooms.filter.CategoryEnabled { t.Fatalf("public visibility filter=%+v", rooms.filter) } if rooms.options != (bizlive.ListOptions{Offset: 20, Limit: 20, OrderBy: "viewer_count_desc"}) { t.Fatalf("list options=%+v", rooms.options) } if total != 21 || len(result) != 1 || result[0].ID != 7 || result[0].Status != bizlive.RoomStatusOffline || result[0].ReplayURL != rooms.items[0].ReplayURL { t.Fatalf("public response total=%d rooms=%+v", total, result) } }) } } func TestGetPublicRoomPreservesOfflineReplayAndAnchorDetails(t *testing.T) { rooms := &roomCatalogStub{item: &bizlive.Room{ ID: 7, Name: "Offline Room", CategoryID: 3, AnchorUserID: 42, ReplayURL: "https://example.test/replay.mp4", Enabled: true, Status: bizlive.RoomStatusOffline, }} service := &CatalogService{rooms: rooms} result, err := service.GetPublicRoom(context.Background(), 7) if err != nil { t.Fatal(err) } if rooms.publicID != 7 || result.StreamID != "room-7" || result.Status != bizlive.RoomStatusOffline || result.AnchorUserID != 42 || result.ReplayURL != rooms.item.ReplayURL { t.Fatalf("public detail=%+v requestedID=%d", result, rooms.publicID) } } func TestPublicCatalogPropagatesUsecaseErrors(t *testing.T) { service := &CatalogService{rooms: &roomCatalogStub{err: bizlive.ErrRoomDisabled}} if items, total, err := service.ListPublicRooms(context.Background(), &dto.LiveRoomListRequest{}); items != nil || total != 0 || !errors.Is(err, bizlive.ErrRoomDisabled) { t.Fatalf("ListPublicRooms items=%+v total=%d error=%v", items, total, err) } if item, err := service.GetPublicRoom(context.Background(), 7); item != nil || !errors.Is(err, bizlive.ErrRoomDisabled) { t.Fatalf("GetPublicRoom item=%+v error=%v", item, err) } }