feat: add a new command - /monitor delete (#23)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #23
This commit is contained in:
parent
d983f5ae08
commit
db2026c6e4
|
@ -193,6 +193,9 @@ func TestGroup_Get(t *testing.T) {
|
|||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
g, err := repo.Get(context.Background(), group.ID.String(), group.ServerID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, group.ToDomain(), g)
|
||||
})
|
||||
|
||||
t.Run("ERR: group not found (unknown ID)", func(t *testing.T) {
|
||||
|
@ -239,19 +242,30 @@ func TestGroup_Delete(t *testing.T) {
|
|||
|
||||
db := newDB(t)
|
||||
fixture := loadFixtures(t, db)
|
||||
repo := bundb.NewGroup(db)
|
||||
groupRepo := bundb.NewGroup(db)
|
||||
monitorRepo := bundb.NewMonitor(db)
|
||||
group := getGroupFromFixture(t, fixture, "group-1-server-1")
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert.NoError(t, repo.Delete(context.Background(), group.ID.String(), group.ServerID))
|
||||
|
||||
groups, err := repo.List(context.Background(), domain.ListGroupsParams{
|
||||
ServerIDs: []string{group.ID.String()},
|
||||
beforeDelete, err := groupRepo.List(context.Background(), domain.ListGroupsParams{
|
||||
ServerIDs: []string{group.ServerID},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, groups, 0)
|
||||
|
||||
assert.NoError(t, groupRepo.Delete(context.Background(), group.ID.String(), 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.String())
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, monitors, 0)
|
||||
})
|
||||
|
||||
t.Run("ERR: group not found", func(t *testing.T) {
|
||||
|
@ -287,7 +301,7 @@ func TestGroup_Delete(t *testing.T) {
|
|||
|
||||
assert.ErrorIs(
|
||||
t,
|
||||
repo.Delete(context.Background(), tt.id, tt.serverID),
|
||||
groupRepo.Delete(context.Background(), tt.id, tt.serverID),
|
||||
domain.GroupNotFoundError{ID: tt.id},
|
||||
)
|
||||
})
|
||||
|
|
|
@ -71,6 +71,47 @@ func (m *Monitor) List(ctx context.Context, groupID string) ([]domain.Monitor, e
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (m *Monitor) Get(ctx context.Context, id string) (domain.Monitor, error) {
|
||||
if _, err := uuid.Parse(id); err != nil {
|
||||
return domain.Monitor{}, domain.MonitorNotFoundError{ID: id}
|
||||
}
|
||||
|
||||
var monitor model.Monitor
|
||||
|
||||
err := m.db.NewSelect().
|
||||
Model(&monitor).
|
||||
Where("id = ?", id).
|
||||
Scan(ctx)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return domain.Monitor{}, domain.MonitorNotFoundError{ID: id}
|
||||
}
|
||||
return domain.Monitor{}, fmt.Errorf("couldn't select monitor from the db (id=%s): %w", id, err)
|
||||
}
|
||||
|
||||
return monitor.ToDomain(), nil
|
||||
}
|
||||
|
||||
func (m *Monitor) Delete(ctx context.Context, id string) error {
|
||||
if _, err := uuid.Parse(id); err != nil {
|
||||
return domain.MonitorNotFoundError{ID: id}
|
||||
}
|
||||
|
||||
res, err := m.db.NewDelete().
|
||||
Model(&model.Monitor{}).
|
||||
Returning("NULL").
|
||||
Where("id = ?", id).
|
||||
Exec(ctx)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return fmt.Errorf("couldn't delete monitor (id=%s): %w", id, err)
|
||||
}
|
||||
if affected, _ := res.RowsAffected(); affected == 0 {
|
||||
return domain.MonitorNotFoundError{ID: id}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapCreateMonitorError(err error, params domain.CreateMonitorParams) error {
|
||||
var pgError pgdriver.Error
|
||||
if !errors.As(err, &pgError) {
|
||||
|
|
|
@ -138,3 +138,111 @@ func TestMonitor_List(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonitor_Get(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db := newDB(t)
|
||||
fixture := loadFixtures(t, db)
|
||||
repo := bundb.NewMonitor(db)
|
||||
group := getGroupFromFixture(t, fixture, "group-1-server-1")
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
monitors, err := repo.List(context.Background(), group.ID.String())
|
||||
require.NoError(t, err)
|
||||
require.Greater(t, len(monitors), 0)
|
||||
|
||||
m, err := repo.Get(context.Background(), monitors[0].ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, monitors[0], m)
|
||||
})
|
||||
|
||||
t.Run("ERR: monitor 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,
|
||||
repo.Delete(context.Background(), tt.id),
|
||||
domain.MonitorNotFoundError{ID: tt.id},
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestMonitor_Delete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db := newDB(t)
|
||||
fixture := loadFixtures(t, db)
|
||||
repo := bundb.NewMonitor(db)
|
||||
group := getGroupFromFixture(t, fixture, "group-1-server-1")
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
beforeDelete, err := repo.List(context.Background(), group.ID.String())
|
||||
assert.NoError(t, err)
|
||||
assert.Greater(t, len(beforeDelete), 0)
|
||||
|
||||
assert.NoError(t, repo.Delete(context.Background(), beforeDelete[0].ID))
|
||||
|
||||
afterDelete, err := repo.List(context.Background(), group.ID.String())
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, afterDelete, len(beforeDelete)-1)
|
||||
})
|
||||
|
||||
t.Run("ERR: monitor 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,
|
||||
repo.Delete(context.Background(), tt.id),
|
||||
domain.MonitorNotFoundError{ID: tt.id},
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ type GroupService interface {
|
|||
|
||||
type MonitorService interface {
|
||||
Create(ctx context.Context, groupID, serverID, tribeTag string) (domain.Monitor, error)
|
||||
Delete(ctx context.Context, id, serverID string) error
|
||||
}
|
||||
|
||||
type ChoiceService interface {
|
||||
|
|
|
@ -57,6 +57,19 @@ func (c *monitorCommand) create(s *discordgo.Session) error {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "delete",
|
||||
Description: "Deletes a monitor",
|
||||
Type: discordgo.ApplicationCommandOptionSubCommand,
|
||||
Options: []*discordgo.ApplicationCommandOption{
|
||||
{
|
||||
Name: "monitor",
|
||||
Description: "Monitor ID",
|
||||
Type: discordgo.ApplicationCommandOptionString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -77,6 +90,9 @@ func (c *monitorCommand) handle(s *discordgo.Session, i *discordgo.InteractionCr
|
|||
case "create":
|
||||
c.handleCreate(s, i)
|
||||
return
|
||||
case "delete":
|
||||
c.handleDelete(s, i)
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
@ -116,3 +132,25 @@ func (c *monitorCommand) handleCreate(s *discordgo.Session, i *discordgo.Interac
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c *monitorCommand) handleDelete(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
ctx := context.Background()
|
||||
|
||||
monitor := i.ApplicationCommandData().Options[0].Options[0].StringValue()
|
||||
if err := c.svc.Delete(ctx, monitor, i.GuildID); err != nil {
|
||||
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: messageFromError(err),
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: "monitor has been successfully deleted",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -82,3 +82,19 @@ func (e MonitorLimitReachedError) UserError() string {
|
|||
func (e MonitorLimitReachedError) Code() ErrorCode {
|
||||
return ErrorCodeValidationError
|
||||
}
|
||||
|
||||
type MonitorNotFoundError struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
func (e MonitorNotFoundError) Error() string {
|
||||
return fmt.Sprintf("monitor (ID=%s) not found", e.ID)
|
||||
}
|
||||
|
||||
func (e MonitorNotFoundError) UserError() string {
|
||||
return e.Error()
|
||||
}
|
||||
|
||||
func (e MonitorNotFoundError) Code() ErrorCode {
|
||||
return ErrorCodeEntityNotFound
|
||||
}
|
||||
|
|
|
@ -91,3 +91,15 @@ func TestMonitorLimitReachedError(t *testing.T) {
|
|||
assert.Equal(t, err.Error(), err.UserError())
|
||||
assert.Equal(t, domain.ErrorCodeValidationError, err.Code())
|
||||
}
|
||||
|
||||
func TestMonitorNotFoundError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
err := domain.MonitorNotFoundError{
|
||||
ID: uuid.NewString(),
|
||||
}
|
||||
var _ domain.UserError = err
|
||||
assert.Equal(t, fmt.Sprintf("monitor (ID=%s) not found", err.ID), err.Error())
|
||||
assert.Equal(t, err.Error(), err.UserError())
|
||||
assert.Equal(t, domain.ErrorCodeEntityNotFound, err.Code())
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ const (
|
|||
type MonitorRepository interface {
|
||||
Create(ctx context.Context, params domain.CreateMonitorParams) (domain.Monitor, error)
|
||||
List(ctx context.Context, groupID string) ([]domain.Monitor, error)
|
||||
Get(ctx context.Context, id string) (domain.Monitor, error)
|
||||
Delete(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
//counterfeiter:generate -o internal/mock/group_getter.gen.go . GroupGetter
|
||||
|
@ -87,3 +89,21 @@ func (m *Monitor) Create(ctx context.Context, groupID, serverID, tribeTag string
|
|||
|
||||
return monitor, nil
|
||||
}
|
||||
|
||||
func (m *Monitor) Delete(ctx context.Context, id, serverID string) error {
|
||||
monitor, err := m.repo.Get(ctx, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("MonitorRepository.Get: %w", err)
|
||||
}
|
||||
|
||||
_, err = m.groupSvc.Get(ctx, monitor.GroupID, serverID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GroupService.Get: %w", err)
|
||||
}
|
||||
|
||||
if err = m.repo.Delete(ctx, id); err != nil {
|
||||
return fmt.Errorf("MonitorRepository.Delete: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user