feat: api - /api/v2/versions/{versionCode}/players - new query param "id"
This commit is contained in:
parent
5cd6c33082
commit
aeee5df100
|
@ -78,6 +78,7 @@ paths:
|
|||
- $ref: "#/components/parameters/PlayerDeletedQueryParam"
|
||||
- $ref: "#/components/parameters/PlayerSortQueryParam"
|
||||
- $ref: "#/components/parameters/PlayerNameQueryParam"
|
||||
- $ref: "#/components/parameters/PlayerIdQueryParam"
|
||||
responses:
|
||||
200:
|
||||
$ref: "#/components/responses/ListPlayersWithServersResponse"
|
||||
|
@ -214,6 +215,7 @@ paths:
|
|||
- $ref: "#/components/parameters/PlayerDeletedQueryParam"
|
||||
- $ref: "#/components/parameters/PlayerSortQueryParam"
|
||||
- $ref: "#/components/parameters/PlayerNameQueryParam"
|
||||
- $ref: "#/components/parameters/PlayerIdQueryParam"
|
||||
responses:
|
||||
200:
|
||||
$ref: "#/components/responses/ListPlayersResponse"
|
||||
|
@ -1766,6 +1768,13 @@ components:
|
|||
minLength: 1
|
||||
maxLength: 150
|
||||
maxItems: 100
|
||||
PlayerIdQueryParam:
|
||||
in: query
|
||||
name: id
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/IntId"
|
||||
VillageCoordsQueryParam:
|
||||
name: coords
|
||||
in: query
|
||||
|
|
|
@ -213,7 +213,7 @@ func TestListEnnoblements(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
@ -821,7 +821,7 @@ func TestListPlayerEnnoblements(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
@ -1487,7 +1487,7 @@ func TestListTribeEnnoblements(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
@ -2140,7 +2140,7 @@ func TestListVillageEnnoblements(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
|
@ -63,6 +63,13 @@ func (h *apiHTTPHandler) ListVersionPlayers(
|
|||
return
|
||||
}
|
||||
|
||||
if params.Id != nil {
|
||||
if err := domainParams.SetIDs(*params.Id); err != nil {
|
||||
h.errorRenderer.withErrorPathFormatter(formatListPlayersErrorPath).render(w, r, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if params.Name != nil {
|
||||
if err := domainParams.SetNames(*params.Name); err != nil {
|
||||
h.errorRenderer.withErrorPathFormatter(formatListPlayersErrorPath).render(w, r, err)
|
||||
|
@ -134,6 +141,13 @@ func (h *apiHTTPHandler) ListServerPlayers(
|
|||
return
|
||||
}
|
||||
|
||||
if params.Id != nil {
|
||||
if err := domainParams.SetIDs(*params.Id); err != nil {
|
||||
h.errorRenderer.withErrorPathFormatter(formatListPlayersErrorPath).render(w, r, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if params.Name != nil {
|
||||
if err := domainParams.SetNames(*params.Name); err != nil {
|
||||
h.errorRenderer.withErrorPathFormatter(formatListPlayersErrorPath).render(w, r, err)
|
||||
|
@ -287,6 +301,7 @@ func playerFromContext(ctx context.Context) (domain.PlayerWithRelations, bool) {
|
|||
return p, ok
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func formatListPlayersErrorPath(segments []domain.ErrorPathSegment) []string {
|
||||
if segments[0].Model != "ListPlayersParams" {
|
||||
return nil
|
||||
|
@ -305,6 +320,12 @@ func formatListPlayersErrorPath(segments []domain.ErrorPathSegment) []string {
|
|||
path = append(path, strconv.Itoa(segments[0].Index))
|
||||
}
|
||||
return path
|
||||
case "ids":
|
||||
path := []string{"$query", "id"}
|
||||
if segments[0].Index >= 0 {
|
||||
path = append(path, strconv.Itoa(segments[0].Index))
|
||||
}
|
||||
return path
|
||||
case "sort":
|
||||
path := []string{"$query", "sort"}
|
||||
if segments[0].Index >= 0 {
|
||||
|
|
|
@ -147,7 +147,7 @@ func TestListPlayerPlayerSnapshots(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
|
@ -218,6 +218,43 @@ func TestListVersionPlayers(t *testing.T) {
|
|||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
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)))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: deleted=false",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
|
@ -261,7 +298,7 @@ func TestListVersionPlayers(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
@ -570,6 +607,71 @@ func TestListVersionPlayers(t *testing.T) {
|
|||
}, body)
|
||||
},
|
||||
},
|
||||
{
|
||||
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)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: len(name) > 100",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
|
@ -958,6 +1060,43 @@ func TestListServerPlayers(t *testing.T) {
|
|||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
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)))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: deleted=false",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
|
@ -1001,7 +1140,7 @@ func TestListServerPlayers(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
@ -1310,6 +1449,71 @@ func TestListServerPlayers(t *testing.T) {
|
|||
}, body)
|
||||
},
|
||||
},
|
||||
{
|
||||
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)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: len(name) > 100",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
|
@ -1660,7 +1864,7 @@ func TestListTribeMembers(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
|
@ -153,7 +153,7 @@ func TestListServers(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
|
@ -228,7 +228,7 @@ func TestListPlayerTribeChanges(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
@ -920,7 +920,7 @@ func TestListTribeMemberChanges(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
|
@ -147,7 +147,7 @@ func TestListTribeTribeSnapshots(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
|
@ -256,7 +256,7 @@ func TestListTribes(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
|
@ -101,7 +101,7 @@ func TestListVersions(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
|
@ -140,7 +140,7 @@ func TestListVillages(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
@ -584,7 +584,7 @@ func TestListPlayerVillages(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
@ -997,7 +997,7 @@ func TestListTribeVillages(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a string",
|
||||
name: "ERR: limit is not an integer",
|
||||
reqModifier: func(t *testing.T, req *http.Request) {
|
||||
t.Helper()
|
||||
q := req.URL.Query()
|
||||
|
|
Loading…
Reference in New Issue