// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. package app import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/mattermost/mattermost/server/public/model" ) func TestSetAutoResponderStatus(t *testing.T) { mainHelper.Parallel(t) th := Setup(t) defer th.TearDown() user := th.CreateUser() defer func() { err := th.App.PermanentDeleteUser(th.Context, user) require.Nil(t, err) }() th.App.SetStatusOnline(user.Id, true) patch := &model.UserPatch{} patch.NotifyProps = make(map[string]string) patch.NotifyProps["auto_responder_active"] = "true" patch.NotifyProps["auto_responder_message"] = "Hello, I'm unavailable today." userUpdated1, _ := th.App.PatchUser(th.Context, user.Id, patch, true) // autoResponder is enabled, status should be OOO th.App.SetAutoResponderStatus(th.Context, userUpdated1, user.NotifyProps) status, err := th.App.GetStatus(userUpdated1.Id) require.Nil(t, err) assert.Equal(t, model.StatusOutOfOffice, status.Status) patch2 := &model.UserPatch{} patch2.NotifyProps = make(map[string]string) patch2.NotifyProps["auto_responder_active"] = "false" patch2.NotifyProps["auto_responder_message"] = "Hello, I'm unavailable today." userUpdated2, _ := th.App.PatchUser(th.Context, user.Id, patch2, true) // autoResponder is disabled, status should be ONLINE th.App.SetAutoResponderStatus(th.Context, userUpdated2, userUpdated1.NotifyProps) status, err = th.App.GetStatus(userUpdated2.Id) require.Nil(t, err) assert.Equal(t, model.StatusOnline, status.Status) } func TestDisableAutoResponder(t *testing.T) { mainHelper.Parallel(t) th := Setup(t) defer th.TearDown() user := th.CreateUser() defer func() { err := th.App.PermanentDeleteUser(th.Context, user) require.Nil(t, err) }() th.App.SetStatusOnline(user.Id, true) patch := &model.UserPatch{} patch.NotifyProps = make(map[string]string) patch.NotifyProps["auto_responder_active"] = "true" patch.NotifyProps["auto_responder_message"] = "Hello, I'm unavailable today." user, appErr := th.App.PatchUser(th.Context, user.Id, patch, true) require.Nil(t, appErr) err := th.App.DisableAutoResponder(th.Context, user.Id, true) require.Nil(t, err) userUpdated1, err := th.App.GetUser(user.Id) require.Nil(t, err) assert.Equal(t, userUpdated1.NotifyProps["auto_responder_active"], "false") err = th.App.DisableAutoResponder(th.Context, user.Id, true) require.Nil(t, err) userUpdated2, err := th.App.GetUser(user.Id) require.Nil(t, err) assert.Equal(t, userUpdated2.NotifyProps["auto_responder_active"], "false") } func TestSendAutoResponseIfNecessary(t *testing.T) { mainHelper.Parallel(t) t.Run("should send auto response when enabled", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() receiver := th.CreateUser() patch := &model.UserPatch{ NotifyProps: map[string]string{ "auto_responder_active": "true", "auto_responder_message": "Hello, I'm unavailable today.", }, } receiver, err := th.App.PatchUser(th.Context, receiver.Id, patch, true) require.Nil(t, err) channel := th.CreateDmChannel(receiver) savedPost, _ := th.App.CreatePost(th.Context, &model.Post{ ChannelId: channel.Id, Message: NewTestId(), UserId: th.BasicUser.Id, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) sent, err := th.App.SendAutoResponseIfNecessary(th.Context, channel, th.BasicUser, savedPost) assert.Nil(t, err) assert.True(t, sent) }) t.Run("should not send auto response when disabled", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() receiver := th.CreateUser() patch := &model.UserPatch{ NotifyProps: map[string]string{ "auto_responder_active": "false", "auto_responder_message": "Hello, I'm unavailable today.", }, } receiver, err := th.App.PatchUser(th.Context, receiver.Id, patch, true) require.Nil(t, err) channel := th.CreateDmChannel(receiver) savedPost, _ := th.App.CreatePost(th.Context, &model.Post{ ChannelId: channel.Id, Message: NewTestId(), UserId: th.BasicUser.Id, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) sent, err := th.App.SendAutoResponseIfNecessary(th.Context, channel, th.BasicUser, savedPost) assert.Nil(t, err) assert.False(t, sent) }) t.Run("should not send auto response for non-DM channel", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() savedPost, _ := th.App.CreatePost(th.Context, &model.Post{ ChannelId: th.BasicChannel.Id, Message: NewTestId(), UserId: th.BasicUser.Id, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) sent, err := th.App.SendAutoResponseIfNecessary(th.Context, th.BasicChannel, th.BasicUser, savedPost) assert.Nil(t, err) assert.False(t, sent) }) t.Run("should not send auto response for bot", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() receiver := th.CreateUser() patch := &model.UserPatch{ NotifyProps: map[string]string{ "auto_responder_active": "true", "auto_responder_message": "Hello, I'm unavailable today.", }, } receiver, err := th.App.PatchUser(th.Context, receiver.Id, patch, true) require.Nil(t, err) channel := th.CreateDmChannel(receiver) bot, err := th.App.CreateBot(th.Context, &model.Bot{ Username: "botusername", Description: "bot", OwnerId: th.BasicUser.Id, }) assert.Nil(t, err) botUser, err := th.App.GetUser(bot.UserId) assert.Nil(t, err) savedPost, _ := th.App.CreatePost(th.Context, &model.Post{ ChannelId: channel.Id, Message: NewTestId(), UserId: botUser.Id, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) sent, err := th.App.SendAutoResponseIfNecessary(th.Context, channel, botUser, savedPost) assert.Nil(t, err) assert.False(t, sent) }) t.Run("should send auto response in dm channel if not already sent today", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() receiver := th.CreateUser() patch := &model.UserPatch{ NotifyProps: map[string]string{ "auto_responder_active": "true", "auto_responder_message": "Hello, I'm unavailable today.", }, } receiver, err := th.App.PatchUser(th.Context, receiver.Id, patch, true) require.Nil(t, err) channel := th.CreateDmChannel(receiver) // Clean up all posts from this user. // There are some dummy messages like "user joined team" etc. // which needs to be cleaned up. require.NoError(t, th.GetSqlStore().Post().PermanentDeleteByUser(th.Context, th.BasicUser.Id)) savedPost, err := th.App.CreatePost(th.Context, &model.Post{ ChannelId: channel.Id, Message: patch.NotifyProps["auto_responder_message"], UserId: receiver.Id, CreateAt: model.GetMillisForTime(time.Now().Add(-48 * time.Hour)), Type: model.PostTypeAutoResponder, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) require.Nil(t, err) savedPost.CreateAt = model.GetMillisForTime(time.Now()) sent, err := th.App.SendAutoResponseIfNecessary(th.Context, channel, th.BasicUser, savedPost) require.Nil(t, err) assert.True(t, sent) }) } func TestSendAutoResponseSuccess(t *testing.T) { mainHelper.Parallel(t) th := Setup(t).InitBasic() defer th.TearDown() user := th.CreateUser() defer func() { err := th.App.PermanentDeleteUser(th.Context, user) require.Nil(t, err) }() patch := &model.UserPatch{} patch.NotifyProps = make(map[string]string) patch.NotifyProps["auto_responder_active"] = "true" patch.NotifyProps["auto_responder_message"] = "Hello, I'm unavailable today." userUpdated1, err := th.App.PatchUser(th.Context, user.Id, patch, true) require.Nil(t, err) savedPost, _ := th.App.CreatePost(th.Context, &model.Post{ ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", UserId: th.BasicUser.Id, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) sent, err := th.App.SendAutoResponse(th.Context, th.BasicChannel, userUpdated1, savedPost) assert.Nil(t, err) assert.True(t, sent) list, err := th.App.GetPosts(th.Context, th.BasicChannel.Id, 0, 1) require.Nil(t, err) autoResponderPostFound := false for _, post := range list.Posts { if post.Type == model.PostTypeAutoResponder { autoResponderPostFound = true assert.Equal(t, savedPost.Id, post.RootId) } } assert.True(t, autoResponderPostFound) } func TestSendAutoResponseSuccessOnThread(t *testing.T) { mainHelper.Parallel(t) th := Setup(t).InitBasic() defer th.TearDown() user := th.CreateUser() defer func() { err := th.App.PermanentDeleteUser(th.Context, user) require.Nil(t, err) }() patch := &model.UserPatch{} patch.NotifyProps = make(map[string]string) patch.NotifyProps["auto_responder_active"] = "true" patch.NotifyProps["auto_responder_message"] = "Hello, I'm unavailable today." userUpdated1, err := th.App.PatchUser(th.Context, user.Id, patch, true) require.Nil(t, err) parentPost, _ := th.App.CreatePost(th.Context, &model.Post{ ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", UserId: th.BasicUser.Id, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) savedPost, _ := th.App.CreatePost(th.Context, &model.Post{ ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", UserId: th.BasicUser.Id, RootId: parentPost.Id, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) sent, err := th.App.SendAutoResponse(th.Context, th.BasicChannel, userUpdated1, savedPost) assert.Nil(t, err) assert.True(t, sent) list, err := th.App.GetPosts(th.Context, th.BasicChannel.Id, 0, 1) require.Nil(t, err) autoResponderPostFound := false for _, post := range list.Posts { if post.Type == model.PostTypeAutoResponder { autoResponderPostFound = true assert.Equal(t, savedPost.RootId, post.RootId) } } assert.True(t, autoResponderPostFound) } func TestSendAutoResponseFailure(t *testing.T) { mainHelper.Parallel(t) th := Setup(t).InitBasic() defer th.TearDown() user := th.CreateUser() defer func() { err := th.App.PermanentDeleteUser(th.Context, user) require.Nil(t, err) }() patch := &model.UserPatch{} patch.NotifyProps = make(map[string]string) patch.NotifyProps["auto_responder_active"] = "false" patch.NotifyProps["auto_responder_message"] = "Hello, I'm unavailable today." userUpdated1, err := th.App.PatchUser(th.Context, user.Id, patch, true) require.Nil(t, err) savedPost, _ := th.App.CreatePost(th.Context, &model.Post{ ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", UserId: th.BasicUser.Id, }, th.BasicChannel, model.CreatePostFlags{SetOnline: true}) sent, err := th.App.SendAutoResponse(th.Context, th.BasicChannel, userUpdated1, savedPost) assert.Nil(t, err) assert.False(t, sent) if list, err := th.App.GetPosts(th.Context, th.BasicChannel.Id, 0, 1); err != nil { require.Nil(t, err) } else { autoResponderPostFound := false for _, post := range list.Posts { if post.Type == model.PostTypeAutoResponder { autoResponderPostFound = true } } assert.False(t, autoResponderPostFound) } }