156 lines
5.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service_test
import (
"context"
"testing"
"time"
roomv1 "hyapp.local/api/proto/room/v1"
walletv1 "hyapp.local/api/proto/wallet/v1"
"hyapp/pkg/appcode"
"hyapp/services/room-service/internal/integration"
roomservice "hyapp/services/room-service/internal/room/service"
"hyapp/services/room-service/internal/router"
"hyapp/services/room-service/internal/testutil/mysqltest"
)
type followTestWallet struct{}
func (followTestWallet) DebitGift(context.Context, *walletv1.DebitGiftRequest) (*walletv1.DebitGiftResponse, error) {
return &walletv1.DebitGiftResponse{BillingReceiptId: "receipt-follow-test"}, nil
}
func (followTestWallet) BatchDebitGift(context.Context, *walletv1.BatchDebitGiftRequest) (*walletv1.BatchDebitGiftResponse, error) {
return &walletv1.BatchDebitGiftResponse{Aggregate: &walletv1.DebitGiftResponse{BillingReceiptId: "receipt-follow-test"}}, nil
}
func (followTestWallet) DebitRobotGift(context.Context, *walletv1.DebitRobotGiftRequest) (*walletv1.DebitGiftResponse, error) {
return &walletv1.DebitGiftResponse{BillingReceiptId: "receipt-robot-follow-test"}, nil
}
func (followTestWallet) GrantResourceGroup(context.Context, *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error) {
return &walletv1.ResourceGrantResponse{Grant: &walletv1.ResourceGrant{GrantId: "grant-follow-test"}}, nil
}
func (followTestWallet) GetMyVip(_ context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) {
return legacyVIPResponse(req.GetUserId()), nil
}
func legacyVIPResponse(userID int64) *walletv1.GetMyVipResponse {
// 大多数既有 room-service 测试运行在 Lalu显式返回 legacy program验证新增门禁不会暗改旧 App 行为。
return &walletv1.GetMyVipResponse{
State: &walletv1.VipState{
ProgramConfig: &walletv1.VipProgramConfig{AppCode: appcode.Default, ProgramType: "legacy_timed", Status: "active"},
EffectiveVip: &walletv1.UserVip{UserId: userID},
},
}
}
func TestRoomFollowAffectsSnapshotAndFollowedFeed(t *testing.T) {
ctx := context.Background()
repository := mysqltest.NewRepository(t)
svc := roomservice.New(roomservice.Config{
NodeID: "node-follow-test",
LeaseTTL: 10 * time.Second,
RankLimit: 20,
SnapshotEveryN: 1,
}, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())
roomID := "room-follow-flow"
ownerID := int64(1001)
viewerID := int64(2002)
if _, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{
Meta: roomservice.NewRequestMeta(roomID, ownerID),
SeatCount: 10,
Mode: "voice",
VisibleRegionId: 1001,
RoomName: "Follow Flow",
RoomAvatar: testRoomCoverURL,
RoomShortId: "follow-flow",
}); err != nil {
t.Fatalf("create room failed: %v", err)
}
if _, err := svc.JoinRoom(ctx, &roomv1.JoinRoomRequest{
Meta: roomservice.NewRequestMeta(roomID, viewerID),
Role: "audience",
}); err != nil {
t.Fatalf("join room failed: %v", err)
}
beforeFollow, err := svc.GetRoomSnapshot(ctx, &roomv1.GetRoomSnapshotRequest{
Meta: &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID},
RoomId: roomID,
ViewerUserId: viewerID,
})
if err != nil {
t.Fatalf("snapshot before follow failed: %v", err)
}
if beforeFollow.GetIsFollowed() {
t.Fatalf("new viewer must not be followed before FollowRoom")
}
followResp, err := svc.FollowRoom(ctx, &roomv1.FollowRoomRequest{
Meta: &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID},
RoomId: roomID,
UserId: viewerID,
})
if err != nil {
t.Fatalf("follow room failed: %v", err)
}
if !followResp.GetFollowed() || followResp.GetFollowedAtMs() <= 0 {
t.Fatalf("follow response mismatch: %+v", followResp)
}
afterFollow, err := svc.GetRoomSnapshot(ctx, &roomv1.GetRoomSnapshotRequest{
Meta: &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID},
RoomId: roomID,
ViewerUserId: viewerID,
})
if err != nil {
t.Fatalf("snapshot after follow failed: %v", err)
}
if !afterFollow.GetIsFollowed() {
t.Fatalf("snapshot must expose is_followed=true after FollowRoom")
}
feedResp, err := svc.ListRoomFeeds(ctx, &roomv1.ListRoomFeedsRequest{
Meta: &roomv1.RequestMeta{AppCode: appcode.Default},
ViewerUserId: viewerID,
VisibleRegionId: 1001,
Tab: "followed",
Limit: 20,
})
if err != nil {
t.Fatalf("followed feed failed: %v", err)
}
if len(feedResp.GetRooms()) != 1 || feedResp.GetRooms()[0].GetRoomId() != roomID {
t.Fatalf("followed feed must return followed room: %+v", feedResp.GetRooms())
}
unfollowResp, err := svc.UnfollowRoom(ctx, &roomv1.UnfollowRoomRequest{
Meta: &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID},
RoomId: roomID,
UserId: viewerID,
})
if err != nil {
t.Fatalf("unfollow room failed: %v", err)
}
if unfollowResp.GetFollowed() {
t.Fatalf("unfollow response mismatch: %+v", unfollowResp)
}
emptyFeedResp, err := svc.ListRoomFeeds(ctx, &roomv1.ListRoomFeedsRequest{
Meta: &roomv1.RequestMeta{AppCode: appcode.Default},
ViewerUserId: viewerID,
VisibleRegionId: 1001,
Tab: "followed",
Limit: 20,
})
if err != nil {
t.Fatalf("followed feed after unfollow failed: %v", err)
}
if len(emptyFeedResp.GetRooms()) != 0 {
t.Fatalf("followed feed must be empty after UnfollowRoom: %+v", emptyFeedResp.GetRooms())
}
}