Skip to content

Commit

Permalink
feat: get all teams (#1126)
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksandrMatsko authored Nov 20, 2024
1 parent e728cbd commit c7e4998
Show file tree
Hide file tree
Showing 15 changed files with 1,027 additions and 195 deletions.
13 changes: 13 additions & 0 deletions api/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package api

// SortOrder represents the sorting order for entities.
type SortOrder string

const (
// NoSortOrder means that entities may be unsorted.
NoSortOrder SortOrder = ""
// AscSortOrder means that entities should be ordered ascending (example: from 1 to 9).
AscSortOrder SortOrder = "asc"
// DescSortOrder means that entities should be ordered descending (example: from 9 to 1).
DescSortOrder SortOrder = "desc"
)
61 changes: 61 additions & 0 deletions api/controller/team.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package controller
import (
"errors"
"fmt"
"regexp"
"slices"
"strings"

"github.com/go-redis/redis/v8"
Expand Down Expand Up @@ -81,6 +83,65 @@ func GetTeam(dataBase moira.Database, teamID string) (dto.TeamModel, *api.ErrorR
return teamModel, nil
}

// SearchTeams is a controller function that returns all teams.
func SearchTeams(dataBase moira.Database, page, size int64, textRegexp *regexp.Regexp, sortOrder api.SortOrder) (dto.TeamsList, *api.ErrorResponse) {
teams, err := dataBase.GetAllTeams()
if err != nil {
return dto.TeamsList{}, api.ErrorInternalServer(fmt.Errorf("cannot get teams from database: %w", err))
}

filteredTeams := make([]moira.Team, 0)
for _, team := range teams {
if textRegexp.MatchString(team.Name) || textRegexp.MatchString(team.ID) {
filteredTeams = append(filteredTeams, team)
}
}

teams = filteredTeams

if sortOrder == api.AscSortOrder || sortOrder == api.DescSortOrder {
slices.SortFunc(teams, func(first, second moira.Team) int {
cmpRes := strings.Compare(strings.ToLower(first.Name), strings.ToLower(second.Name))
if sortOrder == api.DescSortOrder {
return cmpRes * -1
} else {
return cmpRes
}
})
}

total := int64(len(teams))

if page < 0 || (page > 0 && size < 0) {
return dto.TeamsList{
List: []dto.TeamModel{},
Page: page,
Size: size,
Total: total,
}, nil
}

if page >= 0 && size >= 0 {
shift := page * size
if shift < int64(len(teams)) {
teams = teams[shift:]
} else {
teams = []moira.Team{}
}

if size <= int64(len(teams)) {
teams = teams[:size]
}
}

model := dto.NewTeamsList(teams)
model.Page = page
model.Size = size
model.Total = total

return model, nil
}

// GetUserTeams is a controller function that returns a teams in which user is a member bu user ID.
func GetUserTeams(dataBase moira.Database, userID string) (dto.UserTeams, *api.ErrorResponse) {
teams, err := dataBase.GetUserTeams(userID)
Expand Down
265 changes: 265 additions & 0 deletions api/controller/team_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package controller
import (
"errors"
"fmt"
"regexp"
"testing"

"github.com/gofrs/uuid"
Expand Down Expand Up @@ -193,6 +194,270 @@ func TestGetTeam(t *testing.T) {
})
}

func TestSearchTeams(t *testing.T) {
Convey("SearchTeams", t, func() {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
dataBase := mock_moira_alert.NewMockDatabase(mockCtrl)

teams := []moira.Team{
{
ID: "first-team-id",
Name: "First team",
},
{
ID: "second-team-id",
Name: "Second team",
},
{
ID: "third-team-id",
Name: "Third team",
},
{
ID: "fourth-team-id",
Name: "Fourth team",
},
{
ID: "fifth-team-id",
Name: "Fifth team",
},
{
ID: "sixth-team-id",
Name: "Sixth team",
},
{
ID: "seventh-team-id",
Name: "Seventh team",
},
}

teamModels := dto.NewTeamsList(teams).List

anyText := regexp.MustCompile(".*")

var (
firstPage int64 = 0
allTeamsSize int64 = -1
)

Convey("with page < 0 returns empty list", func() {
dataBase.EXPECT().GetAllTeams().Return(teams, nil)
var (
page int64 = -1
total = int64(len(teamModels))
)

response, err := SearchTeams(dataBase, page, allTeamsSize, anyText, api.NoSortOrder)

So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: []dto.TeamModel{},
Page: page,
Size: allTeamsSize,
Total: total,
})
})

Convey("with page > 0 and size < 0, returns empty list", func() {
dataBase.EXPECT().GetAllTeams().Return(teams, nil)
var (
page int64 = 1
total = int64(len(teamModels))
)

response, err := SearchTeams(dataBase, page, allTeamsSize, anyText, api.NoSortOrder)

So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: []dto.TeamModel{},
Page: page,
Size: allTeamsSize,
Total: total,
})
})

Convey("when database returns error", func() {
dbErr := errors.New("test db err")

dataBase.EXPECT().GetAllTeams().Return(nil, dbErr)

response, err := SearchTeams(dataBase, firstPage, allTeamsSize, anyText, api.NoSortOrder)

So(err, ShouldResemble, api.ErrorInternalServer(fmt.Errorf("cannot get teams from database: %w", dbErr)))
So(response, ShouldResemble, dto.TeamsList{})
})

Convey("get all teams default options", func() {
dataBase.EXPECT().GetAllTeams().Return(teams, nil)
total := int64(len(teamModels))

response, err := SearchTeams(dataBase, firstPage, allTeamsSize, anyText, api.NoSortOrder)

So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: teamModels,
Page: firstPage,
Size: allTeamsSize,
Total: total,
})
})

