yumi-golang/internal/service/taskcenter/taskcenter_test.go
2026-07-09 23:02:09 +08:00

725 lines
21 KiB
Go

package taskcenter
import (
"context"
"strings"
"testing"
"time"
"chatapp3-golang/internal/common"
"chatapp3-golang/internal/config"
"chatapp3-golang/internal/integration"
"chatapp3-golang/internal/model"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func newTestService(t *testing.T, java taskCenterJavaGateway) (*Service, *gorm.DB) {
t.Helper()
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{})
if err != nil {
t.Fatalf("open sqlite: %v", err)
}
if err := db.AutoMigrate(
&model.TaskCenterConfig{},
&model.TaskCenterTaskConfig{},
&model.TaskCenterConditionJumpConfig{},
&model.TaskCenterUserProgress{},
&model.TaskCenterEvent{},
&model.TaskCenterEventDedup{},
&model.TaskCenterEventArchiveOutbox{},
&model.TaskCenterClaimRecord{},
); err != nil {
t.Fatalf("auto migrate: %v", err)
}
service := NewService(config.Config{
TaskCenter: config.TaskCenterConfig{
DefaultSysOrigin: "LIKEI",
Timezone: "Asia/Riyadh",
},
}, db, java)
return service, db
}
func TestNormalizeTaskCenterArchiveBatchSize(t *testing.T) {
tests := []struct {
name string
input int
want int
}{
{name: "default", input: 0, want: defaultTaskCenterArchiveBatchSize},
{name: "negative default", input: -1, want: defaultTaskCenterArchiveBatchSize},
{name: "keeps configured value", input: 200, want: 200},
{name: "caps large batch", input: 10000, want: maxTaskCenterArchiveBatchSize},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := normalizeTaskCenterArchiveBatchSize(tt.input); got != tt.want {
t.Fatalf("normalizeTaskCenterArchiveBatchSize(%d) = %d, want %d", tt.input, got, tt.want)
}
})
}
}
func TestTaskCenterArchiveClaimLimitsReserveStaleRows(t *testing.T) {
tests := []struct {
name string
batchSize int
wantStale int
wantRetryable int
}{
{name: "single row", batchSize: 1, wantStale: 1, wantRetryable: 0},
{name: "small batch keeps one stale slot", batchSize: 5, wantStale: 1, wantRetryable: 4},
{name: "normal batch uses ten percent", batchSize: 500, wantStale: 50, wantRetryable: 450},
{name: "large batch caps stale slot", batchSize: 1000, wantStale: 100, wantRetryable: 900},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotStale, gotRetryable := taskCenterArchiveClaimLimits(tt.batchSize)
if gotStale != tt.wantStale || gotRetryable != tt.wantRetryable {
t.Fatalf("taskCenterArchiveClaimLimits(%d) = (%d, %d), want (%d, %d)",
tt.batchSize, gotStale, gotRetryable, tt.wantStale, tt.wantRetryable)
}
})
}
}
func TestTaskCenterArchivePendingClaimLimitReservesFailedRows(t *testing.T) {
tests := []struct {
name string
retryableLimit int
want int
}{
{name: "empty", retryableLimit: 0, want: 0},
{name: "single row stays pending first", retryableLimit: 1, want: 1},
{name: "small retry batch keeps one failed slot", retryableLimit: 4, want: 3},
{name: "normal retry batch reserves ten percent", retryableLimit: 450, want: 405},
{name: "large retry batch caps failed reserve", retryableLimit: 900, want: 810},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := taskCenterArchivePendingClaimLimit(tt.retryableLimit); got != tt.want {
t.Fatalf("taskCenterArchivePendingClaimLimit(%d) = %d, want %d", tt.retryableLimit, got, tt.want)
}
})
}
}
func TestDailyTaskConfigEventListAndClaim(t *testing.T) {
java := &taskCenterTestGateway{events: map[string]bool{}}
service, db := newTestService(t, java)
ctx := context.Background()
configResp, err := service.SaveConfig(ctx, SaveConfigRequest{
SysOrigin: "likei",
Enabled: true,
Timezone: "Asia/Riyadh",
TaskCategory: TaskCategoryDaily,
Tasks: []SaveTaskConfigInput{
{
TaskCode: "daily_mic_duration",
Enabled: true,
TaskName: "使用麦克风 %d 分钟。",
TaskDesc: "进度 / 目标",
ConditionType: "mic_duration_seconds",
TargetValue: 60,
TargetUnit: "second",
RewardGold: 1100,
JumpType: "ROOM_RANDOM_WITH_MIC",
SortOrder: 10,
},
},
})
if err != nil {
t.Fatalf("SaveConfig() error = %v", err)
}
if !configResp.Configured || !configResp.Enabled || len(configResp.Tasks) != 1 {
t.Fatalf("SaveConfig() resp = %+v", configResp)
}
user := common.AuthUser{UserID: 1001, SysOrigin: "LIKEI"}
tasks, err := service.ListTasks(ctx, user)
if err != nil {
t.Fatalf("ListTasks() error = %v", err)
}
if len(tasks) != 1 || tasks[0].TaskStatus != 0 || tasks[0].CompletedValue != 0 {
t.Fatalf("initial tasks = %+v", tasks)
}
eventResp, err := service.ReceiveEvent(ctx, EventRequest{
SysOrigin: "LIKEI",
EventID: "event-1",
EventType: "MIC_DURATION_SECONDS",
UserID: flexibleInt64(user.UserID),
DeltaValue: 60,
})
if err != nil {
t.Fatalf("ReceiveEvent() error = %v", err)
}
if !eventResp.Processed || eventResp.Updated != 1 {
t.Fatalf("ReceiveEvent() resp = %+v", eventResp)
}
duplicateResp, err := service.ReceiveEvent(ctx, EventRequest{
SysOrigin: "LIKEI",
EventID: "event-1",
EventType: "MIC_DURATION_SECONDS",
UserID: flexibleInt64(user.UserID),
DeltaValue: 60,
})
if err != nil {
t.Fatalf("ReceiveEvent() duplicate error = %v", err)
}
if duplicateResp.Processed || duplicateResp.Reason != "duplicate_event" {
t.Fatalf("ReceiveEvent() duplicate resp = %+v", duplicateResp)
}
var dedupCount int64
if err := db.Model(&model.TaskCenterEventDedup{}).
Where("sys_origin = ? AND event_id = ?", "LIKEI", "event-1").
Count(&dedupCount).Error; err != nil {
t.Fatalf("count dedup: %v", err)
}
if dedupCount != 1 {
t.Fatalf("dedup rows = %d, want 1", dedupCount)
}
var outboxCount int64
if err := db.Model(&model.TaskCenterEventArchiveOutbox{}).
Where("sys_origin = ? AND event_id = ?", "LIKEI", "event-1").
Count(&outboxCount).Error; err != nil {
t.Fatalf("count archive outbox: %v", err)
}
if outboxCount != 1 {
t.Fatalf("archive outbox rows = %d, want 1", outboxCount)
}
var legacyEventCount int64
if err := db.Model(&model.TaskCenterEvent{}).
Where("sys_origin = ? AND event_id = ?", "LIKEI", "event-1").
Count(&legacyEventCount).Error; err != nil {
t.Fatalf("count legacy task event: %v", err)
}
if legacyEventCount != 0 {
t.Fatalf("legacy task event rows = %d, want 0", legacyEventCount)
}
tasks, err = service.ListTasks(ctx, user)
if err != nil {
t.Fatalf("ListTasks() after event error = %v", err)
}
if len(tasks) != 1 || tasks[0].TaskStatus != 1 || tasks[0].CompletedValue != 60 {
t.Fatalf("completed tasks = %+v", tasks)
}
ok, err := service.Claim(ctx, user, tasks[0].TaskID)
if err != nil {
t.Fatalf("Claim() error = %v", err)
}
if !ok {
t.Fatalf("Claim() = false, want true")
}
if len(java.changedEvents) != 1 {
t.Fatalf("wallet changes = %d, want 1", len(java.changedEvents))
}
if java.changedCommands[0].Origin != "DAILY_TASK" {
t.Fatalf("wallet origin = %q, want DAILY_TASK", java.changedCommands[0].Origin)
}
if len(java.changedEvents[0]) > 50 {
t.Fatalf("wallet event id length = %d, want <= 50: %s", len(java.changedEvents[0]), java.changedEvents[0])
}
ok, err = service.Claim(ctx, user, tasks[0].TaskID)
if err != nil {
t.Fatalf("Claim() duplicate error = %v", err)
}
if !ok || len(java.changedEvents) != 1 {
t.Fatalf("duplicate claim ok=%v changes=%d, want true/1", ok, len(java.changedEvents))
}
}
func TestExclusiveTaskConfigUsesLifetimeCycleAndHidesAfterClaim(t *testing.T) {
java := &taskCenterTestGateway{events: map[string]bool{}}
service, _ := newTestService(t, java)
ctx := context.Background()
_, err := service.SaveConfig(ctx, SaveConfigRequest{
SysOrigin: "LIKEI",
Enabled: true,
Timezone: "Asia/Riyadh",
TaskCategory: TaskCategoryNewbie,
Tasks: []SaveTaskConfigInput{
{
TaskCode: "EXCLUSIVE_RECHARGE",
Enabled: true,
TaskName: "专属充值任务",
ConditionType: "RECHARGE_GOLD",
TargetValue: 10,
TargetUnit: "gold",
RewardGold: 100,
},
},
})
if err != nil {
t.Fatalf("SaveConfig() error = %v", err)
}
user := common.AuthUser{UserID: 2001, SysOrigin: "LIKEI"}
tasks, err := service.ListTasks(ctx, user)
if err != nil {
t.Fatalf("ListTasks() error = %v", err)
}
if len(tasks) != 1 || tasks[0].TaskType != 1 {
t.Fatalf("exclusive tasks = %+v, want one taskType=1", tasks)
}
if tasks[0].JumpPage != defaultRechargeJumpPage {
t.Fatalf("exclusive recharge jumpPage = %q, want %q", tasks[0].JumpPage, defaultRechargeJumpPage)
}
eventResp, err := service.ReceiveEvent(ctx, EventRequest{
SysOrigin: "LIKEI",
EventID: "recharge-1",
EventType: "RECHARGE_GOLD",
UserID: flexibleInt64(user.UserID),
DeltaValue: 10,
})
if err != nil {
t.Fatalf("ReceiveEvent() error = %v", err)
}
if !eventResp.Processed || eventResp.Updated != 1 {
t.Fatalf("ReceiveEvent() resp = %+v", eventResp)
}
ok, err := service.Claim(ctx, user, tasks[0].TaskID)
if err != nil {
t.Fatalf("Claim() error = %v", err)
}
if !ok {
t.Fatalf("Claim() = false, want true")
}
tasks, err = service.ListTasks(ctx, user)
if err != nil {
t.Fatalf("ListTasks() after claim error = %v", err)
}
if len(tasks) != 0 {
t.Fatalf("exclusive tasks after claim = %+v, want hidden", tasks)
}
}
func TestProcessEventWithProductionGameEventShape(t *testing.T) {
service, db := newTestService(t, nil)
ctx := context.Background()
now := time.Now()
configRow := model.TaskCenterConfig{
ID: 2052721146352111616,
SysOrigin: "LIKEI",
Enabled: true,
Timezone: "Asia/Riyadh",
CreateTime: now,
UpdateTime: now,
}
if err := db.Create(&configRow).Error; err != nil {
t.Fatalf("create config: %v", err)
}
tasks := []model.TaskCenterTaskConfig{
{
ID: 2053002284639457280,
ConfigID: configRow.ID,
SysOrigin: "LIKEI",
TaskCode: "GAME_200K",
TaskCategory: TaskCategoryDaily,
Enabled: true,
TaskName: "Spend 200K coins in the game.",
TaskDesc: "progress",
ConditionType: EventTypeGameConsumeGold,
TargetValue: 200000,
TargetUnit: "gold",
RewardGold: 500,
JumpType: "ROOM_RANDOM_WITH_MIC",
JumpPage: "/room?gameId=0",
SortOrder: 30,
CreateTime: now,
UpdateTime: now,
},
{
ID: 2053005491679793152,
ConfigID: configRow.ID,
SysOrigin: "LIKEI",
TaskCode: "GAME_40K",
TaskCategory: TaskCategoryNewbie,
Enabled: true,
TaskName: "Spend 40K coins in the game.",
TaskDesc: "progress",
ConditionType: EventTypeGameConsumeGold,
TargetValue: 40000,
TargetUnit: "gold",
RewardGold: 200,
JumpType: "ROOM_RANDOM_WITH_MIC",
SortOrder: 30,
CreateTime: now,
UpdateTime: now,
},
}
if err := db.Create(&tasks).Error; err != nil {
t.Fatalf("create tasks: %v", err)
}
resp, err := service.ProcessEvent(ctx, EventRequest{
SysOrigin: "LIKEI",
EventID: "BAISHUN_GAME_CONSUME:LIKEI:ee2d4218-4f58-406a-bf0f-d6b09f7e9930",
EventType: EventTypeGameConsumeGold,
UserID: flexibleInt64(2053169065266049025),
DeltaValue: 100,
OccurredAt: "2026-05-09T20:48:30.291+03:00",
Payload: map[string]any{
"diffMsg": "bet",
"gameId": float64(1067),
"gameRoundId": "20260510000171",
"orderId": "ee2d4218-4f58-406a-bf0f-d6b09f7e9930",
"provider": "BAISHUN",
},
})
if err != nil {
t.Fatalf("ProcessEvent() error = %v", err)
}
if !resp.Processed || resp.Updated != 2 {
t.Fatalf("ProcessEvent() resp = %+v, want processed with two task updates", resp)
}
var progressCount int64
if err := db.Model(&model.TaskCenterUserProgress{}).
Where("sys_origin = ? AND user_id = ? AND completed_value = ?", "LIKEI", int64(2053169065266049025), int64(100)).
Count(&progressCount).Error; err != nil {
t.Fatalf("count progress: %v", err)
}
if progressCount != 2 {
t.Fatalf("progress rows = %d, want 2", progressCount)
}
var outbox model.TaskCenterEventArchiveOutbox
if err := db.Where("sys_origin = ? AND event_id = ?", "LIKEI", "BAISHUN_GAME_CONSUME:LIKEI:ee2d4218-4f58-406a-bf0f-d6b09f7e9930").
First(&outbox).Error; err != nil {
t.Fatalf("load archive outbox: %v", err)
}
if outbox.Status != ArchiveStatusPending || !strings.Contains(outbox.RawJSON, "BAISHUN_GAME_CONSUME") {
t.Fatalf("archive outbox = %+v", outbox)
}
}
func TestConditionJumpConfigAppliesToTasks(t *testing.T) {
service, _ := newTestService(t, nil)
ctx := context.Background()
resp, err := service.SaveConfig(ctx, SaveConfigRequest{
SysOrigin: "LIKEI",
Enabled: true,
Timezone: "Asia/Riyadh",
TaskCategory: TaskCategoryDaily,
ConditionJumps: []SaveConditionJumpConfigInput{
{
ConditionType: "MIC_DURATION_SECONDS",
JumpType: "APP_ROUTE",
JumpPage: "/task/mic-guide",
SortOrder: 10,
},
{
ConditionType: "GIFT_CONSUME_GOLD",
JumpType: "ROOM_RANDOM",
JumpPage: "/room?source=custom",
SortOrder: 20,
},
},
Tasks: []SaveTaskConfigInput{
{
TaskCode: "DAILY_MIC",
Enabled: true,
TaskName: "Mic task",
ConditionType: "MIC_DURATION_SECONDS",
TargetValue: 60,
TargetUnit: "second",
RewardGold: 100,
JumpType: "ROOM_RANDOM_WITH_MIC",
SortOrder: 10,
},
{
TaskCode: "DAILY_GIFT",
Enabled: true,
TaskName: "Gift task",
ConditionType: "GIFT_CONSUME_GOLD",
TargetValue: 1,
TargetUnit: "gold",
RewardGold: 100,
SortOrder: 20,
},
},
})
if err != nil {
t.Fatalf("SaveConfig() error = %v", err)
}
if len(resp.ConditionJumps) != 2 {
t.Fatalf("condition jumps = %+v, want 2 rows", resp.ConditionJumps)
}
if resp.ConditionJumps[1].JumpPage != "/room?source=custom" {
t.Fatalf("room condition jump page = %q, want preserved", resp.ConditionJumps[1].JumpPage)
}
if resp.Tasks[0].JumpType != "APP_ROUTE" || resp.Tasks[0].JumpPage != "/task/mic-guide" {
t.Fatalf("mic task jump = %s %s, want APP_ROUTE /task/mic-guide", resp.Tasks[0].JumpType, resp.Tasks[0].JumpPage)
}
if resp.Tasks[1].JumpType != "ROOM_RANDOM" || resp.Tasks[1].JumpPage != "/room?source=custom" {
t.Fatalf("gift task jump = %s %s, want ROOM_RANDOM /room?source=custom", resp.Tasks[1].JumpType, resp.Tasks[1].JumpPage)
}
tasks, err := service.ListTasks(ctx, common.AuthUser{UserID: 3001, SysOrigin: "LIKEI"})
if err != nil {
t.Fatalf("ListTasks() error = %v", err)
}
if len(tasks) != 2 || tasks[0].JumpPage != "/task/mic-guide" || tasks[1].JumpPage != "/room?source=custom" {
t.Fatalf("app task jumps = %+v, want custom route and custom room param", tasks)
}
}
func TestPageClaimRecordsFiltersTimeAndSummarizesGold(t *testing.T) {
service, db := newTestService(t, nil)
ctx := context.Background()
base := time.Date(2026, 5, 15, 10, 0, 0, 0, time.Local)
claimedAt := base
rows := []model.TaskCenterClaimRecord{
{
ID: 1,
SysOrigin: "LIKEI",
UserID: 1001,
TaskID: 11,
TaskCode: "DAILY_MIC",
TaskName: "Mic",
TaskCategory: TaskCategoryDaily,
CycleKey: "20260515",
RewardGold: 100,
WalletEventID: "wallet-1",
Status: ClaimStatusSuccess,
ClaimedAt: &claimedAt,
CreateTime: base,
UpdateTime: base,
},
{
ID: 2,
SysOrigin: "LIKEI",
UserID: 1002,
TaskID: 12,
TaskCode: "DAILY_GIFT",
TaskName: "Gift",
TaskCategory: TaskCategoryDaily,
CycleKey: "20260515",
RewardGold: 200,
WalletEventID: "wallet-2",
Status: ClaimStatusSuccess,
ClaimedAt: &claimedAt,
CreateTime: base.Add(time.Hour),
UpdateTime: base.Add(time.Hour),
},
{
ID: 3,
SysOrigin: "LIKEI",
UserID: 1003,
TaskID: 11,
TaskCode: "DAILY_MIC",
TaskName: "Mic",
TaskCategory: TaskCategoryDaily,
CycleKey: "20260515",
RewardGold: 999,
WalletEventID: "wallet-3",
Status: ClaimStatusFailed,
FailureReason: "wallet failed",
CreateTime: base.Add(2 * time.Hour),
UpdateTime: base.Add(2 * time.Hour),
},
{
ID: 4,
SysOrigin: "LIKEI",
UserID: 1004,
TaskID: 13,
TaskCode: "DAILY_OLD",
TaskName: "Old",
TaskCategory: TaskCategoryDaily,
CycleKey: "20260514",
RewardGold: 700,
WalletEventID: "wallet-4",
Status: ClaimStatusSuccess,
ClaimedAt: &claimedAt,
CreateTime: base.AddDate(0, 0, -1),
UpdateTime: base.AddDate(0, 0, -1),
},
}
if err := db.Create(&rows).Error; err != nil {
t.Fatalf("create claim records: %v", err)
}
resp, err := service.PageClaimRecords(
ctx,
"LIKEI",
TaskCategoryDaily,
0,
"daily_mic",
"",
base.Format("2006-01-02 15:04:05"),
base.Add(3*time.Hour).Format("2006-01-02 15:04:05"),
1,
20,
)
if err != nil {
t.Fatalf("PageClaimRecords() error = %v", err)
}
if resp.Total != 2 || len(resp.Records) != 2 {
t.Fatalf("records total=%d len=%d, want 2", resp.Total, len(resp.Records))
}
if resp.Summary.TotalRewardGold != 300 {
t.Fatalf("total reward gold = %d, want 300", resp.Summary.TotalRewardGold)
}
if resp.Summary.SelectedTaskRewardGold != 100 {
t.Fatalf("selected task reward gold = %d, want 100", resp.Summary.SelectedTaskRewardGold)
}
}
func TestSaveConfigDerivesConditionJumpsWhenPayloadOmitted(t *testing.T) {
service, _ := newTestService(t, nil)
ctx := context.Background()
resp, err := service.SaveConfig(ctx, SaveConfigRequest{
SysOrigin: "LIKEI",
Enabled: true,
Timezone: "Asia/Riyadh",
TaskCategory: TaskCategoryDaily,
Tasks: []SaveTaskConfigInput{
{
TaskCode: "DAILY_MIC",
Enabled: true,
TaskName: "Mic task",
ConditionType: "MIC_DURATION_SECONDS",
TargetValue: 60,
TargetUnit: "second",
RewardGold: 100,
JumpType: "APP_ROUTE",
JumpPage: "/task/mic-guide",
SortOrder: 10,
},
{
TaskCode: "DAILY_GIFT",
Enabled: true,
TaskName: "Gift task",
ConditionType: "GIFT_CONSUME_GOLD",
TargetValue: 1,
TargetUnit: "gold",
RewardGold: 100,
JumpType: "ROOM_RANDOM",
JumpPage: "/room?source=custom",
SortOrder: 20,
},
},
})
if err != nil {
t.Fatalf("SaveConfig() error = %v", err)
}
if len(resp.ConditionJumps) != 2 {
t.Fatalf("condition jumps = %+v, want derived rows", resp.ConditionJumps)
}
if resp.ConditionJumps[0].JumpPage != "/task/mic-guide" || resp.ConditionJumps[1].JumpPage != "/room?source=custom" {
t.Fatalf("condition jump pages = %+v, want task jump fields persisted", resp.ConditionJumps)
}
if resp.Tasks[0].JumpType != "APP_ROUTE" || resp.Tasks[0].JumpPage != "/task/mic-guide" {
t.Fatalf("mic task jump = %s %s, want APP_ROUTE /task/mic-guide", resp.Tasks[0].JumpType, resp.Tasks[0].JumpPage)
}
}
func TestResolveJumpPageUsesRechargeRouteForRechargeTask(t *testing.T) {
tests := []struct {
name string
task model.TaskCenterTaskConfig
want string
}{
{
name: "recharge task with old room jump type",
task: model.TaskCenterTaskConfig{
ConditionType: EventTypeRechargeGold,
JumpType: "ROOM_RANDOM_WITH_MIC",
},
want: defaultRechargeJumpPage,
},
{
name: "recharge jump type",
task: model.TaskCenterTaskConfig{
JumpType: JumpTypeRechargeInApp,
},
want: defaultRechargeJumpPage,
},
{
name: "explicit jump page wins",
task: model.TaskCenterTaskConfig{
ConditionType: EventTypeRechargeGold,
JumpPage: "/custom/recharge",
JumpType: "ROOM_RANDOM_WITH_MIC",
},
want: "/custom/recharge",
},
{
name: "room task keeps room jump",
task: model.TaskCenterTaskConfig{
ConditionType: EventTypeMicDurationSeconds,
JumpType: "ROOM_RANDOM_WITH_MIC",
},
want: "/room",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := resolveJumpPage(tt.task); got != tt.want {
t.Fatalf("resolveJumpPage() = %q, want %q", got, tt.want)
}
})
}
}
func TestTaskConfigRejectsRemovedConditionTypes(t *testing.T) {
service, _ := newTestService(t, nil)
for _, conditionType := range []string{"POST_MOOD_COUNT", "INTERACTIVE_GAME_COUNT", "CP_BIND_COUNT"} {
t.Run(conditionType, func(t *testing.T) {
_, err := service.SaveConfig(context.Background(), SaveConfigRequest{
SysOrigin: "LIKEI",
Enabled: true,
Timezone: "Asia/Riyadh",
TaskCategory: TaskCategoryDaily,
Tasks: []SaveTaskConfigInput{
{
TaskCode: "REMOVED_" + conditionType,
Enabled: true,
TaskName: "Removed condition",
ConditionType: conditionType,
TargetValue: 1,
TargetUnit: "count",
RewardGold: 100,
},
},
})
if err == nil {
t.Fatalf("SaveConfig() error = nil, want invalid condition")
}
})
}
}
type taskCenterTestGateway struct {
changedEvents []string
changedCommands []integration.GoldReceiptCommand
events map[string]bool
}
func (g *taskCenterTestGateway) ExistsGoldEvent(_ context.Context, eventID string) (bool, error) {
return g.events[eventID], nil
}
func (g *taskCenterTestGateway) ChangeGoldBalance(_ context.Context, cmd integration.GoldReceiptCommand) error {
g.changedEvents = append(g.changedEvents, cmd.EventID)
g.changedCommands = append(g.changedCommands, cmd)
g.events[cmd.EventID] = true
return nil
}