package appuser import ( "context" "testing" "hyapp-admin-server/internal/appctx" activityv1 "hyapp.local/api/proto/activity/v1" userv1 "hyapp.local/api/proto/user/v1" ) type fakeUserAdminProjectionClient struct { profiles map[int64]*userv1.UserAdminProfile } func (f *fakeUserAdminProjectionClient) BatchGetUserAdminProfiles(context.Context, *userv1.BatchGetUserAdminProfilesRequest) (*userv1.BatchGetUserAdminProfilesResponse, error) { return &userv1.BatchGetUserAdminProfilesResponse{Profiles: f.profiles}, nil } func (f *fakeUserAdminProjectionClient) AdminBanUser(context.Context, *userv1.AdminBanUserRequest) (*userv1.AdminBanUserResponse, error) { return &userv1.AdminBanUserResponse{}, nil } func (f *fakeUserAdminProjectionClient) AdminUnbanUser(context.Context, *userv1.AdminUnbanUserRequest) (*userv1.AdminUnbanUserResponse, error) { return &userv1.AdminUnbanUserResponse{}, nil } type fakeLevelAdminProjectionClient struct { profiles []*activityv1.AdminUserLevelProfile } func (f *fakeLevelAdminProjectionClient) BatchGetUserLevelAdminProfiles(context.Context, *activityv1.BatchGetUserLevelAdminProfilesRequest) (*activityv1.BatchGetUserLevelAdminProfilesResponse, error) { return &activityv1.BatchGetUserLevelAdminProfilesResponse{Profiles: f.profiles}, nil } func (f *fakeLevelAdminProjectionClient) AdjustTemporaryUserLevels(context.Context, *activityv1.AdjustTemporaryUserLevelsRequest) (*activityv1.AdjustTemporaryUserLevelsResponse, error) { return &activityv1.AdjustTemporaryUserLevelsResponse{}, nil } func TestAdminProjectionEnrichmentMapsOwnerFacts(t *testing.T) { service := &Service{ userAdminClient: &fakeUserAdminProjectionClient{profiles: map[int64]*userv1.UserAdminProfile{ 10001: { Birth: "2000-02-03", RegisterDevice: "Pixel 9", LastSuccessLoginAtMs: 7000, Roles: []string{"host", "bd_leader", "manager"}, Ban: &userv1.ActiveUserBanSummary{ Active: true, Source: "admin", BanId: "ban-1", Permanent: false, ExpiresAtMs: 9000, Reason: "risk", }, }, }}, levelAdminClient: &fakeLevelAdminProjectionClient{profiles: []*activityv1.AdminUserLevelProfile{ {UserId: 10001, Tracks: []*activityv1.AdminLevelTrackProfile{ {Track: "wealth", RealLevel: 8, RealTotalValue: 800, DisplayLevel: 14, DisplayValue: 1400, TemporaryLevelId: "temp-1", TemporaryTargetLevel: 14, StartedAtMs: 1000, ExpiresAtMs: 9000}, {Track: "charm", RealLevel: 9, RealTotalValue: 900, DisplayLevel: 9, DisplayValue: 900}, {Track: "game", RealLevel: 6, RealTotalValue: 600, DisplayLevel: 6, DisplayValue: 600}, }}, }}, } items := []AppUser{{UserID: "10001"}} ctx := appctx.WithContext(context.Background(), "lalu") if err := service.fillUserAdminProfiles(ctx, items, []int64{10001}); err != nil { t.Fatalf("fill user profiles: %v", err) } if err := service.fillLevelAdminProfiles(ctx, items, []int64{10001}); err != nil { t.Fatalf("fill level profiles: %v", err) } item := items[0] if item.Birth != "2000-02-03" || item.RegisterDevice != "Pixel 9" || item.LastLoginAtMs != 7000 { t.Fatalf("user owner facts mismatch: %+v", item) } if len(item.Roles) != 3 || item.Roles[0] != "主播" || item.Roles[1] != "BD Leader" || item.Roles[2] != "经理" { t.Fatalf("roles mismatch: %#v", item.Roles) } if !item.Ban.Active || item.Ban.ID != "ban-1" || item.Ban.ExpiresAtMs != 9000 { t.Fatalf("ban mismatch: %+v", item.Ban) } if item.Levels.Wealth.RealLevel != 8 || item.Levels.Wealth.DisplayLevel != 14 || item.Levels.Wealth.TemporaryTargetLevel != 14 { t.Fatalf("wealth overlay mismatch: %+v", item.Levels.Wealth) } if item.Levels.Game.DisplayLevel != 6 || item.Levels.Charm.DisplayLevel != 9 { t.Fatalf("read-only levels mismatch: %+v", item.Levels) } }