Skip to content

Commit

Permalink
Merge branch 'main' of github.com:givery-bootcamp/dena-2024-team10 in…
Browse files Browse the repository at this point in the history
…to bug-fix/delete-post
  • Loading branch information
shunsuke-tamura committed Jun 28, 2024
2 parents 8076f3b + 281e804 commit 78d36f8
Show file tree
Hide file tree
Showing 14 changed files with 726 additions and 14 deletions.
32 changes: 32 additions & 0 deletions backend/internal/controllers/comment_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,35 @@ func DeleteComment(ctx *gin.Context) {

ctx.JSON(http.StatusNoContent, nil)
}

func GetComments(ctx *gin.Context) {
repository := repositories.NewCommentRepository(DB(ctx))
usecase := usecases.NewGetAllPostCommentUsecase(repository)

postId := ctx.Param("postId")
postIdInt64, err := strconv.ParseInt(postId, 10, 64)
if err != nil {
ctx.Error(exception.ErrNotFound)
return
}

limit, err := strconv.ParseInt(ctx.DefaultQuery("limit", "20"), 10, 64)
if err != nil {
ctx.Error(exception.ErrInvalidQuery)
return
}

offset, err := strconv.ParseInt(ctx.DefaultQuery("offset", "0"), 10, 64)
if err != nil {
ctx.Error(exception.ErrInvalidQuery)
return
}

comments, err := usecase.Execute(postIdInt64, limit, offset)
if err != nil {
ctx.Error(err)
return
}

ctx.JSON(http.StatusOK, comments)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ type CommentRepository interface {
GetById(commentId int64) (*entities.Comment, error)
Update(comment *entities.Comment) (*entities.Comment, error)
Delete(commentId int64) error
GetAllByPostId(postId, limit, offset int64) ([]*entities.Comment, error)
}
1 change: 1 addition & 0 deletions backend/internal/middleware/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ func SetupRoutes(app *gin.Engine) {
authenticated.PUT("/posts/:postId/comments/:commentId", controllers.UpdateComment)
authenticated.DELETE("/posts/:postId/comments/:commentId", controllers.DeleteComment)
authenticated.GET("/comments/:commentId", controllers.GetComment)
authenticated.GET("/posts/:postId/comments", controllers.GetComments)
}
}
22 changes: 22 additions & 0 deletions backend/internal/repositories/comment_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,25 @@ func (r *CommentRepository) Update(comment *entities.Comment) (*entities.Comment
func (r *CommentRepository) Delete(commentId int64) error {
return r.Conn.Delete(&model.Comment{}, commentId).Error
}

func (r *CommentRepository) GetAllByPostId(postId, limit, offset int64) ([]*entities.Comment, error) {
var modelComments []*model.Comment
if err := r.Conn.
Preload("User").
Where("post_id = ?", postId).
Limit(int(limit)).
Offset(int(offset)).
Order("id").
Find(&modelComments).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, err
}

result := []*entities.Comment{}
for _, comment := range modelComments {
result = append(result, model.ConvertCommentModelToEntity(comment))
}
return result, nil
}
38 changes: 38 additions & 0 deletions backend/internal/usecases/get_all_post_comment_usecase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package usecases

import (
"myapp/internal/entities"
"myapp/internal/interfaces"
)

type GetAllPostCommentUsecase struct {
CommentRepository interfaces.CommentRepository
}

func NewGetAllPostCommentUsecase(cr interfaces.CommentRepository) *GetAllPostCommentUsecase {
return &GetAllPostCommentUsecase{
CommentRepository: cr,
}
}

func (u *GetAllPostCommentUsecase) Execute(postId, limit, offset int64) ([]*entities.Comment, error) {
// Validate limit
if limit <= 0 {
limit = 20
}
if limit > 100 {
limit = 100
}

// Validate offset
if offset < 0 {
offset = 0
}

comments, err := u.CommentRepository.GetAllByPostId(postId, limit, offset)
if err != nil {
return nil, err
}

return comments, nil
}
15 changes: 15 additions & 0 deletions backend/test/mock/mock_interfaces/comment_repository_interface.go

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

86 changes: 86 additions & 0 deletions backend/test/repositories/comment_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,89 @@ func TestDeleteComment(t *testing.T) {
})
}
}

