This repository has been archived on 2024-04-06. You can view files and clone it, but cannot push or open issues or pull requests.
core-old/internal/service/player_test.go
Dawid Wysokiński 0aed6f8fed
All checks were successful
continuous-integration/drone/push Build is passing
refactor: base models (#106)
Reviewed-on: twhelp/core#106
2022-10-20 04:16:37 +00:00

369 lines
8.6 KiB
Go

package service_test
import (
"context"
"fmt"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/tw"
"github.com/google/go-cmp/cmp"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"gitea.dwysokinski.me/twhelp/core/internal/service"
"gitea.dwysokinski.me/twhelp/core/internal/service/internal/mock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPlayer_Refresh(t *testing.T) {
t.Parallel()
serverKey, serverUrl := "pl169", "https://pl169.plemiona.pl"
players := []tw.Player{
{
OpponentsDefeated: tw.OpponentsDefeated{
RankAtt: 8,
ScoreAtt: 7,
RankDef: 6,
ScoreDef: 5,
RankSup: 4,
ScoreSup: 3,
RankTotal: 2,
ScoreTotal: 1,
},
ID: 998,
Name: "name 998",
NumVillages: 5,
Points: 4,
Rank: 2,
ProfileURL: "profile-998",
},
{
OpponentsDefeated: tw.OpponentsDefeated{
RankAtt: 1,
ScoreAtt: 2,
RankDef: 3,
ScoreDef: 4,
RankSup: 5,
ScoreSup: 6,
RankTotal: 7,
ScoreTotal: 8,
},
ID: 999,
Name: "name 999",
NumVillages: 3,
Points: 4,
Rank: 6,
TribeID: 1234,
ProfileURL: "profile-999",
},
}
client := &mock.FakePlayerGetter{}
client.GetPlayersReturns(players, nil)
existingPlayers := []domain.Player{
{
OpponentsDefeated: domain.OpponentsDefeated{
RankAtt: 8,
ScoreAtt: 7,
RankDef: 6,
ScoreDef: 5,
RankSup: 4,
ScoreSup: 3,
RankTotal: 2,
ScoreTotal: 1,
},
ID: 997,
Name: "name 997",
NumVillages: 5,
Points: 4,
Rank: 2,
ProfileURL: "profile-997",
ServerKey: serverKey,
CreatedAt: time.Now(),
},
{
OpponentsDefeated: domain.OpponentsDefeated(players[0].OpponentsDefeated),
ID: players[0].ID,
Name: players[0].Name,
NumVillages: players[0].NumVillages,
Points: players[0].Points,
Rank: players[0].Rank,
TribeID: players[0].TribeID,
ProfileURL: players[0].ProfileURL,
ServerKey: serverKey,
CreatedAt: time.Now(),
},
}
repo := &mock.FakePlayerRepository{}
repo.ListReturnsOnCall(0, existingPlayers, 0, nil)
repo.CreateOrUpdateReturns(nil)
repo.DeleteByIDReturns(nil)
numPlayers, err := service.NewPlayer(repo, client).Refresh(context.Background(), serverKey, serverUrl)
assert.NoError(t, err)
assert.EqualValues(t, len(players), numPlayers)
require.Equal(t, 1, client.GetPlayersCallCount())
_, passedServerUrl := client.GetPlayersArgsForCall(0)
assert.Equal(t, passedServerUrl, serverUrl)
require.Equal(t, 1, repo.CreateOrUpdateCallCount())
_, params := repo.CreateOrUpdateArgsForCall(0)
assert.Len(t, params, len(players))
for i, p := range params {
assert.EqualValues(t, players[i].OpponentsDefeated, p.OpponentsDefeated)
assert.Equal(t, players[i].ID, p.ID)
assert.Equal(t, players[i].Name, p.Name)
assert.Equal(t, players[i].NumVillages, p.NumVillages)
assert.Equal(t, players[i].Points, p.Points)
assert.Equal(t, players[i].Rank, p.Rank)
assert.Equal(t, players[i].TribeID, p.TribeID)
assert.Equal(t, players[i].ProfileURL, p.ProfileURL)
assert.Equal(t, serverKey, p.ServerKey)
}
require.Equal(t, 1, repo.DeleteByIDCallCount())
_, playersToDelete := repo.DeleteByIDArgsForCall(0)
require.Len(t, playersToDelete, 1)
assert.Equal(t, existingPlayers[0].ID, playersToDelete[0])
require.Equal(t, 1, repo.ListCallCount())
}
func TestPlayer_List(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
limit int32
sort []domain.PlayerSort
}{
{
name: "default limit, default sort",
limit: 0,
sort: nil,
},
{
name: "custom limit",
limit: 199,
},
{
name: "custom sort",
limit: 0,
sort: []domain.PlayerSort{
{By: domain.PlayerSortByPoints, 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 = 200
}
repo := &mock.FakePlayerRepository{}
repo.ListCalls(func(_ context.Context, params domain.ListPlayersParams) ([]domain.Player, int64, error) {
expectedParams := domain.ListPlayersParams{
Pagination: domain.Pagination{
Limit: limit,
},
Sort: func(sort []domain.PlayerSort) []domain.PlayerSort {
if len(sort) == 0 {
return []domain.PlayerSort{
{
By: domain.PlayerSortByID,
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.Player, params.Pagination.Limit), int64(params.Pagination.Limit), nil
})
client := &mock.FakePlayerGetter{}
players, count, err := service.NewPlayer(repo, client).
List(context.Background(), domain.ListPlayersParams{
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.ListPlayersParams
expectedErr error
}{
{
name: "params.Pagination.Limit < 0",
params: domain.ListPlayersParams{
Pagination: domain.Pagination{
Limit: -1,
},
},
expectedErr: domain.ValidationError{
Field: "limit",
Err: domain.MinError{
Min: 1,
},
},
},
{
name: "params.Pagination.Limit > 200",
params: domain.ListPlayersParams{
Pagination: domain.Pagination{
Limit: 201,
},
},
expectedErr: domain.ValidationError{
Field: "limit",
Err: domain.MaxError{
Max: 200,
},
},
},
{
name: "params.Pagination.Offset < 0",
params: domain.ListPlayersParams{
Pagination: domain.Pagination{
Offset: -1,
},
},
expectedErr: domain.ValidationError{
Field: "offset",
Err: domain.MinError{
Min: 0,
},
},
},
{
name: "len(params.Sort) > 3",
params: domain.ListPlayersParams{
Sort: []domain.PlayerSort{
{
By: domain.PlayerSortByID,
Direction: domain.SortDirectionASC,
},
{
By: domain.PlayerSortByScoreDef,
Direction: domain.SortDirectionDESC,
},
{
By: domain.PlayerSortByScoreTotal,
Direction: domain.SortDirectionASC,
},
{
By: domain.PlayerSortByScoreAtt,
Direction: domain.SortDirectionASC,
},
},
},
expectedErr: domain.ValidationError{
Field: "sort",
Err: domain.MaxLengthError{
Max: 3,
},
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
repo := &mock.FakePlayerRepository{}
client := &mock.FakePlayerGetter{}
players, count, err := service.NewPlayer(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())
})
}
})
}
func TestPlayer_GetByServerKeyAndID(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
player := domain.Player{
ID: 123,
TribeID: 123,
Tribe: domain.NullTribe{
Valid: true,
Tribe: domain.Tribe{
ID: 123,
},
},
ServerKey: "pl151",
}
repo := &mock.FakePlayerRepository{}
repo.ListReturns([]domain.Player{player}, 0, nil)
client := &mock.FakePlayerGetter{}
res, err := service.NewPlayer(repo, client).
GetByServerKeyAndID(context.Background(), player.ServerKey, player.ID, true)
assert.NoError(t, err)
assert.Equal(t, player, res)
require.Equal(t, 1, repo.ListCallCount())
_, params := repo.ListArgsForCall(0)
assert.Equal(t, domain.ListPlayersParams{
IDs: []int64{player.ID},
ServerKeys: []string{player.ServerKey},
IncludeTribe: true,
Pagination: domain.Pagination{
Limit: 1,
},
}, params)
})
t.Run("ERR: player not found", func(t *testing.T) {
t.Parallel()
repo := &mock.FakePlayerRepository{}
client := &mock.FakePlayerGetter{}
var id int64 = 123
res, err := service.NewPlayer(repo, client).
GetByServerKeyAndID(context.Background(), "pl151", id, false)
assert.ErrorIs(t, err, domain.PlayerNotFoundError{ID: id})
assert.Zero(t, res)
})
}