Skip to content

Commit

Permalink
Merge pull request #40 from k3forx/impl-delete-by-id
Browse files Browse the repository at this point in the history
impl usecase to delete by id
  • Loading branch information
k3forx authored May 31, 2022
2 parents 891fdea + de007db commit 710775e
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 0 deletions.
1 change: 1 addition & 0 deletions go/pkg/model/user_brew_recipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type BrewRecipeStatus int
const (
BrewRecipeStatusUnknown BrewRecipeStatus = iota
BrewRecipeStatusCreated
BrewRecipeStatusDeletedByUser
)

type CoffeeBeanGrind string
Expand Down
5 changes: 5 additions & 0 deletions go/pkg/usecase/user_brew_recipe/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ type GetByIDInput struct {
UserID int
UserBrewRecipeID int
}

type DeleteByIDInput struct {
UserID int
UserBrewRecipeID int
}
32 changes: 32 additions & 0 deletions go/pkg/usecase/user_brew_recipe/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ func NewUsecase(injector inject.Injector) *UserBrewRecipeUsecase {
//go:generate mockgen -source=./usecase.go -destination=./usecase_mock.go -package=user_brew_recipe
type Usecase interface {
Create(ctx context.Context, in CreateInput) *result.Result
GetByID(ctx context.Context, in GetByIDInput) (*GetByIDOutput, *result.Result)
DeleteByID(ctx context.Context, in DeleteByIDInput) *result.Result
}

type UserBrewRecipeUsecase struct {
Expand Down Expand Up @@ -93,3 +95,33 @@ func (u *UserBrewRecipeUsecase) GetByID(ctx context.Context, in GetByIDInput) (*

return &GetByIDOutput{UserBrewRecipe: userBrewRecipe}, result.OK()
}

func (u *UserBrewRecipeUsecase) DeleteByID(ctx context.Context, in DeleteByIDInput) *result.Result {
user, err := u.injector.Reader.User.GetByID(ctx, in.UserID)
if err != nil {
logger.Error(ctx, err)
return result.Error()
}
if !user.Exists() {
return result.New(result.CodeNotFound, "アカウントが存在しません")
}

userBrewRecipe, err := u.injector.Reader.UserBrewRecipe.GetByID(ctx, in.UserBrewRecipeID)
if err != nil {
logger.Error(ctx, err)
return result.Error()
}
if !userBrewRecipe.Exists() {
return result.New(result.CodeNotFound, "ドリップレシピが見つかりません")
}
if userBrewRecipe.User.ID != user.ID {
return result.New(result.CodeForbidden, result.CodeForbidden.String())
}

if err := u.injector.Writer.UserBrewRecipe.Delete(ctx, &userBrewRecipe); err != nil {
logger.Error(ctx, err)
return result.Error()
}

return result.OK()
}
29 changes: 29 additions & 0 deletions go/pkg/usecase/user_brew_recipe/usecase_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

188 changes: 188 additions & 0 deletions go/pkg/usecase/user_brew_recipe/usecase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,3 +382,191 @@ func TestUserBrewRecipeUsecase_GetByID(t *testing.T) {
})
}
}

