package service_test import ( "context" "fmt" "testing" "time" "gitea.dwysokinski.me/twhelp/dcbot/internal/domain" "gitea.dwysokinski.me/twhelp/dcbot/internal/service" "gitea.dwysokinski.me/twhelp/dcbot/internal/service/internal/mock" "gitea.dwysokinski.me/twhelp/dcbot/internal/twhelp" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" ) func TestGroup_Create(t *testing.T) { t.Parallel() params, err := domain.NewCreateGroupParams( "592292203234328587", "en", "en113", "1234", "1235", true, true, ) require.NoError(t, err) t.Run("OK", func(t *testing.T) { t.Parallel() repo := &mock.FakeGroupRepository{} repo.CreateCalls(func(_ context.Context, p domain.CreateGroupParams) (domain.Group, error) { return domain.Group{ ID: uuid.NewString(), ServerID: p.ServerID(), ChannelGains: p.ChannelGains(), ChannelLosses: p.ChannelLosses(), Barbarians: p.Barbarians(), Internals: p.Internals(), ServerKey: p.ServerKey(), VersionCode: p.VersionCode(), CreatedAt: time.Now(), }, nil }) repo.ListReturns(nil, nil) client := &mock.FakeTWHelpClient{} client.GetServerCalls(func(_ context.Context, _ string, server string) (twhelp.Server, error) { return twhelp.Server{ Key: server, URL: fmt.Sprintf("https://%s.tribalwars.net", server), Open: true, }, nil }) g, err := service.NewGroup(repo, client, zap.NewNop(), 1).Create(context.Background(), params) assert.NoError(t, err) assert.NotEmpty(t, g.ID) assert.Equal(t, params.ServerID(), g.ServerID) assert.Equal(t, params.ServerKey(), g.ServerKey) assert.Equal(t, params.VersionCode(), g.VersionCode) assert.Equal(t, params.ChannelGains(), g.ChannelGains) assert.Equal(t, params.ChannelLosses(), g.ChannelLosses) assert.Equal(t, params.Barbarians(), g.Barbarians) assert.Equal(t, params.Internals(), g.Barbarians) assert.NotEmpty(t, g.CreatedAt) }) t.Run("ERR: group limit has been reached", func(t *testing.T) { t.Parallel() const maxGroupsPerServer = 10 repo := &mock.FakeGroupRepository{} repo.ListReturns(make([]domain.Group, maxGroupsPerServer), nil) g, err := service.NewGroup(repo, nil, zap.NewNop(), maxGroupsPerServer).Create(context.Background(), params) assert.ErrorIs(t, err, domain.GroupLimitReachedError{ Current: maxGroupsPerServer, Limit: maxGroupsPerServer, }) assert.Zero(t, g) }) t.Run("ERR: server doesn't exist", func(t *testing.T) { t.Parallel() repo := &mock.FakeGroupRepository{} repo.ListReturns(nil, nil) client := &mock.FakeTWHelpClient{} client.GetServerCalls(func(_ context.Context, _ string, _ string) (twhelp.Server, error) { return twhelp.Server{}, twhelp.APIError{ Code: twhelp.ErrorCodeEntityNotFound, Message: "server not found", } }) g, err := service.NewGroup(repo, client, zap.NewNop(), 1).Create(context.Background(), params) assert.ErrorIs(t, err, domain.ServerDoesNotExistError{ VersionCode: params.VersionCode(), Key: params.ServerKey(), }) assert.Zero(t, g) }) t.Run("ERR: server is closed", func(t *testing.T) { t.Parallel() repo := &mock.FakeGroupRepository{} repo.ListReturns(nil, nil) client := &mock.FakeTWHelpClient{} client.GetServerCalls(func(ctx context.Context, _ string, server string) (twhelp.Server, error) { return twhelp.Server{ Key: server, URL: fmt.Sprintf("https://%s.tribalwars.net", server), Open: false, }, nil }) g, err := service.NewGroup(repo, client, zap.NewNop(), 1).Create(context.Background(), params) assert.ErrorIs(t, err, domain.ServerIsClosedError{ VersionCode: params.VersionCode(), Key: params.ServerKey(), }) assert.Zero(t, g) }) } func TestGroup_CleanUp(t *testing.T) { t.Parallel() repo := &mock.FakeGroupRepository{} groupsWithDisabledNotifications := []domain.Group{ { ID: uuid.NewString(), ServerID: uuid.NewString(), ChannelGains: "", ChannelLosses: "", Internals: true, Barbarians: true, ServerKey: "pl181", VersionCode: "pl", CreatedAt: time.Now().Add(-48 * time.Hour), }, { ID: uuid.NewString(), ServerID: uuid.NewString(), ChannelGains: "", ChannelLosses: "", Internals: true, Barbarians: true, ServerKey: "pl181", VersionCode: "pl", CreatedAt: time.Now().Add(-45 * time.Hour), }, } repo.ListReturnsOnCall(0, groupsWithDisabledNotifications, nil) groupsPL := []domain.Group{ { ID: uuid.NewString(), ServerID: uuid.NewString(), ChannelGains: uuid.NewString(), ChannelLosses: "", Internals: true, Barbarians: true, ServerKey: "pl181", VersionCode: "pl", CreatedAt: time.Now().Add(-120 * time.Hour), }, { ID: uuid.NewString(), ServerID: uuid.NewString(), ChannelGains: uuid.NewString(), ChannelLosses: uuid.NewString(), Internals: true, Barbarians: true, ServerKey: "pl181", VersionCode: "pl", CreatedAt: time.Now().Add(-11 * time.Hour), }, } repo.ListReturnsOnCall(1, groupsPL, nil) groupsUK := []domain.Group{ { ID: uuid.NewString(), ServerID: uuid.NewString(), ChannelGains: uuid.NewString(), ChannelLosses: uuid.NewString(), Internals: true, Barbarians: true, ServerKey: "uk51", VersionCode: "uk", CreatedAt: time.Now().Add(-150 * time.Hour), }, { ID: uuid.NewString(), ServerID: uuid.NewString(), ChannelGains: uuid.NewString(), ChannelLosses: uuid.NewString(), Internals: true, Barbarians: true, ServerKey: "uk52", VersionCode: "uk", CreatedAt: time.Now().Add(-200 * time.Hour), }, } repo.ListReturnsOnCall(2, groupsUK, nil) repo.DeleteManyReturns(nil) client := &mock.FakeTWHelpClient{} versions := []twhelp.Version{ { Code: "pl", Host: "www.plemiona.pl", Name: "Poland", Timezone: "Europe/Warsaw", }, { Code: "uk", Host: "www.tribalwars.co.uk", Name: "United Kingdom", Timezone: "Europe/London", }, { Code: "tr", Host: "www.klanlar.org", Name: "Turkey", Timezone: "Europe/Istanbul", }, } client.ListVersionsReturns(versions, nil) serversPL := []twhelp.Server{ { Key: "pl181", URL: "https://pl181.plemiona.pl", Open: false, }, } client.ListServersReturnsOnCall(0, serversPL, nil) serversUK := []twhelp.Server{ { Key: "uk51", URL: "https://uk51.tribalwars.co.uk", Open: false, }, { Key: "uk52", URL: "https://uk52.tribalwars.co.uk", Open: false, }, } client.ListServersReturnsOnCall(1, serversUK, nil) client.ListServersReturnsOnCall(1, serversUK, nil) client.ListServersReturnsOnCall(2, nil, nil) // Turkey assert.NoError(t, service.NewGroup(repo, client, zap.NewNop(), 1).CleanUp(context.Background())) require.Equal(t, 3, repo.ListCallCount()) require.Equal(t, 3, repo.DeleteManyCallCount()) for _, tt := range []struct { i int groups []domain.Group }{ { i: 0, groups: groupsWithDisabledNotifications, }, { i: 1, groups: groupsPL, }, { i: 2, groups: groupsUK, }, } { _, ids := repo.DeleteManyArgsForCall(tt.i) assert.Len(t, ids, len(tt.groups)) for i, id := range ids { assert.Equal(t, tt.groups[i].ID, id) } } require.Equal(t, 1, client.ListVersionsCallCount()) require.Equal(t, 3, client.ListServersCallCount()) }