github.com/k0marov/go-socnet@v0.0.0-20220715154813-90d07867c782/features/profiles/domain/service/service_test.go (about) 1 package service_test 2 3 import ( 4 "fmt" 5 "github.com/k0marov/go-socnet/core/general/client_errors" 6 "github.com/k0marov/go-socnet/core/general/core_err" 7 "github.com/k0marov/go-socnet/core/general/core_values" 8 "github.com/k0marov/go-socnet/core/general/core_values/ref" 9 "github.com/k0marov/go-socnet/core/general/static_store" 10 . "github.com/k0marov/go-socnet/core/helpers/test_helpers" 11 "testing" 12 13 "github.com/k0marov/go-socnet/features/profiles/domain/models" 14 15 "github.com/k0marov/go-socnet/features/profiles/domain/entities" 16 "github.com/k0marov/go-socnet/features/profiles/domain/service" 17 "github.com/k0marov/go-socnet/features/profiles/domain/values" 18 ) 19 20 func TestProfileGetter(t *testing.T) { 21 target := RandomString() 22 caller := RandomString() 23 profile := RandomProfile() 24 contextedProfile := RandomContextedProfile() 25 getProfile := func(id core_values.UserId) (entities.Profile, error) { 26 if id == target { 27 return profile, nil 28 } 29 panic("called with unexpected arguments") 30 } 31 t.Run("error case - store returns NotFoundErr", func(t *testing.T) { 32 getProfile := func(core_values.UserId) (entities.Profile, error) { 33 return entities.Profile{}, core_err.ErrNotFound 34 } 35 sut := service.NewProfileGetter(getProfile, nil) 36 _, err := sut(target, caller) 37 AssertError(t, err, client_errors.NotFound) 38 }) 39 t.Run("error case - store returns some other error", func(t *testing.T) { 40 getProfile := func(core_values.UserId) (entities.Profile, error) { 41 return entities.Profile{}, RandomError() 42 } 43 sut := service.NewProfileGetter(getProfile, nil) 44 _, err := sut(target, caller) 45 AssertSomeError(t, err) 46 }) 47 addContext := func(prof entities.Profile, callerId core_values.UserId) (entities.ContextedProfile, error) { 48 if prof == profile && callerId == caller { 49 return contextedProfile, nil 50 } 51 panic("unexpected args") 52 } 53 t.Run("error case - adding context returns some error", func(t *testing.T) { 54 addContext := func(profile2 entities.Profile, id core_values.UserId) (entities.ContextedProfile, error) { 55 return entities.ContextedProfile{}, RandomError() 56 } 57 _, err := service.NewProfileGetter(getProfile, addContext)(target, caller) 58 AssertSomeError(t, err) 59 }) 60 t.Run("happy case", func(t *testing.T) { 61 gotProfile, err := service.NewProfileGetter(getProfile, addContext)(target, caller) 62 AssertNoError(t, err) 63 Assert(t, gotProfile, contextedProfile, "returned profile") 64 }) 65 } 66 67 func TestFollowsGetter(t *testing.T) { 68 target := RandomId() 69 caller := RandomId() 70 follows := []core_values.UserId{RandomId()} 71 wantFollows := []entities.ContextedProfile{RandomContextedProfile()} 72 73 getFollows := func(id core_values.UserId) ([]core_values.UserId, error) { 74 if id == target { 75 return follows, nil 76 } 77 panic("unexpected args") 78 } 79 t.Run("error case - getting follows throws", func(t *testing.T) { 80 getFollows := func(core_values.UserId) ([]core_values.UserId, error) { 81 return nil, RandomError() 82 } 83 _, err := service.NewFollowsGetter(getFollows, nil)(target, caller) 84 AssertSomeError(t, err) 85 86 }) 87 getProfile := func(targetId, callerId core_values.UserId) (entities.ContextedProfile, error) { 88 if targetId == follows[0] && callerId == caller { 89 return wantFollows[0], nil 90 } 91 panic("unexpected args") 92 } 93 t.Run("error case - getting profile throws", func(t *testing.T) { 94 getProfile := func(target, caller core_values.UserId) (entities.ContextedProfile, error) { 95 return entities.ContextedProfile{}, RandomError() 96 } 97 _, err := service.NewFollowsGetter(getFollows, getProfile)(target, caller) 98 AssertSomeError(t, err) 99 }) 100 101 t.Run("happy case", func(t *testing.T) { 102 sut := service.NewFollowsGetter(getFollows, getProfile) 103 gotFollows, err := sut(target, caller) 104 AssertNoError(t, err) 105 Assert(t, gotFollows, wantFollows, "returned follows") 106 }) 107 } 108 109 func TestProfileCreator(t *testing.T) { 110 user := RandomUser() 111 t.Run("happy case", func(t *testing.T) { 112 testNewProfile := models.ProfileModel{ 113 Id: user.Id, 114 Username: user.Username, 115 About: service.DefaultAbout, 116 AvatarPath: service.DefaultAvatarPath, 117 } 118 wantCreatedProfile := entities.Profile{ 119 ProfileModel: testNewProfile, 120 Follows: 0, 121 Followers: 0, 122 } 123 storeNew := func(profile models.ProfileModel) error { 124 if profile == testNewProfile { 125 return nil 126 } 127 panic(fmt.Sprintf("StoreNew called with unexpected profile: %v", profile)) 128 } 129 sut := service.NewProfileCreator(storeNew) 130 131 gotProfile, err := sut(user) 132 AssertNoError(t, err) 133 Assert(t, gotProfile, wantCreatedProfile, "created profile") 134 }) 135 t.Run("error case - store throws, it is NOT a client error", func(t *testing.T) { 136 storeNew := func(model models.ProfileModel) error { 137 return RandomError() 138 } 139 sut := service.NewProfileCreator(storeNew) 140 141 _, err := sut(user) 142 143 AssertSomeError(t, err) 144 }) 145 } 146 147 func TestProfileUpdater(t *testing.T) { 148 user := RandomUser() 149 testUpdateData := values.ProfileUpdateData{ 150 About: RandomString(), 151 } 152 validator := func(values.ProfileUpdateData) (client_errors.ClientError, bool) { 153 return client_errors.ClientError{}, true 154 } 155 t.Run("error case - validator throws", func(t *testing.T) { 156 clientError := RandomClientError() 157 validator := func(updData values.ProfileUpdateData) (client_errors.ClientError, bool) { 158 if updData == testUpdateData { 159 return clientError, false 160 } 161 panic(fmt.Sprintf("validator called with unexpected args, updData=%v", updData)) 162 } 163 sut := service.NewProfileUpdater(validator, nil, nil) // store is nil, since it shouldn't be accessed 164 _, gotErr := sut(user, testUpdateData) 165 AssertError(t, gotErr, clientError) 166 }) 167 storeUpdater := func(id string, updData values.ProfileUpdateData) error { 168 if id == user.Id && updData == testUpdateData { 169 return nil 170 } 171 panic(fmt.Sprintf("update called with unexpected arguments: id: %v and updateData: %v", id, updData)) 172 } 173 t.Run("error case - store throws an error", func(t *testing.T) { 174 storeUpdater := func(string, values.ProfileUpdateData) error { 175 return RandomError() 176 } 177 sut := service.NewProfileUpdater(validator, storeUpdater, nil) 178 _, err := sut(user, testUpdateData) 179 AssertSomeError(t, err) 180 }) 181 wantUpdatedProfile := RandomContextedProfile() 182 profileGetter := func(target, caller core_values.UserId) (entities.ContextedProfile, error) { 183 if target == user.Id && caller == user.Id { 184 return wantUpdatedProfile, nil 185 } 186 panic("unexpected args") 187 } 188 t.Run("error case - getting updated profile throws", func(t *testing.T) { 189 tErr := RandomError() 190 profileGetter := func(target, caller core_values.UserId) (entities.ContextedProfile, error) { 191 return entities.ContextedProfile{}, tErr 192 } 193 _, err := service.NewProfileUpdater(validator, storeUpdater, profileGetter)(user, testUpdateData) 194 AssertError(t, err, tErr) 195 }) 196 t.Run("happy case", func(t *testing.T) { 197 sut := service.NewProfileUpdater(validator, storeUpdater, profileGetter) 198 199 gotUpdatedProfile, err := sut(user, testUpdateData) 200 AssertNoError(t, err) 201 Assert(t, gotUpdatedProfile, wantUpdatedProfile, "the returned profile") 202 }) 203 } 204 205 func TestAvatarUpdater(t *testing.T) { 206 user := RandomUser() 207 data := []byte(RandomString()) 208 dataRef, _ := ref.NewRef(&data) 209 testAvatarData := values.AvatarData{ 210 Data: dataRef, 211 } 212 213 silentValidator := func(values.AvatarData) (client_errors.ClientError, bool) { 214 return client_errors.ClientError{}, true 215 } 216 217 t.Run("happy case", func(t *testing.T) { 218 path := RandomString() 219 wantURL := static_store.PathToURL(path) 220 storeAvatar := func(userId string, avatarData values.AvatarData) (core_values.FileURL, error) { 221 if userId == user.Id && avatarData == testAvatarData { 222 return path, nil 223 } 224 panic(fmt.Sprintf("StoreAvatar called with unexpected arguments: userId=%v and avatarData=%v", userId, avatarData)) 225 } 226 sut := service.NewAvatarUpdater(silentValidator, storeAvatar) 227 228 gotURL, err := sut(user, testAvatarData) 229 AssertNoError(t, err) 230 Assert(t, gotURL, wantURL, "returned profile") 231 }) 232 t.Run("validator throws", func(t *testing.T) { 233 clientError := RandomClientError() 234 validator := func(avatar values.AvatarData) (client_errors.ClientError, bool) { 235 if avatar == testAvatarData { 236 return clientError, false 237 } 238 panic(fmt.Sprintf("validator called with unexpected args, avatar=%v", avatar)) 239 } 240 sut := service.NewAvatarUpdater(validator, nil) // storeAvatar is nil, since it shouldn't be called 241 242 _, err := sut(user, testAvatarData) 243 AssertError(t, err, clientError) 244 }) 245 t.Run("store throws an error", func(t *testing.T) { 246 storeAvatar := func(string, values.AvatarData) (core_values.FileURL, error) { 247 return "", RandomError() 248 } 249 sut := service.NewAvatarUpdater(silentValidator, storeAvatar) 250 251 _, err := sut(user, testAvatarData) 252 AssertSomeError(t, err) 253 }) 254 }