func TestGetCommentByPostId(t *testing.T) {
// initialize DB
repo, teardown := setupCommentRepository()
defer teardown()

// create test cases
testcases := []struct {
testName string
postId int64
limit int64
offset int64
expectedComments []*entities.Comment
expectedError error
}{
{
"Success limit=1 offset=0",
1,
1,
0,
[]*entities.Comment{
{ // defined in the seed
Id: 1,
PostId: 1,
UserId: 1,
Body: "comment1 on test1",
Username: "taro",
// CreatedAt and UpdatedAt are not checked
// because they are set by the database.
},
},
nil,
// Do not test the case where DB returns an unknown error
// because it is difficult to reproduce.
},
{
"Success limit=2 offset=1",
1,
2,
1,
[]*entities.Comment{
{ // defined in the seed
Id: 2,
PostId: 1,
UserId: 2,
Body: "comment2 on test1",
Username: "hanako",
},
{ // defined in the seed
Id: 3,
PostId: 1,
UserId: 1,
Body: "comment3 on test1",
Username: "taro",
},
},
nil,
// Do not test the case where DB returns an unknown error
// because it is difficult to reproduce.
},
{
"Success limit=1 offset=25 (return empty)",
1,
1,
25,
[]*entities.Comment{},
nil,
},
}

for _, tc := range testcases {
t.Run(tc.testName, func(t *testing.T) {
result, err := repo.GetAllByPostId(tc.postId, tc.limit, tc.offset)
assert.Equal(t, tc.expectedError, err)

for i, comment := range result {
assert.Equal(t, tc.expectedComments[i].Id, comment.Id)
assert.Equal(t, tc.expectedComments[i].PostId, comment.PostId)
assert.Equal(t, tc.expectedComments[i].UserId, comment.UserId)
assert.Equal(t, tc.expectedComments[i].Body, comment.Body)
assert.Equal(t, tc.expectedComments[i].Username, comment.Username)

}
})
}
}
115 changes: 115 additions & 0 deletions backend/test/usecases/get_all_post_comment_usecase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package usecases

import (
"fmt"
"myapp/internal/entities"
"myapp/internal/usecases"
"myapp/test/mock/mock_interfaces"
"testing"
"time"

"github.com/stretchr/testify/assert"
gomock "go.uber.org/mock/gomock"
)

type getAllPostCommentInput struct {
postId int64
limit int64
offset int64
}

type responceFromCommentRepositoryGetAll struct {
comments []*entities.Comment
err error
}

func TestGetAllPostComment(t *testing.T) {
testcases := []struct {
testName string
usecaseInput *getAllPostCommentInput
repositoryOutput *responceFromCommentRepositoryGetAll
expectedComment []*entities.Comment
expectedError error
}{
{
"Success get all posts",
&getAllPostCommentInput{
postId: 1,
limit: 1,
offset: 0,
},
&responceFromCommentRepositoryGetAll{
[]*entities.Comment{
{
Id: 1,
PostId: 1,
UserId: 1,
Body: "mock comment",
CreatedAt: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
UpdatedAt: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
},
nil,
},
[]*entities.Comment{
{
Id: 1,
PostId: 1,
UserId: 1,
Body: "mock comment",
CreatedAt: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
UpdatedAt: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC),
},
},
nil,
},
{
"Success get all comments with empty posts",
&getAllPostCommentInput{
postId: 1,
limit: 1,
offset: 0,
},
&responceFromCommentRepositoryGetAll{
[]*entities.Comment{},
nil,
},
[]*entities.Comment{},
nil,
},
{
"Fail with error from GetAllCommentByPostId",
&getAllPostCommentInput{
1,
1,
0,
},
&responceFromCommentRepositoryGetAll{
nil,
fmt.Errorf("error from GetAllCommentByPostId"),
},
nil,
fmt.Errorf("error from GetAllCommentByPostId"),
},
}

for _, tc := range testcases {
t.Run(tc.testName, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

mockCommentRepository := mock_interfaces.NewMockCommentRepository(mockCtrl)
mockCommentRepository.EXPECT().
GetAllByPostId(tc.usecaseInput.postId, tc.usecaseInput.limit, tc.usecaseInput.offset).
Return(tc.repositoryOutput.comments, tc.repositoryOutput.err)
usecase := usecases.NewGetAllPostCommentUsecase(mockCommentRepository)
comments, err := usecase.Execute(tc.usecaseInput.postId, tc.usecaseInput.limit, tc.usecaseInput.offset)

assert.Equal(t, tc.expectedError, err)
assert.Len(t, comments, len(tc.expectedComment))
for i, comment := range comments {
assert.Equal(t, tc.expectedComment[i], comment)
}
})
}
}
3 changes: 2 additions & 1 deletion frontend/app/apiClient/apiClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createApiClient } from "./output.generated";

export const API_BASE_URL = process.env.API_BASE_URL ?? "http://localhost:4010";
// export const API_BASE_URL = process.env.API_BASE_URL ?? "http://localhost:4010";
export const API_BASE_URL = process.env.API_BASE_URL ?? "http://localhost:9000";

const apiClient = createApiClient(API_BASE_URL, {});

Expand Down
Loading

0 comments on commit 78d36f8

Please sign in to comment.