[MM-42739] Insights - Top Channels API Endpoint (#19953)
* [MM-42739] Initial setup for top channels for team * [MM-42739] Add initial tests * [MM-42739] Update tests * [MM-42739] Add top channels for user * [MM-42739] Fix query * [MM-42739] Update query * [MM-42739] Improve query performance * [MM-42739] Remove rank * [MM-42739] Fix tests to use new time range today * [MM-42739] Add tests for top channels for user * [MM-42739] Add test for pagination * Remove top channels by time struct * [MM-42739] Update test names * [MM-42739] Remove rank from top reactions * [MM-42739] Return empty array instead of nil when result is empty * [MM-42739] Add additional tests and update permissions check for teams * [MM-42739] Add excluded channel tests for top reactions * [MM-42739] Move insights to api4/insights and keep time range as string until required * [MM-42739] Update queries only check DeleteAt after union * [MM-42739] Improve query performance by using publicchannels table * [MM-42739] Fix broken query after merge
Этот коммит содержится в:
@@ -134,6 +134,9 @@ type Routes struct {
|
||||
SharedChannels *mux.Router // 'api/v4/sharedchannels'
|
||||
|
||||
Permissions *mux.Router // 'api/v4/permissions'
|
||||
|
||||
InsightsForTeam *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/top'
|
||||
InsightsForUser *mux.Router // 'api/v4/users/me/top'
|
||||
}
|
||||
|
||||
type API struct {
|
||||
@@ -255,6 +258,9 @@ func Init(srv *app.Server) (*API, error) {
|
||||
|
||||
api.BaseRoutes.Permissions = api.BaseRoutes.APIRoot.PathPrefix("/permissions").Subrouter()
|
||||
|
||||
api.BaseRoutes.InsightsForTeam = api.BaseRoutes.Team.PathPrefix("/top").Subrouter()
|
||||
api.BaseRoutes.InsightsForUser = api.BaseRoutes.Users.PathPrefix("/me/top").Subrouter()
|
||||
|
||||
api.InitUser()
|
||||
api.InitBot()
|
||||
api.InitTeam()
|
||||
@@ -296,6 +302,7 @@ func Init(srv *app.Server) (*API, error) {
|
||||
api.InitSharedChannels()
|
||||
api.InitPermissions()
|
||||
api.InitExport()
|
||||
api.InitInsights()
|
||||
if err := api.InitGraphQL(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
204
api4/insights.go
Обычный файл
204
api4/insights.go
Обычный файл
@@ -0,0 +1,204 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package api4
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
)
|
||||
|
||||
func (api *API) InitInsights() {
|
||||
// Reactions
|
||||
api.BaseRoutes.InsightsForTeam.Handle("/reactions", api.APISessionRequired(getTopReactionsForTeamSince)).Methods("GET")
|
||||
api.BaseRoutes.InsightsForUser.Handle("/reactions", api.APISessionRequired(getTopReactionsForUserSince)).Methods("GET")
|
||||
|
||||
// Channels
|
||||
api.BaseRoutes.InsightsForTeam.Handle("/channels", api.APISessionRequired(getTopChannelsForTeamSince)).Methods("GET")
|
||||
api.BaseRoutes.InsightsForUser.Handle("/channels", api.APISessionRequired(getTopChannelsForUserSince)).Methods("GET")
|
||||
}
|
||||
|
||||
// Top Reactions
|
||||
|
||||
func getTopReactionsForTeamSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireTeamId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
team, err := c.App.GetTeam(c.Params.TeamId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PermissionViewTeam) {
|
||||
c.SetPermissionError(model.PermissionViewTeam)
|
||||
return
|
||||
}
|
||||
|
||||
startTime, err := model.GetStartUnixMilliForTimeRange(c.Params.TimeRange)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
topReactionList, err := c.App.GetTopReactionsForTeamSince(c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{
|
||||
StartUnixMilli: startTime,
|
||||
Page: c.Params.Page,
|
||||
PerPage: c.Params.PerPage,
|
||||
})
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
js, jsonErr := json.Marshal(topReactionList)
|
||||
if jsonErr != nil {
|
||||
c.Err = model.NewAppError("getTopReactionsForTeamSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
func getTopReactionsForUserSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.Params.TeamId = r.URL.Query().Get("team_id")
|
||||
|
||||
// TeamId is an optional parameter
|
||||
if c.Params.TeamId != "" {
|
||||
if !model.IsValidId(c.Params.TeamId) {
|
||||
c.SetInvalidURLParam("team_id")
|
||||
return
|
||||
}
|
||||
|
||||
team, teamErr := c.App.GetTeam(c.Params.TeamId)
|
||||
if teamErr != nil {
|
||||
c.Err = teamErr
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PermissionViewTeam) {
|
||||
c.SetPermissionError(model.PermissionViewTeam)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
startTime, err := model.GetStartUnixMilliForTimeRange(c.Params.TimeRange)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
topReactionList, err := c.App.GetTopReactionsForUserSince(c.AppContext.Session().UserId, c.Params.TeamId, &model.InsightsOpts{
|
||||
StartUnixMilli: startTime,
|
||||
Page: c.Params.Page,
|
||||
PerPage: c.Params.PerPage,
|
||||
})
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
js, jsonErr := json.Marshal(topReactionList)
|
||||
if jsonErr != nil {
|
||||
c.Err = model.NewAppError("getTopReactionsForUserSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
// Top Channels
|
||||
|
||||
func getTopChannelsForTeamSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireTeamId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
team, err := c.App.GetTeam(c.Params.TeamId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PermissionViewTeam) {
|
||||
c.SetPermissionError(model.PermissionViewTeam)
|
||||
return
|
||||
}
|
||||
|
||||
startTime, err := model.GetStartUnixMilliForTimeRange(c.Params.TimeRange)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
topChannels, err := c.App.GetTopChannelsForTeamSince(c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{
|
||||
StartUnixMilli: startTime,
|
||||
Page: c.Params.Page,
|
||||
PerPage: c.Params.PerPage,
|
||||
})
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
js, jsonErr := json.Marshal(topChannels)
|
||||
if jsonErr != nil {
|
||||
c.Err = model.NewAppError("getTopChannelsForTeamSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
func getTopChannelsForUserSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.Params.TeamId = r.URL.Query().Get("team_id")
|
||||
|
||||
// TeamId is an optional parameter
|
||||
if c.Params.TeamId != "" {
|
||||
if !model.IsValidId(c.Params.TeamId) {
|
||||
c.SetInvalidURLParam("team_id")
|
||||
return
|
||||
}
|
||||
|
||||
team, teamErr := c.App.GetTeam(c.Params.TeamId)
|
||||
if teamErr != nil {
|
||||
c.Err = teamErr
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PermissionViewTeam) {
|
||||
c.SetPermissionError(model.PermissionViewTeam)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
startTime, err := model.GetStartUnixMilliForTimeRange(c.Params.TimeRange)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
topChannels, err := c.App.GetTopChannelsForUserSince(c.AppContext.Session().UserId, c.Params.TeamId, &model.InsightsOpts{
|
||||
StartUnixMilli: startTime,
|
||||
Page: c.Params.Page,
|
||||
PerPage: c.Params.PerPage,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
js, jsonErr := json.Marshal(topChannels)
|
||||
if jsonErr != nil {
|
||||
c.Err = model.NewAppError("getTopChannelsForUserSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(js)
|
||||
}
|
||||
600
api4/insights_test.go
Обычный файл
600
api4/insights_test.go
Обычный файл
@@ -0,0 +1,600 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package api4
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Top Reactions
|
||||
|
||||
func TestGetTopReactionsForTeamSince(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.ConfigStore.SetReadOnlyFF(false)
|
||||
defer th.ConfigStore.SetReadOnlyFF(true)
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = true })
|
||||
|
||||
client := th.Client
|
||||
|
||||
userId := th.BasicUser.Id
|
||||
user2Id := th.BasicUser2.Id
|
||||
|
||||
post1 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post2 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post3 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post4 := &model.Post{UserId: user2Id, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post5 := &model.Post{UserId: user2Id, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
|
||||
post1, _, _ = client.CreatePost(post1)
|
||||
post2, _, _ = client.CreatePost(post2)
|
||||
post3, _, _ = client.CreatePost(post3)
|
||||
post4, _, _ = client.CreatePost(post4)
|
||||
post5, _, _ = client.CreatePost(post5)
|
||||
|
||||
userReactions := []*model.Reaction{
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "sad",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "sad",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "sad",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "100",
|
||||
CreateAt: model.GetMillisForTime(time.Now().Add(time.Hour * time.Duration(-25))),
|
||||
},
|
||||
}
|
||||
|
||||
for _, userReaction := range userReactions {
|
||||
_, err := th.App.Srv().Store.Reaction().Save(userReaction)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
teamId := th.BasicChannel.TeamId
|
||||
|
||||
var expectedTopReactions [5]*model.TopReaction
|
||||
expectedTopReactions[0] = &model.TopReaction{EmojiName: "100", Count: int64(6)}
|
||||
expectedTopReactions[1] = &model.TopReaction{EmojiName: "joy", Count: int64(5)}
|
||||
expectedTopReactions[2] = &model.TopReaction{EmojiName: "smile", Count: int64(4)}
|
||||
expectedTopReactions[3] = &model.TopReaction{EmojiName: "sad", Count: int64(3)}
|
||||
expectedTopReactions[4] = &model.TopReaction{EmojiName: "happy", Count: int64(2)}
|
||||
|
||||
t.Run("get-top-reactions-for-team-since", func(t *testing.T) {
|
||||
topReactions, _, err := client.GetTopReactionsForTeamSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
require.NoError(t, err)
|
||||
reactions := topReactions.Items
|
||||
|
||||
for i, reaction := range reactions {
|
||||
assert.Equal(t, expectedTopReactions[i].EmojiName, reaction.EmojiName)
|
||||
assert.Equal(t, expectedTopReactions[i].Count, reaction.Count)
|
||||
}
|
||||
|
||||
topReactions, _, err = client.GetTopReactionsForTeamSince(teamId, model.TimeRangeToday, 1, 5)
|
||||
require.NoError(t, err)
|
||||
reactions = topReactions.Items
|
||||
|
||||
assert.Equal(t, "+1", reactions[0].EmojiName)
|
||||
assert.Equal(t, int64(1), reactions[0].Count)
|
||||
})
|
||||
|
||||
t.Run("get-top-reactions-for-team-since exclude channels user is not member of", func(t *testing.T) {
|
||||
excludedChannel := th.CreatePrivateChannel()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
post, _, err := client.CreatePost(&model.Post{UserId: userId, ChannelId: excludedChannel.Id, Message: "zz" + model.NewId() + "a"})
|
||||
require.NoError(t, err)
|
||||
|
||||
reaction := &model.Reaction{
|
||||
UserId: userId,
|
||||
PostId: post.Id,
|
||||
EmojiName: "confused",
|
||||
}
|
||||
|
||||
_, err = th.App.Srv().Store.Reaction().Save(reaction)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
th.RemoveUserFromChannel(th.BasicUser, excludedChannel)
|
||||
|
||||
topReactions, _, err := client.GetTopReactionsForTeamSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
require.NoError(t, err)
|
||||
reactions := topReactions.Items
|
||||
|
||||
for i, reaction := range reactions {
|
||||
assert.Equal(t, expectedTopReactions[i].EmojiName, reaction.EmojiName)
|
||||
assert.Equal(t, expectedTopReactions[i].Count, reaction.Count)
|
||||
}
|
||||
|
||||
topReactions, _, err = client.GetTopReactionsForTeamSince(teamId, model.TimeRangeToday, 1, 5)
|
||||
require.NoError(t, err)
|
||||
reactions = topReactions.Items
|
||||
|
||||
assert.Equal(t, "+1", reactions[0].EmojiName)
|
||||
assert.Equal(t, int64(1), reactions[0].Count)
|
||||
})
|
||||
|
||||
t.Run("get-top-reactions-for-team-since invalid team id", func(t *testing.T) {
|
||||
_, resp, err := client.GetTopReactionsForTeamSince("12345", model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
_, resp, err = client.GetTopReactionsForTeamSince(model.NewId(), model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("get-top-reactions-for-team-since not a member of team", func(t *testing.T) {
|
||||
th.UnlinkUserFromTeam(th.BasicUser, th.BasicTeam)
|
||||
_, resp, err := client.GetTopReactionsForTeamSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetTopReactionsForUserSince(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.ConfigStore.SetReadOnlyFF(false)
|
||||
defer th.ConfigStore.SetReadOnlyFF(true)
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = true })
|
||||
|
||||
client := th.Client
|
||||
|
||||
userId := th.BasicUser.Id
|
||||
|
||||
post1 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post2 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post3 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post4 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post5 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post6 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
|
||||
post1, _, _ = client.CreatePost(post1)
|
||||
post2, _, _ = client.CreatePost(post2)
|
||||
post3, _, _ = client.CreatePost(post3)
|
||||
post4, _, _ = client.CreatePost(post4)
|
||||
post5, _, _ = client.CreatePost(post5)
|
||||
post6, _, _ = client.CreatePost(post6)
|
||||
|
||||
userReactions := []*model.Reaction{
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post6.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "heart",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "heart",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "heart",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "blush",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "blush",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "100",
|
||||
CreateAt: model.GetMillisForTime(time.Now().Add(time.Hour * time.Duration(-25))),
|
||||
},
|
||||
}
|
||||
|
||||
for _, userReaction := range userReactions {
|
||||
_, err := th.App.Srv().Store.Reaction().Save(userReaction)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
teamId := th.BasicChannel.TeamId
|
||||
|
||||
var expectedTopReactions [5]*model.TopReaction
|
||||
expectedTopReactions[0] = &model.TopReaction{EmojiName: "happy", Count: int64(6)}
|
||||
expectedTopReactions[1] = &model.TopReaction{EmojiName: "smile", Count: int64(5)}
|
||||
expectedTopReactions[2] = &model.TopReaction{EmojiName: "+1", Count: int64(4)}
|
||||
expectedTopReactions[3] = &model.TopReaction{EmojiName: "heart", Count: int64(3)}
|
||||
expectedTopReactions[4] = &model.TopReaction{EmojiName: "blush", Count: int64(2)}
|
||||
|
||||
t.Run("get-top-reactions-for-user-since", func(t *testing.T) {
|
||||
topReactions, _, err := client.GetTopReactionsForUserSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
require.NoError(t, err)
|
||||
reactions := topReactions.Items
|
||||
|
||||
for i, reaction := range reactions {
|
||||
assert.Equal(t, expectedTopReactions[i].EmojiName, reaction.EmojiName)
|
||||
assert.Equal(t, expectedTopReactions[i].Count, reaction.Count)
|
||||
}
|
||||
|
||||
topReactions, _, err = client.GetTopReactionsForUserSince(teamId, model.TimeRangeToday, 1, 5)
|
||||
require.NoError(t, err)
|
||||
reactions = topReactions.Items
|
||||
assert.Equal(t, "100", reactions[0].EmojiName)
|
||||
assert.Equal(t, int64(1), reactions[0].Count)
|
||||
})
|
||||
|
||||
t.Run("get-top-reactions-for-user-since invalid team id", func(t *testing.T) {
|
||||
_, resp, err := client.GetTopReactionsForUserSince("invalid_team_id", model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
_, resp, err = client.GetTopReactionsForUserSince(model.NewId(), model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("get-top-reactions-for-user-since not a member of team", func(t *testing.T) {
|
||||
th.UnlinkUserFromTeam(th.BasicUser, th.BasicTeam)
|
||||
_, resp, err := client.GetTopReactionsForUserSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
// Top Channels
|
||||
|
||||
func TestGetTopChannelsForTeamSince(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.ConfigStore.SetReadOnlyFF(false)
|
||||
defer th.ConfigStore.SetReadOnlyFF(true)
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = true })
|
||||
|
||||
client := th.Client
|
||||
userId := th.BasicUser.Id
|
||||
|
||||
channel4 := th.CreatePublicChannel()
|
||||
channel5 := th.CreatePrivateChannel()
|
||||
channel6 := th.CreatePrivateChannel()
|
||||
th.App.AddUserToChannel(th.BasicUser, channel4, false)
|
||||
th.App.AddUserToChannel(th.BasicUser, channel5, false)
|
||||
th.App.AddUserToChannel(th.BasicUser, channel6, false)
|
||||
|
||||
channelIDs := [6]string{th.BasicChannel.Id, th.BasicChannel2.Id, th.BasicPrivateChannel.Id, channel4.Id, channel5.Id, channel6.Id}
|
||||
|
||||
i := len(channelIDs)
|
||||
for _, channelID := range channelIDs {
|
||||
for j := i; j > 0; j-- {
|
||||
_, _, err := client.CreatePost(&model.Post{UserId: userId, ChannelId: channelID, Message: "zz" + model.NewId() + "a"})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
i--
|
||||
}
|
||||
|
||||
teamId := th.BasicChannel.TeamId
|
||||
|
||||
expectedTopChannels := []struct {
|
||||
ID string
|
||||
MessageCount int64
|
||||
}{
|
||||
{ID: th.BasicChannel.Id, MessageCount: 7},
|
||||
{ID: th.BasicChannel2.Id, MessageCount: 5},
|
||||
{ID: th.BasicPrivateChannel.Id, MessageCount: 4},
|
||||
{ID: channel4.Id, MessageCount: 3},
|
||||
{ID: channel5.Id, MessageCount: 2},
|
||||
}
|
||||
|
||||
t.Run("get-top-channels-for-team-since", func(t *testing.T) {
|
||||
topChannels, _, err := client.GetTopChannelsForTeamSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
require.NoError(t, err)
|
||||
|
||||
for i, channel := range topChannels.Items {
|
||||
assert.Equal(t, expectedTopChannels[i].ID, channel.ID)
|
||||
assert.Equal(t, expectedTopChannels[i].MessageCount, channel.MessageCount)
|
||||
}
|
||||
|
||||
topChannels, _, err = client.GetTopChannelsForTeamSince(teamId, model.TimeRangeToday, 1, 5)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, channel6.Id, topChannels.Items[0].ID)
|
||||
assert.Equal(t, int64(1), topChannels.Items[0].MessageCount)
|
||||
})
|
||||
|
||||
t.Run("get-top-channels-for-user-since exclude channels user is not member of", func(t *testing.T) {
|
||||
excludedChannel := th.CreatePrivateChannel()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
_, _, err := client.CreatePost(&model.Post{UserId: userId, ChannelId: excludedChannel.Id, Message: "zz" + model.NewId() + "a"})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
th.RemoveUserFromChannel(th.BasicUser, excludedChannel)
|
||||
|
||||
topChannels, _, err := client.GetTopChannelsForTeamSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
require.NoError(t, err)
|
||||
|
||||
for i, channel := range topChannels.Items {
|
||||
assert.Equal(t, expectedTopChannels[i].ID, channel.ID)
|
||||
assert.Equal(t, expectedTopChannels[i].MessageCount, channel.MessageCount)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("get-top-channels-for-team-since invalid team id", func(t *testing.T) {
|
||||
_, resp, err := client.GetTopChannelsForTeamSince("12345", model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
_, resp, err = client.GetTopChannelsForTeamSince(model.NewId(), model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("get-top-channels-for-team-since not a member of team", func(t *testing.T) {
|
||||
th.UnlinkUserFromTeam(th.BasicUser, th.BasicTeam)
|
||||
_, resp, err := client.GetTopChannelsForTeamSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetTopChannelsForUserSince(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.ConfigStore.SetReadOnlyFF(false)
|
||||
defer th.ConfigStore.SetReadOnlyFF(true)
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = true })
|
||||
|
||||
client := th.Client
|
||||
userId := th.BasicUser.Id
|
||||
|
||||
channel4 := th.CreatePublicChannel()
|
||||
channel5 := th.CreatePrivateChannel()
|
||||
channel6 := th.CreatePrivateChannel()
|
||||
th.App.AddUserToChannel(th.BasicUser, channel4, false)
|
||||
th.App.AddUserToChannel(th.BasicUser, channel5, false)
|
||||
th.App.AddUserToChannel(th.BasicUser, channel6, false)
|
||||
|
||||
channelIDs := [6]string{th.BasicChannel.Id, th.BasicChannel2.Id, th.BasicPrivateChannel.Id, channel4.Id, channel5.Id, channel6.Id}
|
||||
|
||||
i := len(channelIDs)
|
||||
for _, channelID := range channelIDs {
|
||||
for j := i; j > 0; j-- {
|
||||
_, _, err := client.CreatePost(&model.Post{UserId: userId, ChannelId: channelID, Message: "zz" + model.NewId() + "a"})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
i--
|
||||
}
|
||||
|
||||
teamId := th.BasicChannel.TeamId
|
||||
|
||||
expectedTopChannels := []struct {
|
||||
ID string
|
||||
MessageCount int64
|
||||
}{
|
||||
{ID: th.BasicChannel.Id, MessageCount: 6},
|
||||
{ID: th.BasicChannel2.Id, MessageCount: 5},
|
||||
{ID: th.BasicPrivateChannel.Id, MessageCount: 4},
|
||||
{ID: channel4.Id, MessageCount: 3},
|
||||
{ID: channel5.Id, MessageCount: 2},
|
||||
}
|
||||
|
||||
t.Run("get-top-channels-for-user-since", func(t *testing.T) {
|
||||
topChannels, _, err := client.GetTopChannelsForUserSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
require.NoError(t, err)
|
||||
|
||||
for i, channel := range topChannels.Items {
|
||||
assert.Equal(t, expectedTopChannels[i].ID, channel.ID)
|
||||
assert.Equal(t, expectedTopChannels[i].MessageCount, channel.MessageCount)
|
||||
}
|
||||
|
||||
topChannels, _, err = client.GetTopChannelsForUserSince("", model.TimeRangeToday, 1, 5)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, channel6.Id, topChannels.Items[0].ID)
|
||||
assert.Equal(t, int64(1), topChannels.Items[0].MessageCount)
|
||||
})
|
||||
|
||||
t.Run("get-top-channels-for-user-since invalid team id", func(t *testing.T) {
|
||||
_, resp, err := client.GetTopChannelsForUserSince("12345", model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
_, resp, err = client.GetTopChannelsForUserSince(model.NewId(), model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("get-top-channels-for-user-since not a member of team", func(t *testing.T) {
|
||||
th.UnlinkUserFromTeam(th.BasicUser, th.BasicTeam)
|
||||
_, resp, err := client.GetTopChannelsForUserSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
}
|
||||
@@ -16,9 +16,6 @@ func (api *API) InitReaction() {
|
||||
api.BaseRoutes.Post.Handle("/reactions", api.APISessionRequired(getReactions)).Methods("GET")
|
||||
api.BaseRoutes.ReactionByNameForPostForUser.Handle("", api.APISessionRequired(deleteReaction)).Methods("DELETE")
|
||||
api.BaseRoutes.Posts.Handle("/ids/reactions", api.APISessionRequired(getBulkReactions)).Methods("POST")
|
||||
|
||||
api.BaseRoutes.Team.Handle("/top/reactions", api.APISessionRequired(getTopReactionsForTeamSince)).Methods("GET")
|
||||
api.BaseRoutes.Users.Handle("/me/top/reactions", api.APISessionRequired(getTopReactionsForUserSince)).Methods("GET")
|
||||
}
|
||||
|
||||
func saveReaction(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -141,85 +138,3 @@ func getBulkReactions(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
func getTopReactionsForTeamSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireTeamId().RequireTimeRange()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
team, err := c.App.GetTeam(c.Params.TeamId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
if (!team.AllowOpenInvite || team.Type != model.TeamOpen) && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PermissionViewTeam) {
|
||||
c.SetPermissionError(model.PermissionViewTeam)
|
||||
return
|
||||
}
|
||||
|
||||
topReactionList, err := c.App.GetTopReactionsForTeamSince(c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{
|
||||
StartUnixMilli: c.Params.TimeRange,
|
||||
Page: c.Params.Page,
|
||||
PerPage: c.Params.PerPage,
|
||||
})
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
js, jsonErr := json.Marshal(topReactionList)
|
||||
if jsonErr != nil {
|
||||
c.Err = model.NewAppError("getTopReactionsForTeamSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
func getTopReactionsForUserSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireTimeRange()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.Params.TeamId = r.URL.Query().Get("team_id")
|
||||
|
||||
// TeamId is an optional parameter
|
||||
if c.Params.TeamId != "" {
|
||||
if !model.IsValidId(c.Params.TeamId) {
|
||||
c.SetInvalidURLParam("team_id")
|
||||
return
|
||||
}
|
||||
|
||||
team, teamErr := c.App.GetTeam(c.Params.TeamId)
|
||||
if teamErr != nil {
|
||||
c.Err = teamErr
|
||||
return
|
||||
}
|
||||
|
||||
if (!team.AllowOpenInvite || team.Type != model.TeamOpen) && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PermissionViewTeam) {
|
||||
c.SetPermissionError(model.PermissionViewTeam)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
topReactionList, err := c.App.GetTopReactionsForUserSince(c.AppContext.Session().UserId, c.Params.TeamId, &model.InsightsOpts{
|
||||
StartUnixMilli: c.Params.TimeRange,
|
||||
Page: c.Params.Page,
|
||||
PerPage: c.Params.PerPage,
|
||||
})
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
js, jsonErr := json.Marshal(topReactionList)
|
||||
if jsonErr != nil {
|
||||
c.Err = model.NewAppError("getTopReactionsForUserSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ package api4
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -585,367 +584,3 @@ func TestGetBulkReactions(t *testing.T) {
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetTopReactionsForTeamSince(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.ConfigStore.SetReadOnlyFF(false)
|
||||
defer th.ConfigStore.SetReadOnlyFF(true)
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = true })
|
||||
|
||||
client := th.Client
|
||||
|
||||
userId := th.BasicUser.Id
|
||||
user2Id := th.BasicUser2.Id
|
||||
|
||||
post1 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post2 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post3 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post4 := &model.Post{UserId: user2Id, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post5 := &model.Post{UserId: user2Id, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
|
||||
post1, _, _ = client.CreatePost(post1)
|
||||
post2, _, _ = client.CreatePost(post2)
|
||||
post3, _, _ = client.CreatePost(post3)
|
||||
post4, _, _ = client.CreatePost(post4)
|
||||
post5, _, _ = client.CreatePost(post5)
|
||||
|
||||
userReactions := []*model.Reaction{
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "sad",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "sad",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "sad",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "joy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: user2Id,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "100",
|
||||
CreateAt: model.GetMillisForTime(time.Now().Add(time.Hour * time.Duration(-25))),
|
||||
},
|
||||
}
|
||||
|
||||
for _, userReaction := range userReactions {
|
||||
_, err := th.App.Srv().Store.Reaction().Save(userReaction)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
teamId := th.BasicChannel.TeamId
|
||||
|
||||
var expectedTopReactions [5]*model.TopReaction
|
||||
expectedTopReactions[0] = &model.TopReaction{EmojiName: "100", Count: int64(6)}
|
||||
expectedTopReactions[1] = &model.TopReaction{EmojiName: "joy", Count: int64(5)}
|
||||
expectedTopReactions[2] = &model.TopReaction{EmojiName: "smile", Count: int64(4)}
|
||||
expectedTopReactions[3] = &model.TopReaction{EmojiName: "sad", Count: int64(3)}
|
||||
expectedTopReactions[4] = &model.TopReaction{EmojiName: "happy", Count: int64(2)}
|
||||
|
||||
t.Run("get-top-reactions-for-team-since", func(t *testing.T) {
|
||||
topReactions, _, err := client.GetTopReactionsForTeamSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
require.NoError(t, err)
|
||||
reactions := topReactions.Items
|
||||
|
||||
for i, reaction := range reactions {
|
||||
assert.Equal(t, expectedTopReactions[i].EmojiName, reaction.EmojiName)
|
||||
assert.Equal(t, expectedTopReactions[i].Count, reaction.Count)
|
||||
}
|
||||
|
||||
topReactions, _, err = client.GetTopReactionsForTeamSince(teamId, model.TimeRangeToday, 1, 5)
|
||||
require.NoError(t, err)
|
||||
reactions = topReactions.Items
|
||||
|
||||
assert.Equal(t, "+1", reactions[0].EmojiName)
|
||||
assert.Equal(t, int64(1), reactions[0].Count)
|
||||
})
|
||||
|
||||
t.Run("get-top-reactions-for-team-since invalid team id", func(t *testing.T) {
|
||||
_, resp, err := client.GetTopReactionsForTeamSince("12345", model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
_, resp, err = client.GetTopReactionsForTeamSince(model.NewId(), model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetTopReactionsForUserSince(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.ConfigStore.SetReadOnlyFF(false)
|
||||
defer th.ConfigStore.SetReadOnlyFF(true)
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = true })
|
||||
|
||||
client := th.Client
|
||||
|
||||
userId := th.BasicUser.Id
|
||||
|
||||
post1 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post2 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post3 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post4 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post5 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
post6 := &model.Post{UserId: userId, ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a"}
|
||||
|
||||
post1, _, _ = client.CreatePost(post1)
|
||||
post2, _, _ = client.CreatePost(post2)
|
||||
post3, _, _ = client.CreatePost(post3)
|
||||
post4, _, _ = client.CreatePost(post4)
|
||||
post5, _, _ = client.CreatePost(post5)
|
||||
post6, _, _ = client.CreatePost(post6)
|
||||
|
||||
userReactions := []*model.Reaction{
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post6.Id,
|
||||
EmojiName: "happy",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post5.Id,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post4.Id,
|
||||
EmojiName: "+1",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "heart",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "heart",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post3.Id,
|
||||
EmojiName: "heart",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "blush",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post2.Id,
|
||||
EmojiName: "blush",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "100",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
PostId: post1.Id,
|
||||
EmojiName: "100",
|
||||
CreateAt: model.GetMillisForTime(time.Now().Add(time.Hour * time.Duration(-25))),
|
||||
},
|
||||
}
|
||||
|
||||
for _, userReaction := range userReactions {
|
||||
_, err := th.App.Srv().Store.Reaction().Save(userReaction)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
teamId := th.BasicChannel.TeamId
|
||||
|
||||
var expectedTopReactions [5]*model.TopReaction
|
||||
expectedTopReactions[0] = &model.TopReaction{EmojiName: "happy", Count: int64(6)}
|
||||
expectedTopReactions[1] = &model.TopReaction{EmojiName: "smile", Count: int64(5)}
|
||||
expectedTopReactions[2] = &model.TopReaction{EmojiName: "+1", Count: int64(4)}
|
||||
expectedTopReactions[3] = &model.TopReaction{EmojiName: "heart", Count: int64(3)}
|
||||
expectedTopReactions[4] = &model.TopReaction{EmojiName: "blush", Count: int64(2)}
|
||||
|
||||
t.Run("get-top-reactions-for-user-since", func(t *testing.T) {
|
||||
topReactions, _, err := client.GetTopReactionsForUserSince(teamId, model.TimeRangeToday, 0, 5)
|
||||
require.NoError(t, err)
|
||||
reactions := topReactions.Items
|
||||
|
||||
for i, reaction := range reactions {
|
||||
assert.Equal(t, expectedTopReactions[i].EmojiName, reaction.EmojiName)
|
||||
assert.Equal(t, expectedTopReactions[i].Count, reaction.Count)
|
||||
}
|
||||
|
||||
topReactions, _, err = client.GetTopReactionsForUserSince(teamId, model.TimeRangeToday, 1, 5)
|
||||
require.NoError(t, err)
|
||||
reactions = topReactions.Items
|
||||
assert.Equal(t, "100", reactions[0].EmojiName)
|
||||
assert.Equal(t, int64(1), reactions[0].Count)
|
||||
})
|
||||
|
||||
t.Run("get-top-reactions-for-user-since invalid team id", func(t *testing.T) {
|
||||
_, resp, err := client.GetTopReactionsForUserSince("invalid_team_id", model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
_, resp, err = client.GetTopReactionsForUserSince(model.NewId(), model.TimeRangeToday, 0, 5)
|
||||
assert.Error(t, err)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user