package prettyid import ( "context" "errors" "reflect" "strconv" "testing" "hyapp-admin-server/internal/integration/userclient" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type fakeGrantTargetResolver struct { users map[int64]*userclient.User displays map[string]*userclient.UserIdentity calls []string } type fakeAssignedUserBatchGetter struct { calls [][]int64 err error users map[int64]*userclient.User } func (f *fakeAssignedUserBatchGetter) BatchGetUsers(_ context.Context, req userclient.BatchGetUsersRequest) (map[int64]*userclient.User, error) { f.calls = append(f.calls, append([]int64(nil), req.UserIDs...)) if f.err != nil { return nil, f.err } return f.users, nil } func (f *fakeGrantTargetResolver) GetUser(_ context.Context, req userclient.GetUserRequest) (*userclient.User, error) { f.calls = append(f.calls, "get:"+strconv.FormatInt(req.UserID, 10)) if user := f.users[req.UserID]; user != nil { return user, nil } return nil, status.Error(codes.NotFound, "user not found") } func (f *fakeGrantTargetResolver) ResolveDisplayUserID(_ context.Context, req userclient.ResolveDisplayUserIDRequest) (*userclient.UserIdentity, error) { f.calls = append(f.calls, "resolve:"+req.DisplayUserID) if identity := f.displays[req.DisplayUserID]; identity != nil { return identity, nil } return nil, status.Error(codes.NotFound, "display_user_id not found") } func TestAttachAssignedUsersAddsSnapshotsAndSkipsZero(t *testing.T) { getter := &fakeAssignedUserBatchGetter{ users: map[int64]*userclient.User{ 42: { Avatar: "https://cdn.example/u42.png", DefaultDisplayUserID: "100042", DisplayUserID: "VIP42", PrettyDisplayUserID: "VIP42", UserID: 42, Username: "owner42", }, }, } items := []*userclient.PrettyDisplayID{ {PrettyID: "available", AssignedUserID: 0}, {PrettyID: "assigned-42", AssignedUserID: 42}, {PrettyID: "assigned-42-dup", AssignedUserID: 42}, {PrettyID: "stale-77", AssignedUserID: 77}, } if err := attachAssignedUsers(context.Background(), getter, "req", items); err != nil { t.Fatalf("attachAssignedUsers returned error: %v", err) } if want := [][]int64{{42, 77}}; !reflect.DeepEqual(getter.calls, want) { t.Fatalf("calls mismatch: got %v want %v", getter.calls, want) } if items[0].AssignedUser != nil { t.Fatalf("zero assigned user should stay empty: %+v", items[0].AssignedUser) } if items[1].AssignedUser == nil || items[1].AssignedUser.Username != "owner42" || items[1].AssignedUser.DefaultDisplayUserID != "100042" { t.Fatalf("assigned snapshot mismatch: %+v", items[1].AssignedUser) } if items[2].AssignedUser == nil || items[2].AssignedUser.UserID != 42 { t.Fatalf("duplicate assigned id should reuse snapshot: %+v", items[2].AssignedUser) } if items[3].AssignedUser != nil { t.Fatalf("missing batch user should stay empty: %+v", items[3].AssignedUser) } } func TestAttachAssignedUsersReturnsBatchError(t *testing.T) { wantErr := errors.New("batch failed") err := attachAssignedUsers(context.Background(), &fakeAssignedUserBatchGetter{err: wantErr}, "req", []*userclient.PrettyDisplayID{ {PrettyID: "assigned", AssignedUserID: 42}, }) if !errors.Is(err, wantErr) { t.Fatalf("error mismatch: got %v want %v", err, wantErr) } } func TestResolveGrantTargetUserIDUsesShortDisplayID(t *testing.T) { resolver := &fakeGrantTargetResolver{ users: map[int64]*userclient.User{}, displays: map[string]*userclient.UserIdentity{ "163001": {UserID: 312899006709637120, DisplayUserID: "163001"}, }, } userID, kind, err := resolveGrantTargetUserID(context.Background(), resolver, "req", "163001") if err != nil { t.Fatalf("resolveGrantTargetUserID returned error: %v", err) } if userID != 312899006709637120 || kind != "display_user_id" { t.Fatalf("target mismatch: userID=%d kind=%s", userID, kind) } if want := []string{"resolve:163001"}; !reflect.DeepEqual(resolver.calls, want) { t.Fatalf("calls mismatch: got %v want %v", resolver.calls, want) } } func TestResolveGrantTargetUserIDKeepsLongInternalID(t *testing.T) { resolver := &fakeGrantTargetResolver{ users: map[int64]*userclient.User{ 312899006709637120: {UserID: 312899006709637120, DisplayUserID: "163001"}, }, displays: map[string]*userclient.UserIdentity{}, } userID, kind, err := resolveGrantTargetUserID(context.Background(), resolver, "req", "312899006709637120") if err != nil { t.Fatalf("resolveGrantTargetUserID returned error: %v", err) } if userID != 312899006709637120 || kind != "user_id" { t.Fatalf("target mismatch: userID=%d kind=%s", userID, kind) } if want := []string{"get:312899006709637120"}; !reflect.DeepEqual(resolver.calls, want) { t.Fatalf("calls mismatch: got %v want %v", resolver.calls, want) } } func TestResolveGrantTargetUserIDFallsBackForLongDisplayID(t *testing.T) { resolver := &fakeGrantTargetResolver{ users: map[int64]*userclient.User{}, displays: map[string]*userclient.UserIdentity{ "312899006709637120": {UserID: 411, DisplayUserID: "312899006709637120"}, }, } userID, kind, err := resolveGrantTargetUserID(context.Background(), resolver, "req", "312899006709637120") if err != nil { t.Fatalf("resolveGrantTargetUserID returned error: %v", err) } if userID != 411 || kind != "display_user_id" { t.Fatalf("target mismatch: userID=%d kind=%s", userID, kind) } if want := []string{"get:312899006709637120", "resolve:312899006709637120"}; !reflect.DeepEqual(resolver.calls, want) { t.Fatalf("calls mismatch: got %v want %v", resolver.calls, want) } } func TestResolveGrantTargetUserIDAcceptsPrettyDisplayID(t *testing.T) { resolver := &fakeGrantTargetResolver{ users: map[int64]*userclient.User{}, displays: map[string]*userclient.UserIdentity{ "VIP2026": {UserID: 88, DisplayUserID: "VIP2026"}, }, } userID, kind, err := resolveGrantTargetUserID(context.Background(), resolver, "req", "VIP2026") if err != nil { t.Fatalf("resolveGrantTargetUserID returned error: %v", err) } if userID != 88 || kind != "display_user_id" { t.Fatalf("target mismatch: userID=%d kind=%s", userID, kind) } if want := []string{"resolve:VIP2026"}; !reflect.DeepEqual(resolver.calls, want) { t.Fatalf("calls mismatch: got %v want %v", resolver.calls, want) } } func TestResolveGrantTargetUserIDReportsMissingTarget(t *testing.T) { resolver := &fakeGrantTargetResolver{ users: map[int64]*userclient.User{}, displays: map[string]*userclient.UserIdentity{}, } _, _, err := resolveGrantTargetUserID(context.Background(), resolver, "req", "163001") if err != errGrantTargetNotFound { t.Fatalf("error mismatch: got %v want %v", err, errGrantTargetNotFound) } }