feat: add a new endpoint - GET /api/v1/versions/:code/servers/:key/ennoblements (#71)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: twhelp/core#71
This commit is contained in:
parent
71700a589b
commit
e468a1f391
|
@ -97,6 +97,7 @@ func newServer(cfg serverConfig) (*http.Server, error) {
|
|||
tribeRepo := bundb.NewTribe(cfg.db)
|
||||
playerRepo := bundb.NewPlayer(cfg.db)
|
||||
villageRepo := bundb.NewVillage(cfg.db)
|
||||
ennoblementRepo := bundb.NewEnnoblement(cfg.db)
|
||||
|
||||
// services
|
||||
versionSvc := service.NewVersion(versionRepo)
|
||||
|
@ -104,6 +105,7 @@ func newServer(cfg serverConfig) (*http.Server, error) {
|
|||
tribeSvc := service.NewTribe(tribeRepo, client)
|
||||
playerSvc := service.NewPlayer(playerRepo, client)
|
||||
villageSvc := service.NewVillage(villageRepo, client)
|
||||
ennoblementSvc := service.NewEnnoblement(ennoblementRepo, client)
|
||||
|
||||
// router
|
||||
r := chi.NewRouter()
|
||||
|
@ -115,6 +117,7 @@ func newServer(cfg serverConfig) (*http.Server, error) {
|
|||
TribeService: tribeSvc,
|
||||
PlayerService: playerSvc,
|
||||
VillageService: villageSvc,
|
||||
EnnoblementService: ennoblementSvc,
|
||||
CORS: rest.CORSConfig{
|
||||
Enabled: apiCfg.CORSEnabled,
|
||||
AllowedOrigins: nil,
|
||||
|
|
|
@ -76,7 +76,35 @@ func (l listEnnoblementsParamsApplier) apply(q *bun.SelectQuery) (*bun.SelectQue
|
|||
var err error
|
||||
|
||||
if l.params.ServerKeys != nil {
|
||||
q = q.Where("server_key IN (?)", bun.In(l.params.ServerKeys))
|
||||
q = q.Where("ennoblement.server_key IN (?)", bun.In(l.params.ServerKeys))
|
||||
}
|
||||
|
||||
if l.params.CreatedAtGTE.Valid {
|
||||
q = q.Where("ennoblement.created_at >= ?", l.params.CreatedAtGTE.Time)
|
||||
}
|
||||
|
||||
if l.params.CreatedAtLTE.Valid {
|
||||
q = q.Where("ennoblement.created_at <= ?", l.params.CreatedAtLTE.Time)
|
||||
}
|
||||
|
||||
if l.params.IncludeVillage {
|
||||
q = q.Relation("Village")
|
||||
}
|
||||
|
||||
if l.params.IncludeNewOwner {
|
||||
q = q.Relation("NewOwner")
|
||||
}
|
||||
|
||||
if l.params.IncludeNewTribe {
|
||||
q = q.Relation("NewTribe")
|
||||
}
|
||||
|
||||
if l.params.IncludeOldOwner {
|
||||
q = q.Relation("OldOwner")
|
||||
}
|
||||
|
||||
if l.params.IncludeOldTribe {
|
||||
q = q.Relation("OldTribe")
|
||||
}
|
||||
|
||||
q, err = l.applySort(q)
|
||||
|
|
|
@ -125,36 +125,19 @@ func TestEnnoblement_List(t *testing.T) {
|
|||
type expectedEnnoblement struct {
|
||||
id int64
|
||||
serverKey string
|
||||
}
|
||||
|
||||
newExpectedEnnoblement := func(e model.Ennoblement) expectedEnnoblement {
|
||||
return expectedEnnoblement{
|
||||
id: e.ID,
|
||||
serverKey: e.ServerKey,
|
||||
}
|
||||
villageID int64
|
||||
newOwnerID int64
|
||||
newTribeID int64
|
||||
oldOwnerID int64
|
||||
oldTribeID int64
|
||||
}
|
||||
|
||||
allEnnoblements := make([]expectedEnnoblement, 0, len(ennoblements))
|
||||
for _, ennoblement := range ennoblements {
|
||||
allEnnoblements = append(allEnnoblements, newExpectedEnnoblement(ennoblement))
|
||||
}
|
||||
|
||||
//nolint:prealloc
|
||||
var ennoblementsPL169 []expectedEnnoblement
|
||||
for _, ennoblement := range ennoblements {
|
||||
if ennoblement.ServerKey != "pl169" {
|
||||
continue
|
||||
}
|
||||
ennoblementsPL169 = append(ennoblementsPL169, newExpectedEnnoblement(ennoblement))
|
||||
}
|
||||
|
||||
//nolint:prealloc
|
||||
var ennoblementsIT70 []expectedEnnoblement
|
||||
for _, ennoblement := range ennoblements {
|
||||
if ennoblement.ServerKey != "it70" {
|
||||
continue
|
||||
}
|
||||
ennoblementsIT70 = append(ennoblementsIT70, newExpectedEnnoblement(ennoblement))
|
||||
allEnnoblements = append(allEnnoblements, expectedEnnoblement{
|
||||
id: ennoblement.ID,
|
||||
serverKey: ennoblement.ServerKey,
|
||||
})
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
|
@ -182,8 +165,17 @@ func TestEnnoblement_List(t *testing.T) {
|
|||
Count: true,
|
||||
ServerKeys: []string{"pl169"},
|
||||
},
|
||||
expectedEnnoblements: ennoblementsPL169,
|
||||
expectedCount: int64(len(ennoblementsPL169)),
|
||||
expectedEnnoblements: []expectedEnnoblement{
|
||||
{
|
||||
id: 1,
|
||||
serverKey: "pl169",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
serverKey: "pl169",
|
||||
},
|
||||
},
|
||||
expectedCount: 2,
|
||||
},
|
||||
{
|
||||
name: "ServerKeys=[pl169],Sort=[{By=CreatedAt,Direction=DESC}],Limit=1,Count=true",
|
||||
|
@ -198,9 +190,12 @@ func TestEnnoblement_List(t *testing.T) {
|
|||
},
|
||||
},
|
||||
expectedEnnoblements: []expectedEnnoblement{
|
||||
newExpectedEnnoblement(getEnnoblementFromFixture(t, fixture, "pl169-village-2-2")),
|
||||
{
|
||||
id: 2,
|
||||
serverKey: "pl169",
|
||||
},
|
||||
expectedCount: int64(len(ennoblementsPL169)),
|
||||
},
|
||||
expectedCount: 2,
|
||||
},
|
||||
{
|
||||
name: "ServerKeys=[it70],Sort=[{By=ID,Direction=DESC}],Limit=1,Offset=1,Count=true",
|
||||
|
@ -216,9 +211,70 @@ func TestEnnoblement_List(t *testing.T) {
|
|||
},
|
||||
},
|
||||
expectedEnnoblements: []expectedEnnoblement{
|
||||
newExpectedEnnoblement(getEnnoblementFromFixture(t, fixture, "it70-village-2-1")),
|
||||
{
|
||||
id: 3,
|
||||
serverKey: "it70",
|
||||
},
|
||||
expectedCount: int64(len(ennoblementsIT70)),
|
||||
},
|
||||
expectedCount: 2,
|
||||
},
|
||||
{
|
||||
name: "ServerKeys=[it70],IncludeVillage=true,IncludeNewOwner=true,IncludeNewTribe=true,IncludeOldOwner=true,IncludeOldTribe=true,Count=true",
|
||||
params: domain.ListEnnoblementsParams{
|
||||
Count: true,
|
||||
ServerKeys: []string{"it70"},
|
||||
IncludeVillage: true,
|
||||
IncludeNewOwner: true,
|
||||
IncludeNewTribe: true,
|
||||
IncludeOldOwner: true,
|
||||
IncludeOldTribe: true,
|
||||
},
|
||||
expectedEnnoblements: []expectedEnnoblement{
|
||||
{
|
||||
id: 3,
|
||||
serverKey: "it70",
|
||||
villageID: 10023,
|
||||
newOwnerID: 848881282,
|
||||
newTribeID: 31,
|
||||
oldOwnerID: 0,
|
||||
oldTribeID: 0,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
serverKey: "it70",
|
||||
villageID: 10023,
|
||||
newOwnerID: 578014,
|
||||
newTribeID: 1,
|
||||
oldOwnerID: 848881282,
|
||||
oldTribeID: 31,
|
||||
},
|
||||
},
|
||||
expectedCount: 2,
|
||||
},
|
||||
{
|
||||
name: "CreatedAtLTE=2021-12-31T23:59:59Z,CreatedAtGTE=2021-01-01T00:00:00Z,Count=true",
|
||||
params: domain.ListEnnoblementsParams{
|
||||
Count: true,
|
||||
CreatedAtLTE: domain.NullTime{
|
||||
Time: time.Date(2021, time.December, 31, 23, 59, 59, 0, time.UTC),
|
||||
Valid: true,
|
||||
},
|
||||
CreatedAtGTE: domain.NullTime{
|
||||
Time: time.Date(2021, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
Valid: true,
|
||||
},
|
||||
},
|
||||
expectedEnnoblements: []expectedEnnoblement{
|
||||
{
|
||||
id: 1,
|
||||
serverKey: "pl169",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
serverKey: "pl169",
|
||||
},
|
||||
},
|
||||
expectedCount: 2,
|
||||
},
|
||||
{
|
||||
name: "ERR: unsupported sort by",
|
||||
|
@ -256,17 +312,50 @@ func TestEnnoblement_List(t *testing.T) {
|
|||
assert.Len(t, res, len(tt.expectedEnnoblements))
|
||||
for _, expEnnoblement := range tt.expectedEnnoblements {
|
||||
found := false
|
||||
|
||||
for _, ennoblement := range res {
|
||||
if ennoblement.ID == expEnnoblement.id && ennoblement.ServerKey == expEnnoblement.serverKey {
|
||||
if ennoblement.ID != expEnnoblement.id {
|
||||
continue
|
||||
}
|
||||
|
||||
if ennoblement.ServerKey != expEnnoblement.serverKey {
|
||||
continue
|
||||
}
|
||||
|
||||
if ennoblement.Village.Village.ID != expEnnoblement.villageID {
|
||||
continue
|
||||
}
|
||||
|
||||
if ennoblement.NewOwner.Player.ID != expEnnoblement.newOwnerID {
|
||||
continue
|
||||
}
|
||||
|
||||
if ennoblement.NewTribe.Tribe.ID != expEnnoblement.newTribeID {
|
||||
continue
|
||||
}
|
||||
|
||||
if ennoblement.OldOwner.Player.ID != expEnnoblement.oldOwnerID {
|
||||
continue
|
||||
}
|
||||
|
||||
if ennoblement.OldTribe.Tribe.ID != expEnnoblement.oldTribeID {
|
||||
continue
|
||||
}
|
||||
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.True(
|
||||
t,
|
||||
found,
|
||||
"ennoblement (id=%d,serverkey=%s) not found",
|
||||
"ennoblement (id=%d,villageID=%d,newOwnerID=%d,newTribeID=%d,oldOwnerID=%d,oldTribeID=%d,serverkey=%s) not found",
|
||||
expEnnoblement.id,
|
||||
expEnnoblement.villageID,
|
||||
expEnnoblement.newOwnerID,
|
||||
expEnnoblement.newTribeID,
|
||||
expEnnoblement.oldOwnerID,
|
||||
expEnnoblement.oldTribeID,
|
||||
expEnnoblement.serverKey,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewBuildingInfo(t *testing.T) {
|
||||
func TestBuildingInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
info := domain.BuildingInfo{
|
||||
|
|
|
@ -14,10 +14,15 @@ type Ennoblement struct {
|
|||
ID int64 `bun:"id,pk,autoincrement,identity"`
|
||||
ServerKey string `bun:"server_key,nullzero,pk,type:varchar(100)"`
|
||||
VillageID int64 `bun:"village_id,nullzero,notnull"`
|
||||
Village Village `bun:"village,rel:belongs-to,join:village_id=id,join:server_key=server_key"`
|
||||
NewOwnerID int64 `bun:"new_owner_id,nullzero"`
|
||||
NewOwner Player `bun:"new_owner,rel:belongs-to,join:new_owner_id=id,join:server_key=server_key"`
|
||||
NewTribeID int64 `bun:"new_tribe_id,nullzero"`
|
||||
NewTribe Tribe `bun:"new_tribe,rel:belongs-to,join:new_tribe_id=id,join:server_key=server_key"`
|
||||
OldOwnerID int64 `bun:"old_owner_id,nullzero"`
|
||||
OldOwner Player `bun:"old_owner,rel:belongs-to,join:old_owner_id=id,join:server_key=server_key"`
|
||||
OldTribeID int64 `bun:"old_tribe_id,nullzero"`
|
||||
OldTribe Tribe `bun:"old_tribe,rel:belongs-to,join:old_tribe_id=id,join:server_key=server_key"`
|
||||
Points int64 `bun:"points,default:0"`
|
||||
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp"`
|
||||
}
|
||||
|
@ -36,6 +41,46 @@ func NewEnnoblement(p domain.CreateEnnoblementParams) Ennoblement {
|
|||
}
|
||||
|
||||
func (e Ennoblement) ToDomain() domain.Ennoblement {
|
||||
var newOwner domain.NullPlayer
|
||||
if e.NewOwner.ID > 0 {
|
||||
newOwner = domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: e.NewOwner.ToDomain(),
|
||||
}
|
||||
}
|
||||
|
||||
var newTribe domain.NullTribe
|
||||
if e.NewTribe.ID > 0 {
|
||||
newTribe = domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: e.NewTribe.ToDomain(),
|
||||
}
|
||||
}
|
||||
|
||||
var oldOwner domain.NullPlayer
|
||||
if e.OldOwner.ID > 0 {
|
||||
oldOwner = domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: e.OldOwner.ToDomain(),
|
||||
}
|
||||
}
|
||||
|
||||
var oldTribe domain.NullTribe
|
||||
if e.OldTribe.ID > 0 {
|
||||
oldTribe = domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: e.OldTribe.ToDomain(),
|
||||
}
|
||||
}
|
||||
|
||||
var village domain.NullVillage
|
||||
if e.Village.ID > 0 {
|
||||
village = domain.NullVillage{
|
||||
Valid: true,
|
||||
Village: e.Village.ToDomain(),
|
||||
}
|
||||
}
|
||||
|
||||
return domain.Ennoblement{
|
||||
BaseEnnoblement: domain.BaseEnnoblement{
|
||||
VillageID: e.VillageID,
|
||||
|
@ -47,6 +92,11 @@ func (e Ennoblement) ToDomain() domain.Ennoblement {
|
|||
CreatedAt: e.CreatedAt,
|
||||
},
|
||||
ID: e.ID,
|
||||
Village: village,
|
||||
NewOwner: newOwner,
|
||||
NewTribe: newTribe,
|
||||
OldOwner: oldOwner,
|
||||
OldTribe: oldTribe,
|
||||
ServerKey: e.ServerKey,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
)
|
||||
|
||||
func TestNewEnnoblement(t *testing.T) {
|
||||
func TestEnnoblement(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var id int64 = 1234
|
||||
|
@ -29,8 +29,39 @@ func TestNewEnnoblement(t *testing.T) {
|
|||
|
||||
result := model.NewEnnoblement(params)
|
||||
result.ID = id
|
||||
ennoblement := result.ToDomain()
|
||||
assert.Equal(t, params.BaseEnnoblement, ennoblement.BaseEnnoblement)
|
||||
assert.Equal(t, params.ServerKey, ennoblement.ServerKey)
|
||||
assert.Equal(t, id, ennoblement.ID)
|
||||
|
||||
ennoblementWithoutRelations := result.ToDomain()
|
||||
assert.Equal(t, params.BaseEnnoblement, ennoblementWithoutRelations.BaseEnnoblement)
|
||||
assert.Equal(t, params.ServerKey, ennoblementWithoutRelations.ServerKey)
|
||||
assert.Equal(t, id, ennoblementWithoutRelations.ID)
|
||||
|
||||
result.Village = model.Village{
|
||||
ID: 12345,
|
||||
}
|
||||
result.NewOwner = model.Player{
|
||||
ID: 11231,
|
||||
}
|
||||
result.NewTribe = model.Tribe{
|
||||
ID: 11232,
|
||||
}
|
||||
result.OldOwner = model.Player{
|
||||
ID: 11233,
|
||||
}
|
||||
result.OldTribe = model.Tribe{
|
||||
ID: 11234,
|
||||
}
|
||||
ennoblementWithRelations := result.ToDomain()
|
||||
assert.Equal(t, params.BaseEnnoblement, ennoblementWithRelations.BaseEnnoblement)
|
||||
assert.Equal(t, params.ServerKey, ennoblementWithRelations.ServerKey)
|
||||
assert.Equal(t, id, ennoblementWithRelations.ID)
|
||||
assert.True(t, ennoblementWithRelations.Village.Valid)
|
||||
assert.Equal(t, result.Village.ID, ennoblementWithRelations.Village.Village.ID)
|
||||
assert.True(t, ennoblementWithRelations.NewOwner.Valid)
|
||||
assert.Equal(t, result.NewOwner.ID, ennoblementWithRelations.NewOwner.Player.ID)
|
||||
assert.True(t, ennoblementWithRelations.NewTribe.Valid)
|
||||
assert.Equal(t, result.NewTribe.ID, ennoblementWithRelations.NewTribe.Tribe.ID)
|
||||
assert.True(t, ennoblementWithRelations.OldOwner.Valid)
|
||||
assert.Equal(t, result.OldOwner.ID, ennoblementWithRelations.OldOwner.Player.ID)
|
||||
assert.True(t, ennoblementWithRelations.OldTribe.Valid)
|
||||
assert.Equal(t, result.OldTribe.ID, ennoblementWithRelations.OldTribe.Tribe.ID)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewPlayer(t *testing.T) {
|
||||
func TestPlayer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
deletedAt := time.Now().Add(-100 * time.Hour)
|
||||
|
@ -44,20 +44,20 @@ func TestNewPlayer(t *testing.T) {
|
|||
result := model.NewPlayer(playerParams)
|
||||
|
||||
result.DeletedAt = deletedAt
|
||||
player := result.ToDomain()
|
||||
assert.Equal(t, playerParams.BasePlayer, player.BasePlayer)
|
||||
assert.Equal(t, playerParams.ServerKey, player.ServerKey)
|
||||
assert.WithinDuration(t, time.Now(), player.CreatedAt, 10*time.Millisecond)
|
||||
assert.Zero(t, player.Tribe)
|
||||
assert.Equal(t, deletedAt, player.DeletedAt)
|
||||
playerWithoutTribe := result.ToDomain()
|
||||
assert.Equal(t, playerParams.BasePlayer, playerWithoutTribe.BasePlayer)
|
||||
assert.Equal(t, playerParams.ServerKey, playerWithoutTribe.ServerKey)
|
||||
assert.WithinDuration(t, time.Now(), playerWithoutTribe.CreatedAt, 10*time.Millisecond)
|
||||
assert.Zero(t, playerWithoutTribe.Tribe)
|
||||
assert.Equal(t, deletedAt, playerWithoutTribe.DeletedAt)
|
||||
|
||||
result.Tribe = model.NewTribe(tribeParams)
|
||||
result.DeletedAt = time.Time{}
|
||||
player = result.ToDomain()
|
||||
assert.Equal(t, playerParams.BasePlayer, player.BasePlayer)
|
||||
assert.Equal(t, playerParams.ServerKey, player.ServerKey)
|
||||
assert.WithinDuration(t, time.Now(), player.CreatedAt, 10*time.Millisecond)
|
||||
assert.Equal(t, tribeParams.BaseTribe, player.Tribe.Tribe.BaseTribe)
|
||||
assert.True(t, player.Tribe.Valid)
|
||||
assert.Zero(t, player.DeletedAt)
|
||||
playerWithTribe := result.ToDomain()
|
||||
assert.Equal(t, playerParams.BasePlayer, playerWithTribe.BasePlayer)
|
||||
assert.Equal(t, playerParams.ServerKey, playerWithTribe.ServerKey)
|
||||
assert.WithinDuration(t, time.Now(), playerWithTribe.CreatedAt, 10*time.Millisecond)
|
||||
assert.Zero(t, playerWithTribe.DeletedAt)
|
||||
assert.True(t, playerWithTribe.Tribe.Valid)
|
||||
assert.Equal(t, tribeParams.ID, playerWithTribe.Tribe.Tribe.ID)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewServerConfig(t *testing.T) {
|
||||
func TestServerConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := domain.ServerConfig{
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewTribe(t *testing.T) {
|
||||
func TestTribe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
deletedAt := time.Now().Add(-100 * time.Hour)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewUnitInfo(t *testing.T) {
|
||||
func TestUnitInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
info := domain.UnitInfo{
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewVillage(t *testing.T) {
|
||||
func TestVillage(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
params := domain.CreateVillageParams{
|
||||
|
@ -27,8 +27,24 @@ func TestNewVillage(t *testing.T) {
|
|||
}
|
||||
|
||||
result := model.NewVillage(params)
|
||||
village := result.ToDomain()
|
||||
assert.Equal(t, params.BaseVillage, village.BaseVillage)
|
||||
assert.Equal(t, params.ServerKey, village.ServerKey)
|
||||
assert.WithinDuration(t, time.Now(), village.CreatedAt, 10*time.Millisecond)
|
||||
|
||||
villageWithoutPlayer := result.ToDomain()
|
||||
assert.Equal(t, params.BaseVillage, villageWithoutPlayer.BaseVillage)
|
||||
assert.Equal(t, params.ServerKey, villageWithoutPlayer.ServerKey)
|
||||
assert.WithinDuration(t, time.Now(), villageWithoutPlayer.CreatedAt, 10*time.Millisecond)
|
||||
|
||||
result.Player = model.Player{
|
||||
ID: 12321,
|
||||
Tribe: model.Tribe{
|
||||
ID: 1234112,
|
||||
},
|
||||
}
|
||||
villageWithPlayer := result.ToDomain()
|
||||
assert.Equal(t, params.BaseVillage, villageWithPlayer.BaseVillage)
|
||||
assert.Equal(t, params.ServerKey, villageWithPlayer.ServerKey)
|
||||
assert.WithinDuration(t, time.Now(), villageWithPlayer.CreatedAt, 10*time.Millisecond)
|
||||
assert.True(t, villageWithPlayer.Player.Valid)
|
||||
assert.Equal(t, result.Player.ID, villageWithPlayer.Player.Player.ID)
|
||||
assert.True(t, villageWithPlayer.Player.Player.Tribe.Valid)
|
||||
assert.Equal(t, result.Player.Tribe.ID, villageWithPlayer.Player.Player.Tribe.Tribe.ID)
|
||||
}
|
||||
|
|
8
internal/bundb/testdata/fixture.yml
vendored
8
internal/bundb/testdata/fixture.yml
vendored
|
@ -7239,7 +7239,7 @@
|
|||
created_at: 2022-02-25T15:00:10.000Z
|
||||
- model: Ennoblement
|
||||
rows:
|
||||
- _id: pl169-village-2-1
|
||||
- _id: pl169-village-2-1 # id: 1
|
||||
server_key: pl169
|
||||
village_id: 1112
|
||||
new_owner_id: 699513260
|
||||
|
@ -7248,7 +7248,7 @@
|
|||
old_tribe_id: 0
|
||||
points: 2500
|
||||
created_at: 2021-09-30T09:01:00.000Z
|
||||
- _id: pl169-village-2-2
|
||||
- _id: pl169-village-2-2 # id: 2
|
||||
server_key: pl169
|
||||
village_id: 1112
|
||||
new_owner_id: 699783765
|
||||
|
@ -7257,7 +7257,7 @@
|
|||
old_tribe_id: 27
|
||||
points: 5000
|
||||
created_at: 2021-10-30T09:01:00.000Z
|
||||
- _id: it70-village-2-1
|
||||
- _id: it70-village-2-1 # id: 3
|
||||
server_key: it70
|
||||
village_id: 10023
|
||||
new_owner_id: 848881282
|
||||
|
@ -7266,7 +7266,7 @@
|
|||
old_tribe_id: 0
|
||||
points: 2500
|
||||
created_at: 2022-03-15T15:00:10.000Z
|
||||
- _id: it70-village-2-2
|
||||
- _id: it70-village-2-2 # id: 4
|
||||
server_key: it70
|
||||
village_id: 10023
|
||||
new_owner_id: 578014
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type NullBool struct {
|
||||
Bool bool
|
||||
Valid bool // Valid is true if Bool is not NULL
|
||||
|
@ -15,6 +17,11 @@ type NullInt32 struct {
|
|||
Valid bool // Valid is true if Int32 is not NULL
|
||||
}
|
||||
|
||||
type NullTime struct {
|
||||
Time time.Time
|
||||
Valid bool // Valid is true if Time is not NULL
|
||||
}
|
||||
|
||||
type Pagination struct {
|
||||
Offset int32
|
||||
Limit int32
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BaseEnnoblement struct {
|
||||
VillageID int64
|
||||
|
@ -16,6 +19,11 @@ type Ennoblement struct {
|
|||
BaseEnnoblement
|
||||
|
||||
ID int64
|
||||
Village NullVillage
|
||||
NewOwner NullPlayer
|
||||
NewTribe NullTribe
|
||||
OldOwner NullPlayer
|
||||
OldTribe NullTribe
|
||||
ServerKey string
|
||||
}
|
||||
|
||||
|
@ -32,6 +40,16 @@ const (
|
|||
EnnoblementSortByCreatedAt
|
||||
)
|
||||
|
||||
func NewEnnoblementSortBy(s string) (EnnoblementSortBy, error) {
|
||||
switch s {
|
||||
case "id":
|
||||
return EnnoblementSortByID, nil
|
||||
case "createdAt":
|
||||
return EnnoblementSortByCreatedAt, nil
|
||||
}
|
||||
return 0, fmt.Errorf("%w: \"%s\"", ErrUnsupportedSortBy, s)
|
||||
}
|
||||
|
||||
type EnnoblementSort struct {
|
||||
By EnnoblementSortBy
|
||||
Direction SortDirection
|
||||
|
@ -39,8 +57,15 @@ type EnnoblementSort struct {
|
|||
|
||||
type ListEnnoblementsParams struct {
|
||||
ServerKeys []string
|
||||
CreatedAtGTE NullTime
|
||||
CreatedAtLTE NullTime
|
||||
Pagination Pagination
|
||||
Sort []EnnoblementSort
|
||||
IncludeVillage bool
|
||||
IncludeNewOwner bool
|
||||
IncludeNewTribe bool
|
||||
IncludeOldOwner bool
|
||||
IncludeOldTribe bool
|
||||
Count bool
|
||||
}
|
||||
|
||||
|
|
50
internal/domain/ennoblement_test.go
Normal file
50
internal/domain/ennoblement_test.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package domain_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewEnnoblementSortBy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
s string
|
||||
output domain.EnnoblementSortBy
|
||||
}{
|
||||
{
|
||||
s: "id",
|
||||
output: domain.EnnoblementSortByID,
|
||||
},
|
||||
{
|
||||
s: "createdAt",
|
||||
output: domain.EnnoblementSortByCreatedAt,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
t.Run(tt.s, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
res, err := domain.NewEnnoblementSortBy(tt.s)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.output, res)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ERR: unsupported sort by", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
res, err := domain.NewEnnoblementSortBy("unsupported")
|
||||
assert.ErrorIs(t, err, domain.ErrUnsupportedSortBy)
|
||||
assert.Zero(t, res)
|
||||
})
|
||||
}
|
|
@ -24,6 +24,11 @@ type Village struct {
|
|||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type NullVillage struct {
|
||||
Village Village
|
||||
Valid bool
|
||||
}
|
||||
|
||||
type CreateVillageParams struct {
|
||||
BaseVillage
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
replace gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model.NullTribeMeta gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model.TribeMeta
|
||||
replace gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model.NullPlayerMeta gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model.PlayerMeta
|
||||
replace gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model.NullVillageMeta gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model.VillageMeta
|
||||
|
|
91
internal/rest/ennoblement.go
Normal file
91
internal/rest/ennoblement.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model"
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
ennoblementDefaultOffset = 0
|
||||
ennoblementDefaultLimit = 3000
|
||||
)
|
||||
|
||||
//counterfeiter:generate -o internal/mock/ennoblement_service.gen.go . EnnoblementService
|
||||
type EnnoblementService interface {
|
||||
List(ctx context.Context, params domain.ListEnnoblementsParams) ([]domain.Ennoblement, int64, error)
|
||||
}
|
||||
|
||||
type ennoblement struct {
|
||||
svc EnnoblementService
|
||||
}
|
||||
|
||||
// @ID listEnnoblements
|
||||
// @Summary List ennoblements
|
||||
// @Description List all ennoblements
|
||||
// @Tags versions,servers,ennoblements
|
||||
// @Produce json
|
||||
// @Success 200 {object} model.ListEnnoblementsResp
|
||||
// @Success 400 {object} model.ErrorResp
|
||||
// @Success 404 {object} model.ErrorResp
|
||||
// @Failure 500 {object} model.ErrorResp
|
||||
// @Header 200 {integer} X-Total-Count "Total number of records"
|
||||
// @Param versionCode path string true "Version code"
|
||||
// @Param serverKey path string true "Server key"
|
||||
// @Param since query string false "only show items created after the given time, this is a timestamp in RFC 3339 format" format(date-time)
|
||||
// @Param before query string false "only show items created before the given time, this is a timestamp in RFC 3339 format" format(date-time)
|
||||
// @Param offset query int false "specifies where to start a page" minimum(0) default(0)
|
||||
// @Param limit query int false "page size" minimum(1) maximum(3000) default(3000)
|
||||
// @Param sort query []string false "format: field:direction, default: [id:asc]" Enums(id:asc,id:desc,createdAt:asc,createdAt:desc)
|
||||
// @Router /versions/{versionCode}/servers/{serverKey}/ennoblements [get]
|
||||
func (e *ennoblement) list(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
ctx := r.Context()
|
||||
params := domain.ListEnnoblementsParams{
|
||||
ServerKeys: []string{chi.URLParamFromCtx(ctx, "serverKey")},
|
||||
Count: true,
|
||||
IncludeVillage: true,
|
||||
IncludeNewOwner: true,
|
||||
IncludeNewTribe: true,
|
||||
IncludeOldOwner: true,
|
||||
IncludeOldTribe: true,
|
||||
}
|
||||
query := queryParams{r.URL.Query()}
|
||||
|
||||
params.CreatedAtGTE, err = query.nullTime("since")
|
||||
if err != nil {
|
||||
renderErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
params.CreatedAtLTE, err = query.nullTime("before")
|
||||
if err != nil {
|
||||
renderErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
params.Pagination, err = query.pagination(ennoblementDefaultOffset, ennoblementDefaultLimit)
|
||||
if err != nil {
|
||||
renderErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
params.Sort, err = query.ennoblementSort()
|
||||
if err != nil {
|
||||
renderErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
ennoblements, count, err := e.svc.List(ctx, params)
|
||||
if err != nil {
|
||||
renderErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
setTotalCountHeader(w.Header(), count)
|
||||
renderJSON(w, http.StatusOK, model.NewListEnnoblementsResp(ennoblements))
|
||||
}
|
591
internal/rest/ennoblement_test.go
Normal file
591
internal/rest/ennoblement_test.go
Normal file
|
@ -0,0 +1,591 @@
|
|||
package rest_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/rest"
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/rest/internal/mock"
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model"
|
||||
)
|
||||
|
||||
func TestEnnoblement_list(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
now := time.Now()
|
||||
version := domain.Version{
|
||||
Code: "pl",
|
||||
Name: "Poland",
|
||||
Host: "plemiona.pl",
|
||||
Timezone: "Europe/Warsaw",
|
||||
}
|
||||
server := domain.Server{
|
||||
Key: "pl151",
|
||||
URL: "https://pl151.plemiona.pl",
|
||||
Open: true,
|
||||
Special: false,
|
||||
VersionCode: "pl",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
setup func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService)
|
||||
versionCode string
|
||||
key string
|
||||
queryParams url.Values
|
||||
expectedStatus int
|
||||
target any
|
||||
expectedResponse any
|
||||
expectedTotalCount string
|
||||
}{
|
||||
{
|
||||
name: "OK: without params",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
ennoblementSvc.ListCalls(func(_ context.Context, params domain.ListEnnoblementsParams) ([]domain.Ennoblement, int64, error) {
|
||||
expectedParams := domain.ListEnnoblementsParams{
|
||||
ServerKeys: []string{server.Key},
|
||||
IncludeVillage: true,
|
||||
IncludeNewOwner: true,
|
||||
IncludeNewTribe: true,
|
||||
IncludeOldOwner: true,
|
||||
IncludeOldTribe: true,
|
||||
Pagination: domain.Pagination{
|
||||
Limit: 3000,
|
||||
Offset: 0,
|
||||
},
|
||||
Count: true,
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
ennoblements := []domain.Ennoblement{
|
||||
{
|
||||
BaseEnnoblement: domain.BaseEnnoblement{
|
||||
VillageID: 123,
|
||||
NewOwnerID: 124,
|
||||
NewTribeID: 125,
|
||||
OldOwnerID: 126,
|
||||
OldTribeID: 127,
|
||||
Points: 128,
|
||||
CreatedAt: now,
|
||||
},
|
||||
ID: 1234,
|
||||
Village: domain.NullVillage{
|
||||
Valid: true,
|
||||
Village: domain.Village{
|
||||
BaseVillage: domain.BaseVillage{
|
||||
ID: 123,
|
||||
Name: "village name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 124,
|
||||
Name: "new owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 125,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
OldOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 126,
|
||||
Name: "old owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
OldTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 127,
|
||||
Name: "old tribe name",
|
||||
Tag: "old tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
ServerKey: server.Key,
|
||||
},
|
||||
{
|
||||
|
||||
BaseEnnoblement: domain.BaseEnnoblement{
|
||||
VillageID: 311,
|
||||
NewOwnerID: 312,
|
||||
NewTribeID: 313,
|
||||
OldOwnerID: 0,
|
||||
OldTribeID: 0,
|
||||
Points: 129,
|
||||
CreatedAt: now,
|
||||
},
|
||||
ID: 12345,
|
||||
Village: domain.NullVillage{
|
||||
Valid: true,
|
||||
Village: domain.Village{
|
||||
BaseVillage: domain.BaseVillage{
|
||||
ID: 311,
|
||||
Name: "village name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 312,
|
||||
Name: "new owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 313,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
ServerKey: server.Key,
|
||||
},
|
||||
}
|
||||
return ennoblements, int64(len(ennoblements)), nil
|
||||
})
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
expectedStatus: 200,
|
||||
target: &model.ListEnnoblementsResp{},
|
||||
expectedResponse: &model.ListEnnoblementsResp{
|
||||
Data: []model.Ennoblement{
|
||||
{
|
||||
ID: 1234,
|
||||
Points: 128,
|
||||
Village: model.VillageMeta{
|
||||
ID: 123,
|
||||
Name: "village name",
|
||||
},
|
||||
NewOwner: model.NullPlayerMeta{
|
||||
Valid: true,
|
||||
Player: model.PlayerMeta{
|
||||
ID: 124,
|
||||
Name: "new owner name",
|
||||
Tribe: model.NullTribeMeta{
|
||||
Valid: true,
|
||||
Tribe: model.TribeMeta{
|
||||
ID: 125,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
OldOwner: model.NullPlayerMeta{
|
||||
Valid: true,
|
||||
Player: model.PlayerMeta{
|
||||
ID: 126,
|
||||
Name: "old owner name",
|
||||
Tribe: model.NullTribeMeta{
|
||||
Valid: true,
|
||||
Tribe: model.TribeMeta{
|
||||
ID: 127,
|
||||
Name: "old tribe name",
|
||||
Tag: "old tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
CreatedAt: now,
|
||||
},
|
||||
{
|
||||
ID: 12345,
|
||||
Points: 129,
|
||||
Village: model.VillageMeta{
|
||||
ID: 311,
|
||||
Name: "village name",
|
||||
},
|
||||
NewOwner: model.NullPlayerMeta{
|
||||
Valid: true,
|
||||
Player: model.PlayerMeta{
|
||||
ID: 312,
|
||||
Name: "new owner name",
|
||||
Tribe: model.NullTribeMeta{
|
||||
Valid: true,
|
||||
Tribe: model.TribeMeta{
|
||||
ID: 313,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
CreatedAt: now,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "2",
|
||||
},
|
||||
{
|
||||
name: "OK: limit=1,offset=100,since=now-30h,before=now,sort=[createdAt:desc]",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
ennoblementSvc.ListCalls(func(_ context.Context, params domain.ListEnnoblementsParams) ([]domain.Ennoblement, int64, error) {
|
||||
expectedParams := domain.ListEnnoblementsParams{
|
||||
ServerKeys: []string{server.Key},
|
||||
IncludeVillage: true,
|
||||
IncludeNewOwner: true,
|
||||
IncludeNewTribe: true,
|
||||
IncludeOldOwner: true,
|
||||
IncludeOldTribe: true,
|
||||
CreatedAtGTE: domain.NullTime{
|
||||
Valid: true,
|
||||
Time: now.Add(-30 * time.Hour).Truncate(time.Second),
|
||||
},
|
||||
CreatedAtLTE: domain.NullTime{
|
||||
Valid: true,
|
||||
Time: now.Truncate(time.Second),
|
||||
},
|
||||
Sort: []domain.EnnoblementSort{
|
||||
{By: domain.EnnoblementSortByCreatedAt, Direction: domain.SortDirectionDESC},
|
||||
},
|
||||
Pagination: domain.Pagination{
|
||||
Limit: 1,
|
||||
Offset: 100,
|
||||
},
|
||||
Count: true,
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(params, expectedParams, cmpopts.IgnoreUnexported(time.Time{})); diff != "" {
|
||||
return nil, 0, errors.New("invalid params: " + diff)
|
||||
}
|
||||
|
||||
ennoblements := []domain.Ennoblement{
|
||||
{
|
||||
|
||||
BaseEnnoblement: domain.BaseEnnoblement{
|
||||
VillageID: 311,
|
||||
NewOwnerID: 312,
|
||||
NewTribeID: 313,
|
||||
OldOwnerID: 0,
|
||||
OldTribeID: 0,
|
||||
Points: 129,
|
||||
CreatedAt: now,
|
||||
},
|
||||
ID: 12345,
|
||||
Village: domain.NullVillage{
|
||||
Valid: true,
|
||||
Village: domain.Village{
|
||||
BaseVillage: domain.BaseVillage{
|
||||
ID: 311,
|
||||
Name: "village name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 312,
|
||||
Name: "new owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 313,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
ServerKey: server.Key,
|
||||
},
|
||||
}
|
||||
return ennoblements, int64(len(ennoblements)), nil
|
||||
})
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
expectedStatus: 200,
|
||||
queryParams: url.Values{
|
||||
"limit": []string{"1"},
|
||||
"offset": []string{"100"},
|
||||
"sort": []string{"createdAt:DESC"},
|
||||
"since": []string{now.Add(-30 * time.Hour).Format(time.RFC3339)},
|
||||
"before": []string{now.Format(time.RFC3339)},
|
||||
},
|
||||
target: &model.ListEnnoblementsResp{},
|
||||
expectedResponse: &model.ListEnnoblementsResp{
|
||||
Data: []model.Ennoblement{
|
||||
{
|
||||
ID: 12345,
|
||||
Points: 129,
|
||||
Village: model.VillageMeta{
|
||||
ID: 311,
|
||||
Name: "village name",
|
||||
},
|
||||
NewOwner: model.NullPlayerMeta{
|
||||
Valid: true,
|
||||
Player: model.PlayerMeta{
|
||||
ID: 312,
|
||||
Name: "new owner name",
|
||||
Tribe: model.NullTribeMeta{
|
||||
Valid: true,
|
||||
Tribe: model.TribeMeta{
|
||||
ID: 313,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
CreatedAt: now,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "1",
|
||||
},
|
||||
{
|
||||
name: "ERR: since is not a valid timestamp",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, playerSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
queryParams: url.Values{
|
||||
"since": []string{"???"},
|
||||
},
|
||||
expectedStatus: 400,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeValidationError.String(),
|
||||
Message: "since: parsing time \"???\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"???\" as \"2006\"",
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
{
|
||||
name: "ERR: before is not a valid timestamp",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, playerSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
queryParams: url.Values{
|
||||
"before": []string{"???"},
|
||||
},
|
||||
expectedStatus: 400,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeValidationError.String(),
|
||||
Message: "before: parsing time \"???\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"???\" as \"2006\"",
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
{
|
||||
name: "ERR: limit is not a valid int32",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, playerSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
queryParams: url.Values{
|
||||
"limit": []string{"asd"},
|
||||
},
|
||||
expectedStatus: 400,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeValidationError.String(),
|
||||
Message: "limit: strconv.ParseInt: parsing \"asd\": invalid syntax",
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
{
|
||||
name: "ERR: offset is not a valid int32",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
queryParams: url.Values{
|
||||
"offset": []string{"asd"},
|
||||
},
|
||||
expectedStatus: 400,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeValidationError.String(),
|
||||
Message: "offset: strconv.ParseInt: parsing \"asd\": invalid syntax",
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
{
|
||||
name: "ERR: sort - invalid format",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
queryParams: url.Values{
|
||||
"sort": []string{"id:asc", "test"},
|
||||
},
|
||||
expectedStatus: 400,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeValidationError.String(),
|
||||
Message: "sort[1]: parsing \"test\": invalid syntax, expected field:direction",
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
{
|
||||
name: "ERR: sort - unsupported field",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
queryParams: url.Values{
|
||||
"sort": []string{"id:asc", "test:asc"},
|
||||
},
|
||||
expectedStatus: 400,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeValidationError.String(),
|
||||
Message: "sort[1]: unsupported sort by: \"test\"",
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
{
|
||||
name: "ERR: sort - unsupported direction",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key,
|
||||
queryParams: url.Values{
|
||||
"sort": []string{"id:asc2"},
|
||||
},
|
||||
expectedStatus: 400,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeValidationError.String(),
|
||||
Message: "sort[0]: unsupported sort direction: \"asc2\"",
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
{
|
||||
name: "ERR: version not found",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(domain.Version{}, domain.VersionNotFoundError{VerCode: version.Code + "2"})
|
||||
},
|
||||
versionCode: version.Code + "2",
|
||||
key: server.Key,
|
||||
expectedStatus: 404,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeEntityNotFound.String(),
|
||||
Message: fmt.Sprintf("version (code=%s) not found", version.Code+"2"),
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
{
|
||||
name: "ERR: server not found",
|
||||
setup: func(versionSvc *mock.FakeVersionService, serverSvc *mock.FakeServerService, ennoblementSvc *mock.FakeEnnoblementService) {
|
||||
versionSvc.GetByCodeReturns(version, nil)
|
||||
serverSvc.GetNormalByVersionCodeAndKeyReturns(domain.Server{}, domain.ServerNotFoundError{Key: server.Key + "2"})
|
||||
},
|
||||
versionCode: version.Code,
|
||||
key: server.Key + "2",
|
||||
expectedStatus: 404,
|
||||
target: &model.ErrorResp{},
|
||||
expectedResponse: &model.ErrorResp{
|
||||
Error: model.APIError{
|
||||
Code: domain.ErrorCodeEntityNotFound.String(),
|
||||
Message: fmt.Sprintf("server (key=%s) not found", server.Key+"2"),
|
||||
},
|
||||
},
|
||||
expectedTotalCount: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
versionSvc := &mock.FakeVersionService{}
|
||||
serverSvc := &mock.FakeServerService{}
|
||||
ennoblementSvc := &mock.FakeEnnoblementService{}
|
||||
tt.setup(versionSvc, serverSvc, ennoblementSvc)
|
||||
|
||||
router := rest.NewRouter(rest.RouterConfig{
|
||||
VersionService: versionSvc,
|
||||
ServerService: serverSvc,
|
||||
EnnoblementService: ennoblementSvc,
|
||||
})
|
||||
|
||||
target := fmt.Sprintf(
|
||||
"/v1/versions/%s/servers/%s/ennoblements?%s",
|
||||
tt.versionCode,
|
||||
tt.key,
|
||||
tt.queryParams.Encode(),
|
||||
)
|
||||
resp := doRequest(router, http.MethodGet, target, nil)
|
||||
defer resp.Body.Close()
|
||||
assertTotalCount(t, resp.Header, tt.expectedTotalCount)
|
||||
assertJSONResponse(t, resp, tt.expectedStatus, tt.expectedResponse, tt.target)
|
||||
})
|
||||
}
|
||||
}
|
59
internal/rest/internal/model/ennoblement.go
Normal file
59
internal/rest/internal/model/ennoblement.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
)
|
||||
|
||||
type Ennoblement struct {
|
||||
ID int64 `json:"id"`
|
||||
Village VillageMeta `json:"village"`
|
||||
NewOwner NullPlayerMeta `json:"newOwner" extensions:"x-nullable"`
|
||||
OldOwner NullPlayerMeta `json:"oldOwner" extensions:"x-nullable"`
|
||||
Points int64 `json:"points"`
|
||||
CreatedAt time.Time `json:"createdAt" format:"date-time"`
|
||||
} // @name Ennoblement
|
||||
|
||||
func NewEnnoblement(e domain.Ennoblement) Ennoblement {
|
||||
var newOwner NullPlayerMeta
|
||||
if e.NewOwner.Valid {
|
||||
e.NewOwner.Player.Tribe = e.NewTribe
|
||||
newOwner = NullPlayerMeta{
|
||||
Valid: true,
|
||||
Player: NewPlayerMeta(e.NewOwner.Player),
|
||||
}
|
||||
}
|
||||
|
||||
var oldOwner NullPlayerMeta
|
||||
if e.OldOwner.Valid {
|
||||
e.OldOwner.Player.Tribe = e.OldTribe
|
||||
oldOwner = NullPlayerMeta{
|
||||
Valid: true,
|
||||
Player: NewPlayerMeta(e.OldOwner.Player),
|
||||
}
|
||||
}
|
||||
|
||||
return Ennoblement{
|
||||
ID: e.ID,
|
||||
Village: NewVillageMeta(e.Village.Village),
|
||||
NewOwner: newOwner,
|
||||
OldOwner: oldOwner,
|
||||
Points: e.Points,
|
||||
CreatedAt: e.CreatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
type ListEnnoblementsResp struct {
|
||||
Data []Ennoblement `json:"data"`
|
||||
} // @name ListEnnoblementsResp
|
||||
|
||||
func NewListEnnoblementsResp(ennoblements []domain.Ennoblement) ListEnnoblementsResp {
|
||||
resp := ListEnnoblementsResp{
|
||||
Data: make([]Ennoblement, 0, len(ennoblements)),
|
||||
}
|
||||
for _, e := range ennoblements {
|
||||
resp.Data = append(resp.Data, NewEnnoblement(e))
|
||||
}
|
||||
return resp
|
||||
}
|
205
internal/rest/internal/model/ennoblement_test.go
Normal file
205
internal/rest/internal/model/ennoblement_test.go
Normal file
|
@ -0,0 +1,205 @@
|
|||
package model_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/rest/internal/model"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
)
|
||||
|
||||
func TestNewEnnoblement(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ennoblement := domain.Ennoblement{
|
||||
BaseEnnoblement: domain.BaseEnnoblement{
|
||||
VillageID: 123,
|
||||
NewOwnerID: 124,
|
||||
NewTribeID: 125,
|
||||
OldOwnerID: 126,
|
||||
OldTribeID: 127,
|
||||
Points: 128,
|
||||
CreatedAt: time.Now(),
|
||||
},
|
||||
ID: 1234,
|
||||
Village: domain.NullVillage{
|
||||
Valid: true,
|
||||
Village: domain.Village{
|
||||
BaseVillage: domain.BaseVillage{
|
||||
ID: 123,
|
||||
Name: "village name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 124,
|
||||
Name: "new owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 125,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
OldOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 126,
|
||||
Name: "old owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
OldTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 125,
|
||||
Name: "old tribe name",
|
||||
Tag: "old tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
ServerKey: "pl151",
|
||||
}
|
||||
assertEnnoblement(t, ennoblement, model.NewEnnoblement(ennoblement))
|
||||
}
|
||||
|
||||
func TestNewListEnnoblementsResp(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ennoblements := []domain.Ennoblement{
|
||||
{
|
||||
BaseEnnoblement: domain.BaseEnnoblement{
|
||||
VillageID: 123,
|
||||
NewOwnerID: 124,
|
||||
NewTribeID: 125,
|
||||
OldOwnerID: 126,
|
||||
OldTribeID: 127,
|
||||
Points: 128,
|
||||
CreatedAt: time.Now(),
|
||||
},
|
||||
ID: 1234,
|
||||
Village: domain.NullVillage{
|
||||
Valid: true,
|
||||
Village: domain.Village{
|
||||
BaseVillage: domain.BaseVillage{
|
||||
ID: 123,
|
||||
Name: "village name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 124,
|
||||
Name: "new owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 125,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
OldOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 126,
|
||||
Name: "old owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
OldTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 125,
|
||||
Name: "old tribe name",
|
||||
Tag: "old tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
ServerKey: "pl151",
|
||||
},
|
||||
{
|
||||
|
||||
BaseEnnoblement: domain.BaseEnnoblement{
|
||||
VillageID: 311,
|
||||
NewOwnerID: 312,
|
||||
NewTribeID: 313,
|
||||
OldOwnerID: 0,
|
||||
OldTribeID: 0,
|
||||
Points: 129,
|
||||
CreatedAt: time.Now(),
|
||||
},
|
||||
ID: 1234,
|
||||
Village: domain.NullVillage{
|
||||
Valid: true,
|
||||
Village: domain.Village{
|
||||
BaseVillage: domain.BaseVillage{
|
||||
ID: 311,
|
||||
Name: "village name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewOwner: domain.NullPlayer{
|
||||
Valid: true,
|
||||
Player: domain.Player{
|
||||
BasePlayer: domain.BasePlayer{
|
||||
ID: 312,
|
||||
Name: "new owner name",
|
||||
},
|
||||
},
|
||||
},
|
||||
NewTribe: domain.NullTribe{
|
||||
Valid: true,
|
||||
Tribe: domain.Tribe{
|
||||
BaseTribe: domain.BaseTribe{
|
||||
ID: 313,
|
||||
Name: "new tribe name",
|
||||
Tag: "new tribe tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
ServerKey: "pl151",
|
||||
},
|
||||
}
|
||||
resp := model.NewListEnnoblementsResp(ennoblements)
|
||||
assert.Len(t, resp.Data, len(ennoblements))
|
||||
for i, e := range resp.Data {
|
||||
assertEnnoblement(t, ennoblements[i], e)
|
||||
}
|
||||
}
|
||||
|
||||
func assertEnnoblement(tb testing.TB, de domain.Ennoblement, re model.Ennoblement) {
|
||||
tb.Helper()
|
||||
|
||||
assert.Equal(tb, de.ID, re.ID)
|
||||
assert.Equal(tb, de.Points, re.Points)
|
||||
assertVillageMeta(tb, de.Village.Village, re.Village)
|
||||
de.NewOwner.Player.Tribe = de.NewTribe
|
||||
assertNullPlayerMeta(tb, de.NewOwner, re.NewOwner)
|
||||
de.OldOwner.Player.Tribe = de.OldTribe
|
||||
assertNullPlayerMeta(tb, de.OldOwner, re.OldOwner)
|
||||
assert.Equal(tb, de.CreatedAt, re.CreatedAt)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
|
@ -39,6 +40,48 @@ func NewVillage(v domain.Village) Village {
|
|||
}
|
||||
}
|
||||
|
||||
// VillageMeta represents basic village information
|
||||
// @Description Basic village information
|
||||
type VillageMeta struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} // @name VillageMeta
|
||||
|
||||
func NewVillageMeta(v domain.Village) VillageMeta {
|
||||
return VillageMeta{
|
||||
ID: v.ID,
|
||||
Name: v.Name,
|
||||
}
|
||||
}
|
||||
|
||||
type NullVillageMeta struct {
|
||||
Village VillageMeta
|
||||
Valid bool
|
||||
}
|
||||
|
||||
func (v NullVillageMeta) MarshalJSON() ([]byte, error) {
|
||||
if !v.Valid {
|
||||
return []byte("null"), nil
|
||||
}
|
||||
|
||||
return json.Marshal(v.Village)
|
||||
}
|
||||
|
||||
func (v *NullVillageMeta) UnmarshalJSON(data []byte) error {
|
||||
// Ignore null, like in the main JSON package.
|
||||
if string(data) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &v.Village); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.Valid = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ListVillagesResp struct {
|
||||
Data []Village `json:"data"`
|
||||
} // @name ListVillagesResp
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package model_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -99,6 +100,139 @@ func TestNewVillage(t *testing.T) {
|
|||
assertVillage(t, playerVillage, model.NewVillage(playerVillage))
|
||||
}
|
||||
|
||||
func TestNewVillageMeta(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
village := domain.Village{
|
||||
BaseVillage: domain.BaseVillage{
|
||||
ID: 1234,
|
||||
Name: "name",
|
||||
Points: 1,
|
||||
X: 2,
|
||||
Y: 3,
|
||||
Continent: "K11",
|
||||
Bonus: 1,
|
||||
PlayerID: 0,
|
||||
},
|
||||
ServerKey: "pl151",
|
||||
Player: domain.NullPlayer{},
|
||||
CreatedAt: time.Time{},
|
||||
}
|
||||
assertVillageMeta(t, village, model.NewVillageMeta(village))
|
||||
}
|
||||
|
||||
func TestNullVillageMeta_MarshalJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
village model.NullVillageMeta
|
||||
expectedJSON string
|
||||
}{
|
||||
{
|
||||
name: "OK: null 1",
|
||||
village: model.NullVillageMeta{
|
||||
Village: model.VillageMeta{},
|
||||
Valid: false,
|
||||
},
|
||||
expectedJSON: "null",
|
||||
},
|
||||
{
|
||||
name: "OK: null 2",
|
||||
village: model.NullVillageMeta{
|
||||
Village: model.VillageMeta{ID: 1234},
|
||||
Valid: false,
|
||||
},
|
||||
expectedJSON: "null",
|
||||
},
|
||||
{
|
||||
name: "OK: valid struct",
|
||||
village: model.NullVillageMeta{
|
||||
Village: model.VillageMeta{
|
||||
ID: 997,
|
||||
Name: "name 997",
|
||||
},
|
||||
Valid: true,
|
||||
},
|
||||
expectedJSON: `{"id":997,"name":"name 997"}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
b, err := json.Marshal(tt.village)
|
||||
assert.NoError(t, err)
|
||||
assert.JSONEq(t, tt.expectedJSON, string(b))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNullVillageMeta_UnmarshalJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
json string
|
||||
expectedVillage model.NullVillageMeta
|
||||
expectedJSONSyntaxError bool
|
||||
}{
|
||||
{
|
||||
name: "OK: null",
|
||||
json: "null",
|
||||
expectedVillage: model.NullVillageMeta{
|
||||
Village: model.VillageMeta{},
|
||||
Valid: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK: valid struct",
|
||||
//nolint:lll
|
||||
json: `{"id":997,"name":"name 997"}`,
|
||||
expectedVillage: model.NullVillageMeta{
|
||||
Village: model.VillageMeta{
|
||||
ID: 997,
|
||||
Name: "name 997",
|
||||
},
|
||||
Valid: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ERR: invalid tribe 1",
|
||||
json: "2022-07-30T14:13:12.0000005Z",
|
||||
expectedVillage: model.NullVillageMeta{},
|
||||
expectedJSONSyntaxError: true,
|
||||
},
|
||||
{
|
||||
name: "ERR: invalid tribe 2",
|
||||
json: "hello world",
|
||||
expectedVillage: model.NullVillageMeta{},
|
||||
expectedJSONSyntaxError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var target model.NullVillageMeta
|
||||
err := json.Unmarshal([]byte(tt.json), &target)
|
||||
if tt.expectedJSONSyntaxError {
|
||||
var syntaxError *json.SyntaxError
|
||||
assert.ErrorAs(t, err, &syntaxError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, tt.expectedVillage, target)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewListVillagesResp(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@ -227,3 +361,10 @@ func assertVillage(tb testing.TB, dv domain.Village, rv model.Village) {
|
|||
assert.Equal(tb, dv.CreatedAt, rv.CreatedAt)
|
||||
assertNullPlayerMeta(tb, dv.Player, rv.Player)
|
||||
}
|
||||
|
||||
func assertVillageMeta(tb testing.TB, dv domain.Village, rv model.VillageMeta) {
|
||||
tb.Helper()
|
||||
|
||||
assert.Equal(tb, dv.ID, rv.ID)
|
||||
assert.Equal(tb, dv.Name, rv.Name)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package rest_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -53,10 +52,6 @@ func TestPlayer_list(t *testing.T) {
|
|||
serverSvc.GetNormalByVersionCodeAndKeyReturns(server, nil)
|
||||
playerSvc.ListCalls(func(_ context.Context, params domain.ListPlayersParams) ([]domain.Player, int64, error) {
|
||||
expectedParams := domain.ListPlayersParams{
|
||||
Deleted: domain.NullBool{
|
||||
Valid: false,
|
||||
Bool: false,
|
||||
},
|
||||
ServerKeys: []string{server.Key},
|
||||
IncludeTribe: true,
|
||||
Pagination: domain.Pagination{
|
||||
|
@ -66,8 +61,8 @@ func TestPlayer_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
players := []domain.Player{
|
||||
|
@ -226,8 +221,8 @@ func TestPlayer_list(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
players := []domain.Player{
|
||||
|
@ -325,8 +320,8 @@ func TestPlayer_list(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
players := []domain.Player{
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
)
|
||||
|
@ -140,6 +141,42 @@ func (q queryParams) playerSort() ([]domain.PlayerSort, error) {
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (q queryParams) ennoblementSort() ([]domain.EnnoblementSort, error) {
|
||||
ss, err := q.sort()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ss == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
res := make([]domain.EnnoblementSort, 0, len(ss))
|
||||
for i, s := range ss {
|
||||
by, err := domain.NewEnnoblementSortBy(s[0])
|
||||
if err != nil {
|
||||
return nil, domain.ValidationError{
|
||||
Field: fmt.Sprintf("sort[%d]", i),
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
direction, err := domain.NewSortDirection(s[1])
|
||||
if err != nil {
|
||||
return nil, domain.ValidationError{
|
||||
Field: fmt.Sprintf("sort[%d]", i),
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
res = append(res, domain.EnnoblementSort{
|
||||
By: by,
|
||||
Direction: direction,
|
||||
})
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (q queryParams) sort() ([][2]string, error) {
|
||||
ss, ok := q.values["sort"]
|
||||
if !ok || len(ss) == 0 {
|
||||
|
@ -161,3 +198,22 @@ func (q queryParams) sort() ([][2]string, error) {
|
|||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (q queryParams) nullTime(key string) (domain.NullTime, error) {
|
||||
if !q.values.Has(key) {
|
||||
return domain.NullTime{}, nil
|
||||
}
|
||||
|
||||
t, err := time.Parse(time.RFC3339, q.values.Get(key))
|
||||
if err != nil {
|
||||
return domain.NullTime{}, domain.ValidationError{
|
||||
Field: key,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
return domain.NullTime{
|
||||
Valid: true,
|
||||
Time: t,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ type RouterConfig struct {
|
|||
TribeService TribeService
|
||||
PlayerService PlayerService
|
||||
VillageService VillageService
|
||||
EnnoblementService EnnoblementService
|
||||
CORS CORSConfig
|
||||
Swagger bool
|
||||
}
|
||||
|
@ -55,6 +56,9 @@ func NewRouter(cfg RouterConfig) *chi.Mux {
|
|||
villageHandler := &village{
|
||||
svc: cfg.VillageService,
|
||||
}
|
||||
ennoblementHandler := &ennoblement{
|
||||
svc: cfg.EnnoblementService,
|
||||
}
|
||||
|
||||
router := chi.NewRouter()
|
||||
|
||||
|
@ -104,6 +108,8 @@ func NewRouter(cfg RouterConfig) *chi.Mux {
|
|||
r.Get("/", villageHandler.list)
|
||||
r.Get("/{villageId}", villageHandler.getByID)
|
||||
})
|
||||
r.With(verifyServerKeyMiddleware).
|
||||
Get("/ennoblements", ennoblementHandler.list)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -2,7 +2,6 @@ package rest_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -61,8 +60,8 @@ func TestServer_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
servers := []domain.Server{
|
||||
|
@ -177,8 +176,8 @@ func TestServer_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
servers := []domain.Server{
|
||||
|
@ -298,8 +297,8 @@ func TestServer_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
servers := []domain.Server{
|
||||
|
|
|
@ -2,7 +2,6 @@ package rest_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -77,8 +76,8 @@ func TestTribe_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
tribes := []domain.Tribe{
|
||||
|
@ -220,8 +219,8 @@ func TestTribe_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
tribes := []domain.Tribe{
|
||||
|
@ -352,8 +351,8 @@ func TestTribe_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
tribes := []domain.Tribe{
|
||||
|
|
|
@ -2,7 +2,6 @@ package rest_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -63,8 +62,8 @@ func TestVillage_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
villages := []domain.Village{
|
||||
|
@ -220,8 +219,8 @@ func TestVillage_list(t *testing.T) {
|
|||
Count: true,
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, errors.New("invalid params: " + cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
villages := []domain.Village{
|
||||
|
|
|
@ -9,6 +9,11 @@ import (
|
|||
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
ennoblementMaxLimit = 3000
|
||||
ennoblementSortMaxLen = 2
|
||||
)
|
||||
|
||||
var (
|
||||
errEnnoblementNotFound = errors.New("ennoblement not found")
|
||||
)
|
||||
|
@ -64,6 +69,41 @@ func (e *Ennoblement) Refresh(ctx context.Context, key, url string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *Ennoblement) List(ctx context.Context, params domain.ListEnnoblementsParams) ([]domain.Ennoblement, int64, error) {
|
||||
if len(params.Sort) == 0 {
|
||||
params.Sort = []domain.EnnoblementSort{
|
||||
{
|
||||
By: domain.EnnoblementSortByID,
|
||||
Direction: domain.SortDirectionASC,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if len(params.Sort) > ennoblementSortMaxLen {
|
||||
return nil, 0, domain.ValidationError{
|
||||
Field: "sort",
|
||||
Err: domain.MaxLengthError{
|
||||
Max: ennoblementSortMaxLen,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if params.Pagination.Limit == 0 {
|
||||
params.Pagination.Limit = ennoblementMaxLimit
|
||||
}
|
||||
|
||||
if err := validatePagination(params.Pagination, ennoblementMaxLimit); err != nil {
|
||||
return nil, 0, fmt.Errorf("validatePagination: %w", err)
|
||||
}
|
||||
|
||||
ennoblements, count, err := e.repo.List(ctx, params)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("EnnoblementRepository.List: %w", err)
|
||||
}
|
||||
|
||||
return ennoblements, count, nil
|
||||
}
|
||||
|
||||
func (e *Ennoblement) getLatestEnnoblement(ctx context.Context, key string) (domain.Ennoblement, error) {
|
||||
ennoblements, _, err := e.repo.List(ctx, domain.ListEnnoblementsParams{
|
||||
ServerKeys: []string{key},
|
||||
|
|
|
@ -2,9 +2,12 @@ package service_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/core/internal/service"
|
||||
|
@ -123,3 +126,181 @@ func TestEnnoblement_Refresh(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnnoblement_List(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
limit int32
|
||||
sort []domain.EnnoblementSort
|
||||
}{
|
||||
{
|
||||
name: "default limit, default sort",
|
||||
limit: 0,
|
||||
sort: nil,
|
||||
},
|
||||
{
|
||||
name: "custom limit",
|
||||
limit: 2999,
|
||||
},
|
||||
{
|
||||
name: "custom sort",
|
||||
limit: 0,
|
||||
sort: []domain.EnnoblementSort{
|
||||
{By: domain.EnnoblementSortByCreatedAt, Direction: domain.SortDirectionDESC},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
limit := tt.limit
|
||||
if limit == 0 {
|
||||
limit = 3000
|
||||
}
|
||||
|
||||
repo := &mock.FakeEnnoblementRepository{}
|
||||
repo.ListCalls(func(_ context.Context, params domain.ListEnnoblementsParams) ([]domain.Ennoblement, int64, error) {
|
||||
expectedParams := domain.ListEnnoblementsParams{
|
||||
Pagination: domain.Pagination{
|
||||
Limit: limit,
|
||||
},
|
||||
Sort: func(sort []domain.EnnoblementSort) []domain.EnnoblementSort {
|
||||
if len(sort) == 0 {
|
||||
return []domain.EnnoblementSort{
|
||||
{
|
||||
By: domain.EnnoblementSortByID,
|
||||
Direction: domain.SortDirectionASC,
|
||||
},
|
||||
}
|
||||
}
|
||||
return sort
|
||||
}(tt.sort),
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
return make([]domain.Ennoblement, params.Pagination.Limit), int64(params.Pagination.Limit), nil
|
||||
})
|
||||
client := &mock.FakeEnnoblementsGetter{}
|
||||
|
||||
players, count, err := service.NewEnnoblement(repo, client).
|
||||
List(context.Background(), domain.ListEnnoblementsParams{
|
||||
Pagination: domain.Pagination{
|
||||
Limit: tt.limit,
|
||||
},
|
||||
Sort: tt.sort,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, limit, count)
|
||||
assert.Len(t, players, int(limit))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ERR: validation failed", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
params domain.ListEnnoblementsParams
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
name: "params.Pagination.Limit < 0",
|
||||
params: domain.ListEnnoblementsParams{
|
||||
Pagination: domain.Pagination{
|
||||
Limit: -1,
|
||||
},
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
Field: "limit",
|
||||
Err: domain.MinError{
|
||||
Min: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "params.Pagination.Limit > 3000",
|
||||
params: domain.ListEnnoblementsParams{
|
||||
Pagination: domain.Pagination{
|
||||
Limit: 3001,
|
||||
},
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
Field: "limit",
|
||||
Err: domain.MaxError{
|
||||
Max: 3000,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "params.Pagination.Offset < 0",
|
||||
params: domain.ListEnnoblementsParams{
|
||||
Pagination: domain.Pagination{
|
||||
Offset: -1,
|
||||
},
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
Field: "offset",
|
||||
Err: domain.MinError{
|
||||
Min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "len(params.Sort) > 2",
|
||||
params: domain.ListEnnoblementsParams{
|
||||
Sort: []domain.EnnoblementSort{
|
||||
{
|
||||
By: domain.EnnoblementSortByID,
|
||||
Direction: domain.SortDirectionASC,
|
||||
},
|
||||
{
|
||||
By: domain.EnnoblementSortByCreatedAt,
|
||||
Direction: domain.SortDirectionASC,
|
||||
},
|
||||
{
|
||||
By: domain.EnnoblementSortByCreatedAt,
|
||||
Direction: domain.SortDirectionASC,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: domain.ValidationError{
|
||||
Field: "sort",
|
||||
Err: domain.MaxLengthError{
|
||||
Max: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
repo := &mock.FakeEnnoblementRepository{}
|
||||
client := &mock.FakeEnnoblementsGetter{}
|
||||
|
||||
players, count, err := service.NewEnnoblement(repo, client).
|
||||
List(context.Background(), tt.params)
|
||||
assert.ErrorIs(t, err, tt.expectedErr)
|
||||
assert.Zero(t, players)
|
||||
assert.Zero(t, count)
|
||||
assert.Equal(t, 0, repo.ListCallCount())
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -176,8 +176,8 @@ func TestPlayer_List(t *testing.T) {
|
|||
}(tt.sort),
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
return make([]domain.Player, params.Pagination.Limit), int64(params.Pagination.Limit), nil
|
||||
|
|
|
@ -189,8 +189,8 @@ func TestTribe_List(t *testing.T) {
|
|||
}(tt.sort),
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
return make([]domain.Tribe, params.Pagination.Limit), int64(params.Pagination.Limit), nil
|
||||
|
|
|
@ -131,8 +131,8 @@ func TestVillage_List(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
if !cmp.Equal(params, expectedParams) {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", cmp.Diff(params, expectedParams))
|
||||
if diff := cmp.Diff(params, expectedParams); diff != "" {
|
||||
return nil, 0, fmt.Errorf("validation failed: %s", diff)
|
||||
}
|
||||
|
||||
return make([]domain.Village, params.Pagination.Limit), int64(params.Pagination.Limit), nil
|
||||
|
|
Reference in New Issue
Block a user