From 302dae5bb982aad14324a4df61a018557f3dd24e Mon Sep 17 00:00:00 2001 From: Stephen Kiers Date: Fri, 9 Mar 2018 05:48:30 -0700 Subject: MM-9274- Sort Users in Channel by status (#8181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * sort by lastActivity * added status ordering to Users * sort offline before dnd * remove data not needed * added seperate call for when order=‘status’ is on GetUser request * remove PrintLn * styling fix * remove mistake * mistake 2 * better comment * explicit if statemnt * writing tests * removed manually added mocks * generated mock * ICU-668 Added unit tests * style fix * sort by lastActivity * added status ordering to Users * sort offline before dnd * remove data not needed * added seperate call for when order=‘status’ is on GetUser request * remove PrintLn * styling fix * remove mistake * mistake 2 * better comment * explicit if statemnt * writing tests * removed manually added mocks * generated mock * ICU-668 Added unit tests * style fix * reverse dnd and offline * Fixed app.SaveStatusAndBroadcast * Fixed incorrect merge * Fixing incorrect merge again --- api4/apitestlib.go | 16 ++++++ api4/user.go | 14 ++++-- api4/user_test.go | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 3 deletions(-) (limited to 'api4') diff --git a/api4/apitestlib.go b/api4/apitestlib.go index 2bb80ddfb..6edd37812 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -467,6 +467,22 @@ func (me *TestHelper) LinkUserToTeam(user *model.User, team *model.Team) { utils.EnableDebugLogForTest() } +func (me *TestHelper) AddUserToChannel(user *model.User, channel *model.Channel) *model.ChannelMember { + utils.DisableDebugLogForTest() + + member, err := me.App.AddUserToChannel(user, channel) + if err != nil { + l4g.Error(err.Error()) + l4g.Close() + time.Sleep(time.Second) + panic(err) + } + + utils.EnableDebugLogForTest() + + return member +} + func (me *TestHelper) GenerateTestEmail() string { if me.App.Config().EmailSettings.SMTPServer != "dockerhost" && os.Getenv("CI_INBUCKET_PORT") == "" { return strings.ToLower("success+" + model.NewId() + "@simulator.amazonses.com") diff --git a/api4/user.go b/api4/user.go index f82a6e3d5..8f8f08c75 100644 --- a/api4/user.go +++ b/api4/user.go @@ -290,16 +290,21 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - if sort != "" && sort != "last_activity_at" && sort != "create_at" { + if sort != "" && sort != "last_activity_at" && sort != "create_at" && sort != "status" { c.SetInvalidUrlParam("sort") return } // Currently only supports sorting on a team + // or sort="status" on inChannelId if (sort == "last_activity_at" || sort == "create_at") && (inTeamId == "" || notInTeamId != "" || inChannelId != "" || notInChannelId != "" || withoutTeam != "") { c.SetInvalidUrlParam("sort") return } + if sort == "status" && inChannelId == "" { + c.SetInvalidUrlParam("sort") + return + } var profiles []*model.User var err *model.AppError @@ -355,8 +360,11 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { c.SetPermissionError(model.PERMISSION_READ_CHANNEL) return } - - profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + if sort == "status" { + profiles, err = c.App.GetUsersInChannelPageByStatus(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + } else { + profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + } } else { // No permission check required diff --git a/api4/user_test.go b/api4/user_test.go index 4613a8ea9..f04cd6ab2 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -2650,3 +2650,146 @@ func TestUserAccessTokenDisableConfig(t *testing.T) { _, resp = Client.GetMe("") CheckNoError(t, resp) } + +func TestGetUsersByStatus(t *testing.T) { + th := Setup() + defer th.TearDown() + + team, err := th.App.CreateTeam(&model.Team{ + DisplayName: "dn_" + model.NewId(), + Name: GenerateTestTeamName(), + Email: th.GenerateTestEmail(), + Type: model.TEAM_OPEN, + }) + if err != nil { + t.Fatalf("failed to create team: %v", err) + } + + channel, err := th.App.CreateChannel(&model.Channel{ + DisplayName: "dn_" + model.NewId(), + Name: "name_" + model.NewId(), + Type: model.CHANNEL_OPEN, + TeamId: team.Id, + CreatorId: model.NewId(), + }, false) + if err != nil { + t.Fatalf("failed to create channel: %v", err) + } + + createUserWithStatus := func(username string, status string) *model.User { + id := model.NewId() + + user, err := th.App.CreateUser(&model.User{ + Email: "success+" + id + "@simulator.amazonses.com", + Username: "un_" + username + "_" + id, + Nickname: "nn_" + id, + Password: "Password1", + }) + if err != nil { + t.Fatalf("failed to create user: %v", err) + } + + th.LinkUserToTeam(user, team) + th.AddUserToChannel(user, channel) + + th.App.SaveAndBroadcastStatus(&model.Status{ + UserId: user.Id, + Status: status, + Manual: true, + }) + + return user + } + + // Creating these out of order in case that affects results + offlineUser1 := createUserWithStatus("offline1", model.STATUS_OFFLINE) + offlineUser2 := createUserWithStatus("offline2", model.STATUS_OFFLINE) + awayUser1 := createUserWithStatus("away1", model.STATUS_AWAY) + awayUser2 := createUserWithStatus("away2", model.STATUS_AWAY) + onlineUser1 := createUserWithStatus("online1", model.STATUS_ONLINE) + onlineUser2 := createUserWithStatus("online2", model.STATUS_ONLINE) + dndUser1 := createUserWithStatus("dnd1", model.STATUS_DND) + dndUser2 := createUserWithStatus("dnd2", model.STATUS_DND) + + client := th.CreateClient() + if _, resp := client.Login(onlineUser2.Username, "Password1"); resp.Error != nil { + t.Fatal(resp.Error) + } + + t.Run("sorting by status then alphabetical", func(t *testing.T) { + usersByStatus, resp := client.GetUsersInChannelByStatus(channel.Id, 0, 8, "") + if resp.Error != nil { + t.Fatal(resp.Error) + } + + expectedUsersByStatus := []*model.User{ + onlineUser1, + onlineUser2, + awayUser1, + awayUser2, + dndUser1, + dndUser2, + offlineUser1, + offlineUser2, + } + + if len(usersByStatus) != len(expectedUsersByStatus) { + t.Fatalf("received only %v users, expected %v", len(usersByStatus), len(expectedUsersByStatus)) + } + + for i := range usersByStatus { + if usersByStatus[i].Id != expectedUsersByStatus[i].Id { + t.Fatalf("received user %v at index %v, expected %v", usersByStatus[i].Username, i, expectedUsersByStatus[i].Username) + } + } + }) + + t.Run("paging", func(t *testing.T) { + usersByStatus, resp := client.GetUsersInChannelByStatus(channel.Id, 0, 3, "") + if resp.Error != nil { + t.Fatal(resp.Error) + } + + if len(usersByStatus) != 3 { + t.Fatal("received too many users") + } + + if usersByStatus[0].Id != onlineUser1.Id && usersByStatus[1].Id != onlineUser2.Id { + t.Fatal("expected to receive online users first") + } + + if usersByStatus[2].Id != awayUser1.Id { + t.Fatal("expected to receive away users second") + } + + usersByStatus, resp = client.GetUsersInChannelByStatus(channel.Id, 1, 3, "") + if resp.Error != nil { + t.Fatal(resp.Error) + } + + if usersByStatus[0].Id != awayUser2.Id { + t.Fatal("expected to receive away users second") + } + + if usersByStatus[1].Id != dndUser1.Id && usersByStatus[2].Id != dndUser2.Id { + t.Fatal("expected to receive dnd users third") + } + + usersByStatus, resp = client.GetUsersInChannelByStatus(channel.Id, 1, 4, "") + if resp.Error != nil { + t.Fatal(resp.Error) + } + + if len(usersByStatus) != 4 { + t.Fatal("received too many users") + } + + if usersByStatus[0].Id != dndUser1.Id && usersByStatus[1].Id != dndUser2.Id { + t.Fatal("expected to receive dnd users third") + } + + if usersByStatus[2].Id != offlineUser1.Id && usersByStatus[3].Id != offlineUser2.Id { + t.Fatal("expected to receive offline users last") + } + }) +} -- cgit v1.2.3-1-g7c22