github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/reaction_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package api4 5 6 import ( 7 "strings" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 "github.com/masterhung0112/hk_server/v5/model" 14 ) 15 16 func TestSaveReaction(t *testing.T) { 17 th := Setup(t).InitBasic() 18 defer th.TearDown() 19 Client := th.Client 20 userId := th.BasicUser.Id 21 postId := th.BasicPost.Id 22 23 // Check the appropriate permissions are enforced. 24 defaultRolePermissions := th.SaveDefaultRolePermissions() 25 defer func() { 26 th.RestoreDefaultRolePermissions(defaultRolePermissions) 27 }() 28 29 reaction := &model.Reaction{ 30 UserId: userId, 31 PostId: postId, 32 EmojiName: "smile", 33 } 34 35 t.Run("successful-reaction", func(t *testing.T) { 36 rr, resp := Client.SaveReaction(reaction) 37 CheckNoError(t, resp) 38 require.Equal(t, reaction.UserId, rr.UserId, "UserId did not match") 39 require.Equal(t, reaction.PostId, rr.PostId, "PostId did not match") 40 require.Equal(t, reaction.EmojiName, rr.EmojiName, "EmojiName did not match") 41 require.NotEqual(t, 0, rr.CreateAt, "CreateAt should exist") 42 43 reactions, err := th.App.GetReactionsForPost(postId) 44 require.Nil(t, err) 45 require.Equal(t, 1, len(reactions), "didn't save reaction correctly") 46 }) 47 48 t.Run("duplicated-reaction", func(t *testing.T) { 49 _, resp := Client.SaveReaction(reaction) 50 CheckNoError(t, resp) 51 reactions, err := th.App.GetReactionsForPost(postId) 52 require.Nil(t, err) 53 require.Equal(t, 1, len(reactions), "should have not save duplicated reaction") 54 }) 55 56 t.Run("save-second-reaction", func(t *testing.T) { 57 reaction.EmojiName = "sad" 58 59 rr, resp := Client.SaveReaction(reaction) 60 CheckNoError(t, resp) 61 require.Equal(t, rr.EmojiName, reaction.EmojiName, "EmojiName did not match") 62 63 reactions, err := th.App.GetReactionsForPost(postId) 64 require.Nil(t, err, "error saving multiple reactions") 65 require.Equal(t, len(reactions), 2, "should have save multiple reactions") 66 }) 67 68 t.Run("saving-special-case", func(t *testing.T) { 69 reaction.EmojiName = "+1" 70 71 rr, resp := Client.SaveReaction(reaction) 72 CheckNoError(t, resp) 73 require.Equal(t, reaction.EmojiName, rr.EmojiName, "EmojiName did not match") 74 75 reactions, err := th.App.GetReactionsForPost(postId) 76 require.Nil(t, err) 77 require.Equal(t, 3, len(reactions), "should have save multiple reactions") 78 }) 79 80 t.Run("react-to-not-existing-post-id", func(t *testing.T) { 81 reaction.PostId = GenerateTestId() 82 83 _, resp := Client.SaveReaction(reaction) 84 CheckForbiddenStatus(t, resp) 85 }) 86 87 t.Run("react-to-not-valid-post-id", func(t *testing.T) { 88 reaction.PostId = "junk" 89 90 _, resp := Client.SaveReaction(reaction) 91 CheckBadRequestStatus(t, resp) 92 }) 93 94 t.Run("react-as-not-existing-user-id", func(t *testing.T) { 95 reaction.PostId = postId 96 reaction.UserId = GenerateTestId() 97 98 _, resp := Client.SaveReaction(reaction) 99 CheckForbiddenStatus(t, resp) 100 }) 101 102 t.Run("react-as-not-valid-user-id", func(t *testing.T) { 103 reaction.UserId = "junk" 104 105 _, resp := Client.SaveReaction(reaction) 106 CheckBadRequestStatus(t, resp) 107 }) 108 109 t.Run("react-as-empty-emoji-name", func(t *testing.T) { 110 reaction.UserId = userId 111 reaction.EmojiName = "" 112 113 _, resp := Client.SaveReaction(reaction) 114 CheckBadRequestStatus(t, resp) 115 }) 116 117 t.Run("react-as-not-valid-emoji-name", func(t *testing.T) { 118 reaction.EmojiName = strings.Repeat("a", 65) 119 120 _, resp := Client.SaveReaction(reaction) 121 CheckBadRequestStatus(t, resp) 122 }) 123 124 t.Run("react-as-other-user", func(t *testing.T) { 125 reaction.EmojiName = "smile" 126 otherUser := th.CreateUser() 127 Client.Logout() 128 Client.Login(otherUser.Email, otherUser.Password) 129 130 _, resp := Client.SaveReaction(reaction) 131 CheckForbiddenStatus(t, resp) 132 }) 133 134 t.Run("react-being-not-logged-in", func(t *testing.T) { 135 Client.Logout() 136 _, resp := Client.SaveReaction(reaction) 137 CheckUnauthorizedStatus(t, resp) 138 }) 139 140 t.Run("react-as-other-user-being-system-admin", func(t *testing.T) { 141 _, resp := th.SystemAdminClient.SaveReaction(reaction) 142 CheckForbiddenStatus(t, resp) 143 }) 144 145 t.Run("unable-to-create-reaction-without-permissions", func(t *testing.T) { 146 th.LoginBasic() 147 148 th.RemovePermissionFromRole(model.PERMISSION_ADD_REACTION.Id, model.CHANNEL_USER_ROLE_ID) 149 _, resp := Client.SaveReaction(reaction) 150 CheckForbiddenStatus(t, resp) 151 152 reactions, err := th.App.GetReactionsForPost(postId) 153 require.Nil(t, err) 154 require.Equal(t, 3, len(reactions), "should have not created a reactions") 155 th.AddPermissionToRole(model.PERMISSION_ADD_REACTION.Id, model.CHANNEL_USER_ROLE_ID) 156 }) 157 158 t.Run("unable-to-react-in-read-only-town-square", func(t *testing.T) { 159 th.LoginBasic() 160 161 channel, err := th.App.GetChannelByName("town-square", th.BasicTeam.Id, true) 162 assert.Nil(t, err) 163 post := th.CreatePostWithClient(th.Client, channel) 164 165 th.App.Srv().SetLicense(model.NewTestLicense()) 166 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true }) 167 168 reaction := &model.Reaction{ 169 UserId: userId, 170 PostId: post.Id, 171 EmojiName: "smile", 172 } 173 174 _, resp := Client.SaveReaction(reaction) 175 CheckForbiddenStatus(t, resp) 176 177 reactions, err := th.App.GetReactionsForPost(post.Id) 178 require.Nil(t, err) 179 require.Equal(t, 0, len(reactions), "should have not created a reaction") 180 181 th.App.Srv().RemoveLicense() 182 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false }) 183 }) 184 185 t.Run("unable-to-react-in-an-archived-channel", func(t *testing.T) { 186 th.LoginBasic() 187 188 channel := th.CreatePublicChannel() 189 post := th.CreatePostWithClient(th.Client, channel) 190 191 reaction := &model.Reaction{ 192 UserId: userId, 193 PostId: post.Id, 194 EmojiName: "smile", 195 } 196 197 err := th.App.DeleteChannel(th.Context, channel, userId) 198 assert.Nil(t, err) 199 200 _, resp := Client.SaveReaction(reaction) 201 CheckForbiddenStatus(t, resp) 202 203 reactions, err := th.App.GetReactionsForPost(post.Id) 204 require.Nil(t, err) 205 require.Equal(t, 0, len(reactions), "should have not created a reaction") 206 }) 207 } 208 209 func TestGetReactions(t *testing.T) { 210 th := Setup(t).InitBasic() 211 defer th.TearDown() 212 Client := th.Client 213 userId := th.BasicUser.Id 214 user2Id := th.BasicUser2.Id 215 postId := th.BasicPost.Id 216 217 userReactions := []*model.Reaction{ 218 { 219 UserId: userId, 220 PostId: postId, 221 EmojiName: "smile", 222 }, 223 { 224 UserId: userId, 225 PostId: postId, 226 EmojiName: "happy", 227 }, 228 { 229 UserId: userId, 230 PostId: postId, 231 EmojiName: "sad", 232 }, 233 { 234 UserId: user2Id, 235 PostId: postId, 236 EmojiName: "smile", 237 }, 238 { 239 UserId: user2Id, 240 PostId: postId, 241 EmojiName: "sad", 242 }, 243 } 244 245 var reactions []*model.Reaction 246 247 for _, userReaction := range userReactions { 248 reaction, err := th.App.Srv().Store.Reaction().Save(userReaction) 249 require.NoError(t, err) 250 reactions = append(reactions, reaction) 251 } 252 253 t.Run("get-reactions", func(t *testing.T) { 254 rr, resp := Client.GetReactions(postId) 255 CheckNoError(t, resp) 256 257 assert.Len(t, rr, 5) 258 for _, r := range reactions { 259 assert.Contains(t, reactions, r) 260 } 261 }) 262 263 t.Run("get-reactions-of-invalid-post-id", func(t *testing.T) { 264 rr, resp := Client.GetReactions("junk") 265 CheckBadRequestStatus(t, resp) 266 267 assert.Empty(t, rr) 268 }) 269 270 t.Run("get-reactions-of-not-existing-post-id", func(t *testing.T) { 271 _, resp := Client.GetReactions(GenerateTestId()) 272 CheckForbiddenStatus(t, resp) 273 }) 274 275 t.Run("get-reactions-as-anonymous-user", func(t *testing.T) { 276 Client.Logout() 277 278 _, resp := Client.GetReactions(postId) 279 CheckUnauthorizedStatus(t, resp) 280 }) 281 282 t.Run("get-reactions-as-system-admin", func(t *testing.T) { 283 _, resp := th.SystemAdminClient.GetReactions(postId) 284 CheckNoError(t, resp) 285 }) 286 } 287 288 func TestDeleteReaction(t *testing.T) { 289 th := Setup(t).InitBasic() 290 defer th.TearDown() 291 Client := th.Client 292 userId := th.BasicUser.Id 293 user2Id := th.BasicUser2.Id 294 postId := th.BasicPost.Id 295 296 r1 := &model.Reaction{ 297 UserId: userId, 298 PostId: postId, 299 EmojiName: "smile", 300 } 301 302 r2 := &model.Reaction{ 303 UserId: userId, 304 PostId: postId, 305 EmojiName: "smile-", 306 } 307 308 r3 := &model.Reaction{ 309 UserId: userId, 310 PostId: postId, 311 EmojiName: "+1", 312 } 313 314 r4 := &model.Reaction{ 315 UserId: user2Id, 316 PostId: postId, 317 EmojiName: "smile_", 318 } 319 320 // Check the appropriate permissions are enforced. 321 defaultRolePermissions := th.SaveDefaultRolePermissions() 322 defer func() { 323 th.RestoreDefaultRolePermissions(defaultRolePermissions) 324 }() 325 326 t.Run("delete-reaction", func(t *testing.T) { 327 th.App.SaveReactionForPost(th.Context, r1) 328 reactions, err := th.App.GetReactionsForPost(postId) 329 require.Nil(t, err) 330 require.Equal(t, 1, len(reactions), "didn't save reaction correctly") 331 332 ok, resp := Client.DeleteReaction(r1) 333 CheckNoError(t, resp) 334 335 require.True(t, ok, "should have returned true") 336 337 reactions, err = th.App.GetReactionsForPost(postId) 338 require.Nil(t, err) 339 require.Equal(t, 0, len(reactions), "should have deleted reaction") 340 }) 341 342 t.Run("delete-reaction-when-post-has-multiple-reactions", func(t *testing.T) { 343 th.App.SaveReactionForPost(th.Context, r1) 344 th.App.SaveReactionForPost(th.Context, r2) 345 reactions, err := th.App.GetReactionsForPost(postId) 346 require.Nil(t, err) 347 require.Equal(t, len(reactions), 2, "didn't save reactions correctly") 348 349 _, resp := Client.DeleteReaction(r2) 350 CheckNoError(t, resp) 351 352 reactions, err = th.App.GetReactionsForPost(postId) 353 require.Nil(t, err) 354 require.Equal(t, 1, len(reactions), "should have deleted only 1 reaction") 355 require.Equal(t, *r1, *reactions[0], "should have deleted 1 reaction only") 356 }) 357 358 t.Run("delete-reaction-when-plus-one-reaction-name", func(t *testing.T) { 359 th.App.SaveReactionForPost(th.Context, r3) 360 reactions, err := th.App.GetReactionsForPost(postId) 361 require.Nil(t, err) 362 require.Equal(t, 2, len(reactions), "didn't save reactions correctly") 363 364 _, resp := Client.DeleteReaction(r3) 365 CheckNoError(t, resp) 366 367 reactions, err = th.App.GetReactionsForPost(postId) 368 require.Nil(t, err) 369 require.Equal(t, 1, len(reactions), "should have deleted 1 reaction only") 370 require.Equal(t, *r1, *reactions[0], "should have deleted 1 reaction only") 371 }) 372 373 t.Run("delete-reaction-made-by-another-user", func(t *testing.T) { 374 th.LoginBasic2() 375 th.App.SaveReactionForPost(th.Context, r4) 376 reactions, err := th.App.GetReactionsForPost(postId) 377 require.Nil(t, err) 378 require.Equal(t, 2, len(reactions), "didn't save reaction correctly") 379 380 th.LoginBasic() 381 382 ok, resp := Client.DeleteReaction(r4) 383 CheckForbiddenStatus(t, resp) 384 385 require.False(t, ok, "should have returned false") 386 387 reactions, err = th.App.GetReactionsForPost(postId) 388 require.Nil(t, err) 389 require.Equal(t, 2, len(reactions), "should have not deleted a reaction") 390 }) 391 392 t.Run("delete-reaction-from-not-existing-post-id", func(t *testing.T) { 393 r1.PostId = GenerateTestId() 394 _, resp := Client.DeleteReaction(r1) 395 CheckForbiddenStatus(t, resp) 396 }) 397 398 t.Run("delete-reaction-from-not-valid-post-id", func(t *testing.T) { 399 r1.PostId = "junk" 400 401 _, resp := Client.DeleteReaction(r1) 402 CheckBadRequestStatus(t, resp) 403 }) 404 405 t.Run("delete-reaction-from-not-existing-user-id", func(t *testing.T) { 406 r1.PostId = postId 407 r1.UserId = GenerateTestId() 408 409 _, resp := Client.DeleteReaction(r1) 410 CheckForbiddenStatus(t, resp) 411 }) 412 413 t.Run("delete-reaction-from-not-valid-user-id", func(t *testing.T) { 414 r1.UserId = "junk" 415 416 _, resp := Client.DeleteReaction(r1) 417 CheckBadRequestStatus(t, resp) 418 }) 419 420 t.Run("delete-reaction-with-empty-name", func(t *testing.T) { 421 r1.UserId = userId 422 r1.EmojiName = "" 423 424 _, resp := Client.DeleteReaction(r1) 425 CheckNotFoundStatus(t, resp) 426 }) 427 428 t.Run("delete-reaction-with-not-existing-name", func(t *testing.T) { 429 r1.EmojiName = strings.Repeat("a", 65) 430 431 _, resp := Client.DeleteReaction(r1) 432 CheckBadRequestStatus(t, resp) 433 }) 434 435 t.Run("delete-reaction-as-anonymous-user", func(t *testing.T) { 436 Client.Logout() 437 r1.EmojiName = "smile" 438 439 _, resp := Client.DeleteReaction(r1) 440 CheckUnauthorizedStatus(t, resp) 441 }) 442 443 t.Run("delete-reaction-as-system-admin", func(t *testing.T) { 444 _, resp := th.SystemAdminClient.DeleteReaction(r1) 445 CheckNoError(t, resp) 446 447 _, resp = th.SystemAdminClient.DeleteReaction(r4) 448 CheckNoError(t, resp) 449 450 reactions, err := th.App.GetReactionsForPost(postId) 451 require.Nil(t, err) 452 require.Equal(t, 0, len(reactions), "should have deleted both reactions") 453 }) 454 455 t.Run("unable-to-delete-reaction-without-permissions", func(t *testing.T) { 456 th.LoginBasic() 457 458 th.RemovePermissionFromRole(model.PERMISSION_REMOVE_REACTION.Id, model.CHANNEL_USER_ROLE_ID) 459 th.App.SaveReactionForPost(th.Context, r1) 460 461 _, resp := Client.DeleteReaction(r1) 462 CheckForbiddenStatus(t, resp) 463 464 reactions, err := th.App.GetReactionsForPost(postId) 465 require.Nil(t, err) 466 require.Equal(t, 1, len(reactions), "should have not deleted a reactions") 467 th.AddPermissionToRole(model.PERMISSION_REMOVE_REACTION.Id, model.CHANNEL_USER_ROLE_ID) 468 }) 469 470 t.Run("unable-to-delete-others-reactions-without-permissions", func(t *testing.T) { 471 th.RemovePermissionFromRole(model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id, model.SYSTEM_ADMIN_ROLE_ID) 472 th.App.SaveReactionForPost(th.Context, r1) 473 474 _, resp := th.SystemAdminClient.DeleteReaction(r1) 475 CheckForbiddenStatus(t, resp) 476 477 reactions, err := th.App.GetReactionsForPost(postId) 478 require.Nil(t, err) 479 require.Equal(t, 1, len(reactions), "should have not deleted a reactions") 480 th.AddPermissionToRole(model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id, model.SYSTEM_ADMIN_ROLE_ID) 481 }) 482 483 t.Run("unable-to-delete-reactions-in-read-only-town-square", func(t *testing.T) { 484 th.LoginBasic() 485 486 channel, err := th.App.GetChannelByName("town-square", th.BasicTeam.Id, true) 487 assert.Nil(t, err) 488 post := th.CreatePostWithClient(th.Client, channel) 489 490 th.App.Srv().SetLicense(model.NewTestLicense()) 491 492 reaction := &model.Reaction{ 493 UserId: userId, 494 PostId: post.Id, 495 EmojiName: "smile", 496 } 497 498 r1, resp := Client.SaveReaction(reaction) 499 CheckNoError(t, resp) 500 501 reactions, err := th.App.GetReactionsForPost(postId) 502 require.Nil(t, err) 503 require.Equal(t, 1, len(reactions), "should have created a reaction") 504 505 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true }) 506 507 _, resp = th.SystemAdminClient.DeleteReaction(r1) 508 CheckForbiddenStatus(t, resp) 509 510 reactions, err = th.App.GetReactionsForPost(postId) 511 require.Nil(t, err) 512 require.Equal(t, 1, len(reactions), "should have not deleted a reaction") 513 514 th.App.Srv().RemoveLicense() 515 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false }) 516 }) 517 518 t.Run("unable-to-delete-reactions-in-an-archived-channel", func(t *testing.T) { 519 th.LoginBasic() 520 521 channel := th.CreatePublicChannel() 522 post := th.CreatePostWithClient(th.Client, channel) 523 524 reaction := &model.Reaction{ 525 UserId: userId, 526 PostId: post.Id, 527 EmojiName: "smile", 528 } 529 530 r1, resp := Client.SaveReaction(reaction) 531 CheckNoError(t, resp) 532 533 reactions, err := th.App.GetReactionsForPost(postId) 534 require.Nil(t, err) 535 require.Equal(t, 1, len(reactions), "should have created a reaction") 536 537 err = th.App.DeleteChannel(th.Context, channel, userId) 538 assert.Nil(t, err) 539 540 _, resp = Client.SaveReaction(r1) 541 CheckForbiddenStatus(t, resp) 542 543 reactions, err = th.App.GetReactionsForPost(post.Id) 544 require.Nil(t, err) 545 require.Equal(t, 1, len(reactions), "should have not deleted a reaction") 546 }) 547 } 548 549 func TestGetBulkReactions(t *testing.T) { 550 th := Setup(t).InitBasic() 551 defer th.TearDown() 552 Client := th.Client 553 userId := th.BasicUser.Id 554 user2Id := th.BasicUser2.Id 555 post1 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"} 556 post2 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"} 557 post3 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"} 558 559 post4 := &model.Post{UserId: user2Id, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"} 560 post5 := &model.Post{UserId: user2Id, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"} 561 562 post1, _ = Client.CreatePost(post1) 563 post2, _ = Client.CreatePost(post2) 564 post3, _ = Client.CreatePost(post3) 565 post4, _ = Client.CreatePost(post4) 566 post5, _ = Client.CreatePost(post5) 567 568 expectedPostIdsReactionsMap := make(map[string][]*model.Reaction) 569 expectedPostIdsReactionsMap[post1.Id] = []*model.Reaction{} 570 expectedPostIdsReactionsMap[post2.Id] = []*model.Reaction{} 571 expectedPostIdsReactionsMap[post3.Id] = []*model.Reaction{} 572 expectedPostIdsReactionsMap[post5.Id] = []*model.Reaction{} 573 574 userReactions := []*model.Reaction{ 575 { 576 UserId: userId, 577 PostId: post1.Id, 578 EmojiName: "happy", 579 }, 580 { 581 UserId: userId, 582 PostId: post1.Id, 583 EmojiName: "sad", 584 }, 585 { 586 UserId: userId, 587 PostId: post2.Id, 588 EmojiName: "smile", 589 }, 590 { 591 UserId: user2Id, 592 PostId: post4.Id, 593 EmojiName: "smile", 594 }, 595 } 596 597 for _, userReaction := range userReactions { 598 reactions := expectedPostIdsReactionsMap[userReaction.PostId] 599 reaction, err := th.App.Srv().Store.Reaction().Save(userReaction) 600 require.NoError(t, err) 601 reactions = append(reactions, reaction) 602 expectedPostIdsReactionsMap[userReaction.PostId] = reactions 603 } 604 605 postIds := []string{post1.Id, post2.Id, post3.Id, post4.Id, post5.Id} 606 607 t.Run("get-reactions", func(t *testing.T) { 608 postIdsReactionsMap, resp := Client.GetBulkReactions(postIds) 609 CheckNoError(t, resp) 610 611 assert.ElementsMatch(t, expectedPostIdsReactionsMap[post1.Id], postIdsReactionsMap[post1.Id]) 612 assert.ElementsMatch(t, expectedPostIdsReactionsMap[post2.Id], postIdsReactionsMap[post2.Id]) 613 assert.ElementsMatch(t, expectedPostIdsReactionsMap[post3.Id], postIdsReactionsMap[post3.Id]) 614 assert.ElementsMatch(t, expectedPostIdsReactionsMap[post4.Id], postIdsReactionsMap[post4.Id]) 615 assert.ElementsMatch(t, expectedPostIdsReactionsMap[post5.Id], postIdsReactionsMap[post5.Id]) 616 assert.Equal(t, expectedPostIdsReactionsMap, postIdsReactionsMap) 617 618 }) 619 620 t.Run("get-reactions-as-anonymous-user", func(t *testing.T) { 621 Client.Logout() 622 623 _, resp := Client.GetBulkReactions(postIds) 624 CheckUnauthorizedStatus(t, resp) 625 }) 626 }