Add test notification tool (#28334)
* Add test notification tool * Add frontend styles * Remove option from admin view * Refactor create post and add translations * Fix several CI errors * Fix API and frontend snapshots * Refactor trailing and leading icon on buttons * Add different button states * i18n-extract * Fix wrong text * Add tests * Fix wrong string * Fix test * feat: E2E send test notifications (#28371) * Refactor send desktop notification * Address rest of the feedback * Fix tests * Add correct link * Fix test --------- Co-authored-by: Mattermost Build <build@mattermost.com> Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
30a6ddc995
Коммит
118d0346ee
@@ -1103,6 +1103,7 @@ type AppIface interface {
|
||||
SendPasswordReset(rctx request.CTX, email string, siteURL string) (bool, *model.AppError)
|
||||
SendPersistentNotifications() error
|
||||
SendReportToUser(rctx request.CTX, job *model.Job, format string) *model.AppError
|
||||
SendTestMessage(c request.CTX, userID string) (*model.Post, *model.AppError)
|
||||
SendTestPushNotification(deviceID string) string
|
||||
ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, sourcePluginId, destinationPluginId string)
|
||||
SessionHasPermissionTo(session model.Session, permission *model.Permission) bool
|
||||
|
||||
@@ -599,6 +599,10 @@ func (a *App) getMobileAppSessions(userID string) ([]*model.Session, *model.AppE
|
||||
}
|
||||
|
||||
func (a *App) ShouldSendPushNotification(user *model.User, channelNotifyProps model.StringMap, wasMentioned bool, status *model.Status, post *model.Post, isGM bool) bool {
|
||||
if prop := post.GetProp(model.PostPropsForceNotification); prop != nil && prop != "" {
|
||||
return true
|
||||
}
|
||||
|
||||
if notifyPropsAllowedReason := DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, wasMentioned, isGM); notifyPropsAllowedReason != "" {
|
||||
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, notifyPropsAllowedReason, model.NotificationNoPlatform)
|
||||
a.NotificationsLog().Debug("Notification not sent - notify props",
|
||||
|
||||
@@ -1103,6 +1103,39 @@ func TestSendPushNotifications(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestShouldSendPushNotifications(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
t.Run("should return true if forced", func(t *testing.T) {
|
||||
user := &model.User{Id: model.NewId(), Email: "unit@test.com", NotifyProps: make(map[string]string)}
|
||||
user.NotifyProps[model.PushNotifyProp] = model.UserNotifyNone
|
||||
|
||||
post := &model.Post{UserId: user.Id, ChannelId: model.NewId()}
|
||||
post.AddProp(model.PostPropsForceNotification, model.NewId())
|
||||
|
||||
channelNotifyProps := map[string]string{model.PushNotifyProp: model.ChannelNotifyNone, model.MarkUnreadNotifyProp: model.ChannelMarkUnreadMention}
|
||||
|
||||
status := &model.Status{UserId: user.Id, Status: model.StatusOnline, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: post.ChannelId}
|
||||
|
||||
result := th.App.ShouldSendPushNotification(user, channelNotifyProps, false, status, post, false)
|
||||
assert.True(t, result)
|
||||
})
|
||||
|
||||
t.Run("should return false if force undefined", func(t *testing.T) {
|
||||
user := &model.User{Id: model.NewId(), Email: "unit@test.com", NotifyProps: make(map[string]string)}
|
||||
user.NotifyProps[model.PushNotifyProp] = model.UserNotifyNone
|
||||
|
||||
post := &model.Post{UserId: user.Id, ChannelId: model.NewId()}
|
||||
|
||||
channelNotifyProps := map[string]string{model.PushNotifyProp: model.ChannelNotifyNone, model.MarkUnreadNotifyProp: model.ChannelMarkUnreadMention}
|
||||
|
||||
status := &model.Status{UserId: user.Id, Status: model.StatusOnline, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: post.ChannelId}
|
||||
|
||||
result := th.App.ShouldSendPushNotification(user, channelNotifyProps, false, status, post, false)
|
||||
assert.False(t, result)
|
||||
})
|
||||
}
|
||||
|
||||
// testPushNotificationHandler is an HTTP handler to record push notifications
|
||||
// being sent from the client.
|
||||
// It records the number of requests sent to it, and stores all the requests
|
||||
|
||||
@@ -16398,6 +16398,28 @@ func (a *OpenTracingAppLayer) SendSubscriptionHistoryEvent(userID string) (*mode
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) SendTestMessage(c request.CTX, userID string) (*model.Post, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SendTestMessage")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.SendTestMessage(c, userID)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) SendTestPushNotification(deviceID string) string {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SendTestPushNotification")
|
||||
|
||||
@@ -242,6 +242,10 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
|
||||
post.AddProp(model.PostPropsFromBot, "true")
|
||||
}
|
||||
|
||||
if flags.ForceNotification {
|
||||
post.AddProp(model.PostPropsForceNotification, model.NewId())
|
||||
}
|
||||
|
||||
if c.Session().IsOAuth {
|
||||
post.AddProp(model.PostPropsFromOAuthApp, "true")
|
||||
}
|
||||
@@ -2722,3 +2726,34 @@ func (a *App) CleanUpAfterPostDeletion(c request.CTX, post *model.Post, deleteBy
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) SendTestMessage(c request.CTX, userID string) (*model.Post, *model.AppError) {
|
||||
bot, err := a.GetSystemBot(c)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SendTestMessage", "app.notifications.send_test_message.errors.no_bot", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
channel, err := a.GetOrCreateDirectChannel(c, userID, bot.UserId)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SendTestMessage", "app.notifications.send_test_message.errors.no_channel", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
user, err := a.GetUser(userID)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SendTestMessage", "app.notifications.send_test_message.errors.no_user", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
T := i18n.GetUserTranslations(user.Locale)
|
||||
post := &model.Post{
|
||||
ChannelId: channel.Id,
|
||||
Message: T("app.notifications.send_test_message.message_body"),
|
||||
Type: model.PostTypeDefault,
|
||||
UserId: bot.UserId,
|
||||
}
|
||||
|
||||
post, err = a.CreatePost(c, post, channel, model.CreatePostFlags{ForceNotification: true})
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SendTestMessage", "app.notifications.send_test_message.errors.create_post", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
return post, nil
|
||||
}
|
||||
|
||||
@@ -1178,6 +1178,37 @@ func TestCreatePost(t *testing.T) {
|
||||
|
||||
wg.Wait()
|
||||
})
|
||||
|
||||
t.Run("should sanitize the force notifications prop if the flag is not set", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
th.AddUserToChannel(th.BasicUser, th.BasicChannel)
|
||||
|
||||
postToCreate := &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "hello world",
|
||||
UserId: th.BasicUser.Id,
|
||||
}
|
||||
postToCreate.AddProp(model.PostPropsForceNotification, model.NewId())
|
||||
createdPost, err := th.App.CreatePost(th.Context, postToCreate, th.BasicChannel, model.CreatePostFlags{})
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, createdPost.GetProp(model.PostPropsForceNotification))
|
||||
})
|
||||
|
||||
t.Run("should add the force notifications prop if the flag is set", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
th.AddUserToChannel(th.BasicUser, th.BasicChannel)
|
||||
|
||||
postToCreate := &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "hello world",
|
||||
UserId: th.BasicUser.Id,
|
||||
}
|
||||
createdPost, err := th.App.CreatePost(th.Context, postToCreate, th.BasicChannel, model.CreatePostFlags{ForceNotification: true})
|
||||
require.Nil(t, err)
|
||||
require.NotEmpty(t, createdPost.GetProp(model.PostPropsForceNotification))
|
||||
})
|
||||
}
|
||||
|
||||
func TestPatchPost(t *testing.T) {
|
||||
@@ -3739,3 +3770,13 @@ func TestPermanentDeletePost(t *testing.T) {
|
||||
assert.Len(t, infos, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSendTestMessage(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
t.Run("Should create the post with the correct prop", func(t *testing.T) {
|
||||
post, result := th.App.SendTestMessage(th.Context, th.BasicUser.Id)
|
||||
assert.Nil(t, result)
|
||||
assert.NotEmpty(t, post.GetProp(model.PostPropsForceNotification))
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user