package service_test import ( "context" "testing" "time" activityv1 "hyapp.local/api/proto/activity/v1" 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 luckyGiftTestClient struct { checks []*activityv1.CheckLuckyGiftRequest draws []*activityv1.ExecuteLuckyGiftDrawRequest } func (c *luckyGiftTestClient) CheckLuckyGift(_ context.Context, req *activityv1.CheckLuckyGiftRequest) (*activityv1.CheckLuckyGiftResponse, error) { c.checks = append(c.checks, req) return &activityv1.CheckLuckyGiftResponse{ Enabled: true, Reason: "enabled", GiftId: req.GetGiftId(), PoolId: req.GetPoolId(), RuleVersion: 12, ExperiencePool: "novice", }, nil } func (c *luckyGiftTestClient) ExecuteLuckyGiftDraw(_ context.Context, req *activityv1.ExecuteLuckyGiftDrawRequest) (*activityv1.ExecuteLuckyGiftDrawResponse, error) { c.draws = append(c.draws, req) meta := req.GetLuckyGift() return &activityv1.ExecuteLuckyGiftDrawResponse{Result: &activityv1.LuckyGiftDrawResult{ DrawId: "lucky_draw_test", CommandId: meta.GetCommandId(), PoolId: meta.GetPoolId(), GiftId: meta.GetGiftId(), RuleVersion: 12, ExperiencePool: "novice", SelectedTierId: "novice_2x", MultiplierPpm: 2_000_000, BaseRewardCoins: 200, EffectiveRewardCoins: 200, RewardStatus: "pending", CreatedAtMs: 1_779_258_000_000, }}, nil } func TestSendGiftReturnsLuckyGiftDrawResult(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{{ BillingReceiptId: "receipt-lucky", CoinSpent: 100, GiftPointAdded: 100, HeatValue: 100, GiftTypeCode: "super_lucky", }}} luckyGift := &luckyGiftTestClient{} svc := roomservice.New(roomservice.Config{ NodeID: "node-lucky-test", LeaseTTL: 10 * time.Second, RankLimit: 20, SnapshotEveryN: 1, }, router.NewMemoryDirectory(), repository, wallet, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher(), luckyGift) roomID := "room-lucky-gift" ownerID := int64(101) viewerID := int64(202) createTreasureRoom(t, ctx, svc, roomID, ownerID, 9001) joinTreasureRoom(t, ctx, svc, roomID, viewerID) resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ Meta: &roomv1.RequestMeta{ RequestId: "req-lucky", CommandId: "cmd-lucky", ActorUserId: ownerID, RoomId: roomID, SessionId: "device-session-1", AppCode: appcode.Default, SentAtMs: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC).UnixMilli(), }, TargetType: "user", TargetUserId: viewerID, GiftId: "rose", GiftCount: 1, PoolId: "super_lucky", }) if err != nil { t.Fatalf("send lucky gift failed: %v", err) } if resp.GetLuckyGift().GetDrawId() != "lucky_draw_test" || resp.GetLuckyGift().GetMultiplierPpm() != 2_000_000 || resp.GetLuckyGift().GetEffectiveRewardCoins() != 200 { t.Fatalf("lucky gift result mismatch: %+v", resp.GetLuckyGift()) } if len(luckyGift.checks) != 1 || luckyGift.checks[0].GetPoolId() != "super_lucky" || luckyGift.checks[0].GetGiftId() != "rose" { t.Fatalf("lucky check request mismatch: %+v", luckyGift.checks) } if len(luckyGift.draws) != 1 { t.Fatalf("expected one lucky draw, got %d", len(luckyGift.draws)) } drawMeta := luckyGift.draws[0].GetLuckyGift() if drawMeta.GetCommandId() != "cmd-lucky" || drawMeta.GetCoinSpent() != 100 || drawMeta.GetDeviceId() != "device-session-1" || drawMeta.GetAnchorId() != "101" { t.Fatalf("lucky draw meta mismatch: %+v", drawMeta) } }