package service_test import ( "context" "errors" "fmt" "testing" "time" "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/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestTribeSnapshot_Create(t *testing.T) { t.Parallel() serverKey := "pl151" tribeSvc := &mock.FakeTribeLister{} tribes := []domain.Tribe{ { OpponentsDefeated: domain.OpponentsDefeated{ 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, ProfileURL: "profile-997", ServerKey: "pl151", Dominance: 12.5, CreatedAt: time.Now(), }, { OpponentsDefeated: domain.OpponentsDefeated{ RankAtt: 1, ScoreAtt: 2, RankDef: 3, ScoreDef: 4, RankSup: 5, ScoreSup: 6, RankTotal: 7, ScoreTotal: 9, }, ID: 998, Name: "name 998", Tag: "tag 998", NumMembers: 1, NumVillages: 2, Points: 3, AllPoints: 4, Rank: 5, ProfileURL: "profile-998", ServerKey: "pl151", Dominance: 12.55, CreatedAt: time.Now().Add(-5000 * time.Hour), DeletedAt: time.Now(), }, } tribeSvc.ListCalls(func(ctx context.Context, params domain.ListTribesParams) ([]domain.Tribe, error) { if len(params.ServerKeys) == 0 || params.ServerKeys[0] != serverKey { return nil, errors.New("incorrect server key") } return tribes, nil }) repo := &mock.FakeTribeSnapshotRepository{} repo.CreateReturns(nil) date := time.Now() assert.NoError(t, service.NewTribeSnapshot(repo, tribeSvc).Create(context.Background(), serverKey, date)) require.Equal(t, 1, repo.CreateCallCount()) _, argParams := repo.CreateArgsForCall(0) require.Len(t, argParams, len(tribes)) for i, tribe := range tribes { assert.Equal(t, domain.CreateTribeSnapshotParams{ OpponentsDefeated: tribe.OpponentsDefeated, TribeID: tribe.ID, ServerKey: serverKey, NumMembers: tribe.NumMembers, NumVillages: tribe.NumVillages, Points: tribe.Points, AllPoints: tribe.AllPoints, Rank: tribe.Rank, Dominance: tribe.Dominance, Date: date, }, argParams[i]) } } func TestTribeSnapshot_ListCount(t *testing.T) { t.Parallel() var defaultLimit int32 = 100 defaultSort := []domain.TribeSnapshotSort{ { By: domain.TribeSnapshotSortByDate, Direction: domain.SortDirectionASC, }, { By: domain.TribeSnapshotSortByID, Direction: domain.SortDirectionASC, }, } tests := []struct { name string params domain.ListTribeSnapshotsParams expectedParams domain.ListTribeSnapshotsParams expectedErr error }{ { name: "OK: default limit/default sort", params: domain.ListTribeSnapshotsParams{}, expectedParams: domain.ListTribeSnapshotsParams{ Sort: defaultSort, Pagination: domain.Pagination{ Limit: defaultLimit, }, }, }, { name: "OK: custom pagination", params: domain.ListTribeSnapshotsParams{ Pagination: domain.Pagination{ Limit: 99, Offset: 1, }, }, expectedParams: domain.ListTribeSnapshotsParams{ Sort: defaultSort, Pagination: domain.Pagination{ Limit: 99, Offset: 1, }, }, }, { name: "OK: custom sort", params: domain.ListTribeSnapshotsParams{ Sort: []domain.TribeSnapshotSort{ {By: domain.TribeSnapshotSortByDate, Direction: domain.SortDirectionDESC}, }, }, expectedParams: domain.ListTribeSnapshotsParams{ Sort: []domain.TribeSnapshotSort{ {By: domain.TribeSnapshotSortByDate, Direction: domain.SortDirectionDESC}, }, Pagination: domain.Pagination{ Limit: defaultLimit, }, }, }, { name: "ERR: params.Pagination.Limit < 0", params: domain.ListTribeSnapshotsParams{ Pagination: domain.Pagination{ Limit: -1, }, }, expectedErr: domain.ValidationError{ Field: "limit", Err: domain.MinError{ Min: 1, }, }, }, { name: "ERR: params.Pagination.Limit > 100", params: domain.ListTribeSnapshotsParams{ Pagination: domain.Pagination{ Limit: 101, }, }, expectedErr: domain.ValidationError{ Field: "limit", Err: domain.MaxError{ Max: 100, }, }, }, { name: "ERR: params.Pagination.Offset < 0", params: domain.ListTribeSnapshotsParams{ Pagination: domain.Pagination{ Offset: -1, }, }, expectedErr: domain.ValidationError{ Field: "offset", Err: domain.MinError{ Min: 0, }, }, }, { name: "ERR: len(params.Sort) > 2", params: domain.ListTribeSnapshotsParams{ Sort: []domain.TribeSnapshotSort{ { By: domain.TribeSnapshotSortByID, Direction: domain.SortDirectionASC, }, { By: domain.TribeSnapshotSortByDate, Direction: domain.SortDirectionASC, }, { By: domain.TribeSnapshotSortByID, Direction: domain.SortDirectionDESC, }, }, }, 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.FakeTribeSnapshotRepository{} repo.ListCountCalls(func( _ context.Context, params domain.ListTribeSnapshotsParams, ) ([]domain.TribeSnapshot, int64, error) { if diff := cmp.Diff(params, tt.expectedParams); diff != "" { return nil, 0, fmt.Errorf("validation failed: %s", diff) } return make([]domain.TribeSnapshot, params.Pagination.Limit), int64(params.Pagination.Limit), nil }) snapshots, count, err := service.NewTribeSnapshot(repo, &mock.FakeTribeLister{}). ListCount(context.Background(), tt.params) assert.ErrorIs(t, err, tt.expectedErr) assert.EqualValues(t, tt.expectedParams.Pagination.Limit, count) assert.Len(t, snapshots, int(tt.expectedParams.Pagination.Limit)) }) } } func TestTribeSnapshot_CleanUp(t *testing.T) { t.Parallel() serverKey := "pl151" tribeSvc := &mock.FakeTribeLister{} repo := &mock.FakeTribeSnapshotRepository{} repo.DeleteReturns(nil) svc := service.NewTribeSnapshot(repo, tribeSvc) assert.NoError(t, svc.CleanUp(context.Background(), domain.Server{ Key: serverKey, Special: true, Open: false, TribeSnapshotsCreatedAt: time.Now().Add(-30 * 24 * time.Hour), })) assert.Equal(t, 0, repo.DeleteCallCount()) // only servers with Special = false assert.NoError(t, svc.CleanUp(context.Background(), domain.Server{ Key: serverKey, Special: false, Open: true, TribeSnapshotsCreatedAt: time.Now().Add(-30 * 24 * time.Hour), })) assert.Equal(t, 0, repo.DeleteCallCount()) // only servers with Open = false assert.NoError(t, svc.CleanUp(context.Background(), domain.Server{ Key: serverKey, Special: false, Open: false, TribeSnapshotsCreatedAt: time.Now(), })) assert.Equal(t, 0, repo.DeleteCallCount()) // only servers with TribeSnapshotsCreatedAt < now - 30 days assert.NoError(t, svc.CleanUp(context.Background(), domain.Server{ Key: serverKey, Special: false, Open: false, TribeSnapshotsCreatedAt: time.Now().Add(-30 * 24 * time.Hour), })) require.Equal(t, 1, repo.DeleteCallCount()) _, argServerKey, argCreatedAtLTE := repo.DeleteArgsForCall(0) assert.Equal(t, serverKey, argServerKey) assert.WithinDuration(t, time.Now().Add(-180*24*time.Hour), argCreatedAtLTE, time.Second) }