package mysql import ( "context" "testing" "time" "hyapp/internal/testutil/mysqlschema" "hyapp/pkg/appcode" gamedomain "hyapp/services/game-service/internal/domain/game" ) func TestMarkOrderSucceededCreatesClaimableLevelOutboxEvent(t *testing.T) { caller := mysqlschema.CallerFile(t, 1) schema := mysqlschema.New(t, mysqlschema.Config{ InitDBPath: mysqlschema.InitDBPath(t, caller, "../../../deploy/mysql/initdb/001_game_service.sql"), DatabasePrefix: "hy_game_test", }) ctx := appcode.WithContext(context.Background(), "lalu") repo, err := Open(ctx, schema.DSN) if err != nil { t.Fatalf("open repository failed: %v", err) } t.Cleanup(func() { _ = repo.Close() }) order := gamedomain.GameOrder{ AppCode: "lalu", OrderID: "order_1", PlatformCode: "demo", ProviderOrderID: "provider_order_1", GameID: "demo_rocket_001", ProviderGameID: "rocket_001", UserID: 42, RoomID: "room_1", OpType: "debit", CoinAmount: 120, Status: gamedomain.OrderStatusWalletApplying, RequestHash: "hash_1", CreatedAtMS: 1700000000000, UpdatedAtMS: 1700000000000, } if _, _, err := repo.CreateGameOrder(ctx, order); err != nil { t.Fatalf("create order failed: %v", err) } if err := repo.MarkOrderSucceeded(ctx, "lalu", "order_1", "wtx-game-1", 880, 1700000001000); err != nil { t.Fatalf("mark order succeeded failed: %v", err) } events, err := repo.ClaimPendingLevelEvents(ctx, "worker_1", 1700000002000, 30*time.Second, 10) if err != nil { t.Fatalf("claim level events failed: %v", err) } if len(events) != 1 { t.Fatalf("expected one level event, got %+v", events) } event := events[0] if event.EventID != "game_level:order_1" || event.UserID != 42 || event.CoinAmount != 120 { t.Fatalf("level event mismatch: %+v", event) } if event.PayloadJSON == "" || event.WalletTransactionID != "wtx-game-1" { t.Fatalf("level event payload mismatch: %+v", event) } } func TestUpsertCatalogCreatesDefaultVoiceRoomDisplayRule(t *testing.T) { caller := mysqlschema.CallerFile(t, 1) schema := mysqlschema.New(t, mysqlschema.Config{ InitDBPath: mysqlschema.InitDBPath(t, caller, "../../../deploy/mysql/initdb/001_game_service.sql"), DatabasePrefix: "hy_game_test", }) ctx := appcode.WithContext(context.Background(), "lalu") repo, err := Open(ctx, schema.DSN) if err != nil { t.Fatalf("open repository failed: %v", err) } t.Cleanup(func() { _ = repo.Close() }) item := gamedomain.CatalogItem{ AppCode: "lalu", GameID: "sync_game_001", PlatformCode: "demo", ProviderGameID: "provider_sync_001", GameName: "Sync Game", Category: "casino", LaunchMode: gamedomain.LaunchModeH5Popup, Orientation: "portrait", Status: gamedomain.StatusActive, SortOrder: 70, Tags: []string{"sync"}, } if _, err := repo.UpsertCatalog(ctx, item); err != nil { t.Fatalf("upsert catalog failed: %v", err) } var scene string var visible, enabled bool var sortOrder int32 if err := repo.db.QueryRowContext(ctx, `SELECT scene, visible, enabled, sort_order FROM game_display_rules WHERE app_code = ? AND rule_id = ? AND game_id = ?`, "lalu", defaultVoiceRoomRuleID(item.GameID), item.GameID, ).Scan(&scene, &visible, &enabled, &sortOrder); err != nil { t.Fatalf("query display rule failed: %v", err) } if scene != gamedomain.SceneVoiceRoom || !visible || !enabled || sortOrder != item.SortOrder { t.Fatalf("display rule mismatch: scene=%s visible=%v enabled=%v sort=%d", scene, visible, enabled, sortOrder) } } func TestDeleteCatalogRemovesGameAndDisplayRule(t *testing.T) { caller := mysqlschema.CallerFile(t, 1) schema := mysqlschema.New(t, mysqlschema.Config{ InitDBPath: mysqlschema.InitDBPath(t, caller, "../../../deploy/mysql/initdb/001_game_service.sql"), DatabasePrefix: "hy_game_test", }) ctx := appcode.WithContext(context.Background(), "lalu") repo, err := Open(ctx, schema.DSN) if err != nil { t.Fatalf("open repository failed: %v", err) } t.Cleanup(func() { _ = repo.Close() }) item := gamedomain.CatalogItem{ AppCode: "lalu", GameID: "delete_game_001", PlatformCode: "demo", ProviderGameID: "provider_delete_001", GameName: "Delete Game", Category: "casino", LaunchMode: gamedomain.LaunchModeH5Popup, Orientation: "portrait", Status: gamedomain.StatusActive, SortOrder: 80, } if _, err := repo.UpsertCatalog(ctx, item); err != nil { t.Fatalf("upsert catalog failed: %v", err) } if err := repo.DeleteCatalog(ctx, "lalu", item.GameID); err != nil { t.Fatalf("delete catalog failed: %v", err) } var gameCount int if err := repo.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM game_catalog WHERE app_code = ? AND game_id = ?`, "lalu", item.GameID, ).Scan(&gameCount); err != nil { t.Fatalf("query catalog count failed: %v", err) } if gameCount != 0 { t.Fatalf("game_catalog count = %d, want 0", gameCount) } var ruleCount int if err := repo.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM game_display_rules WHERE app_code = ? AND game_id = ?`, "lalu", item.GameID, ).Scan(&ruleCount); err != nil { t.Fatalf("query display rule count failed: %v", err) } if ruleCount != 0 { t.Fatalf("game_display_rules count = %d, want 0", ruleCount) } }