func TestUserBrewRecipeUsecase_DeleteByID(t *testing.T) {
t.Parallel()

const (
userID = 123
userBrewRecipeID = 345
)
returnedUser := model.User{
ID: userID,
}
returnedUserBrewRecipe := model.UserBrewRecipe{
ID: userBrewRecipeID,
User: model.User{
ID: userID,
},
}
err := errors.New("server error")

cases := map[string]struct {
setup func(ctrl *gomock.Controller) inject.Injector
in user_brew_recipe.DeleteByIDInput
res *result.Result
}{
"success": {
setup: func(ctrl *gomock.Controller) inject.Injector {
injector := inject.NewMockInjector(ctrl)

userReader := injector.Reader.User.(*readerMock.MockUser)
userReader.EXPECT().GetByID(gomock.Any(), userID).
Return(returnedUser, nil)

userBrewRecipeReader := injector.Reader.UserBrewRecipe.(*readerMock.MockUserBrewRecipe)
userBrewRecipeReader.EXPECT().GetByID(gomock.Any(), userBrewRecipeID).
Return(returnedUserBrewRecipe, nil)

userBrewRecipeWriter := injector.Writer.UserBrewRecipe.(*writerMock.MockUserBrewRecipe)
userBrewRecipeWriter.EXPECT().Delete(gomock.Any(), &returnedUserBrewRecipe).Return(nil)

return injector
},
in: user_brew_recipe.DeleteByIDInput{
UserID: userID,
UserBrewRecipeID: userBrewRecipeID,
},
res: result.OK(),
},
"error_in_getting_user": {
setup: func(ctrl *gomock.Controller) inject.Injector {
injector := inject.NewMockInjector(ctrl)

userReader := injector.Reader.User.(*readerMock.MockUser)
userReader.EXPECT().GetByID(gomock.Any(), userID).
Return(model.User{}, err)

return injector
},
in: user_brew_recipe.DeleteByIDInput{
UserID: userID,
UserBrewRecipeID: userBrewRecipeID,
},
res: result.Error(),
},
"user_does_not_exist": {
setup: func(ctrl *gomock.Controller) inject.Injector {
injector := inject.NewMockInjector(ctrl)

userReader := injector.Reader.User.(*readerMock.MockUser)
userReader.EXPECT().GetByID(gomock.Any(), userID).
Return(model.User{}, nil)

return injector
},
in: user_brew_recipe.DeleteByIDInput{
UserID: userID,
UserBrewRecipeID: userBrewRecipeID,
},
res: result.New(result.CodeNotFound, "アカウントが存在しません"),
},
"error_in_getting_user_brew_recipe": {
setup: func(ctrl *gomock.Controller) inject.Injector {
injector := inject.NewMockInjector(ctrl)

userReader := injector.Reader.User.(*readerMock.MockUser)
userReader.EXPECT().GetByID(gomock.Any(), userID).
Return(returnedUser, nil)

userBrewRecipeReader := injector.Reader.UserBrewRecipe.(*readerMock.MockUserBrewRecipe)
userBrewRecipeReader.EXPECT().GetByID(gomock.Any(), userBrewRecipeID).
Return(model.UserBrewRecipe{}, err)

return injector
},
in: user_brew_recipe.DeleteByIDInput{
UserID: userID,
UserBrewRecipeID: userBrewRecipeID,
},
res: result.Error(),
},
"user_brew_recipe_does_not_exist": {
setup: func(ctrl *gomock.Controller) inject.Injector {
injector := inject.NewMockInjector(ctrl)

userReader := injector.Reader.User.(*readerMock.MockUser)
userReader.EXPECT().GetByID(gomock.Any(), userID).
Return(returnedUser, nil)

userBrewRecipeReader := injector.Reader.UserBrewRecipe.(*readerMock.MockUserBrewRecipe)
userBrewRecipeReader.EXPECT().GetByID(gomock.Any(), userBrewRecipeID).
Return(model.UserBrewRecipe{}, nil)

return injector
},
in: user_brew_recipe.DeleteByIDInput{
UserID: userID,
UserBrewRecipeID: userBrewRecipeID,
},
res: result.New(result.CodeNotFound, "ドリップレシピが見つかりません"),
},
"user_brew_recipe_user_id_is_different": {
setup: func(ctrl *gomock.Controller) inject.Injector {
injector := inject.NewMockInjector(ctrl)

userReader := injector.Reader.User.(*readerMock.MockUser)
userReader.EXPECT().GetByID(gomock.Any(), userID).
Return(returnedUser, nil)

userBrewRecipeReader := injector.Reader.UserBrewRecipe.(*readerMock.MockUserBrewRecipe)
userBrewRecipeReader.EXPECT().GetByID(gomock.Any(), userBrewRecipeID).
Return(
model.UserBrewRecipe{
ID: userBrewRecipeID,
User: model.User{
ID: 9,
},
},
nil,
)

return injector
},
in: user_brew_recipe.DeleteByIDInput{
UserID: userID,
UserBrewRecipeID: userBrewRecipeID,
},
res: result.New(result.CodeForbidden, result.CodeForbidden.String()),
},
"error_in_deleting_user_brew_recipe": {
setup: func(ctrl *gomock.Controller) inject.Injector {
injector := inject.NewMockInjector(ctrl)

userReader := injector.Reader.User.(*readerMock.MockUser)
userReader.EXPECT().GetByID(gomock.Any(), userID).
Return(returnedUser, nil)

userBrewRecipeReader := injector.Reader.UserBrewRecipe.(*readerMock.MockUserBrewRecipe)
userBrewRecipeReader.EXPECT().GetByID(gomock.Any(), userBrewRecipeID).
Return(returnedUserBrewRecipe, nil)

userBrewRecipeWriter := injector.Writer.UserBrewRecipe.(*writerMock.MockUserBrewRecipe)
userBrewRecipeWriter.EXPECT().Delete(gomock.Any(), &returnedUserBrewRecipe).Return(err)

return injector
},
in: user_brew_recipe.DeleteByIDInput{
UserID: userID,
UserBrewRecipeID: userBrewRecipeID,
},
res: result.Error(),
},
}

for name, c := range cases {
c := c
t.Run(name, func(t *testing.T) {
t.Parallel()

ctrl := gomock.NewController(t)
injector := c.setup(ctrl)
u := user_brew_recipe.NewUsecase(injector)

res := u.DeleteByID(context.Background(), c.in)
if diff := cmp.Diff(c.res, res); diff != "" {
t.Errorf("GetByID result mismatch (-want +got):\n%s", diff)
}
})
}
}
14 changes: 14 additions & 0 deletions go/pkg/writer/mock/user_brew_recipe_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions go/pkg/writer/user_brew_recipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func NewUserBrewRecipeWriter(db *ent.Client) *UserBrewRecipeWriter {
//go:generate mockgen -source=./user_brew_recipe.go -destination=./mock/user_brew_recipe_mock.go -package=writer
type UserBrewRecipe interface {
Create(ctx context.Context, userBrewRecipe *model.UserBrewRecipe) error
Delete(ctx context.Context, userBrewRecipe *model.UserBrewRecipe) error
}

type UserBrewRecipeWriter struct {
Expand Down Expand Up @@ -50,3 +51,14 @@ func (impl *UserBrewRecipeWriter) Create(ctx context.Context, userBrewRecipe *mo
*userBrewRecipe = model.NewUserBrewRecipe(e)
return nil
}

func (impl *UserBrewRecipeWriter) Delete(ctx context.Context, userBrewRecipe *model.UserBrewRecipe) error {
now := time.Now().In(time.UTC)
if _, err := impl.db.UserBrewRecipe.UpdateOneID(int32(userBrewRecipe.ID)).
SetStatus(int32(model.BrewRecipeStatusDeletedByUser)).
SetDeletedAt(now).
Save(ctx); err != nil {
return err
}
return nil
}
68 changes: 68 additions & 0 deletions go/pkg/writer/user_brew_recipe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,71 @@ func TestUserBrewRecipeWriter_Create(t *testing.T) {
})
}
}

