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/tribe_test.go
Dawid Wysokiński 42f95d6dd1
All checks were successful
continuous-integration/drone/push Build is passing
fix: tribe - fix incorrect most points logic
2023-02-26 09:51:52 +01:00

515 lines
13 KiB
Go

package service_test
import (
"context"
"fmt"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/tw"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"gitea.dwysokinski.me/twhelp/core/internal/service"
"github.com/stretchr/testify/assert"
"gitea.dwysokinski.me/twhelp/core/internal/service/internal/mock"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
)
func TestTribe_Refresh(t *testing.T) {
t.Parallel()
serverKey, serverUrl := "pl169", "https://pl169.plemiona.pl"
tribes := []tw.Tribe{
{
OpponentsDefeated: tw.OpponentsDefeated{ // update
RankAtt: 8,
ScoreAtt: 7,
RankDef: 6,
ScoreDef: 5,
RankSup: 4,
ScoreSup: 3,
RankTotal: 2,
ScoreTotal: 1,
},
ID: 998,
Name: "name 998",
Tag: "tag 998",
NumMembers: 6,
NumVillages: 5,
Points: 4,
AllPoints: 3,
Rank: 2,
ProfileURL: "profile-998",
},
{
OpponentsDefeated: tw.OpponentsDefeated{ // create
RankAtt: 1,
ScoreAtt: 2,
RankDef: 3,
ScoreDef: 4,
RankSup: 5,
ScoreSup: 6,
RankTotal: 7,
ScoreTotal: 8,
},
ID: 999,
Name: "name 999",
Tag: "tag 999",
NumMembers: 2,
NumVillages: 3,
Points: 4,
AllPoints: 5,
Rank: 6,
ProfileURL: "profile-999",
},
{
OpponentsDefeated: tw.OpponentsDefeated{ // update
RankAtt: 111,
ScoreAtt: 222,
RankDef: 333,
ScoreDef: 444,
RankSup: 555,
ScoreSup: 666,
RankTotal: 777,
ScoreTotal: 888,
},
ID: 1000,
Name: "name 1000",
Tag: "tag 1000",
NumMembers: 222,
NumVillages: 333,
Points: 444,
AllPoints: 555,
Rank: 666,
ProfileURL: "profile-1000",
},
}
client := &mock.FakeTribeGetter{}
client.GetTribesReturns(tribes, nil)
existingTribes := []domain.Tribe{
{
OpponentsDefeated: domain.OpponentsDefeated{ // delete
RankAtt: 8,
ScoreAtt: 7,
RankDef: 6,
ScoreDef: 5,
RankSup: 4,
ScoreSup: 3,
RankTotal: 2,
ScoreTotal: 1,
},
ID: 997,
Name: "name 997",
Tag: "tag 997",
NumMembers: 6,
NumVillages: 5,
Points: 4,
AllPoints: 3,
Rank: 2,
Dominance: 12.5,
ProfileURL: "profile-997",
BestRank: 2,
BestRankAt: time.Now(),
MostPoints: 4,
MostPointsAt: time.Now(),
MostVillages: 5,
MostVillagesAt: time.Now(),
ServerKey: serverKey,
CreatedAt: time.Now(),
},
{
OpponentsDefeated: domain.OpponentsDefeated(tribes[0].OpponentsDefeated), // update
ID: tribes[0].ID,
Name: tribes[0].Name,
Tag: tribes[0].Tag,
NumMembers: tribes[0].NumMembers,
NumVillages: tribes[0].NumVillages,
Points: tribes[0].Points,
AllPoints: tribes[0].AllPoints,
Rank: tribes[0].Rank,
Dominance: 11.5,
ProfileURL: tribes[0].ProfileURL,
BestRank: tribes[0].Rank,
BestRankAt: time.Now().Add(-5 * time.Minute),
MostPoints: tribes[0].Points,
MostPointsAt: time.Now().Add(-5 * time.Minute),
MostVillages: tribes[0].NumVillages,
MostVillagesAt: time.Now().Add(-5 * time.Minute),
ServerKey: serverKey,
CreatedAt: time.Now().Add(-5 * time.Minute),
},
{
OpponentsDefeated: domain.OpponentsDefeated(tribes[2].OpponentsDefeated), // update
ID: tribes[2].ID,
Name: tribes[2].Name,
Tag: tribes[2].Tag,
NumMembers: tribes[2].NumMembers,
NumVillages: tribes[2].NumVillages,
Points: tribes[2].Points,
AllPoints: tribes[2].AllPoints,
Rank: tribes[2].Rank,
Dominance: 11.5,
ProfileURL: tribes[2].ProfileURL,
BestRank: tribes[2].Rank + 1,
BestRankAt: time.Now().Add(-15 * time.Minute),
MostPoints: tribes[2].Points - 1,
MostPointsAt: time.Now().Add(-20 * time.Minute),
MostVillages: tribes[2].NumVillages - 1,
MostVillagesAt: time.Now().Add(-13 * time.Minute),
ServerKey: serverKey,
CreatedAt: time.Now(),
DeletedAt: time.Time{},
},
}
repo := &mock.FakeTribeRepository{}
repo.ListReturns(existingTribes, nil)
repo.CreateOrUpdateReturns(nil)
repo.DeleteReturns(nil)
numTribes, err := service.NewTribe(repo, client).Refresh(context.Background(), serverKey, serverUrl)
assert.NoError(t, err)
assert.EqualValues(t, len(tribes), numTribes)
require.Equal(t, 1, client.GetTribesCallCount())
_, passedServerUrl := client.GetTribesArgsForCall(0)
assert.Equal(t, passedServerUrl, serverUrl)
require.Equal(t, 1, repo.CreateOrUpdateCallCount())
_, params := repo.CreateOrUpdateArgsForCall(0)
expectedParams := []domain.CreateTribeParams{
{
OpponentsDefeated: domain.OpponentsDefeated(tribes[0].OpponentsDefeated),
ID: tribes[0].ID,
Name: tribes[0].Name,
Tag: tribes[0].Tag,
NumMembers: tribes[0].NumMembers,
NumVillages: tribes[0].NumVillages,
Points: tribes[0].Points,
AllPoints: tribes[0].AllPoints,
Rank: tribes[0].Rank,
ProfileURL: tribes[0].ProfileURL,
BestRank: existingTribes[1].BestRank,
BestRankAt: existingTribes[1].BestRankAt,
MostPoints: existingTribes[1].MostPoints,
MostPointsAt: existingTribes[1].MostPointsAt,
MostVillages: existingTribes[1].MostVillages,
MostVillagesAt: existingTribes[1].MostVillagesAt,
ServerKey: serverKey,
},
{
OpponentsDefeated: domain.OpponentsDefeated(tribes[1].OpponentsDefeated),
ID: tribes[1].ID,
Name: tribes[1].Name,
Tag: tribes[1].Tag,
NumMembers: tribes[1].NumMembers,
NumVillages: tribes[1].NumVillages,
Points: tribes[1].Points,
AllPoints: tribes[1].AllPoints,
Rank: tribes[1].Rank,
ProfileURL: tribes[1].ProfileURL,
BestRank: tribes[1].Rank,
BestRankAt: time.Now(),
MostPoints: tribes[1].AllPoints,
MostPointsAt: time.Now(),
MostVillages: tribes[1].NumVillages,
MostVillagesAt: time.Now(),
ServerKey: serverKey,
},
{
OpponentsDefeated: domain.OpponentsDefeated(tribes[2].OpponentsDefeated),
ID: tribes[2].ID,
Name: tribes[2].Name,
Tag: tribes[2].Tag,
NumMembers: tribes[2].NumMembers,
NumVillages: tribes[2].NumVillages,
Points: tribes[2].Points,
AllPoints: tribes[2].AllPoints,
Rank: tribes[2].Rank,
ProfileURL: tribes[2].ProfileURL,
BestRank: tribes[2].Rank,
BestRankAt: time.Now(),
MostPoints: tribes[2].AllPoints,
MostPointsAt: time.Now(),
MostVillages: tribes[2].NumVillages,
MostVillagesAt: time.Now(),
ServerKey: serverKey,
},
}
assert.Empty(t, cmp.Diff(
params,
expectedParams,
cmp.Comparer(func(x time.Time, y time.Time) bool {
dt := x.Sub(y)
return dt > -time.Second || dt < time.Second
}),
))
require.Equal(t, 1, repo.DeleteCallCount())
_, serverKeyDelete, tribesToDelete := repo.DeleteArgsForCall(0)
assert.Equal(t, serverKey, serverKeyDelete)
assert.Contains(t, tribesToDelete, existingTribes[0].ID)
require.Equal(t, 2, repo.ListCallCount())
}
func TestTribe_List_ListCount(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
limit int32
sort []domain.TribeSort
}{
{
name: "default limit, default sort",
limit: 0,
sort: nil,
},
{
name: "custom limit",
limit: 199,
},
{
name: "custom sort",
limit: 0,
sort: []domain.TribeSort{
{By: domain.TribeSortByPoints, 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.FakeTribeRepository{}
repo.ListCountCalls(func(_ context.Context, params domain.ListTribesParams) ([]domain.Tribe, int64, error) {
expectedParams := domain.ListTribesParams{
Pagination: domain.Pagination{
Limit: limit,
},
Sort: func(sort []domain.TribeSort) []domain.TribeSort {
if len(sort) == 0 {
return []domain.TribeSort{
{
By: domain.TribeSortByID,
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.Tribe, params.Pagination.Limit), int64(params.Pagination.Limit), nil
})
repo.ListCalls(func(ctx context.Context, params domain.ListTribesParams) ([]domain.Tribe, error) {
tribes, _, err := repo.ListCount(ctx, params)
return tribes, err
})
client := &mock.FakeTribeGetter{}
svc := service.NewTribe(repo, client)
params := domain.ListTribesParams{
Pagination: domain.Pagination{
Limit: tt.limit,
},
Sort: tt.sort,
}
tribesListCount, count, err := svc.ListCount(context.Background(), params)
assert.NoError(t, err)
assert.EqualValues(t, limit, count)
assert.Len(t, tribesListCount, int(limit))
tribesList, err := svc.List(context.Background(), params)
assert.NoError(t, err)
assert.Equal(t, tribesListCount, tribesList)
})
}
})
t.Run("ERR: validation failed", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
params domain.ListTribesParams
expectedErr error
}{
{
name: "params.Pagination.Limit < 0",
params: domain.ListTribesParams{
Pagination: domain.Pagination{
Limit: -1,
},
},
expectedErr: domain.ValidationError{
Field: "limit",
Err: domain.MinError{
Min: 1,
},
},
},
{
name: "params.Pagination.Limit > 200",
params: domain.ListTribesParams{
Pagination: domain.Pagination{
Limit: 201,
},
},
expectedErr: domain.ValidationError{
Field: "limit",
Err: domain.MaxError{
Max: 200,
},
},
},
{
name: "params.Pagination.Offset < 0",
params: domain.ListTribesParams{
Pagination: domain.Pagination{
Offset: -1,
},
},
expectedErr: domain.ValidationError{
Field: "offset",
Err: domain.MinError{
Min: 0,
},
},
},
{
name: "len(params.Sort) > 3",
params: domain.ListTribesParams{
Sort: []domain.TribeSort{
{
By: domain.TribeSortByID,
Direction: domain.SortDirectionASC,
},
{
By: domain.TribeSortByScoreDef,
Direction: domain.SortDirectionDESC,
},
{
By: domain.TribeSortByScoreTotal,
Direction: domain.SortDirectionASC,
},
{
By: domain.TribeSortByScoreAtt,
Direction: domain.SortDirectionASC,
},
},
},
expectedErr: domain.ValidationError{
Field: "sort",
Err: domain.MaxLengthError{
Max: 3,
},
},
},
{
name: "len(params.Tags) > 20",
params: domain.ListTribesParams{
Tags: make([]string, 21),
},
expectedErr: domain.ValidationError{
Field: "tag",
Err: domain.MaxLengthError{
Max: 20,
},
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
repo := &mock.FakeTribeRepository{}
client := &mock.FakeTribeGetter{}
svc := service.NewTribe(repo, client)
tribes, count, err := svc.ListCount(context.Background(), tt.params)
assert.ErrorIs(t, err, tt.expectedErr)
assert.Zero(t, tribes)
assert.Zero(t, count)
assert.Equal(t, 0, repo.ListCountCallCount())
tribes, err = svc.List(context.Background(), tt.params)
assert.ErrorIs(t, err, tt.expectedErr)
assert.Zero(t, tribes)
assert.Equal(t, 0, repo.ListCallCount())
})
}
})
}
func TestTribe_GetByServerKeyAndID(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
tribe := domain.Tribe{
ID: 123,
ServerKey: "pl151",
}
repo := &mock.FakeTribeRepository{}
repo.ListReturns([]domain.Tribe{tribe}, nil)
client := &mock.FakeTribeGetter{}
res, err := service.NewTribe(repo, client).
GetByServerKeyAndID(context.Background(), tribe.ServerKey, tribe.ID)
assert.NoError(t, err)
assert.Equal(t, tribe, res)
require.Equal(t, 1, repo.ListCallCount())
_, params := repo.ListArgsForCall(0)
assert.Equal(t, domain.ListTribesParams{
IDs: []int64{tribe.ID},
ServerKeys: []string{tribe.ServerKey},
Pagination: domain.Pagination{
Limit: 1,
},
}, params)
})
t.Run("ERR: tribe not found", func(t *testing.T) {
t.Parallel()
repo := &mock.FakeTribeRepository{}
client := &mock.FakeTribeGetter{}
var id int64 = 123
res, err := service.NewTribe(repo, client).
GetByServerKeyAndID(context.Background(), "pl151", id)
assert.ErrorIs(t, err, domain.TribeNotFoundError{ID: id})
assert.Zero(t, res)
})
}