217 lines
6.9 KiB
Go
217 lines
6.9 KiB
Go
package roomadmin
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"hyapp-admin-server/internal/integration/robotclient"
|
|
)
|
|
|
|
func TestNormalizeRoomListSortKeepsOnlyContributionSort(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
query listQuery
|
|
wantOrder string
|
|
}{
|
|
{
|
|
name: "default",
|
|
query: listQuery{},
|
|
wantOrder: "rle.created_at_ms DESC, rle.room_id DESC",
|
|
},
|
|
{
|
|
name: "contribution_desc",
|
|
query: listQuery{SortBy: "room_contribution", SortDirection: "desc"},
|
|
wantOrder: "rle.heat DESC, rle.created_at_ms DESC, rle.room_id DESC",
|
|
},
|
|
{
|
|
name: "contribution_asc",
|
|
query: listQuery{SortBy: "heat", SortDirection: "asc"},
|
|
wantOrder: "rle.heat ASC, rle.created_at_ms DESC, rle.room_id DESC",
|
|
},
|
|
{
|
|
name: "unknown_falls_back",
|
|
query: listQuery{SortBy: "owner_user_id", SortDirection: "asc"},
|
|
wantOrder: "rle.created_at_ms DESC, rle.room_id DESC",
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
query := normalizeListQuery(test.query)
|
|
if got := roomListOrderBy(query); got != test.wantOrder {
|
|
t.Fatalf("order by mismatch: got %q want %q", got, test.wantOrder)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRobotRoomProfileFromOwnerUsesOwnerNameAndAvatar(t *testing.T) {
|
|
name, avatar, err := robotRoomProfileFromOwner(RoomOwner{
|
|
Username: " Robot Host ",
|
|
Avatar: " https://cdn.example.com/robot.png ",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("robot room owner profile should be valid: %v", err)
|
|
}
|
|
if name != "Robot Host" || avatar != "https://cdn.example.com/robot.png" {
|
|
t.Fatalf("owner profile mismatch: name=%q avatar=%q", name, avatar)
|
|
}
|
|
}
|
|
|
|
func TestRobotRoomProfileFromOwnerRequiresNameAndAvatar(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
owner RoomOwner
|
|
}{
|
|
{name: "missing_name", owner: RoomOwner{Avatar: "https://cdn.example.com/robot.png"}},
|
|
{name: "missing_avatar", owner: RoomOwner{Username: "Robot Host"}},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
_, _, err := robotRoomProfileFromOwner(test.owner)
|
|
if !errors.Is(err, ErrInvalidArgument) {
|
|
t.Fatalf("expected ErrInvalidArgument, got %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestApplyOwnerProfileToRobotRoomRequestFollowsOwnerRegionAndCountry(t *testing.T) {
|
|
req := createRobotRoomRequest{
|
|
RoomName: "manual name",
|
|
RoomAvatar: "https://cdn.example.com/manual.png",
|
|
VisibleRegionID: 999,
|
|
OwnerCountryCode: "XX",
|
|
}
|
|
err := applyOwnerProfileToRobotRoomRequest(&req, RoomOwner{
|
|
Username: " Robot Owner ",
|
|
Avatar: " https://cdn.example.com/owner.png ",
|
|
CountryCode: " ae ",
|
|
VisibleRegionID: 686,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("apply owner profile failed: %v", err)
|
|
}
|
|
if req.RoomName != "Robot Owner" || req.RoomAvatar != "https://cdn.example.com/owner.png" {
|
|
t.Fatalf("owner display profile mismatch: name=%q avatar=%q", req.RoomName, req.RoomAvatar)
|
|
}
|
|
if req.VisibleRegionID != 686 || req.OwnerCountryCode != "AE" {
|
|
t.Fatalf("owner region or country mismatch: region=%d country=%q", req.VisibleRegionID, req.OwnerCountryCode)
|
|
}
|
|
}
|
|
|
|
func TestCreateRobotRoomRequestAcceptsStringInt64IDs(t *testing.T) {
|
|
var req createRobotRoomRequest
|
|
if err := json.Unmarshal([]byte(`{
|
|
"ownerRobotUserId":"325379237278126080",
|
|
"candidateRobotUserIds":["325379237278126080","325455441691676672","325455441691676672"],
|
|
"minRobotCount":2,
|
|
"maxRobotCount":8,
|
|
"giftIds":["84"],
|
|
"luckyGiftIds":["28"],
|
|
"normalGiftIntervalMs":10000,
|
|
"luckyComboMin":100,
|
|
"luckyComboMax":10000,
|
|
"luckyPauseMinMs":5000,
|
|
"luckyPauseMaxMs":20000
|
|
}`), &req); err != nil {
|
|
t.Fatalf("robot room request should accept string int64 ids: %v", err)
|
|
}
|
|
|
|
normalized, err := normalizeCreateRobotRoomRequest(req)
|
|
if err != nil {
|
|
t.Fatalf("robot room request should normalize: %v", err)
|
|
}
|
|
if got := int64(normalized.OwnerRobotUserID); got != 325379237278126080 {
|
|
t.Fatalf("owner id mismatch: got %d", got)
|
|
}
|
|
if got := []int64(normalized.CandidateRobotUserIDs); len(got) != 1 || got[0] != 325455441691676672 {
|
|
t.Fatalf("candidate ids should drop owner and duplicates, got %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestCreateRobotRoomRequestBindsStringInt64IDsFromHTTP(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
body := `{
|
|
"ownerRobotUserId":"325379237278126080",
|
|
"candidateRobotUserIds":["325455441691676672"],
|
|
"minRobotCount":2,
|
|
"maxRobotCount":8,
|
|
"giftIds":["84"],
|
|
"luckyGiftIds":["28"],
|
|
"normalGiftIntervalMs":10000,
|
|
"luckyComboMin":100,
|
|
"luckyComboMax":10000,
|
|
"luckyPauseMinMs":5000,
|
|
"luckyPauseMaxMs":20000
|
|
}`
|
|
req := httptest.NewRequest(http.MethodPost, "/admin/rooms/robot-rooms", strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
ctx, _ := gin.CreateTestContext(rec)
|
|
ctx.Request = req
|
|
|
|
var payload createRobotRoomRequest
|
|
if err := ctx.ShouldBindJSON(&payload); err != nil {
|
|
t.Fatalf("gin binding should accept string int64 ids: %v", err)
|
|
}
|
|
if got := int64(payload.OwnerRobotUserID); got != 325379237278126080 {
|
|
t.Fatalf("owner id mismatch: got %d", got)
|
|
}
|
|
if got := []int64(payload.CandidateRobotUserIDs); len(got) != 1 || got[0] != 325455441691676672 {
|
|
t.Fatalf("candidate ids mismatch: %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeRoomWhitelistUserIDsKeepsStringInt64Order(t *testing.T) {
|
|
got, err := normalizeRoomWhitelistUserIDs([]string{"325379237278126080", "1001", "1001"})
|
|
if err != nil {
|
|
t.Fatalf("normalize room whitelist failed: %v", err)
|
|
}
|
|
want := []string{"1001", "325379237278126080"}
|
|
if len(got) != len(want) {
|
|
t.Fatalf("whitelist length mismatch: got %+v want %+v", got, want)
|
|
}
|
|
for index := range want {
|
|
if got[index] != want[index] {
|
|
t.Fatalf("whitelist id %d mismatch: got %+v want %+v", index, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNormalizeRoomWhitelistUserIDsRejectsInvalidID(t *testing.T) {
|
|
if _, err := normalizeRoomWhitelistUserIDs([]string{"1.2"}); !errors.Is(err, ErrInvalidArgument) {
|
|
t.Fatalf("invalid id should return ErrInvalidArgument, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAvailableRoomRobotsFromGamePoolKeepsOnlyRoomAvailableUsers(t *testing.T) {
|
|
robots := []robotclient.Robot{
|
|
{UserID: 101, Status: "active", LastUsedAtMS: 1000, UsedCount: 2},
|
|
{UserID: 102, Status: "active", LastUsedAtMS: 2000, UsedCount: 3},
|
|
{UserID: 103, Status: "active", LastUsedAtMS: 3000, UsedCount: 4},
|
|
}
|
|
owners := map[int64]RoomOwner{
|
|
101: {UserID: "101", Username: "Robot A"},
|
|
103: {UserID: "103", Username: "Robot C"},
|
|
}
|
|
|
|
items := availableRoomRobotsFromGamePool(robots, []int64{103, 101}, owners)
|
|
if len(items) != 2 {
|
|
t.Fatalf("available robots length mismatch: got %d want 2", len(items))
|
|
}
|
|
if items[0].UserID != "101" || items[0].User.Username != "Robot A" || items[0].UsedCount != 2 {
|
|
t.Fatalf("first available robot mismatch: %+v", items[0])
|
|
}
|
|
if items[1].UserID != "103" || items[1].User.Username != "Robot C" || items[1].LastUsedAtMS != 3000 {
|
|
t.Fatalf("second available robot mismatch: %+v", items[1])
|
|
}
|
|
}
|