2024-02-26 07:15:11 +00:00
|
|
|
package port_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"cmp"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"slices"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
2024-02-27 07:09:24 +00:00
|
|
|
"time"
|
2024-02-26 07:15:11 +00:00
|
|
|
|
2024-04-06 04:32:29 +00:00
|
|
|
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
|
|
|
"gitea.dwysokinski.me/twhelp/core/internal/domain/domaintest"
|
|
|
|
"gitea.dwysokinski.me/twhelp/core/internal/port/internal/apimodel"
|
2024-03-01 07:15:06 +00:00
|
|
|
"github.com/brianvoe/gofakeit/v7"
|
2024-02-26 07:15:11 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2024-03-27 06:18:37 +00:00
|
|
|
const endpointListVersionPlayers = "/v2/versions/%s/players"
|
2024-02-26 07:15:11 +00:00
|
|
|
|
2024-03-27 06:18:37 +00:00
|
|
|
func TestListVersionPlayers(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
handler := newAPIHTTPHandler(t)
|
|
|
|
players := getAllPlayers(t, handler)
|
|
|
|
var version apimodel.Version
|
|
|
|
|
|
|
|
for _, p := range players {
|
|
|
|
if p.DeletedAt != nil {
|
|
|
|
version = p.Server.Version
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NotZero(t, version)
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
reqModifier func(t *testing.T, req *http.Request)
|
|
|
|
assertResp func(t *testing.T, req *http.Request, resp *http.Response)
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "OK: without params",
|
|
|
|
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.Id, b.Id),
|
|
|
|
)
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: limit=1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "1")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersWithServersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Cursor.Next)
|
|
|
|
assert.NotZero(t, body.Cursor.Self)
|
|
|
|
assert.NotZero(t, body.Data)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Len(t, body.Data, limit)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: limit=1 cursor",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "1")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
|
|
|
|
resp := doCustomRequest(handler, req.Clone(req.Context()))
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body := decodeJSON[apimodel.ListPlayersWithServersResponse](t, resp.Body)
|
|
|
|
require.NotEmpty(t, body.Cursor.Next)
|
|
|
|
|
|
|
|
q.Set("cursor", body.Cursor.Next)
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersWithServersResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, req.URL.Query().Get("cursor"), body.Cursor.Self)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Len(t, body.Data, limit)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: sort=[deletedAt:DESC,points:ASC]",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "deletedAt:DESC")
|
|
|
|
q.Add("sort", "points:ASC")
|
|
|
|
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 {
|
|
|
|
var aDeletedAt time.Time
|
|
|
|
if a.DeletedAt != nil {
|
|
|
|
aDeletedAt = *a.DeletedAt
|
|
|
|
}
|
|
|
|
|
|
|
|
var bDeletedAt time.Time
|
|
|
|
if b.DeletedAt != nil {
|
|
|
|
bDeletedAt = *b.DeletedAt
|
|
|
|
}
|
|
|
|
|
|
|
|
return cmp.Or(
|
|
|
|
cmp.Compare(a.Server.Key, b.Server.Key),
|
|
|
|
aDeletedAt.Compare(bDeletedAt)*-1,
|
|
|
|
cmp.Compare(a.Points, b.Points),
|
|
|
|
cmp.Compare(a.Id, b.Id),
|
|
|
|
)
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: sort=[odScoreAtt:DESC]",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("sort", "odScoreAtt: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.OpponentsDefeated.ScoreAtt, b.OpponentsDefeated.ScoreAtt)*-1,
|
|
|
|
cmp.Compare(a.Id, b.Id),
|
|
|
|
)
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: name",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
q := req.URL.Query()
|
|
|
|
|
|
|
|
for _, p := range players {
|
|
|
|
if p.Server.Version.Code == version.Code {
|
|
|
|
q.Add("name", p.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(q["name"]) == 2 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NotEmpty(t, q["name"])
|
|
|
|
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersWithServersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Cursor.Self)
|
|
|
|
assert.NotZero(t, body.Data)
|
|
|
|
names := req.URL.Query()["name"]
|
|
|
|
assert.Len(t, body.Data, len(names))
|
|
|
|
for _, p := range body.Data {
|
|
|
|
assert.True(t, slices.Contains(names, p.Name))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
2024-03-27 07:03:54 +00:00
|
|
|
{
|
|
|
|
name: "OK: id",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
q := req.URL.Query()
|
|
|
|
|
|
|
|
for _, p := range players {
|
|
|
|
if p.Server.Version.Code == version.Code {
|
|
|
|
q.Add("id", strconv.Itoa(p.Id))
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(q["id"]) == 2 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NotEmpty(t, q["id"])
|
|
|
|
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersWithServersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Cursor.Self)
|
|
|
|
assert.NotZero(t, body.Data)
|
|
|
|
ids := req.URL.Query()["id"]
|
|
|
|
assert.Len(t, body.Data, len(ids))
|
|
|
|
for _, p := range body.Data {
|
|
|
|
assert.True(t, slices.Contains(ids, strconv.Itoa(p.Id)))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
2024-03-27 06:18:37 +00:00
|
|
|
{
|
|
|
|
name: "OK: deleted=false",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("deleted", "false")
|
|
|
|
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.NotZero(t, body.Data)
|
|
|
|
for _, p := range body.Data {
|
|
|
|
assert.Nil(t, p.DeletedAt)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: deleted=true",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("deleted", "true")
|
|
|
|
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.NotZero(t, body.Data)
|
|
|
|
for _, p := range body.Data {
|
|
|
|
assert.NotNil(t, p.DeletedAt)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-03-27 07:03:54 +00:00
|
|
|
name: "ERR: limit is not an integer",
|
2024-03-27 06:18:37 +00:00
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "asd")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: "invalid-param-format",
|
|
|
|
Message: fmt.Sprintf(
|
|
|
|
"error binding string parameter: strconv.ParseInt: parsing \"%s\": invalid syntax",
|
|
|
|
req.URL.Query().Get("limit"),
|
|
|
|
),
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: limit < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "0")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MinGreaterEqualError{
|
|
|
|
Min: 1,
|
|
|
|
Current: limit,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: fmt.Sprintf("ERR: limit > %d", domain.PlayerListMaxLimit),
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", strconv.Itoa(domain.PlayerListMaxLimit+1))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MaxLessEqualError{
|
|
|
|
Max: domain.PlayerListMaxLimit,
|
|
|
|
Current: limit,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(cursor) < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", "")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 1000,
|
|
|
|
Current: len(req.URL.Query().Get("cursor")),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(cursor) > 1000",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", gofakeit.LetterN(1001))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 1000,
|
|
|
|
Current: len(req.URL.Query().Get("cursor")),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: invalid cursor",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", gofakeit.LetterN(100))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
var domainErr domain.Error
|
|
|
|
require.ErrorAs(t, domain.ErrInvalidCursor, &domainErr)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(sort) > 2",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:DESC")
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "points:ASC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 0,
|
|
|
|
Max: 2,
|
|
|
|
Current: len(req.URL.Query()["sort"]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: invalid sort",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "test:DESC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.UnsupportedSortStringError{
|
|
|
|
Sort: req.URL.Query()["sort"][1],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"sort": domainErr.Sort,
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort", "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: sort conflict",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "odScoreAtt:DESC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
q := req.URL.Query()
|
|
|
|
domainErr := domain.SortConflictError{
|
|
|
|
Sort: [2]string{q["sort"][0], q["sort"][1]},
|
|
|
|
}
|
|
|
|
paramSort := make([]any, len(domainErr.Sort))
|
|
|
|
for i, s := range domainErr.Sort {
|
|
|
|
paramSort[i] = s
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"sort": paramSort,
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
2024-03-27 07:03:54 +00:00
|
|
|
{
|
|
|
|
name: "ERR: id is not an integer",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("id", "asd")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: "invalid-param-format",
|
|
|
|
Message: fmt.Sprintf(
|
|
|
|
"error setting array element: error binding string parameter: strconv.ParseInt: parsing \"%s\": invalid syntax",
|
|
|
|
req.URL.Query().Get("id"),
|
|
|
|
),
|
|
|
|
Path: []string{"$query", "id"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: id < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("id", "0")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
id, err := strconv.Atoi(req.URL.Query().Get("id"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MinGreaterEqualError{
|
|
|
|
Min: 1,
|
|
|
|
Current: id,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "id", "0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
2024-03-27 06:18:37 +00:00
|
|
|
{
|
|
|
|
name: "ERR: len(name) > 100",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
for range 101 {
|
|
|
|
q.Add("name", gofakeit.LetterN(50))
|
|
|
|
}
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 0,
|
|
|
|
Max: 100,
|
|
|
|
Current: len(req.URL.Query()["name"]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "name"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(name[1]) < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("name", gofakeit.LetterN(50))
|
|
|
|
q.Add("name", "")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 150,
|
|
|
|
Current: len(req.URL.Query()["name"][1]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "name", "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(name[1]) > 150",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("name", gofakeit.LetterN(50))
|
|
|
|
q.Add("name", gofakeit.LetterN(151))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 150,
|
|
|
|
Current: len(req.URL.Query()["name"][1]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "name", "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: deleted is not a valid boolean",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("deleted", "asd")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: "invalid-param-format",
|
|
|
|
Message: fmt.Sprintf(
|
|
|
|
"error binding string parameter: strconv.ParseBool: parsing \"%s\": invalid syntax",
|
|
|
|
req.URL.Query().Get("deleted"),
|
|
|
|
),
|
|
|
|
Path: []string{"$query", "deleted"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: version not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
req.URL.Path = fmt.Sprintf(endpointListVersionPlayers, randInvalidVersionCode(t, handler))
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 5)
|
|
|
|
domainErr := domain.VersionNotFoundError{
|
|
|
|
VersionCode: pathSegments[3],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"code": domainErr.VersionCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
req := httptest.NewRequest(
|
|
|
|
http.MethodGet,
|
|
|
|
fmt.Sprintf(endpointListVersionPlayers, version.Code),
|
|
|
|
nil,
|
|
|
|
)
|
|
|
|
if tt.reqModifier != nil {
|
|
|
|
tt.reqModifier(t, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := doCustomRequest(handler, req)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
tt.assertResp(t, req, resp)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const endpointListServerPlayers = "/v2/versions/%s/servers/%s/players"
|
|
|
|
|
|
|
|
func TestListServerPlayers(t *testing.T) {
|
2024-02-26 07:15:11 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
handler := newAPIHTTPHandler(t)
|
|
|
|
players := getAllPlayers(t, handler)
|
|
|
|
var server serverWithVersion
|
|
|
|
|
|
|
|
for _, p := range players {
|
|
|
|
if p.DeletedAt != nil {
|
|
|
|
server = p.Server
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NotZero(t, server)
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
reqModifier func(t *testing.T, req *http.Request)
|
|
|
|
assertResp func(t *testing.T, req *http.Request, resp *http.Response)
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "OK: without params",
|
|
|
|
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](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.Player) int {
|
|
|
|
return cmp.Compare(a.Id, b.Id)
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: limit=1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "1")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Cursor.Next)
|
|
|
|
assert.NotZero(t, body.Cursor.Self)
|
|
|
|
assert.NotZero(t, body.Data)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Len(t, body.Data, limit)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: limit=1 cursor",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "1")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
|
|
|
|
resp := doCustomRequest(handler, req.Clone(req.Context()))
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
require.NotEmpty(t, body.Cursor.Next)
|
|
|
|
|
|
|
|
q.Set("cursor", body.Cursor.Next)
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, req.URL.Query().Get("cursor"), body.Cursor.Self)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Len(t, body.Data, limit)
|
|
|
|
},
|
|
|
|
},
|
2024-02-27 07:09:24 +00:00
|
|
|
{
|
|
|
|
name: "OK: sort=[deletedAt:DESC,points:ASC]",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "deletedAt:DESC")
|
|
|
|
q.Add("sort", "points:ASC")
|
|
|
|
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.ListPlayersResponse](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.Player) int {
|
|
|
|
var aDeletedAt time.Time
|
|
|
|
if a.DeletedAt != nil {
|
|
|
|
aDeletedAt = *a.DeletedAt
|
|
|
|
}
|
|
|
|
|
|
|
|
var bDeletedAt time.Time
|
|
|
|
if b.DeletedAt != nil {
|
|
|
|
bDeletedAt = *b.DeletedAt
|
|
|
|
}
|
|
|
|
|
|
|
|
return cmp.Or(
|
|
|
|
aDeletedAt.Compare(bDeletedAt)*-1,
|
|
|
|
cmp.Compare(a.Points, b.Points),
|
|
|
|
cmp.Compare(a.Id, b.Id),
|
|
|
|
)
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: sort=[odScoreAtt:DESC]",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("sort", "odScoreAtt: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.ListPlayersResponse](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.Player) int {
|
|
|
|
return cmp.Or(
|
|
|
|
cmp.Compare(a.OpponentsDefeated.ScoreAtt, b.OpponentsDefeated.ScoreAtt)*-1,
|
|
|
|
cmp.Compare(a.Id, b.Id),
|
|
|
|
)
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
},
|
2024-02-29 06:03:36 +00:00
|
|
|
{
|
2024-03-04 06:11:00 +00:00
|
|
|
name: "OK: name",
|
2024-02-29 06:03:36 +00:00
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
q := req.URL.Query()
|
|
|
|
|
|
|
|
for _, p := range players {
|
|
|
|
if p.Server.Key == server.Key {
|
|
|
|
q.Add("name", p.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(q["name"]) == 2 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NotEmpty(t, q["name"])
|
|
|
|
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Cursor.Self)
|
|
|
|
assert.NotZero(t, body.Data)
|
|
|
|
names := req.URL.Query()["name"]
|
|
|
|
assert.Len(t, body.Data, len(names))
|
|
|
|
for _, p := range body.Data {
|
|
|
|
assert.True(t, slices.Contains(names, p.Name))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
2024-03-27 07:03:54 +00:00
|
|
|
{
|
|
|
|
name: "OK: id",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
q := req.URL.Query()
|
|
|
|
|
|
|
|
for _, p := range players {
|
|
|
|
if p.Server.Key == server.Key {
|
|
|
|
q.Add("id", strconv.Itoa(p.Id))
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(q["id"]) == 2 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NotEmpty(t, q["id"])
|
|
|
|
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Cursor.Self)
|
|
|
|
assert.NotZero(t, body.Data)
|
|
|
|
ids := req.URL.Query()["id"]
|
|
|
|
assert.Len(t, body.Data, len(ids))
|
|
|
|
for _, p := range body.Data {
|
|
|
|
assert.True(t, slices.Contains(ids, strconv.Itoa(p.Id)))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
2024-02-26 07:15:11 +00:00
|
|
|
{
|
|
|
|
name: "OK: deleted=false",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("deleted", "false")
|
|
|
|
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.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Data)
|
2024-02-27 07:09:24 +00:00
|
|
|
for _, p := range body.Data {
|
|
|
|
assert.Nil(t, p.DeletedAt)
|
2024-02-26 07:15:11 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: deleted=true",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("deleted", "true")
|
|
|
|
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.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Data)
|
2024-02-27 07:09:24 +00:00
|
|
|
for _, p := range body.Data {
|
|
|
|
assert.NotNil(t, p.DeletedAt)
|
2024-02-26 07:15:11 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-03-27 07:03:54 +00:00
|
|
|
name: "ERR: limit is not an integer",
|
2024-02-26 07:15:11 +00:00
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "asd")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: "invalid-param-format",
|
|
|
|
Message: fmt.Sprintf(
|
|
|
|
"error binding string parameter: strconv.ParseInt: parsing \"%s\": invalid syntax",
|
|
|
|
req.URL.Query().Get("limit"),
|
|
|
|
),
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: limit < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "0")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MinGreaterEqualError{
|
|
|
|
Min: 1,
|
|
|
|
Current: limit,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-26 07:15:11 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-03-11 07:16:29 +00:00
|
|
|
name: fmt.Sprintf("ERR: limit > %d", domain.PlayerListMaxLimit),
|
2024-02-26 07:15:11 +00:00
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
2024-03-11 07:16:29 +00:00
|
|
|
q.Set("limit", strconv.Itoa(domain.PlayerListMaxLimit+1))
|
2024-02-26 07:15:11 +00:00
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MaxLessEqualError{
|
2024-03-11 07:16:29 +00:00
|
|
|
Max: domain.PlayerListMaxLimit,
|
2024-02-26 07:15:11 +00:00
|
|
|
Current: limit,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-26 07:15:11 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(cursor) < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", "")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 1000,
|
|
|
|
Current: len(req.URL.Query().Get("cursor")),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-26 07:15:11 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(cursor) > 1000",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", gofakeit.LetterN(1001))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 1000,
|
|
|
|
Current: len(req.URL.Query().Get("cursor")),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-26 07:15:11 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: invalid cursor",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", gofakeit.LetterN(100))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
var domainErr domain.Error
|
|
|
|
require.ErrorAs(t, domain.ErrInvalidCursor, &domainErr)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-26 07:15:11 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
2024-02-27 07:09:24 +00:00
|
|
|
{
|
|
|
|
name: "ERR: len(sort) > 2",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:DESC")
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "points:ASC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
2024-03-25 07:29:37 +00:00
|
|
|
Min: 0,
|
2024-02-27 07:09:24 +00:00
|
|
|
Max: 2,
|
|
|
|
Current: len(req.URL.Query()["sort"]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-27 07:09:24 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: invalid sort",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "test:DESC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.UnsupportedSortStringError{
|
|
|
|
Sort: req.URL.Query()["sort"][1],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-27 07:09:24 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"sort": domainErr.Sort,
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort", "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
2024-03-02 08:49:42 +00:00
|
|
|
{
|
|
|
|
name: "ERR: sort conflict",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "odScoreAtt:DESC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
q := req.URL.Query()
|
|
|
|
domainErr := domain.SortConflictError{
|
|
|
|
Sort: [2]string{q["sort"][0], q["sort"][1]},
|
|
|
|
}
|
|
|
|
paramSort := make([]any, len(domainErr.Sort))
|
|
|
|
for i, s := range domainErr.Sort {
|
|
|
|
paramSort[i] = s
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-02 08:49:42 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"sort": paramSort,
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
2024-03-27 07:03:54 +00:00
|
|
|
{
|
|
|
|
name: "ERR: id is not an integer",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("id", "asd")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: "invalid-param-format",
|
|
|
|
Message: fmt.Sprintf(
|
|
|
|
"error setting array element: error binding string parameter: strconv.ParseInt: parsing \"%s\": invalid syntax",
|
|
|
|
req.URL.Query().Get("id"),
|
|
|
|
),
|
|
|
|
Path: []string{"$query", "id"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: id < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("id", "0")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
id, err := strconv.Atoi(req.URL.Query().Get("id"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MinGreaterEqualError{
|
|
|
|
Min: 1,
|
|
|
|
Current: id,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "id", "0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
2024-02-29 06:03:36 +00:00
|
|
|
{
|
|
|
|
name: "ERR: len(name) > 100",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
for range 101 {
|
|
|
|
q.Add("name", gofakeit.LetterN(50))
|
|
|
|
}
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
2024-03-06 07:20:10 +00:00
|
|
|
Min: 0,
|
2024-02-29 06:03:36 +00:00
|
|
|
Max: 100,
|
|
|
|
Current: len(req.URL.Query()["name"]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-29 06:03:36 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "name"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(name[1]) < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("name", gofakeit.LetterN(50))
|
|
|
|
q.Add("name", "")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 150,
|
|
|
|
Current: len(req.URL.Query()["name"][1]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-29 06:03:36 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "name", "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(name[1]) > 150",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("name", gofakeit.LetterN(50))
|
|
|
|
q.Add("name", gofakeit.LetterN(151))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 150,
|
|
|
|
Current: len(req.URL.Query()["name"][1]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-29 06:03:36 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "name", "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
2024-02-26 07:15:11 +00:00
|
|
|
{
|
|
|
|
name: "ERR: deleted is not a valid boolean",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("deleted", "asd")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: "invalid-param-format",
|
|
|
|
Message: fmt.Sprintf(
|
|
|
|
"error binding string parameter: strconv.ParseBool: parsing \"%s\": invalid syntax",
|
|
|
|
req.URL.Query().Get("deleted"),
|
|
|
|
),
|
|
|
|
Path: []string{"$query", "deleted"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: version not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
2024-03-27 06:18:37 +00:00
|
|
|
req.URL.Path = fmt.Sprintf(endpointListServerPlayers, randInvalidVersionCode(t, handler), server.Key)
|
2024-02-26 07:15:11 +00:00
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 7)
|
|
|
|
domainErr := domain.VersionNotFoundError{
|
|
|
|
VersionCode: pathSegments[3],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-26 07:15:11 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"code": domainErr.VersionCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: server not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
2024-03-27 06:18:37 +00:00
|
|
|
req.URL.Path = fmt.Sprintf(endpointListServerPlayers, server.Version.Code, domaintest.RandServerKey())
|
2024-02-26 07:15:11 +00:00
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 7)
|
|
|
|
domainErr := domain.ServerNotFoundError{
|
|
|
|
Key: pathSegments[5],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-26 07:15:11 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"key": domainErr.Key,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
req := httptest.NewRequest(
|
|
|
|
http.MethodGet,
|
2024-03-27 06:18:37 +00:00
|
|
|
fmt.Sprintf(endpointListServerPlayers, server.Version.Code, server.Key),
|
2024-02-26 07:15:11 +00:00
|
|
|
nil,
|
|
|
|
)
|
|
|
|
if tt.reqModifier != nil {
|
|
|
|
tt.reqModifier(t, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := doCustomRequest(handler, req)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
tt.assertResp(t, req, resp)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-04 06:11:00 +00:00
|
|
|
const endpointListTribeMembers = "/v2/versions/%s/servers/%s/tribes/%d/members"
|
|
|
|
|
|
|
|
func TestListTribeMembers(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
handler := newAPIHTTPHandler(t)
|
|
|
|
players := getAllPlayers(t, handler)
|
|
|
|
var server serverWithVersion
|
|
|
|
var tribeID int
|
|
|
|
|
|
|
|
for _, p := range players {
|
|
|
|
if p.Tribe != nil && p.Tribe.Id > 0 {
|
|
|
|
server = p.Server
|
|
|
|
tribeID = p.Tribe.Id
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NotZero(t, server)
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
reqModifier func(t *testing.T, req *http.Request)
|
|
|
|
assertResp func(t *testing.T, req *http.Request, resp *http.Response)
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "OK: without params",
|
|
|
|
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.Zero(t, body.Cursor.Next)
|
|
|
|
assert.NotZero(t, body.Cursor.Self)
|
|
|
|
assert.NotZero(t, body.Data)
|
|
|
|
assert.False(t, slices.ContainsFunc(body.Data, func(player apimodel.Player) bool {
|
|
|
|
return player.Tribe == nil || player.Tribe.Id != tribeID
|
|
|
|
}))
|
|
|
|
assert.True(t, slices.IsSortedFunc(body.Data, func(a, b apimodel.Player) int {
|
|
|
|
return cmp.Compare(a.Id, b.Id)
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: limit=1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "1")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.NotZero(t, body.Cursor.Next)
|
|
|
|
assert.NotZero(t, body.Cursor.Self)
|
|
|
|
assert.NotZero(t, body.Data)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Len(t, body.Data, limit)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: limit=1 cursor",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "1")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
|
|
|
|
resp := doCustomRequest(handler, req.Clone(req.Context()))
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
require.NotEmpty(t, body.Cursor.Next)
|
|
|
|
|
|
|
|
q.Set("cursor", body.Cursor.Next)
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ListPlayersResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, req.URL.Query().Get("cursor"), body.Cursor.Self)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Len(t, body.Data, limit)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "OK: sort=[odScoreAtt:DESC]",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("sort", "odScoreAtt: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.ListPlayersResponse](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.Player) int {
|
|
|
|
return cmp.Or(
|
|
|
|
cmp.Compare(a.OpponentsDefeated.ScoreAtt, b.OpponentsDefeated.ScoreAtt)*-1,
|
|
|
|
cmp.Compare(a.Id, b.Id),
|
|
|
|
)
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-03-27 07:03:54 +00:00
|
|
|
name: "ERR: limit is not an integer",
|
2024-03-04 06:11:00 +00:00
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "asd")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
|
|
|
Code: "invalid-param-format",
|
|
|
|
Message: fmt.Sprintf(
|
|
|
|
"error binding string parameter: strconv.ParseInt: parsing \"%s\": invalid syntax",
|
|
|
|
req.URL.Query().Get("limit"),
|
|
|
|
),
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: limit < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("limit", "0")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MinGreaterEqualError{
|
|
|
|
Min: 1,
|
|
|
|
Current: limit,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-03-11 07:16:29 +00:00
|
|
|
name: fmt.Sprintf("ERR: limit > %d", domain.PlayerListMaxLimit),
|
2024-03-04 06:11:00 +00:00
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
2024-03-11 07:16:29 +00:00
|
|
|
q.Set("limit", strconv.Itoa(domain.PlayerListMaxLimit+1))
|
2024-03-04 06:11:00 +00:00
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
limit, err := strconv.Atoi(req.URL.Query().Get("limit"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MaxLessEqualError{
|
2024-03-11 07:16:29 +00:00
|
|
|
Max: domain.PlayerListMaxLimit,
|
2024-03-04 06:11:00 +00:00
|
|
|
Current: limit,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "limit"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(cursor) < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", "")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 1000,
|
|
|
|
Current: len(req.URL.Query().Get("cursor")),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(cursor) > 1000",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", gofakeit.LetterN(1001))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
|
|
|
Min: 1,
|
|
|
|
Max: 1000,
|
|
|
|
Current: len(req.URL.Query().Get("cursor")),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: invalid cursor",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Set("cursor", gofakeit.LetterN(100))
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
var domainErr domain.Error
|
|
|
|
require.ErrorAs(t, domain.ErrInvalidCursor, &domainErr)
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Path: []string{"$query", "cursor"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: len(sort) > 2",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:DESC")
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "points:ASC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.LenOutOfRangeError{
|
2024-03-25 07:29:37 +00:00
|
|
|
Min: 0,
|
2024-03-04 06:11:00 +00:00
|
|
|
Max: 2,
|
|
|
|
Current: len(req.URL.Query()["sort"]),
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
"max": float64(domainErr.Max),
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: invalid sort",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "test:DESC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
domainErr := domain.UnsupportedSortStringError{
|
|
|
|
Sort: req.URL.Query()["sort"][1],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"sort": domainErr.Sort,
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort", "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: sort conflict",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
q := req.URL.Query()
|
|
|
|
q.Add("sort", "odScoreAtt:ASC")
|
|
|
|
q.Add("sort", "odScoreAtt:DESC")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
q := req.URL.Query()
|
|
|
|
domainErr := domain.SortConflictError{
|
|
|
|
Sort: [2]string{q["sort"][0], q["sort"][1]},
|
|
|
|
}
|
|
|
|
paramSort := make([]any, len(domainErr.Sort))
|
|
|
|
for i, s := range domainErr.Sort {
|
|
|
|
paramSort[i] = s
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"sort": paramSort,
|
|
|
|
},
|
|
|
|
Path: []string{"$query", "sort"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: version not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
2024-03-15 06:38:38 +00:00
|
|
|
req.URL.Path = fmt.Sprintf(endpointListTribeMembers, randInvalidVersionCode(t, handler), server.Key, tribeID)
|
2024-03-04 06:11:00 +00:00
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 9)
|
|
|
|
domainErr := domain.VersionNotFoundError{
|
|
|
|
VersionCode: pathSegments[3],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"code": domainErr.VersionCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: server not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
req.URL.Path = fmt.Sprintf(endpointListTribeMembers, server.Version.Code, domaintest.RandServerKey(), tribeID)
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 9)
|
|
|
|
domainErr := domain.ServerNotFoundError{
|
|
|
|
Key: pathSegments[5],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"key": domainErr.Key,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: tribe not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
req.URL.Path = fmt.Sprintf(endpointListTribeMembers, server.Version.Code, server.Key, domaintest.RandID())
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 9)
|
|
|
|
id, err := strconv.Atoi(pathSegments[7])
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.TribeNotFoundError{
|
|
|
|
ID: id,
|
|
|
|
ServerKey: pathSegments[5],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-03-04 06:11:00 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"id": float64(domainErr.ID),
|
|
|
|
"serverKey": domainErr.ServerKey,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
req := httptest.NewRequest(
|
|
|
|
http.MethodGet,
|
|
|
|
fmt.Sprintf(endpointListTribeMembers, server.Version.Code, server.Key, tribeID),
|
|
|
|
nil,
|
|
|
|
)
|
|
|
|
if tt.reqModifier != nil {
|
|
|
|
tt.reqModifier(t, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := doCustomRequest(handler, req)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
tt.assertResp(t, req, resp)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-29 06:25:01 +00:00
|
|
|
const endpointGetPlayer = "/v2/versions/%s/servers/%s/players/%d"
|
|
|
|
|
|
|
|
func TestGetPlayer(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
handler := newAPIHTTPHandler(t)
|
2024-03-07 06:01:52 +00:00
|
|
|
player := randSliceElement(getAllPlayers(t, handler))
|
2024-02-29 06:25:01 +00:00
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
reqModifier func(t *testing.T, req *http.Request)
|
|
|
|
assertResp func(t *testing.T, req *http.Request, resp *http.Response)
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "OK",
|
|
|
|
assertResp: func(t *testing.T, _ *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.GetPlayerResponse](t, resp.Body)
|
|
|
|
assert.Equal(t, player.Player, body.Data)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: id < 1",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
req.URL.Path = fmt.Sprintf(
|
|
|
|
endpointGetPlayer,
|
|
|
|
player.Server.Version.Code,
|
|
|
|
player.Server.Key,
|
|
|
|
domaintest.RandID()*-1,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 8)
|
|
|
|
id, err := strconv.Atoi(pathSegments[7])
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.MinGreaterEqualError{
|
|
|
|
Min: 1,
|
|
|
|
Current: id,
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-29 06:25:01 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"min": float64(domainErr.Min),
|
|
|
|
"current": float64(domainErr.Current),
|
|
|
|
},
|
|
|
|
Path: []string{"$path", "playerId"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: version not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
2024-03-15 06:38:38 +00:00
|
|
|
req.URL.Path = fmt.Sprintf(endpointGetPlayer, randInvalidVersionCode(t, handler), player.Server.Key, player.Id)
|
2024-02-29 06:25:01 +00:00
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 8)
|
|
|
|
domainErr := domain.VersionNotFoundError{
|
|
|
|
VersionCode: pathSegments[3],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-29 06:25:01 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"code": domainErr.VersionCode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: server not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
req.URL.Path = fmt.Sprintf(endpointGetPlayer, player.Server.Version.Code, domaintest.RandServerKey(), player.Id)
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 8)
|
|
|
|
domainErr := domain.ServerNotFoundError{
|
|
|
|
Key: pathSegments[5],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-29 06:25:01 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"key": domainErr.Key,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ERR: player not found",
|
|
|
|
reqModifier: func(t *testing.T, req *http.Request) {
|
|
|
|
t.Helper()
|
|
|
|
req.URL.Path = fmt.Sprintf(
|
|
|
|
endpointGetPlayer,
|
|
|
|
player.Server.Version.Code,
|
|
|
|
player.Server.Key,
|
|
|
|
domaintest.RandID(),
|
|
|
|
)
|
|
|
|
},
|
|
|
|
assertResp: func(t *testing.T, req *http.Request, resp *http.Response) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
|
|
|
|
|
|
// body
|
|
|
|
body := decodeJSON[apimodel.ErrorResponse](t, resp.Body)
|
|
|
|
pathSegments := strings.Split(req.URL.Path, "/")
|
|
|
|
require.Len(t, pathSegments, 8)
|
|
|
|
id, err := strconv.Atoi(pathSegments[7])
|
|
|
|
require.NoError(t, err)
|
|
|
|
domainErr := domain.PlayerNotFoundError{
|
|
|
|
ID: id,
|
|
|
|
ServerKey: pathSegments[5],
|
|
|
|
}
|
|
|
|
assert.Equal(t, apimodel.ErrorResponse{
|
|
|
|
Errors: []apimodel.Error{
|
|
|
|
{
|
2024-03-18 07:01:47 +00:00
|
|
|
Code: apimodel.ErrorCode(domainErr.Code()),
|
2024-02-29 06:25:01 +00:00
|
|
|
Message: domainErr.Error(),
|
|
|
|
Params: map[string]any{
|
|
|
|
"id": float64(domainErr.ID),
|
|
|
|
"serverKey": domainErr.ServerKey,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
req := httptest.NewRequest(
|
|
|
|
http.MethodGet,
|
|
|
|
fmt.Sprintf(endpointGetPlayer, player.Server.Version.Code, player.Server.Key, player.Id),
|
|
|
|
nil,
|
|
|
|
)
|
|
|
|
if tt.reqModifier != nil {
|
|
|
|
tt.reqModifier(t, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := doCustomRequest(handler, req)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
tt.assertResp(t, req, resp)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-26 07:15:11 +00:00
|
|
|
type playerWithServer struct {
|
|
|
|
apimodel.Player
|
|
|
|
Server serverWithVersion
|
|
|
|
}
|
|
|
|
|
|
|
|
func getAllPlayers(tb testing.TB, h http.Handler) []playerWithServer {
|
|
|
|
tb.Helper()
|
|
|
|
|
|
|
|
servers := getAllServers(tb, h)
|
|
|
|
|
|
|
|
var players []playerWithServer
|
|
|
|
|
|
|
|
for _, s := range servers {
|
2024-03-27 06:18:37 +00:00
|
|
|
resp := doRequest(h, http.MethodGet, fmt.Sprintf(endpointListServerPlayers, s.Version.Code, s.Key), nil)
|
2024-02-26 07:15:11 +00:00
|
|
|
require.Equal(tb, http.StatusOK, resp.StatusCode)
|
|
|
|
|
|
|
|
for _, p := range decodeJSON[apimodel.ListPlayersResponse](tb, resp.Body).Data {
|
|
|
|
players = append(players, playerWithServer{
|
|
|
|
Player: p,
|
|
|
|
Server: s,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
_ = resp.Body.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NotZero(tb, players)
|
|
|
|
|
|
|
|
return players
|
|
|
|
}
|