package wheel import ( "encoding/json" "testing" ) func TestNormalizeSaveRequestRequiresCategoryProbabilityTotalWhenEnabled(t *testing.T) { req := validSaveRequestForTest() req.Categories[0].Rewards[0].Probability-- _, err := normalizeSaveRequest(req) if err == nil { t.Fatal("normalizeSaveRequest() expected probability total error") } } func TestNormalizeSaveRequestAllowsZeroProbabilityDraftWhenDisabled(t *testing.T) { req := validSaveRequestForTest() req.Enabled = false for categoryIndex := range req.Categories { req.Categories[categoryIndex].Enabled = false for rewardIndex := range req.Categories[categoryIndex].Rewards { req.Categories[categoryIndex].Rewards[rewardIndex].Probability = 0 } } if _, err := normalizeSaveRequest(req); err != nil { t.Fatalf("normalizeSaveRequest() error = %v", err) } } func TestNormalizeSaveCategoryRequestOnlyValidatesTargetCategory(t *testing.T) { req := SaveCategoryConfigRequest{ SysOrigin: "yumi", Timezone: "Asia/Riyadh", Category: validCategoryForTest(wheelCategories[1]), } req.Category.Rewards[0].Probability-- if _, err := normalizeSaveCategoryRequest(req); err == nil { t.Fatal("normalizeSaveCategoryRequest() expected probability total error") } req.Category.Enabled = false for index := range req.Category.Rewards { req.Category.Rewards[index].Probability = 0 req.Category.Rewards[index].ResourceID = 0 } if _, err := normalizeSaveCategoryRequest(req); err != nil { t.Fatalf("normalizeSaveCategoryRequest() disabled draft error = %v", err) } } func TestNormalizeSaveRequestRequiresFixedRewardCount(t *testing.T) { req := validSaveRequestForTest() req.Categories[2].Rewards = req.Categories[2].Rewards[:11] _, err := normalizeSaveRequest(req) if err == nil { t.Fatal("normalizeSaveRequest() expected reward count error") } } func TestNormalizeSaveRequestNormalizesGoldReward(t *testing.T) { req := validSaveRequestForTest() req.Categories[0].Rewards[0] = RewardConfigInput{ Enabled: true, Sort: 1, RewardType: "gold", ResourceID: ResourceID(999), ResourceType: "RIDE", ResourceName: "", GoldAmount: 500, Probability: req.Categories[0].Rewards[0].Probability, } normalized, err := normalizeSaveRequest(req) if err != nil { t.Fatalf("normalizeSaveRequest() error = %v", err) } if normalized.SysOrigin != "YUMI" { t.Fatalf("SysOrigin = %q", normalized.SysOrigin) } reward := normalized.Categories[0].Rewards[0] if reward.RewardType != rewardTypeGold { t.Fatalf("RewardType = %q", reward.RewardType) } if reward.ResourceID.Int64() != 0 { t.Fatal("gold reward should not keep resourceId") } if reward.ResourceName == "" { t.Fatal("gold reward should get a display name") } } func TestNormalizeDrawTimes(t *testing.T) { for _, times := range []int{0, 1, 10, 50} { if _, err := normalizeDrawTimes(times); err != nil { t.Fatalf("normalizeDrawTimes(%d) error = %v", times, err) } } if _, err := normalizeDrawTimes(2); err == nil { t.Fatal("normalizeDrawTimes(2) expected error") } } func TestWheelResourceIDAcceptsStringResourceID(t *testing.T) { var payload RewardConfigInput if err := json.Unmarshal([]byte(`{"resourceId":"2045029471274201089"}`), &payload); err != nil { t.Fatalf("json.Unmarshal() error = %v", err) } if payload.ResourceID.Int64() != 2045029471274201089 { t.Fatalf("resource id = %d", payload.ResourceID.Int64()) } body, err := json.Marshal(RewardConfigPayload{ResourceID: payload.ResourceID}) if err != nil { t.Fatalf("json.Marshal() error = %v", err) } if got := string(body); got != `{"id":0,"enabled":false,"sort":0,"rewardType":"","resourceId":"2045029471274201089","probability":0,"probabilityPercent":""}` { t.Fatalf("json = %s", got) } } func validSaveRequestForTest() SaveConfigRequest { categories := make([]CategoryConfigInput, 0, len(wheelCategories)) for _, meta := range wheelCategories { categories = append(categories, validCategoryForTest(meta)) } return SaveConfigRequest{ SysOrigin: "yumi", Enabled: true, Timezone: "Asia/Riyadh", Categories: categories, } } func validCategoryForTest(meta CategoryMeta) CategoryConfigInput { probabilities := distributedProbabilityForTest(meta.RewardCount) rewards := make([]RewardConfigInput, 0, meta.RewardCount) for index := 0; index < meta.RewardCount; index++ { rewards = append(rewards, RewardConfigInput{ Enabled: true, Sort: index + 1, RewardType: rewardTypeResource, ResourceID: ResourceID(meta.Sort*1000 + index + 1), ResourceType: "RIDE", ResourceName: meta.Label, DurationDays: 7, DisplayGoldAmount: int64(1000 + index), Probability: probabilities[index], }) } return CategoryConfigInput{ Category: meta.Category, Enabled: true, PriceOneGold: meta.DefaultPriceOneGold, PriceTenGold: meta.DefaultPriceTenGold, PriceFiftyGold: meta.DefaultPriceFiftyGold, Rewards: rewards, } } func distributedProbabilityForTest(count int) []int { base := probabilityTotal / count remainder := probabilityTotal % count values := make([]int, count) for index := range values { values[index] = base } values[count-1] += remainder return values }