mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
* api4: fix TestGetUsersNotInTeam assertions This test was relying on data from a previous test run. With the data cleared before each test, the assertions much match reality. * *testlib: always InitSystemAdmin Some tests implicitly relied on the basic user having system administrator privileges because it was the first user created as such. Eliminate `InitSystemAdmin` and explicitly create the system admin user instead to avoid this ambiguity going forward. * *testlib: drop all tables before each test * api4: split up TestChannelDelete to avoid duplicate InitBasic * api4: teardown in TestResetPassword, for when this test comes back * invalidate cache on DropAllTables This is necessary since the test store persists across tests. * disable parallel tests While tests within a package must be explicitly parallelized using `t.Parallel()`, tests across packages are run in parallel by default. This causes problems given that the tests all currently share the same database instance. Unfortunately, this also means that running the tests is much slower, but we can return to this later.
570 lines
15 KiB
Go
570 lines
15 KiB
Go
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
|
// See License.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/mattermost/mattermost-server/model"
|
|
)
|
|
|
|
func TestSaveReaction(t *testing.T) {
|
|
th := Setup().InitBasic()
|
|
defer th.TearDown()
|
|
Client := th.Client
|
|
userId := th.BasicUser.Id
|
|
postId := th.BasicPost.Id
|
|
|
|
// Check the appropriate permissions are enforced.
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions()
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(defaultRolePermissions)
|
|
}()
|
|
|
|
reaction := &model.Reaction{
|
|
UserId: userId,
|
|
PostId: postId,
|
|
EmojiName: "smile",
|
|
}
|
|
|
|
t.Run("successful-reaction", func(t *testing.T) {
|
|
rr, resp := Client.SaveReaction(reaction)
|
|
CheckNoError(t, resp)
|
|
|
|
if rr.UserId != reaction.UserId {
|
|
t.Fatal("UserId did not match")
|
|
}
|
|
|
|
if rr.PostId != reaction.PostId {
|
|
t.Fatal("PostId did not match")
|
|
}
|
|
|
|
if rr.EmojiName != reaction.EmojiName {
|
|
t.Fatal("EmojiName did not match")
|
|
}
|
|
|
|
if rr.CreateAt == 0 {
|
|
t.Fatal("CreateAt should exist")
|
|
}
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil && len(reactions) != 1 {
|
|
t.Fatal("didn't save reaction correctly")
|
|
}
|
|
})
|
|
|
|
t.Run("duplicated-reaction", func(t *testing.T) {
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckNoError(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil && len(reactions) != 1 {
|
|
t.Fatal("should have not save duplicated reaction")
|
|
}
|
|
})
|
|
|
|
t.Run("save-second-reaction", func(t *testing.T) {
|
|
reaction.EmojiName = "sad"
|
|
|
|
rr, resp := Client.SaveReaction(reaction)
|
|
CheckNoError(t, resp)
|
|
|
|
if rr.EmojiName != reaction.EmojiName {
|
|
t.Fatal("EmojiName did not match")
|
|
}
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil && len(reactions) != 2 {
|
|
t.Fatal("should have save multiple reactions")
|
|
}
|
|
})
|
|
|
|
t.Run("saving-special-case", func(t *testing.T) {
|
|
reaction.EmojiName = "+1"
|
|
|
|
rr, resp := Client.SaveReaction(reaction)
|
|
CheckNoError(t, resp)
|
|
|
|
if rr.EmojiName != reaction.EmojiName {
|
|
t.Fatal("EmojiName did not match")
|
|
}
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil && len(reactions) != 3 {
|
|
t.Fatal("should have save multiple reactions")
|
|
}
|
|
})
|
|
|
|
t.Run("react-to-not-existing-post-id", func(t *testing.T) {
|
|
reaction.PostId = GenerateTestId()
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("react-to-not-valid-post-id", func(t *testing.T) {
|
|
reaction.PostId = "junk"
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
|
|
t.Run("react-as-not-existing-user-id", func(t *testing.T) {
|
|
reaction.PostId = postId
|
|
reaction.UserId = GenerateTestId()
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("react-as-not-valid-user-id", func(t *testing.T) {
|
|
reaction.UserId = "junk"
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
|
|
t.Run("react-as-empty-emoji-name", func(t *testing.T) {
|
|
reaction.UserId = userId
|
|
reaction.EmojiName = ""
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
|
|
t.Run("react-as-not-valid-emoji-name", func(t *testing.T) {
|
|
reaction.EmojiName = strings.Repeat("a", 65)
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
|
|
t.Run("react-as-other-user", func(t *testing.T) {
|
|
reaction.EmojiName = "smile"
|
|
otherUser := th.CreateUser()
|
|
Client.Logout()
|
|
Client.Login(otherUser.Email, otherUser.Password)
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("react-being-not-logged-in", func(t *testing.T) {
|
|
Client.Logout()
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
})
|
|
|
|
t.Run("react-as-other-user-being-system-admin", func(t *testing.T) {
|
|
_, resp := th.SystemAdminClient.SaveReaction(reaction)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("unable-to-create-reaction-without-permissions", func(t *testing.T) {
|
|
th.LoginBasic()
|
|
|
|
th.RemovePermissionFromRole(model.PERMISSION_ADD_REACTION.Id, model.CHANNEL_USER_ROLE_ID)
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 3 {
|
|
t.Fatal("should have not created a reactions")
|
|
}
|
|
th.AddPermissionToRole(model.PERMISSION_ADD_REACTION.Id, model.CHANNEL_USER_ROLE_ID)
|
|
})
|
|
|
|
t.Run("unable-to-react-in-read-only-town-square", func(t *testing.T) {
|
|
th.LoginBasic()
|
|
|
|
channel, err := th.App.GetChannelByName("town-square", th.BasicTeam.Id, true)
|
|
assert.Nil(t, err)
|
|
post := th.CreatePostWithClient(th.Client, channel)
|
|
|
|
th.App.SetLicense(model.NewTestLicense())
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true })
|
|
|
|
reaction := &model.Reaction{
|
|
UserId: userId,
|
|
PostId: post.Id,
|
|
EmojiName: "smile",
|
|
}
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 0 {
|
|
t.Fatal("should have not created a reaction")
|
|
}
|
|
|
|
th.App.RemoveLicense()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false })
|
|
})
|
|
|
|
t.Run("unable-to-react-in-an-archived-channel", func(t *testing.T) {
|
|
th.LoginBasic()
|
|
|
|
channel := th.CreatePublicChannel()
|
|
post := th.CreatePostWithClient(th.Client, channel)
|
|
|
|
reaction := &model.Reaction{
|
|
UserId: userId,
|
|
PostId: post.Id,
|
|
EmojiName: "smile",
|
|
}
|
|
|
|
err := th.App.DeleteChannel(channel, userId)
|
|
assert.Nil(t, err)
|
|
|
|
_, resp := Client.SaveReaction(reaction)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 0 {
|
|
t.Fatal("should have not created a reaction")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestGetReactions(t *testing.T) {
|
|
th := Setup().InitBasic()
|
|
defer th.TearDown()
|
|
Client := th.Client
|
|
userId := th.BasicUser.Id
|
|
user2Id := th.BasicUser2.Id
|
|
postId := th.BasicPost.Id
|
|
|
|
userReactions := []*model.Reaction{
|
|
{
|
|
UserId: userId,
|
|
PostId: postId,
|
|
EmojiName: "smile",
|
|
},
|
|
{
|
|
UserId: userId,
|
|
PostId: postId,
|
|
EmojiName: "happy",
|
|
},
|
|
{
|
|
UserId: userId,
|
|
PostId: postId,
|
|
EmojiName: "sad",
|
|
},
|
|
{
|
|
UserId: user2Id,
|
|
PostId: postId,
|
|
EmojiName: "smile",
|
|
},
|
|
{
|
|
UserId: user2Id,
|
|
PostId: postId,
|
|
EmojiName: "sad",
|
|
},
|
|
}
|
|
|
|
var reactions []*model.Reaction
|
|
|
|
for _, userReaction := range userReactions {
|
|
if result := <-th.App.Srv.Store.Reaction().Save(userReaction); result.Err != nil {
|
|
t.Fatal(result.Err)
|
|
} else {
|
|
reactions = append(reactions, result.Data.(*model.Reaction))
|
|
}
|
|
}
|
|
|
|
t.Run("get-reactions", func(t *testing.T) {
|
|
rr, resp := Client.GetReactions(postId)
|
|
CheckNoError(t, resp)
|
|
|
|
assert.Len(t, rr, 5)
|
|
for _, r := range reactions {
|
|
assert.Contains(t, reactions, r)
|
|
}
|
|
})
|
|
|
|
t.Run("get-reactions-of-invalid-post-id", func(t *testing.T) {
|
|
rr, resp := Client.GetReactions("junk")
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
assert.Empty(t, rr)
|
|
})
|
|
|
|
t.Run("get-reactions-of-not-existing-post-id", func(t *testing.T) {
|
|
_, resp := Client.GetReactions(GenerateTestId())
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("get-reactions-as-anonymous-user", func(t *testing.T) {
|
|
Client.Logout()
|
|
|
|
_, resp := Client.GetReactions(postId)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
})
|
|
|
|
t.Run("get-reactions-as-system-admin", func(t *testing.T) {
|
|
_, resp := th.SystemAdminClient.GetReactions(postId)
|
|
CheckNoError(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestDeleteReaction(t *testing.T) {
|
|
th := Setup().InitBasic()
|
|
defer th.TearDown()
|
|
Client := th.Client
|
|
userId := th.BasicUser.Id
|
|
user2Id := th.BasicUser2.Id
|
|
postId := th.BasicPost.Id
|
|
|
|
r1 := &model.Reaction{
|
|
UserId: userId,
|
|
PostId: postId,
|
|
EmojiName: "smile",
|
|
}
|
|
|
|
r2 := &model.Reaction{
|
|
UserId: userId,
|
|
PostId: postId,
|
|
EmojiName: "smile-",
|
|
}
|
|
|
|
r3 := &model.Reaction{
|
|
UserId: userId,
|
|
PostId: postId,
|
|
EmojiName: "+1",
|
|
}
|
|
|
|
r4 := &model.Reaction{
|
|
UserId: user2Id,
|
|
PostId: postId,
|
|
EmojiName: "smile_",
|
|
}
|
|
|
|
// Check the appropriate permissions are enforced.
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions()
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(defaultRolePermissions)
|
|
}()
|
|
|
|
t.Run("delete-reaction", func(t *testing.T) {
|
|
th.App.SaveReactionForPost(r1)
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
|
t.Fatal("didn't save reaction correctly")
|
|
}
|
|
|
|
ok, resp := Client.DeleteReaction(r1)
|
|
CheckNoError(t, resp)
|
|
|
|
if !ok {
|
|
t.Fatal("should have returned true")
|
|
}
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 0 {
|
|
t.Fatal("should have deleted reaction")
|
|
}
|
|
})
|
|
|
|
t.Run("delete-reaction-when-post-has-multiple-reactions", func(t *testing.T) {
|
|
th.App.SaveReactionForPost(r1)
|
|
th.App.SaveReactionForPost(r2)
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 2 {
|
|
t.Fatal("didn't save reactions correctly")
|
|
}
|
|
|
|
_, resp := Client.DeleteReaction(r2)
|
|
CheckNoError(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 || *reactions[0] != *r1 {
|
|
t.Fatal("should have deleted 1 reaction only")
|
|
}
|
|
})
|
|
|
|
t.Run("delete-reaction-when-plus-one-reaction-name", func(t *testing.T) {
|
|
th.App.SaveReactionForPost(r3)
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 2 {
|
|
t.Fatal("didn't save reactions correctly")
|
|
}
|
|
|
|
_, resp := Client.DeleteReaction(r3)
|
|
CheckNoError(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 || *reactions[0] != *r1 {
|
|
t.Fatal("should have deleted 1 reaction only")
|
|
}
|
|
})
|
|
|
|
t.Run("delete-reaction-made-by-another-user", func(t *testing.T) {
|
|
th.LoginBasic2()
|
|
th.App.SaveReactionForPost(r4)
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 2 {
|
|
t.Fatal("didn't save reaction correctly")
|
|
}
|
|
|
|
th.LoginBasic()
|
|
|
|
ok, resp := Client.DeleteReaction(r4)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
if ok {
|
|
t.Fatal("should have returned false")
|
|
}
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 2 {
|
|
t.Fatal("should have not deleted a reaction")
|
|
}
|
|
})
|
|
|
|
t.Run("delete-reaction-from-not-existing-post-id", func(t *testing.T) {
|
|
r1.PostId = GenerateTestId()
|
|
_, resp := Client.DeleteReaction(r1)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("delete-reaction-from-not-valid-post-id", func(t *testing.T) {
|
|
r1.PostId = "junk"
|
|
|
|
_, resp := Client.DeleteReaction(r1)
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
|
|
t.Run("delete-reaction-from-not-existing-user-id", func(t *testing.T) {
|
|
r1.PostId = postId
|
|
r1.UserId = GenerateTestId()
|
|
|
|
_, resp := Client.DeleteReaction(r1)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("delete-reaction-from-not-valid-user-id", func(t *testing.T) {
|
|
r1.UserId = "junk"
|
|
|
|
_, resp := Client.DeleteReaction(r1)
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
|
|
t.Run("delete-reaction-with-empty-name", func(t *testing.T) {
|
|
r1.UserId = userId
|
|
r1.EmojiName = ""
|
|
|
|
_, resp := Client.DeleteReaction(r1)
|
|
CheckNotFoundStatus(t, resp)
|
|
})
|
|
|
|
t.Run("delete-reaction-with-not-existing-name", func(t *testing.T) {
|
|
r1.EmojiName = strings.Repeat("a", 65)
|
|
|
|
_, resp := Client.DeleteReaction(r1)
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
|
|
t.Run("delete-reaction-as-anonymous-user", func(t *testing.T) {
|
|
Client.Logout()
|
|
r1.EmojiName = "smile"
|
|
|
|
_, resp := Client.DeleteReaction(r1)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
})
|
|
|
|
t.Run("delete-reaction-as-system-admin", func(t *testing.T) {
|
|
_, resp := th.SystemAdminClient.DeleteReaction(r1)
|
|
CheckNoError(t, resp)
|
|
|
|
_, resp = th.SystemAdminClient.DeleteReaction(r4)
|
|
CheckNoError(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 0 {
|
|
t.Fatal("should have deleted both reactions")
|
|
}
|
|
})
|
|
|
|
t.Run("unable-to-delete-reaction-without-permissions", func(t *testing.T) {
|
|
th.LoginBasic()
|
|
|
|
th.RemovePermissionFromRole(model.PERMISSION_REMOVE_REACTION.Id, model.CHANNEL_USER_ROLE_ID)
|
|
th.App.SaveReactionForPost(r1)
|
|
|
|
_, resp := Client.DeleteReaction(r1)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
|
t.Fatal("should have not deleted a reactions")
|
|
}
|
|
th.AddPermissionToRole(model.PERMISSION_REMOVE_REACTION.Id, model.CHANNEL_USER_ROLE_ID)
|
|
})
|
|
|
|
t.Run("unable-to-delete-others-reactions-without-permissions", func(t *testing.T) {
|
|
th.RemovePermissionFromRole(model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id, model.SYSTEM_ADMIN_ROLE_ID)
|
|
th.App.SaveReactionForPost(r1)
|
|
|
|
_, resp := th.SystemAdminClient.DeleteReaction(r1)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
|
t.Fatal("should have not deleted a reactions")
|
|
}
|
|
th.AddPermissionToRole(model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id, model.SYSTEM_ADMIN_ROLE_ID)
|
|
})
|
|
|
|
t.Run("unable-to-delete-reactions-in-read-only-town-square", func(t *testing.T) {
|
|
th.LoginBasic()
|
|
|
|
channel, err := th.App.GetChannelByName("town-square", th.BasicTeam.Id, true)
|
|
assert.Nil(t, err)
|
|
post := th.CreatePostWithClient(th.Client, channel)
|
|
|
|
th.App.SetLicense(model.NewTestLicense())
|
|
|
|
reaction := &model.Reaction{
|
|
UserId: userId,
|
|
PostId: post.Id,
|
|
EmojiName: "smile",
|
|
}
|
|
|
|
r1, resp := Client.SaveReaction(reaction)
|
|
CheckNoError(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
|
t.Fatal("should have created a reaction")
|
|
}
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true })
|
|
|
|
_, resp = th.SystemAdminClient.DeleteReaction(r1)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
|
t.Fatal("should have not deleted a reaction")
|
|
}
|
|
|
|
th.App.RemoveLicense()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false })
|
|
})
|
|
|
|
t.Run("unable-to-delete-reactions-in-an-archived-channel", func(t *testing.T) {
|
|
th.LoginBasic()
|
|
|
|
channel := th.CreatePublicChannel()
|
|
post := th.CreatePostWithClient(th.Client, channel)
|
|
|
|
reaction := &model.Reaction{
|
|
UserId: userId,
|
|
PostId: post.Id,
|
|
EmojiName: "smile",
|
|
}
|
|
|
|
r1, resp := Client.SaveReaction(reaction)
|
|
CheckNoError(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
|
t.Fatal("should have created a reaction")
|
|
}
|
|
|
|
err := th.App.DeleteChannel(channel, userId)
|
|
assert.Nil(t, err)
|
|
|
|
_, resp = Client.SaveReaction(r1)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 1 {
|
|
t.Fatal("should have not deleted a reaction")
|
|
}
|
|
})
|
|
}
|