package bundb_test import ( "context" "testing" "time" "gitea.dwysokinski.me/twhelp/dcbot/internal/bundb" "gitea.dwysokinski.me/twhelp/dcbot/internal/domain" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestGroup_Create(t *testing.T) { t.Parallel() if testing.Short() { t.Skip("skipping long-running test") } repo := bundb.NewGroup(newDB(t)) t.Run("OK", func(t *testing.T) { t.Parallel() params, err := domain.NewCreateGroupParams( "592292203234328587", "en", "en113", "1234", "1235", true, true, ) require.NoError(t, err) group, err := repo.Create(context.Background(), params) assert.NoError(t, err) _, err = uuid.Parse(group.ID) assert.NoError(t, err) 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.WithinDuration(t, time.Now(), group.CreatedAt, 1*time.Second) }) } func TestGroup_Update(t *testing.T) { t.Parallel() if testing.Short() { t.Skip("skipping long-running test") } db := newDB(t) fixture := loadFixtures(t, db) repo := bundb.NewGroup(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, }, Barbarians: domain.NullBool{ Bool: !group.Barbarians, Valid: true, }, Internals: domain.NullBool{ Bool: !group.Internals, Valid: true, }, } updatedGroup, err := repo.Update(context.Background(), group.ID, group.ServerID, 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.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 serverID string }{ { name: "ID - not UUID", id: "test", serverID: group.ServerID, }, { name: "ID - random UUID", id: uuid.NewString(), serverID: group.ServerID, }, { name: "ServerID - random UUID", id: group.ID, serverID: 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, tt.serverID, domain.UpdateGroupParams{ ChannelGains: domain.NullString{ String: "update", Valid: true, }, }) assert.ErrorIs(t, err, domain.GroupNotFoundError{ID: tt.id}) assert.Zero(t, updatedGroup) }) } }) } func TestGroup_List(t *testing.T) { t.Parallel() if testing.Short() { t.Skip("skipping long-running test") } db := newDB(t) fixture := loadFixtures(t, db) repo := bundb.NewGroup(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 TestGroup_Get(t *testing.T) { t.Parallel() if testing.Short() { t.Skip("skipping long-running test") } db := newDB(t) fixture := loadFixtures(t, db) repo := bundb.NewGroup(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, group.ServerID) assert.NoError(t, err) assert.Equal(t, group, g) }) t.Run("ERR: group not found (unknown ID)", func(t *testing.T) { t.Parallel() tests := []struct { name string id string serverID string }{ { name: "ID - not UUID", id: "test", serverID: group.ServerID, }, { name: "ID - random UUID", id: uuid.NewString(), serverID: group.ServerID, }, { name: "ServerID - random UUID", id: group.ID, serverID: 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, tt.serverID) assert.ErrorIs(t, err, domain.GroupNotFoundError{ID: tt.id}) assert.Zero(t, g) }) } }) } func TestGroup_Delete(t *testing.T) { t.Parallel() if testing.Short() { t.Skip("skipping long-running test") } db := newDB(t) fixture := loadFixtures(t, db) groupRepo := bundb.NewGroup(db) monitorRepo := bundb.NewMonitor(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, group.ServerID)) afterDelete, err := groupRepo.List(context.Background(), domain.ListGroupsParams{ ServerIDs: []string{group.ServerID}, }) assert.NoError(t, err) assert.Len(t, afterDelete, len(beforeDelete)-1) // monitors should also be deleted monitors, err := monitorRepo.List(context.Background(), group.ID) assert.NoError(t, err) assert.Len(t, monitors, 0) }) t.Run("ERR: group not found", func(t *testing.T) { t.Parallel() tests := []struct { name string id string serverID string }{ { name: "ID - not UUID", id: "test", serverID: group.ServerID, }, { name: "ID - random UUID", id: uuid.NewString(), serverID: group.ServerID, }, { name: "ServerID - random UUID", id: group.ID, serverID: 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, tt.serverID), domain.GroupNotFoundError{ID: tt.id}, ) }) } }) } func TestGroup_DeleteMany(t *testing.T) { t.Parallel() if testing.Short() { t.Skip("skipping long-running test") } db := newDB(t) fixture := loadFixtures(t, db) groupRepo := bundb.NewGroup(db) monitorRepo := bundb.NewMonitor(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)) // monitors should also be deleted for _, id := range ids { monitors, err := monitorRepo.List(context.Background(), id) assert.NoError(t, err) assert.Len(t, monitors, 0) } }) t.Run("OK: 0 ids", func(t *testing.T) { t.Parallel() assert.NoError(t, groupRepo.DeleteMany(context.Background())) }) }