482 lines
12 KiB
Go
482 lines
12 KiB
Go
package usecase
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"code.30cm.net/digimon/app-cloudep-comment-server/pkg/domain/comment"
|
|
"code.30cm.net/digimon/app-cloudep-comment-server/pkg/domain/entity"
|
|
"code.30cm.net/digimon/app-cloudep-comment-server/pkg/domain/repository"
|
|
"code.30cm.net/digimon/app-cloudep-comment-server/pkg/domain/usecase"
|
|
|
|
"github.com/golang/snappy"
|
|
"github.com/stretchr/testify/assert"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.uber.org/mock/gomock"
|
|
|
|
mockRepo "code.30cm.net/digimon/app-cloudep-comment-server/pkg/mock/repository"
|
|
err "code.30cm.net/digimon/app-cloudep-comment-server/pkg/repository"
|
|
)
|
|
|
|
func TestCommentUseCase_CreateCommentItem(t *testing.T) {
|
|
mockCtrl := gomock.NewController(t)
|
|
defer mockCtrl.Finish()
|
|
|
|
mockCommentRepository := mockRepo.NewMockCommentRepository(mockCtrl)
|
|
|
|
uc := MustCommentUseCase(CommentUseCaseParam{
|
|
Comment: mockCommentRepository,
|
|
})
|
|
|
|
tests := []struct {
|
|
name string
|
|
req usecase.CreateCommentDocs
|
|
mockSetup func()
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "successfully create top-level comment",
|
|
req: usecase.CreateCommentDocs{
|
|
UID: "user-123",
|
|
ReferenceID: "ref-001",
|
|
Message: "This is a top-level comment",
|
|
},
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
CreateComment(gomock.Any(), gomock.Any()).
|
|
DoAndReturn(func(ctx context.Context, e *entity.Comments) error {
|
|
// 驗證插入內容是否正確
|
|
assert.Equal(t, "user-123", e.UID)
|
|
assert.Equal(t, "ref-001", e.ReferenceID)
|
|
assert.Equal(t, comment.TopLevelComment, e.Level)
|
|
return nil
|
|
})
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "successfully create sub-level comment",
|
|
req: usecase.CreateCommentDocs{
|
|
UID: "user-456",
|
|
ReferenceID: "ref-002",
|
|
ParentCommentID: "parent-001",
|
|
Message: "This is a sub-level comment",
|
|
},
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
CreateComment(gomock.Any(), gomock.Any()).
|
|
DoAndReturn(func(ctx context.Context, e *entity.Comments) error {
|
|
// 驗證插入內容是否正確
|
|
assert.Equal(t, "user-456", e.UID)
|
|
assert.Equal(t, "ref-002", e.ReferenceID)
|
|
assert.Equal(t, "parent-001", e.ParentCommentID)
|
|
assert.Equal(t, comment.SubLevelComment, e.Level)
|
|
return nil
|
|
})
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "failed to create comment due to repository error",
|
|
req: usecase.CreateCommentDocs{
|
|
UID: "user-789",
|
|
ReferenceID: "ref-003",
|
|
Message: "This is a failing comment",
|
|
},
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
CreateComment(gomock.Any(), gomock.Any()).
|
|
Return(errors.New("database error"))
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
tt.mockSetup()
|
|
err := uc.CreateCommentItem(context.Background(), tt.req)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
if err != nil {
|
|
assert.Contains(t, err.Error(), "failed to create comment")
|
|
}
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommentUseCase_GetCommentItem(t *testing.T) {
|
|
mockCtrl := gomock.NewController(t)
|
|
defer mockCtrl.Finish()
|
|
|
|
mockCommentRepository := mockRepo.NewMockCommentRepository(mockCtrl)
|
|
|
|
uc := MustCommentUseCase(CommentUseCaseParam{
|
|
Comment: mockCommentRepository,
|
|
})
|
|
|
|
tests := []struct {
|
|
name string
|
|
id string
|
|
mockSetup func()
|
|
wantErr bool
|
|
expected *usecase.CommentDocs
|
|
}{
|
|
{
|
|
name: "successfully get comment item",
|
|
id: "64a1f2e9347e1a001d345678",
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
ListComments(gomock.Any(), gomock.Any()).
|
|
DoAndReturn(func(ctx context.Context, req repository.ListCommentRequest) ([]*entity.Comments, int64, error) {
|
|
assert.Equal(t, "64a1f2e9347e1a001d345678", *req.ReferenceID)
|
|
return []*entity.Comments{
|
|
{
|
|
ID: primitive.NewObjectID(),
|
|
UID: "user-123",
|
|
ReferenceID: "64a1f2e9347e1a001d345678",
|
|
ParentCommentID: "",
|
|
Message: base64.StdEncoding.EncodeToString(snappy.Encode(nil, []byte("This is a test comment"))),
|
|
UpdatedAt: time.Now().UTC().UnixNano(),
|
|
CreatedAt: time.Now().UTC().UnixNano(),
|
|
},
|
|
}, 1, nil
|
|
})
|
|
},
|
|
wantErr: false,
|
|
expected: &usecase.CommentDocs{
|
|
UID: "user-123",
|
|
ReferenceID: "64a1f2e9347e1a001d345678",
|
|
ParentCommentID: "",
|
|
Message: "This is a test comment",
|
|
},
|
|
},
|
|
{
|
|
name: "comment not found",
|
|
id: "64a1f2e9347e1a001d345679",
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
ListComments(gomock.Any(), gomock.Any()).
|
|
Return([]*entity.Comments{}, int64(0), err.ErrNotFound)
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "database error",
|
|
id: "64a1f2e9347e1a001d345680",
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
ListComments(gomock.Any(), gomock.Any()).
|
|
Return([]*entity.Comments{}, int64(0), errors.New("database error"))
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
tt.mockSetup()
|
|
comment, err := uc.GetCommentItem(context.Background(), tt.id)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, comment)
|
|
assert.Equal(t, tt.expected.UID, comment.UID)
|
|
assert.Equal(t, tt.expected.ReferenceID, comment.ReferenceID)
|
|
assert.Equal(t, tt.expected.Message, comment.Message)
|
|
assert.Equal(t, tt.expected.ParentCommentID, comment.ParentCommentID)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommentUseCase_UpdateCommentMessage(t *testing.T) {
|
|
mockCtrl := gomock.NewController(t)
|
|
defer mockCtrl.Finish()
|
|
|
|
// Mock Repository
|
|
mockCommentRepository := mockRepo.NewMockCommentRepository(mockCtrl)
|
|
|
|
// UseCase Initialization
|
|
uc := MustCommentUseCase(CommentUseCaseParam{
|
|
Comment: mockCommentRepository,
|
|
})
|
|
|
|
tests := []struct {
|
|
name string
|
|
id string
|
|
message string
|
|
mockSetup func()
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "successfully update comment message",
|
|
id: "64a1f2e9347e1a001d345678", // Valid ObjectID
|
|
message: "Updated comment message",
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
UpdateCommentMessage(gomock.Any(), "64a1f2e9347e1a001d345678", "Updated comment message").
|
|
Return(nil)
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "invalid ObjectID format",
|
|
id: "invalid-id", // Invalid ObjectID
|
|
message: "Invalid ID test",
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
UpdateCommentMessage(gomock.Any(), "invalid-id", "Invalid ID test").
|
|
Return(err.ErrInvalidObjectID)
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "comment not found",
|
|
id: "64a1f2e9347e1a001d345679", // Non-existent ObjectID
|
|
message: "Non-existent comment",
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
UpdateCommentMessage(gomock.Any(), "64a1f2e9347e1a001d345679", "Non-existent comment").
|
|
Return(err.ErrNotFound)
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "database error while updating",
|
|
id: "64a1f2e9347e1a001d345680",
|
|
message: "Database error test",
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
UpdateCommentMessage(gomock.Any(), "64a1f2e9347e1a001d345680", "Database error test").
|
|
Return(errors.New("database error"))
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Mock Setup
|
|
tt.mockSetup()
|
|
|
|
// Execute UseCase
|
|
err := uc.UpdateCommentMessage(context.Background(), tt.id, tt.message)
|
|
|
|
// Assert Results
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
if err != nil {
|
|
assert.Contains(t, err.Error(), "failed to update comment")
|
|
}
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommentUseCase_RemoveCommentItem(t *testing.T) {
|
|
mockCtrl := gomock.NewController(t)
|
|
defer mockCtrl.Finish()
|
|
|
|
// Mock Repository
|
|
mockCommentRepository := mockRepo.NewMockCommentRepository(mockCtrl)
|
|
|
|
// UseCase Initialization
|
|
uc := MustCommentUseCase(CommentUseCaseParam{
|
|
Comment: mockCommentRepository,
|
|
})
|
|
|
|
tests := []struct {
|
|
name string
|
|
id string
|
|
mockSetup func()
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "successfully remove comment item",
|
|
id: "64a1f2e9347e1a001d345678", // Valid ObjectID
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
DeleteCommentByID(gomock.Any(), "64a1f2e9347e1a001d345678").
|
|
Return(nil)
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "invalid ObjectID format",
|
|
id: "invalid-id", // Invalid ObjectID
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
DeleteCommentByID(gomock.Any(), "invalid-id").
|
|
Return(err.ErrInvalidObjectID)
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "comment not found",
|
|
id: "64a1f2e9347e1a001d345679", // Non-existent ObjectID
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
DeleteCommentByID(gomock.Any(), "64a1f2e9347e1a001d345679").
|
|
Return(err.ErrNotFound)
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "database error while deleting",
|
|
id: "64a1f2e9347e1a001d345680",
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
DeleteCommentByID(gomock.Any(), "64a1f2e9347e1a001d345680").
|
|
Return(errors.New("database error"))
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Mock Setup
|
|
tt.mockSetup()
|
|
|
|
// Execute UseCase
|
|
err := uc.RemoveCommentItem(context.Background(), tt.id)
|
|
|
|
// Assert Results
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
if err != nil {
|
|
assert.Contains(t, err.Error(), "failed to del comment")
|
|
}
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommentUseCase_ListComment(t *testing.T) {
|
|
mockCtrl := gomock.NewController(t)
|
|
defer mockCtrl.Finish()
|
|
|
|
// Mock Repository
|
|
mockCommentRepository := mockRepo.NewMockCommentRepository(mockCtrl)
|
|
|
|
// UseCase Initialization
|
|
uc := MustCommentUseCase(CommentUseCaseParam{
|
|
Comment: mockCommentRepository,
|
|
})
|
|
|
|
tests := []struct {
|
|
name string
|
|
req usecase.ListCommentRequest
|
|
mockSetup func()
|
|
wantErr bool
|
|
expected []*usecase.CommentDocs
|
|
total int64
|
|
}{
|
|
{
|
|
name: "successfully list comments with replies",
|
|
req: usecase.ListCommentRequest{
|
|
PageSize: 10,
|
|
PageIndex: 1,
|
|
},
|
|
mockSetup: func() {
|
|
// Mock main layer comments
|
|
mockCommentRepository.EXPECT().
|
|
ListComments(gomock.Any(), gomock.Any()).
|
|
Return([]*entity.Comments{
|
|
{
|
|
ID: primitive.NewObjectID(),
|
|
UID: "user-123",
|
|
ReferenceID: "ref-001",
|
|
Message: base64.StdEncoding.EncodeToString(snappy.Encode(nil, []byte("Comment 1"))),
|
|
UpdatedAt: time.Now().UnixNano(),
|
|
CreatedAt: time.Now().UnixNano(),
|
|
},
|
|
}, int64(1), nil)
|
|
|
|
// Mock replies
|
|
mockCommentRepository.EXPECT().
|
|
ListComments(gomock.Any(), gomock.Any()).
|
|
Return([]*entity.Comments{
|
|
{
|
|
ID: primitive.NewObjectID(),
|
|
UID: "user-456",
|
|
ReferenceID: "ref-001",
|
|
ParentCommentID: "parent-001",
|
|
Message: base64.StdEncoding.EncodeToString(snappy.Encode(nil, []byte("Reply 1"))),
|
|
UpdatedAt: time.Now().UnixNano(),
|
|
CreatedAt: time.Now().UnixNano(),
|
|
},
|
|
}, int64(1), nil)
|
|
},
|
|
wantErr: false,
|
|
expected: []*usecase.CommentDocs{
|
|
{
|
|
UID: "user-123",
|
|
ReferenceID: "ref-001",
|
|
Message: "Comment 1",
|
|
Replies: []*usecase.CommentDocs{
|
|
{
|
|
UID: "user-456",
|
|
ReferenceID: "ref-001",
|
|
ParentCommentID: "parent-001",
|
|
Message: "Reply 1",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
total: 1,
|
|
},
|
|
{
|
|
name: "database error while listing comments",
|
|
req: usecase.ListCommentRequest{
|
|
PageSize: 10,
|
|
PageIndex: 1,
|
|
},
|
|
mockSetup: func() {
|
|
mockCommentRepository.EXPECT().
|
|
ListComments(gomock.Any(), gomock.Any()).
|
|
Return([]*entity.Comments{}, int64(0), errors.New("database error"))
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Mock Setup
|
|
tt.mockSetup()
|
|
|
|
// Execute UseCase
|
|
results, total, err := uc.ListComment(context.Background(), tt.req)
|
|
|
|
// Assert Results
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
assert.Nil(t, results)
|
|
assert.Equal(t, int64(0), total)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.total, total)
|
|
assert.Len(t, results, len(tt.expected))
|
|
for i, expectedComment := range tt.expected {
|
|
assert.Equal(t, expectedComment.Message, results[i].Message)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|