dcbot/internal/adapter/group_bun_repository_test.go

594 lines
13 KiB
Go

package adapter_test
import (
"context"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/dcbot/internal/adapter"
"gitea.dwysokinski.me/twhelp/dcbot/internal/domain"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/text/language"
)
func TestGroupBunRepository_Create(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
repo := adapter.NewGroupBunRepository(newBunDB(t))
t.Run("OK", func(t *testing.T) {
t.Parallel()
params, err := domain.NewCreateGroupParams(
"592292203234328587",
"en",
"en113",
language.Polish.String(),
"1234",
"1235",
true,
true,
)
require.NoError(t, err)
group, err := repo.Create(context.Background(), params)
assert.NoError(t, err)
assert.NotZero(t, group.ID)
assert.Equal(t, params.ServerID(), group.ServerID)
assert.Equal(t, params.ServerKey(), group.ServerKey)
assert.Equal(t, params.VersionCode(), group.VersionCode)
assert.Equal(t, params.ChannelGains(), group.ChannelGains)
assert.Equal(t, params.ChannelLosses(), group.ChannelLosses)
assert.Equal(t, params.Barbarians(), group.Barbarians)
assert.Equal(t, params.Internals(), group.Internals)
assert.Equal(t, params.LanguageTag(), group.LanguageTag)
assert.WithinDuration(t, time.Now(), group.CreatedAt, 1*time.Second)
})
}
func TestGroupBunRepository_Update(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := adapter.NewGroupBunRepository(db)
group := fixture.group(t, "group-1-server-1")
t.Run("OK", func(t *testing.T) {
t.Parallel()
params := domain.UpdateGroupParams{
ChannelGains: domain.NullString{
String: group.ChannelGains + "update",
Valid: true,
},
ChannelLosses: domain.NullString{
String: group.ChannelLosses + "update",
Valid: true,
},
LanguageTag: domain.NullString{
String: language.AmericanEnglish.String(),
Valid: true,
},
Barbarians: domain.NullBool{
Bool: !group.Barbarians,
Valid: true,
},
Internals: domain.NullBool{
Bool: !group.Internals,
Valid: true,
},
}
updatedGroup, err := repo.Update(context.Background(), group.ID, params)
assert.NoError(t, err)
assert.Equal(t, params.ChannelGains.String, updatedGroup.ChannelGains)
assert.Equal(t, params.ChannelLosses.String, updatedGroup.ChannelLosses)
assert.Equal(t, params.LanguageTag.String, updatedGroup.LanguageTag)
assert.Equal(t, params.Barbarians.Bool, updatedGroup.Barbarians)
assert.Equal(t, params.Internals.Bool, updatedGroup.Internals)
})
t.Run("ERR: nothing to update", func(t *testing.T) {
t.Parallel()
updatedGroup, err := repo.Update(context.Background(), "", domain.UpdateGroupParams{})
assert.ErrorIs(t, err, domain.ErrNothingToUpdate)
assert.Zero(t, updatedGroup)
})
t.Run("ERR: group not found", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
id string
}{
{
name: "ID - not UUID",
id: "test",
},
{
name: "ID - random UUID",
id: uuid.NewString(),
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
updatedGroup, err := repo.Update(context.Background(), tt.id, domain.UpdateGroupParams{
ChannelGains: domain.NullString{
String: "update",
Valid: true,
},
})
assert.ErrorIs(t, err, domain.GroupNotFoundError{ID: tt.id})
assert.Zero(t, updatedGroup)
})
}
})
}
func TestGroupBunRepository_AddMonitor(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := adapter.NewGroupBunRepository(db)
group := fixture.group(t, "group-1-server-1")
t.Run("OK", func(t *testing.T) {
t.Parallel()
var tribeID int64 = 91283718
updatedGroup, err := repo.AddMonitor(context.Background(), group.ID, tribeID)
assert.NoError(t, err)
var found bool
for _, m := range updatedGroup.Monitors {
if m.GroupID == group.ID && m.TribeID == tribeID {
found = true
break
}
}
assert.True(t, found)
})
t.Run("ERR: group doesn't exist", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
id string
}{
{
name: "ID - not UUID",
id: "test",
},
{
name: "ID - random UUID",
id: uuid.NewString(),
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
updatedGroup, err := repo.AddMonitor(context.Background(), tt.id, 125)
assert.ErrorIs(t, err, domain.GroupDoesNotExistError{ID: tt.id})
assert.Zero(t, updatedGroup)
})
}
})
t.Run("ERR: monitor already exists", func(t *testing.T) {
t.Parallel()
monitor := fixture.monitor(t, "monitor-2-group-1-server-1")
updatedGroup, err := repo.AddMonitor(context.Background(), monitor.GroupID, monitor.TribeID)
assert.ErrorIs(t, err, domain.MonitorAlreadyExistsError{
TribeID: monitor.TribeID,
GroupID: monitor.GroupID,
})
assert.Zero(t, updatedGroup)
})
}
func TestGroupBunRepository_DeleteMonitors(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := adapter.NewGroupBunRepository(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
monitor := fixture.monitor(t, "monitor-1-group-1-server-1")
updatedGroup, err := repo.DeleteMonitors(context.Background(), monitor.GroupID, monitor.ID)
assert.NoError(t, err)
var found bool
for _, m := range updatedGroup.Monitors {
if m.ID == monitor.ID {
found = true
break
}
}
assert.False(t, found)
})
t.Run("ERR: group not found", func(t *testing.T) {
t.Parallel()
monitor := fixture.monitor(t, "monitor-2-group-1-server-1")
tests := []struct {
name string
id string
}{
{
name: "group ID - not UUID",
id: "id",
},
{
name: "group ID - not UUID",
id: uuid.NewString(),
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
updatedGroup, err := repo.DeleteMonitors(context.Background(), tt.id, monitor.ID)
assert.ErrorIs(t, err, domain.GroupNotFoundError{ID: tt.id})
assert.Zero(t, updatedGroup)
})
}
})
t.Run("ERR: monitor not found", func(t *testing.T) {
t.Parallel()
monitor := fixture.monitor(t, "monitor-2-group-1-server-1")
tests := []struct {
name string
monitorID string
}{
{
name: "monitor ID - not UUID",
monitorID: "id",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
updatedGroup, err := repo.DeleteMonitors(context.Background(), monitor.GroupID, tt.monitorID)
assert.ErrorIs(t, err, domain.MonitorNotFoundError{ID: tt.monitorID})
assert.Zero(t, updatedGroup)
})
}
})
}
func TestGroupBunRepository_List(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := adapter.NewGroupBunRepository(db)
groups := fixture.groups(t)
allGroups := make([]string, 0, len(groups))
for _, g := range groups {
allGroups = append(allGroups, g.ID)
}
tests := []struct {
name string
params domain.ListGroupsParams
expectedGroups []string
}{
{
name: "no params",
params: domain.ListGroupsParams{},
expectedGroups: allGroups,
},
{
name: "ServerIDs=[server-1]",
params: domain.ListGroupsParams{
ServerIDs: []string{"server-1"},
},
expectedGroups: []string{
"d56ad37f-2637-48ea-98f8-79627f3fcc96",
"429b790e-7186-4106-b531-4cc4931ce2ba",
},
},
{
name: "ServerIDs=[server-1],EnabledNotifications=true",
params: domain.ListGroupsParams{
ServerIDs: []string{"server-1"},
EnabledNotifications: domain.NullBool{
Bool: true,
Valid: true,
},
},
expectedGroups: []string{
"d56ad37f-2637-48ea-98f8-79627f3fcc96",
"429b790e-7186-4106-b531-4cc4931ce2ba",
},
},
{
name: "ServerIDs=[server-2],EnabledNotifications=true",
params: domain.ListGroupsParams{
ServerIDs: []string{"server-2"},
EnabledNotifications: domain.NullBool{
Bool: true,
Valid: true,
},
},
expectedGroups: []string{
"0be82203-4ca3-4b4c-a0c8-3a70099d88f7",
},
},
{
name: "ServerIDs=[server-2],EnabledNotifications=false",
params: domain.ListGroupsParams{
ServerIDs: []string{"server-2"},
EnabledNotifications: domain.NullBool{
Bool: false,
Valid: true,
},
},
expectedGroups: []string{
"abeb6c8e-70b6-445c-989f-890cd2a1f87a",
},
},
{
name: "VersionCode=pl",
params: domain.ListGroupsParams{
VersionCode: domain.NullString{
String: "pl",
Valid: true,
},
},
expectedGroups: []string{
"d56ad37f-2637-48ea-98f8-79627f3fcc96",
"429b790e-7186-4106-b531-4cc4931ce2ba",
"abeb6c8e-70b6-445c-989f-890cd2a1f87a",
"0be82203-4ca3-4b4c-a0c8-3a70099d88f7",
"982a9765-471c-43e8-9abb-1e4ee4f03738",
},
},
{
name: "VersionCode=pl,ServerKeys=[pl180]",
params: domain.ListGroupsParams{
VersionCode: domain.NullString{
String: "pl",
Valid: true,
},
ServerKeys: []string{"pl180"},
},
expectedGroups: []string{
"982a9765-471c-43e8-9abb-1e4ee4f03738",
},
},
{
name: "CreatedAtLTE=2022-03-15T15:00:10.000Z",
params: domain.ListGroupsParams{
CreatedAtLTE: time.Date(2022, time.March, 15, 15, 00, 10, 0, time.UTC),
},
expectedGroups: []string{
"d56ad37f-2637-48ea-98f8-79627f3fcc96",
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
res, err := repo.List(context.Background(), tt.params)
assert.NoError(t, err)
assert.Len(t, res, len(tt.expectedGroups))
for _, id := range tt.expectedGroups {
found := false
for _, grp := range res {
if grp.ID == id {
found = true
break
}
}
assert.True(t, found, "group (id=%s) not found", id)
}
})
}
}
func TestGroupBunRepository_Get(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := adapter.NewGroupBunRepository(db)
group := fixture.group(t, "group-1-server-1")
t.Run("OK", func(t *testing.T) {
t.Parallel()
g, err := repo.Get(context.Background(), group.ID)
assert.NoError(t, err)
assert.Equal(t, group.ID, g.ID)
})
t.Run("ERR: group not found (unknown ID)", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
id string
}{
{
name: "ID - not UUID",
id: "test",
},
{
name: "ID - random UUID",
id: uuid.NewString(),
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
g, err := repo.Get(context.Background(), tt.id)
assert.ErrorIs(t, err, domain.GroupNotFoundError{ID: tt.id})
assert.Zero(t, g)
})
}
})
}
func TestGroupBunRepository_Delete(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
db := newBunDB(t)
fixture := loadFixtures(t, db)
groupRepo := adapter.NewGroupBunRepository(db)
group := fixture.group(t, "group-1-server-1")
t.Run("OK", func(t *testing.T) {
t.Parallel()
beforeDelete, err := groupRepo.List(context.Background(), domain.ListGroupsParams{
ServerIDs: []string{group.ServerID},
})
assert.NoError(t, err)
assert.NoError(t, groupRepo.Delete(context.Background(), group.ID))
afterDelete, err := groupRepo.List(context.Background(), domain.ListGroupsParams{
ServerIDs: []string{group.ServerID},
})
assert.NoError(t, err)
assert.Len(t, afterDelete, len(beforeDelete)-1)
})
t.Run("ERR: group not found", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
id string
}{
{
name: "ID - not UUID",
id: "test",
},
{
name: "ID - random UUID",
id: uuid.NewString(),
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
assert.ErrorIs(t, groupRepo.Delete(context.Background(), tt.id), domain.GroupNotFoundError{ID: tt.id})
})
}
})
}
func TestGroupBunRepository_DeleteMany(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
db := newBunDB(t)
fixture := loadFixtures(t, db)
groupRepo := adapter.NewGroupBunRepository(db)
group1 := fixture.group(t, "group-1-server-1")
group2 := fixture.group(t, "group-2-server-1")
ids := []string{group1.ID, group2.ID}
serverIDs := []string{group1.ServerID}
t.Run("OK", func(t *testing.T) {
t.Parallel()
beforeDelete, err := groupRepo.List(context.Background(), domain.ListGroupsParams{
ServerIDs: serverIDs,
})
assert.NoError(t, err)
assert.NoError(t, groupRepo.DeleteMany(context.Background(), ids...))
afterDelete, err := groupRepo.List(context.Background(), domain.ListGroupsParams{
ServerIDs: serverIDs,
})
assert.NoError(t, err)
assert.Len(t, afterDelete, len(beforeDelete)-len(ids))
})
t.Run("OK: 0 ids", func(t *testing.T) {
t.Parallel()
assert.NoError(t, groupRepo.DeleteMany(context.Background()))
})
}