parent
cf3eb9053d
commit
4db3fee03f
|
@ -1834,6 +1834,8 @@ components:
|
|||
- odScoreTotal:DESC
|
||||
- points:ASC
|
||||
- points:DESC
|
||||
- mostPoints:ASC
|
||||
- mostPoints:DESC
|
||||
- deletedAt:ASC
|
||||
- deletedAt:DESC
|
||||
maxItems: 2
|
||||
|
|
|
@ -280,6 +280,9 @@ func (a listPlayersParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQue
|
|||
case domain.PlayerSortPointsASC,
|
||||
domain.PlayerSortPointsDESC:
|
||||
el.value = cursor.Points()
|
||||
case domain.PlayerSortMostPointsASC,
|
||||
domain.PlayerSortMostPointsDESC:
|
||||
el.value = cursor.MostPoints()
|
||||
case domain.PlayerSortDeletedAtASC,
|
||||
domain.PlayerSortDeletedAtDESC:
|
||||
el.value = cursor.DeletedAt()
|
||||
|
@ -326,6 +329,10 @@ func (a listPlayersParamsApplier) sortToColumnAndDirection(
|
|||
return "player.points", sortDirectionASC, nil
|
||||
case domain.PlayerSortPointsDESC:
|
||||
return "player.points", sortDirectionDESC, nil
|
||||
case domain.PlayerSortMostPointsASC:
|
||||
return "player.most_points", sortDirectionASC, nil
|
||||
case domain.PlayerSortMostPointsDESC:
|
||||
return "player.most_points", sortDirectionDESC, nil
|
||||
case domain.PlayerSortDeletedAtASC:
|
||||
return "COALESCE(player.deleted_at, '0001-01-01 00:00:00+00:00')", sortDirectionASC, nil
|
||||
case domain.PlayerSortDeletedAtDESC:
|
||||
|
|
|
@ -276,6 +276,56 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
|||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: sort=[mostPoints ASC, serverKey ASC, id ASC]",
|
||||
params: func(t *testing.T) domain.ListPlayersParams {
|
||||
t.Helper()
|
||||
params := domain.NewListPlayersParams()
|
||||
require.NoError(t, params.SetSort([]domain.PlayerSort{
|
||||
domain.PlayerSortMostPointsASC,
|
||||
domain.PlayerSortServerKeyASC,
|
||||
domain.PlayerSortIDASC,
|
||||
}))
|
||||
return params
|
||||
},
|
||||
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
|
||||
t.Helper()
|
||||
players := res.Players()
|
||||
assert.NotEmpty(t, players)
|
||||
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.MostPoints(), b.MostPoints()),
|
||||
cmp.Compare(a.ServerKey(), b.ServerKey()),
|
||||
cmp.Compare(a.ID(), b.ID()),
|
||||
)
|
||||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: sort=[mostPoints DESC, serverKey ASC, id ASC]",
|
||||
params: func(t *testing.T) domain.ListPlayersParams {
|
||||
t.Helper()
|
||||
params := domain.NewListPlayersParams()
|
||||
require.NoError(t, params.SetSort([]domain.PlayerSort{
|
||||
domain.PlayerSortMostPointsDESC,
|
||||
domain.PlayerSortServerKeyASC,
|
||||
domain.PlayerSortIDASC,
|
||||
}))
|
||||
return params
|
||||
},
|
||||
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
|
||||
t.Helper()
|
||||
players := res.Players()
|
||||
assert.NotEmpty(t, players)
|
||||
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.MostPoints(), b.MostPoints())*-1,
|
||||
cmp.Compare(a.ServerKey(), b.ServerKey()),
|
||||
cmp.Compare(a.ID(), b.ID()),
|
||||
)
|
||||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: sort=[deletedAt ASC, serverKey ASC, id ASC]",
|
||||
params: func(t *testing.T) domain.ListPlayersParams {
|
||||
|
|
1408
internal/adapter/testdata/fixture.yml
vendored
1408
internal/adapter/testdata/fixture.yml
vendored
File diff suppressed because it is too large
Load Diff
|
@ -17,6 +17,7 @@ type PlayerCursorConfig struct {
|
|||
ODScoreSup int
|
||||
ODScoreTotal int
|
||||
Points int
|
||||
MostPoints int
|
||||
DeletedAt time.Time
|
||||
}
|
||||
|
||||
|
@ -31,6 +32,7 @@ func NewPlayerCursor(tb TestingTB, opts ...func(cfg *PlayerCursorConfig)) domain
|
|||
ODScoreSup: gofakeit.IntRange(0, math.MaxInt),
|
||||
ODScoreTotal: gofakeit.IntRange(0, math.MaxInt),
|
||||
Points: gofakeit.IntRange(0, math.MaxInt),
|
||||
MostPoints: gofakeit.IntRange(0, math.MaxInt),
|
||||
DeletedAt: time.Time{},
|
||||
}
|
||||
|
||||
|
@ -46,6 +48,7 @@ func NewPlayerCursor(tb TestingTB, opts ...func(cfg *PlayerCursorConfig)) domain
|
|||
cfg.ODScoreSup,
|
||||
cfg.ODScoreTotal,
|
||||
cfg.Points,
|
||||
cfg.MostPoints,
|
||||
cfg.DeletedAt,
|
||||
)
|
||||
require.NoError(tb, err)
|
||||
|
|
|
@ -200,6 +200,7 @@ func (p Player) ToCursor() (PlayerCursor, error) {
|
|||
p.od.scoreSup,
|
||||
p.od.scoreTotal,
|
||||
p.points,
|
||||
p.mostPoints,
|
||||
p.deletedAt,
|
||||
)
|
||||
}
|
||||
|
@ -552,6 +553,8 @@ const (
|
|||
PlayerSortODScoreTotalDESC
|
||||
PlayerSortPointsASC
|
||||
PlayerSortPointsDESC
|
||||
PlayerSortMostPointsASC
|
||||
PlayerSortMostPointsDESC
|
||||
PlayerSortDeletedAtASC
|
||||
PlayerSortDeletedAtDESC
|
||||
)
|
||||
|
@ -592,6 +595,10 @@ func (s PlayerSort) String() string {
|
|||
return "points:ASC"
|
||||
case PlayerSortPointsDESC:
|
||||
return "points:DESC"
|
||||
case PlayerSortMostPointsASC:
|
||||
return "mostPoints:ASC"
|
||||
case PlayerSortMostPointsDESC:
|
||||
return "mostPoints:DESC"
|
||||
case PlayerSortDeletedAtASC:
|
||||
return "deletedAt:ASC"
|
||||
case PlayerSortDeletedAtDESC:
|
||||
|
@ -609,6 +616,7 @@ type PlayerCursor struct {
|
|||
odScoreSup int
|
||||
odScoreTotal int
|
||||
points int
|
||||
mostPoints int
|
||||
deletedAt time.Time
|
||||
}
|
||||
|
||||
|
@ -622,6 +630,7 @@ func NewPlayerCursor(
|
|||
odScoreSup int,
|
||||
odScoreTotal int,
|
||||
points int,
|
||||
mostPoints int,
|
||||
deletedAt time.Time,
|
||||
) (PlayerCursor, error) {
|
||||
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
|
||||
|
@ -680,6 +689,14 @@ func NewPlayerCursor(
|
|||
}
|
||||
}
|
||||
|
||||
if err := validateIntInRange(mostPoints, 0, math.MaxInt); err != nil {
|
||||
return PlayerCursor{}, ValidationError{
|
||||
Model: playerCursorModelName,
|
||||
Field: "mostPoints",
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
return PlayerCursor{
|
||||
id: id,
|
||||
serverKey: serverKey,
|
||||
|
@ -688,6 +705,7 @@ func NewPlayerCursor(
|
|||
odScoreSup: odScoreSup,
|
||||
odScoreTotal: odScoreTotal,
|
||||
points: points,
|
||||
mostPoints: mostPoints,
|
||||
deletedAt: deletedAt,
|
||||
}, nil
|
||||
}
|
||||
|
@ -734,6 +752,11 @@ func decodePlayerCursor(encoded string) (PlayerCursor, error) {
|
|||
return PlayerCursor{}, ErrInvalidCursor
|
||||
}
|
||||
|
||||
mostPoints, err := m.int("mostPoints")
|
||||
if err != nil {
|
||||
return PlayerCursor{}, ErrInvalidCursor
|
||||
}
|
||||
|
||||
deletedAt, err := m.time("deletedAt")
|
||||
if err != nil {
|
||||
return PlayerCursor{}, ErrInvalidCursor
|
||||
|
@ -747,6 +770,7 @@ func decodePlayerCursor(encoded string) (PlayerCursor, error) {
|
|||
odScoreSup,
|
||||
odScoreTotal,
|
||||
points,
|
||||
mostPoints,
|
||||
deletedAt,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -784,6 +808,10 @@ func (pc PlayerCursor) Points() int {
|
|||
return pc.points
|
||||
}
|
||||
|
||||
func (pc PlayerCursor) MostPoints() int {
|
||||
return pc.mostPoints
|
||||
}
|
||||
|
||||
func (pc PlayerCursor) DeletedAt() time.Time {
|
||||
return pc.deletedAt
|
||||
}
|
||||
|
@ -805,6 +833,7 @@ func (pc PlayerCursor) Encode() string {
|
|||
{"odScoreSup", pc.odScoreSup},
|
||||
{"odScoreTotal", pc.odScoreTotal},
|
||||
{"points", pc.points},
|
||||
{"mostPoints", pc.mostPoints},
|
||||
{"deletedAt", pc.deletedAt},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -303,6 +303,13 @@ func TestPlayerSort_IsInConflict(t *testing.T) {
|
|||
},
|
||||
expectedRes: true,
|
||||
},
|
||||
{
|
||||
name: "OK: mostPoints:ASC mostPoints:DESC",
|
||||
args: args{
|
||||
sorts: [2]domain.PlayerSort{domain.PlayerSortMostPointsASC, domain.PlayerSortMostPointsDESC},
|
||||
},
|
||||
expectedRes: true,
|
||||
},
|
||||
{
|
||||
name: "OK: deletedAt:ASC deletedAt:DESC",
|
||||
args: args{
|
||||
|
@ -334,6 +341,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
odScoreSup int
|
||||
odScoreTotal int
|
||||
points int
|
||||
mostPoints int
|
||||
deletedAt time.Time
|
||||
}
|
||||
|
||||
|
@ -354,6 +362,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
odScoreSup: validPlayerCursor.ODScoreSup(),
|
||||
odScoreTotal: validPlayerCursor.ODScoreTotal(),
|
||||
points: validPlayerCursor.Points(),
|
||||
mostPoints: validPlayerCursor.MostPoints(),
|
||||
deletedAt: validPlayerCursor.DeletedAt(),
|
||||
},
|
||||
expectedErr: nil,
|
||||
|
@ -368,6 +377,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
odScoreSup: validPlayerCursor.ODScoreSup(),
|
||||
odScoreTotal: validPlayerCursor.ODScoreTotal(),
|
||||
points: validPlayerCursor.Points(),
|
||||
mostPoints: validPlayerCursor.MostPoints(),
|
||||
deletedAt: validPlayerCursor.DeletedAt(),
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
|
@ -389,6 +399,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
odScoreSup: validPlayerCursor.ODScoreSup(),
|
||||
odScoreTotal: validPlayerCursor.ODScoreTotal(),
|
||||
points: validPlayerCursor.Points(),
|
||||
mostPoints: validPlayerCursor.MostPoints(),
|
||||
deletedAt: validPlayerCursor.DeletedAt(),
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
|
@ -410,6 +421,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
odScoreSup: validPlayerCursor.ODScoreSup(),
|
||||
odScoreTotal: validPlayerCursor.ODScoreTotal(),
|
||||
points: validPlayerCursor.Points(),
|
||||
mostPoints: validPlayerCursor.MostPoints(),
|
||||
deletedAt: validPlayerCursor.DeletedAt(),
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
|
@ -431,6 +443,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
odScoreSup: -1,
|
||||
odScoreTotal: validPlayerCursor.ODScoreTotal(),
|
||||
points: validPlayerCursor.Points(),
|
||||
mostPoints: validPlayerCursor.MostPoints(),
|
||||
deletedAt: validPlayerCursor.DeletedAt(),
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
|
@ -452,6 +465,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
odScoreSup: validPlayerCursor.ODScoreSup(),
|
||||
odScoreTotal: -1,
|
||||
points: validPlayerCursor.Points(),
|
||||
mostPoints: validPlayerCursor.MostPoints(),
|
||||
deletedAt: validPlayerCursor.DeletedAt(),
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
|
@ -473,6 +487,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
odScoreSup: validPlayerCursor.ODScoreSup(),
|
||||
odScoreTotal: validPlayerCursor.ODScoreTotal(),
|
||||
points: -1,
|
||||
mostPoints: validPlayerCursor.MostPoints(),
|
||||
deletedAt: validPlayerCursor.DeletedAt(),
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
|
@ -484,6 +499,28 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: mostPoints < 0",
|
||||
args: args{
|
||||
id: validPlayerCursor.ID(),
|
||||
serverKey: validPlayerCursor.ServerKey(),
|
||||
odScoreAtt: validPlayerCursor.ODScoreAtt(),
|
||||
odScoreDef: validPlayerCursor.ODScoreDef(),
|
||||
odScoreSup: validPlayerCursor.ODScoreSup(),
|
||||
odScoreTotal: validPlayerCursor.ODScoreTotal(),
|
||||
points: validPlayerCursor.Points(),
|
||||
mostPoints: -1,
|
||||
deletedAt: validPlayerCursor.DeletedAt(),
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
Model: "PlayerCursor",
|
||||
Field: "mostPoints",
|
||||
Err: domain.MinGreaterEqualError{
|
||||
Min: 0,
|
||||
Current: -1,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, serverKeyTest := range newServerKeyValidationTests() {
|
||||
|
@ -518,6 +555,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
tt.args.odScoreSup,
|
||||
tt.args.odScoreTotal,
|
||||
tt.args.points,
|
||||
tt.args.mostPoints,
|
||||
tt.args.deletedAt,
|
||||
)
|
||||
require.ErrorIs(t, err, tt.expectedErr)
|
||||
|
@ -531,6 +569,7 @@ func TestNewPlayerCursor(t *testing.T) {
|
|||
assert.Equal(t, tt.args.odScoreSup, pc.ODScoreSup())
|
||||
assert.Equal(t, tt.args.odScoreTotal, pc.ODScoreTotal())
|
||||
assert.Equal(t, tt.args.points, pc.Points())
|
||||
assert.Equal(t, tt.args.mostPoints, pc.MostPoints())
|
||||
assert.Equal(t, tt.args.deletedAt, pc.DeletedAt())
|
||||
assert.NotEmpty(t, pc.Encode())
|
||||
})
|
||||
|
|
|
@ -24,6 +24,8 @@ var apiPlayerSortAllowedValues = []domain.PlayerSort{
|
|||
domain.PlayerSortODScoreTotalDESC,
|
||||
domain.PlayerSortPointsASC,
|
||||
domain.PlayerSortPointsDESC,
|
||||
domain.PlayerSortMostPointsASC,
|
||||
domain.PlayerSortMostPointsDESC,
|
||||
domain.PlayerSortDeletedAtASC,
|
||||
domain.PlayerSortDeletedAtDESC,
|
||||
}
|
||||
|
|
|
@ -181,6 +181,33 @@ func TestListVersionPlayers(t *testing.T) {
|
|||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: sort=[mostPoints:DESC]",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
q.Set("sort", "mostPoints:DESC")
|
||||
req.URL.RawQuery = q.Encode()
|
||||
},
|
||||
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
||||
t.Helper()
|
||||
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// body
|
||||
body := decodeJSON[apimodel.ListPlayersWithServersResponse](t, resp.Body)
|
||||
assert.Zero(t, body.Cursor.Next)
|
||||
assert.NotZero(t, body.Cursor.Self)
|
||||
assert.NotZero(t, body.Data)
|
||||
assert.True(t, slices.IsSortedFunc(body.Data, func(a, b apimodel.PlayerWithServer) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.Server.Key, b.Server.Key),
|
||||
cmp.Compare(a.MostPoints, b.MostPoints)*-1,
|
||||
cmp.Compare(a.Id, b.Id),
|
||||
)
|
||||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: name",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
|
@ -1023,6 +1050,32 @@ func TestListServerPlayers(t *testing.T) {
|
|||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: sort=[mostPoints:DESC]",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
q.Set("sort", "mostPoints:DESC")
|
||||
req.URL.RawQuery = q.Encode()
|
||||
},
|
||||
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
||||
t.Helper()
|
||||
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// body
|
||||
body := decodeJSON[apimodel.ListPlayersWithServersResponse](t, resp.Body)
|
||||
assert.Zero(t, body.Cursor.Next)
|
||||
assert.NotZero(t, body.Cursor.Self)
|
||||
assert.NotZero(t, body.Data)
|
||||
assert.True(t, slices.IsSortedFunc(body.Data, func(a, b apimodel.PlayerWithServer) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.MostPoints, b.MostPoints)*-1,
|
||||
cmp.Compare(a.Id, b.Id),
|
||||
)
|
||||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: name",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
|
@ -1863,6 +1916,32 @@ func TestListTribeMembers(t *testing.T) {
|
|||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: sort=[mostPoints:DESC]",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
q.Set("sort", "mostPoints:DESC")
|
||||
req.URL.RawQuery = q.Encode()
|
||||
},
|
||||
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
||||
t.Helper()
|
||||
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// body
|
||||
body := decodeJSON[apimodel.ListPlayersWithServersResponse](t, resp.Body)
|
||||
assert.Zero(t, body.Cursor.Next)
|
||||
assert.NotZero(t, body.Cursor.Self)
|
||||
assert.NotZero(t, body.Data)
|
||||
assert.True(t, slices.IsSortedFunc(body.Data, func(a, b apimodel.PlayerWithServer) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.MostPoints, b.MostPoints)*-1,
|
||||
cmp.Compare(a.Id, b.Id),
|
||||
)
|
||||
}))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
|
|
1414
internal/port/testdata/api/fixture.yml
vendored
1414
internal/port/testdata/api/fixture.yml
vendored
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user