package main import ( "fmt" "testing" "github.com/tinode/chat/server/store" "github.com/tinode/chat/server/store/types" ) type defaultAvatarConfigStore map[string]string func (s defaultAvatarConfigStore) Get(_ string, keys ...string) (map[string]string, error) { out := make(map[string]string, len(keys)) for _, key := range keys { out[key] = s[key] } return out, nil } func TestUserSummaryPayloadAppliesDefaultAvatarByGenderAndUserID(t *testing.T) { oldConfig := store.ThirdPartyConfig store.ThirdPartyConfig = defaultAvatarConfigStore{ imDefaultMaleAvatarURLsConfig: `["https://oss.example.com/m0.png","https://oss.example.com/m1.png","https://oss.example.com/m2.png","https://oss.example.com/m3.png","https://oss.example.com/m4.png"]`, imDefaultFemaleAvatarURLsConfig: `["https://oss.example.com/f0.png","https://oss.example.com/f1.png","https://oss.example.com/f2.png","https://oss.example.com/f3.png","https://oss.example.com/f4.png"]`, } defer func() { store.ThirdPartyConfig = oldConfig }() for i, gender := range []string{"male", "female"} { uid := types.Uid(10 + i) payload := userSummaryPayload(&types.User{ ObjHeader: types.ObjHeader{Id: uid.String()}, Public: map[string]any{"display_name": "Alice", "gender": gender}, }, "") wantPrefix := "m" if gender == "female" { wantPrefix = "f" } want := fmt.Sprintf("https://oss.example.com/%s%d.png", wantPrefix, uint64(uid)%5) if payload["avatar_file_id"] != want { t.Fatalf("gender=%s avatar=%v want %s", gender, payload["avatar_file_id"], want) } if payload["avatar_url"] != want { t.Fatalf("gender=%s avatar_url=%v want %s", gender, payload["avatar_url"], want) } } } func TestUserSummaryPayloadKeepsUploadedAvatar(t *testing.T) { oldConfig := store.ThirdPartyConfig store.ThirdPartyConfig = defaultAvatarConfigStore{ imDefaultMaleAvatarURLsConfig: `["m0","m1","m2","m3","m4"]`, } defer func() { store.ThirdPartyConfig = oldConfig }() payload := userSummaryPayload(&types.User{ ObjHeader: types.ObjHeader{Id: types.Uid(10).String()}, Public: map[string]any{"display_name": "Alice", "gender": "male", "avatar_file_id": "uploaded.png"}, }, "") if payload["avatar_file_id"] != "uploaded.png" { t.Fatalf("avatar=%v", payload["avatar_file_id"]) } if _, ok := payload["avatar_url"]; ok { t.Fatalf("non-url uploaded avatar must not be exposed as avatar_url: %#v", payload) } } func TestPublicWithDefaultUserAvatarMatchesHTTPSummary(t *testing.T) { oldConfig := store.ThirdPartyConfig store.ThirdPartyConfig = defaultAvatarConfigStore{ imDefaultMaleAvatarURLsConfig: `["https://oss.example.com/m0.png","https://oss.example.com/m1.png"]`, imDefaultFemaleAvatarURLsConfig: `["https://oss.example.com/f0.png","https://oss.example.com/f1.png"]`, } defer func() { store.ThirdPartyConfig = oldConfig }() uid := types.Uid(11) public := publicWithDefaultUserAvatar(map[string]any{"display_name": "Alice", "gender": "female"}, uid.UserId()).(map[string]any) want := "https://oss.example.com/f1.png" if public["avatar_file_id"] != want || public["avatar_url"] != want { t.Fatalf("default avatar not applied to protocol public: %#v", public) } summary := userSummaryPayload(&types.User{ ObjHeader: types.ObjHeader{Id: uid.String()}, Public: map[string]any{"display_name": "Alice", "gender": "female"}, }, "") if summary["avatar_file_id"] != public["avatar_file_id"] || summary["avatar_url"] != public["avatar_url"] { t.Fatalf("protocol public and HTTP summary diverged: public=%#v summary=%#v", public, summary) } } func TestPublicWithDefaultUserAvatarKeepsExistingAvatarURL(t *testing.T) { oldConfig := store.ThirdPartyConfig store.ThirdPartyConfig = defaultAvatarConfigStore{ imDefaultMaleAvatarURLsConfig: `["https://oss.example.com/default.png"]`, } defer func() { store.ThirdPartyConfig = oldConfig }() public := publicWithDefaultUserAvatar(types.KVMap{ "display_name": "Bob", "avatar_file_id": "file_1", "avatar_url": "https://oss.example.com/file_1.png", }, types.Uid(20).UserId()).(map[string]any) if public["avatar_file_id"] != "file_1" || public["avatar_url"] != "https://oss.example.com/file_1.png" { t.Fatalf("existing avatar should be kept: %#v", public) } }