func TestUserBrewRecipeWriter_Delete(t *testing.T) {
impl := writer.NewUserBrewRecipeWriter(testClient)

user := dbHelper.InsertAndDeleteUsers(t, testClient, func(u *ent.User) {
u.Email = "test-user-brew-recipe-writer-delete"
})
userCoffeeBean := dbHelper.InsertAndDeleteUserCoffeeBean(t, testClient, user, func(cb *ent.UserCoffeeBean) {
cb.UserID = user.ID
})
now := time.Now().In(time.UTC)
userBrewRecipe := dbHelper.InsertAndDeleteUserBrewRecipe(t, testClient, user, userCoffeeBean, func(ubr *ent.UserBrewRecipe) {
ubr.CreatedAt = now
ubr.UpdatedAt = now
})

cases := map[string]struct {
m model.UserBrewRecipe
expected model.UserBrewRecipe
}{
"success": {
m: model.NewUserBrewRecipe(userBrewRecipe),
expected: model.UserBrewRecipe{
ID: int(userBrewRecipe.ID),
Status: model.BrewRecipeStatusDeletedByUser,
User: model.User{
ID: int(user.ID),
},
UserCoffeeBean: model.UserCoffeeBean{
ID: int(userCoffeeBean.ID),
},
CoffeeBeanWeight: 16,
CoffeeBeanGrind: model.CoffeeBeanGrindCoarse,
LiquidWeight: 240,
Temperature: 92,
StepOne: "step 1",
StepTwo: "step 2",
Memo: "good taste!",
DeletedAt: now,
CreatedAt: now,
UpdatedAt: now,
},
},
}

for name, c := range cases {
t.Run(name, func(t *testing.T) {
ctx := context.Background()

if err := impl.Delete(ctx, &c.m); err != nil {
t.Errorf("err should be nil but, got %q", err)
}

userBrewRecipeEntity, err := testClient.UserBrewRecipe.Get(ctx, int32(c.m.ID))
if err != nil {
t.Errorf("err should be nil, but got %v", err)
}

actualUserBrewRecipe := model.NewUserBrewRecipe(userBrewRecipeEntity)
opts := cmp.Options{
cmpopts.EquateApproxTime(time.Minute),
}
if diff := cmp.Diff(c.expected, actualUserBrewRecipe, opts); diff != "" {
t.Errorf("user brew recipe mismatch (-want +got):\n%s", diff)
}
})
}
}

0 comments on commit 710775e

Please sign in to comment.