Convey("with paginating", func() {
Convey("page and size in range of teams", func() {
var (
page0 int64 = 0
page1 int64 = 1
size int64 = 3
total = int64(len(teamModels))
)

dataBase.EXPECT().GetAllTeams().Return(teams, nil)

response, err := SearchTeams(dataBase, page0, size, anyText, api.NoSortOrder)
So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: teamModels[:size],
Page: page0,
Size: size,
Total: total,
})

dataBase.EXPECT().GetAllTeams().Return(teams, nil)

response, err = SearchTeams(dataBase, page1, size, anyText, api.NoSortOrder)
So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: teamModels[page1*size : page1*size+size],
Page: page1,
Size: size,
Total: total,
})
})

Convey("page ok, but size out of range", func() {
var (
page int64 = 1
size int64 = 5
total = int64(len(teamModels))
)

dataBase.EXPECT().GetAllTeams().Return(teams, nil)

response, err := SearchTeams(dataBase, page, size, anyText, api.NoSortOrder)
So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: teamModels[page*size:],
Page: page,
Size: size,
Total: total,
})
})

Convey("page and size out of range", func() {
var (
page int64 = 2
size int64 = 5
total = int64(len(teamModels))
)

dataBase.EXPECT().GetAllTeams().Return(teams, nil)

response, err := SearchTeams(dataBase, page, size, anyText, api.NoSortOrder)
So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: []dto.TeamModel{},
Page: page,
Size: size,
Total: total,
})
})
})

Convey("with text regexp", func() {
dataBase.EXPECT().GetAllTeams().Return(teams, nil)
textRegexp := regexp.MustCompile(".*th-team-id")
total := int64(len(teamModels)) - 3

response, err := SearchTeams(dataBase, firstPage, allTeamsSize, textRegexp, api.NoSortOrder)
So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: teamModels[3:],
Page: firstPage,
Size: allTeamsSize,
Total: total,
})
})

Convey("with sorting", func() {
Convey("when asc", func() {
dataBase.EXPECT().GetAllTeams().Return(teams, nil)
total := int64(len(teamModels))

response, err := SearchTeams(dataBase, firstPage, allTeamsSize, anyText, api.AscSortOrder)
So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: []dto.TeamModel{
teamModels[4],
teamModels[0],
teamModels[3],
teamModels[1],
teamModels[6],
teamModels[5],
teamModels[2],
},
Page: firstPage,
Size: allTeamsSize,
Total: total,
})
})

Convey("when desc", func() {
dataBase.EXPECT().GetAllTeams().Return(teams, nil)
total := int64(len(teamModels))

response, err := SearchTeams(dataBase, firstPage, allTeamsSize, anyText, api.DescSortOrder)
So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: []dto.TeamModel{
teamModels[2],
teamModels[5],
teamModels[6],
teamModels[1],
teamModels[3],
teamModels[0],
teamModels[4],
},
Page: firstPage,
Size: allTeamsSize,
Total: total,
})
})
})

Convey("with all options", func() {
dataBase.EXPECT().GetAllTeams().Return(teams, nil)
textRegexp := regexp.MustCompile(".*th-team-id")
var (
total = int64(len(teamModels)) - 3
page int64 = 1
size int64 = 2
)

response, err := SearchTeams(dataBase, page, size, textRegexp, api.DescSortOrder)
So(err, ShouldBeNil)
So(response, ShouldResemble, dto.TeamsList{
List: []dto.TeamModel{
teamModels[3],
teamModels[4],
},
Page: page,
Size: size,
Total: total,
})
})
})
}

func TestGetUserTeams(t *testing.T) {
Convey("GetUserTeams", t, func() {
mockCtrl := gomock.NewController(t)
Expand Down
Loading

0 comments on commit c7e4998

Please sign in to comment.