diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..3cd32524 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +.PHONY: test cover coveralls + +test: +# running on directory + go test -v -cover + +cover: +# running on directory with view out + go test -coverprofile=cover.out && go tool cover -html=cover.out + +coveralls: +# running on features directory + go list ./... | grep service | xargs -n1 go test -cover diff --git a/features/achievement/service/service_test.go b/features/achievement/service/service_test.go new file mode 100644 index 00000000..e697d4c0 --- /dev/null +++ b/features/achievement/service/service_test.go @@ -0,0 +1,180 @@ +package service + +import ( + "errors" + "log" + "recything/features/achievement/entity" + "recything/mocks" + "recything/utils/constanta" + + "testing" + + "github.com/stretchr/testify/assert" +) + +var dataAchievements = []entity.AchievementCore{ + {Id: 1, Name: "platinum", TargetPoint: 250000}, + {Id: 2, Name: "gold", TargetPoint: 100000}, + {Id: 3, Name: "silver", TargetPoint: 50000}, + {Id: 4, Name: "bronze", TargetPoint: 0}, +} + +var dataAchievement = entity.AchievementCore{ + Id: 1, Name: "platinum", TargetPoint: 250000, +} + +func TestGetAllAchievement(t *testing.T) { + + t.Run("Succes GetAll", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + mockRepo.On("GetAllAchievement").Return(dataAchievements, nil) + + result, err := achievementService.GetAllAchievement() + + assert.NoError(t, err) + assert.NotNil(t, result) + mockRepo.AssertExpectations(t) + + }) + + t.Run("Error", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + mockRepo.On("GetAllAchievement").Return(nil, errors.New("failed")) + + result, err := achievementService.GetAllAchievement() + + assert.Error(t, err) + assert.Empty(t, result) + mockRepo.AssertExpectations(t) + }) +} + +func TestUpdateById(t *testing.T) { + t.Run("Sukses Update", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + achivementID := 1 + point := 249000 + + expectedAchievement := dataAchievements[achivementID-1] + mockRepo.On("FindById", achivementID).Return(expectedAchievement, nil) + mockRepo.On("UpdateById", achivementID, point).Return(nil) + + err := achievementService.UpdateById(achivementID, point) + + assert.NoError(t, err) + assert.Equal(t, achivementID, expectedAchievement.Id) + mockRepo.AssertExpectations(t) + }) + + t.Run("Invalid ID", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + achivementID := 0 + point := 249000 + + err := achievementService.UpdateById(achivementID, point) + + assert.Error(t, err) + mockRepo.AssertExpectations(t) + }) + + t.Run("Data Not Found", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + achivementID := 9 + point := 249000 + + mockRepo.On("FindById", achivementID).Return(dataAchievement, errors.New(constanta.ERROR_RECORD_NOT_FOUND)) + + err := achievementService.UpdateById(achivementID, point) + + assert.Error(t, err) + assert.NotEqual(t, achivementID, dataAchievement.Id) + mockRepo.AssertExpectations(t) + }) + + t.Run("Invalid Point for Bronze", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + achivementID := 4 + point := 100 + + mockRepo.On("FindById", achivementID).Return(dataAchievements[achivementID-1], nil) + + err := achievementService.UpdateById(achivementID, point) + + assert.Error(t, err) + mockRepo.AssertExpectations(t) + }) + + t.Run("Invalid Point for Silver", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + achivementID := 3 + point := 70000 + + mockRepo.On("FindById", achivementID).Return(dataAchievements[achivementID-1], nil) + + err := achievementService.UpdateById(achivementID, point) + log.Println("er", err) + assert.Error(t, err) + mockRepo.AssertExpectations(t) + }) + + t.Run("Invalid Point for Gold", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + achivementID := 2 + point := 100 + + mockRepo.On("FindById", achivementID).Return(dataAchievements[achivementID-1], nil) + + err := achievementService.UpdateById(achivementID, point) + + assert.Error(t, err) + mockRepo.AssertExpectations(t) + }) + + t.Run("Invalid Point for Platinum", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + achivementID := 1 + point := 500000 + + mockRepo.On("FindById", achivementID).Return(dataAchievements[achivementID-1], nil) + + err := achievementService.UpdateById(achivementID, point) + + assert.Error(t, err) + mockRepo.AssertExpectations(t) + }) + + t.Run("Error Repository", func(t *testing.T) { + mockRepo := new(mocks.AchievementRepositoryInterface) + achievementService := NewAchievementService(mockRepo) + + achivementID := 1 + point := 249000 + + mockRepo.On("FindById", achivementID).Return(dataAchievements[achivementID-1],nil) + mockRepo.On("UpdateById", achivementID, point).Return(errors.New("failed")) + + err := achievementService.UpdateById(achivementID, point) + + assert.Error(t, err) + mockRepo.AssertExpectations(t) + }) + +} diff --git a/features/admin/dto/response/mapping.go b/features/admin/dto/response/mapping.go index 45755a82..7dffdab5 100644 --- a/features/admin/dto/response/mapping.go +++ b/features/admin/dto/response/mapping.go @@ -27,6 +27,7 @@ func AdminCoreToAdminResponseLogin(admin entity.AdminCore, token string) AdminRe ID: admin.Id, Fullname: admin.Fullname, Email: admin.Email, + Image: admin.Image, Token: token, } } diff --git a/features/admin/dto/response/respon.go b/features/admin/dto/response/respon.go index a21e418f..61a32829 100644 --- a/features/admin/dto/response/respon.go +++ b/features/admin/dto/response/respon.go @@ -15,5 +15,6 @@ type AdminResponseLogin struct { ID string `json:"id"` Fullname string `json:"fullname"` Email string `json:"email"` + Image string `json:"image"` Token string `json:"token"` } diff --git a/features/admin/repository/repository.go b/features/admin/repository/repository.go index 332dd9e5..4fab7021 100644 --- a/features/admin/repository/repository.go +++ b/features/admin/repository/repository.go @@ -40,7 +40,7 @@ func (ar *AdminRepository) Create(image *multipart.FileHeader, data entity.Admin } dataAdmins.Image = imageURL } else { - dataAdmins.Image = "https://ui-avatars.com/api/?background=56cc33&color=fff&name=" + data.Fullname + dataAdmins.Image = constanta.IMAGE_ADMIN + data.Fullname } tx := ar.db.Create(&dataAdmins) diff --git a/features/admin/service/service_test.go b/features/admin/service/service_test.go index ee7c2f58..0e86b2b3 100644 --- a/features/admin/service/service_test.go +++ b/features/admin/service/service_test.go @@ -17,14 +17,20 @@ import ( "github.com/stretchr/testify/mock" ) -var dataUsers = user.UsersCore{ +var dataUser = user.UsersCore{ Id: "1", Fullname: "recything", Email: "recything@example.com", Point: 2000, } -var dataAdmins = entity.AdminCore{ +var dataUsers = []user.UsersCore{ + {Id: "1", Fullname: "recything", Email: "recything@example.com", Point: 2000}, + {Id: "2", Fullname: "recything2", Email: "recything2@example.com", Point: 3000}, + {Id: "3", Fullname: "recything3", Email: "recything3@example.com", Point: 4000}, +} + +var dataAdmin = entity.AdminCore{ Fullname: "John Doe", Email: "john@example.com", Password: "password123", @@ -32,6 +38,12 @@ var dataAdmins = entity.AdminCore{ Status: "aktif", } +var dataAdmins = []entity.AdminCore{ + {Id: "1", Fullname: "recything", Email: "recything@example.com", Status: "aktif"}, + {Id: "2", Fullname: "recything2", Email: "recything2@example.com", Status: "aktif"}, + {Id: "3", Fullname: "recything3", Email: "recything3@example.com", Status: "aktif"}, +} + var dataReport = report.ReportCore{ ID: "1", ReportType: "tumpukan sampah", @@ -39,6 +51,12 @@ var dataReport = report.ReportCore{ Status: "perlu tinjauan", } +var dataReports = []report.ReportCore{ + {ID: "1", ReportType: "tumpukan sampah", UserId: "user1", Status: "perlu tinjauan"}, + {ID: "2", ReportType: "pelanggaran sampah", UserId: "user2", Status: "perlu tinjauan"}, + {ID: "3", ReportType: "tumpukan sampah", UserId: "user3", Status: "perlu tinjauan"}, +} + func TestCreateAdmin(t *testing.T) { t.Run("Succes Create", func(t *testing.T) { @@ -58,7 +76,7 @@ func TestCreateAdmin(t *testing.T) { _, err := adminService.Create(nil, requestBody) assert.NoError(t, err) - assert.NotEqual(t, requestBody.Email, dataAdmins.Email) + assert.NotEqual(t, requestBody.Email, dataAdmin.Email) mockRepo.AssertExpectations(t) }) @@ -153,7 +171,7 @@ func TestCreateAdmin(t *testing.T) { _, err := adminService.Create(nil, requestBody) assert.Error(t, err) - assert.Equal(t, requestBody.Email, dataAdmins.Email) + assert.Equal(t, requestBody.Email, dataAdmin.Email) mockRepo.AssertExpectations(t) }) @@ -193,11 +211,25 @@ func TestGetAllAdmins(t *testing.T) { assert.Equal(t, pagination.PageInfo{}, pageInfo) assert.Equal(t, 0, count) }) + t.Run("Repository Error", func(t *testing.T) { + mockRepo := new(mocks.AdminRepositoryInterface) + adminService := NewAdminService(mockRepo) + + mockRepo.On("SelectAll", 1, 10, "").Return(dataAdmins, pagination.PageInfo{}, len(dataAdmins), errors.New("repository error")) + + result, pageInfo, count, err := adminService.GetAll("", "", "") + + assert.Error(t, err) + assert.Nil(t, result) + assert.Empty(t, pageInfo) + assert.Empty(t, count) + + mockRepo.AssertExpectations(t) + }) } func TestGetAdminById(t *testing.T) { - // Mock data mockData := entity.AdminCore{ Id: "1", @@ -205,7 +237,6 @@ func TestGetAdminById(t *testing.T) { Email: "john@example.com", Status: "aktif", } - t.Run("Succes GetBYID", func(t *testing.T) { mockRepo := new(mocks.AdminRepositoryInterface) adminService := NewAdminService(mockRepo) @@ -400,7 +431,7 @@ func TestDeleteAdmin(t *testing.T) { } -func TestAdminService_FindByEmailANDPassword(t *testing.T) { +func TestFindByEmailANDPassword(t *testing.T) { dataAdmin := entity.AdminCore{ Email: "admin@example.com", Password: "hashedpassword", @@ -511,6 +542,21 @@ func TestGetAllUsers(t *testing.T) { assert.Equal(t, pagination.PageInfo{}, pageInfo) assert.Equal(t, 0, count) }) + t.Run("Repository Error", func(t *testing.T) { + mockRepo := new(mocks.AdminRepositoryInterface) + adminService := NewAdminService(mockRepo) + + mockRepo.On("GetAllUsers", "", 1, 10).Return(dataUsers, pagination.PageInfo{}, len(dataUsers), errors.New("repository error")) + + result, pageInfo, count, err := adminService.GetAllUsers("", "", "") + + assert.Error(t, err) + assert.Nil(t, result) + assert.Empty(t, pageInfo) + assert.Empty(t, count) + + mockRepo.AssertExpectations(t) + }) } @@ -566,7 +612,7 @@ func TestDeleteUsers(t *testing.T) { err := adminService.DeleteUsers(usersID) assert.NoError(t, err) - assert.Equal(t, usersID, dataUsers.Id) + assert.Equal(t, usersID, dataUser.Id) mockRepo.AssertExpectations(t) @@ -582,13 +628,13 @@ func TestDeleteUsers(t *testing.T) { err := adminService.DeleteUsers(usersID) assert.Error(t, err) - assert.NotEqual(t, usersID, dataUsers.Id) + assert.NotEqual(t, usersID, dataUser.Id) mockRepo.AssertExpectations(t) }) } -func TestAdminService_GetReportById(t *testing.T) { +func TestGetReportById(t *testing.T) { t.Run("Succes GetReportId", func(t *testing.T) { mockRepo := new(mocks.AdminRepositoryInterface) adminService := NewAdminService(mockRepo) @@ -709,4 +755,116 @@ func TestUpdateStatusReport(t *testing.T) { mockRepo.AssertExpectations(t) }) + + t.Run("Repository Error", func(t *testing.T) { + mockRepo := new(mocks.AdminRepositoryInterface) + adminService := NewAdminService(mockRepo) + + id := "1" + status := "diterima" + reason := "" + + mockRepo.On("GetReportById", id).Return(report.ReportCore{}, nil) + mockRepo.On("UpdateStatusReport", id, status, reason).Return(report.ReportCore{}, errors.New("repository error")) + + result, err := adminService.UpdateStatusReport(id, status, reason) + + assert.Error(t, err) + assert.Equal(t,id,dataReport.ID) + assert.Empty(t,result) + mockRepo.AssertExpectations(t) + }) +} + +func TestGetAllReport(t *testing.T) { + + t.Run("Succes Get all Report", func(t *testing.T) { + mockRepo := new(mocks.AdminRepositoryInterface) + adminService := NewAdminService(mockRepo) + + mockRepo.On("GetAllReport", "", "", 1, 10).Return(dataReports, pagination.PageInfo{}, pagination.CountDataInfo{}, nil) + + reports, pageInfo, count, err := adminService.GetAllReport("", "", "", "") + + assert.NoError(t, err) + assert.NotNil(t, reports) + assert.NotNil(t, pageInfo) + assert.NotNil(t, count) + + mockRepo.AssertExpectations(t) + }) + t.Run("Validation Error", func(t *testing.T) { + mockRepo := new(mocks.AdminRepositoryInterface) + adminService := NewAdminService(mockRepo) + + status := "perlu ditinjau" + search := "example search" + page := "1" + limit := "10" + + mockRepo.On("GetAllReport", status, search, 1, 10).Return(dataReports, pagination.PageInfo{}, pagination.CountDataInfo{}, errors.New("failed")) + + reports, pageInfo, count, err := adminService.GetAllReport(status, search, page, limit) + + assert.Error(t, err) + assert.Nil(t, reports) + assert.NotNil(t, pageInfo) + assert.NotNil(t, count) + + mockRepo.AssertExpectations(t) + }) + + t.Run("Wrong Limit Pagination", func(t *testing.T) { + mockRepo := mocks.NewAdminRepositoryInterface(t) + adminService := NewAdminService(mockRepo) + + result, pageInfo, count, err := adminService.GetAllReport("", "", "", "20") + + assert.Error(t, err) + assert.Nil(t, result) + assert.Empty(t, pageInfo) + assert.Empty(t, count) + mockRepo.AssertExpectations(t) + + }) + + t.Run("Status Invalid Input", func(t *testing.T) { + mockRepo := new(mocks.AdminRepositoryInterface) + adminService := NewAdminService(mockRepo) + + status := "perlu" + search := "example search" + page := "1" + limit := "10" + + reports, pageInfo, count, err := adminService.GetAllReport(status, search, page, limit) + + assert.Error(t, err) + assert.Nil(t, reports) + assert.NotNil(t, pageInfo) + assert.NotNil(t, count) + + mockRepo.AssertExpectations(t) + }) + + t.Run("Repository Error", func(t *testing.T) { + mockRepo := new(mocks.AdminRepositoryInterface) + adminService := NewAdminService(mockRepo) + + status := "perlu ditinjau" + search := "example search" + page := "1" + limit := "10" + + mockRepo.On("GetAllReport", status, search, 1, 10).Return(dataReports, pagination.PageInfo{}, pagination.CountDataInfo{}, errors.New("repository error")) + + reports, pageInfo, count, err := adminService.GetAllReport(status, search, page, limit) + + assert.Error(t, err) + assert.Nil(t, reports) + assert.Empty(t, pageInfo) + assert.Empty(t, count) + + mockRepo.AssertExpectations(t) + }) } diff --git a/features/article/service/service.go b/features/article/service/service.go index cca7ffd0..0d5df972 100644 --- a/features/article/service/service.go +++ b/features/article/service/service.go @@ -145,6 +145,10 @@ func (article *articleService) PostLike(idArticle string, idUser string) error { // PostShare implements entity.ArticleServiceInterface. func (article *articleService) PostShare(idArticle string) error { + if idArticle == "" { + return errors.New(constanta.ERROR_ID_INVALID) + } + postShare := article.ArticleRepository.PostShare(idArticle) if postShare != nil { return postShare diff --git a/features/article/service/service_test.go b/features/article/service/service_test.go new file mode 100644 index 00000000..b0ad3bb8 --- /dev/null +++ b/features/article/service/service_test.go @@ -0,0 +1,480 @@ +package service_test + +import ( + "errors" + "mime/multipart" + "testing" + "time" + + "recything/features/article/entity" + "recything/features/article/service" + "recything/mocks" + "recything/utils/constanta" + "recything/utils/pagination" + + "github.com/stretchr/testify/assert" +) + +func TestDeleteArticleSuccess(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + articleID := "12345abc" + + repoData.On("DeleteArticle", articleID).Return(nil) + err := articleService.DeleteArticle(articleID) + + assert.NoError(t, err) +} + +func TestDeleteArticleEmptyID(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + err := articleService.DeleteArticle("") + + assert.Error(t, err) + assert.Contains(t, err.Error(), "id artikel tidak ditemukan") +} + +func TestDeleteArticleRepositoryError(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + articleID := "12345abc" + + repoData.On("DeleteArticle", articleID).Return(errors.New("repository error")) + err := articleService.DeleteArticle(articleID) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "gagal menghapus artikel") +} + +func TestGetSpecificArticleSuccess(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticle := entity.ArticleCore{ + ID: "12345abc", + Title: "Sample Article", + Content: "ini isi dari artikel", + } + + repoData.On("GetSpecificArticle", mockArticle.ID).Return(mockArticle, nil) + articleData, err := articleService.GetSpecificArticle(mockArticle.ID) + + assert.NoError(t, err) + assert.Equal(t, mockArticle, articleData) +} + +func TestGetSpecificArticleEmptyID(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + articleData, err := articleService.GetSpecificArticle("") + + assert.Error(t, err) + assert.Equal(t, entity.ArticleCore{}, articleData) + assert.Contains(t, err.Error(), "id tidak cocok") +} + +func TestGetSpecificArticleRepositoryError(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "12345abc" + + repoData.On("GetSpecificArticle", mockArticleID).Return(entity.ArticleCore{}, errors.New("repository error")) + articleData, err := articleService.GetSpecificArticle(mockArticleID) + + assert.Error(t, err) + assert.Equal(t, entity.ArticleCore{}, articleData) + assert.Contains(t, err.Error(), "gagal membaca data") +} + +func TestUpdateArticleSuccess(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "12345abc" + mockArticleInput := entity.ArticleCore{ + Title: "Updated Article", + Content: "Updated Article Content", + Category_id: []string{"123", "456"}, + } + + repoData.On("UpdateArticle", mockArticleID, mockArticleInput, (*multipart.FileHeader)(nil)).Return(mockArticleInput, nil) + updatedArticle, err := articleService.UpdateArticle(mockArticleID, mockArticleInput, nil) + + assert.NoError(t, err) + assert.Equal(t, mockArticleInput, updatedArticle) +} + +func TestUpdateArticleEmptyID(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + updatedArticle, err := articleService.UpdateArticle("", entity.ArticleCore{}, nil) + + assert.Error(t, err) + assert.Equal(t, entity.ArticleCore{}, updatedArticle) + assert.Contains(t, err.Error(), "id tidak ditemukan") +} + +func TestUpdateArticleInvalidData(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "12345abc" + invalidArticleInput := entity.ArticleCore{ + Title: "Updated Article", + } + + updatedArticle, err := articleService.UpdateArticle(mockArticleID, invalidArticleInput, nil) + + assert.Error(t, err) + assert.Equal(t, entity.ArticleCore{}, updatedArticle) + assert.Contains(t, err.Error(), "artikel tidak boleh kosong") +} + +func TestUpdateArticleInvalidCategory(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "12345abc" + invalidCategoryInput := entity.ArticleCore{ + Title: "Updated Article", + Content: "Updated Article Content", + Category_id: []string{}, + } + + updatedArticle, err := articleService.UpdateArticle(mockArticleID, invalidCategoryInput, nil) + + assert.Error(t, err) + assert.Equal(t, entity.ArticleCore{}, updatedArticle) + assert.Contains(t, err.Error(), "kategori tidak boleh kosong") +} + +func TestUpdateArticleLargeImage(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "12345abc" + mockArticleInput := entity.ArticleCore{ + Title: "Updated Article", + Content: "Updated Article Content", + Category_id: []string{"123", "456"}, + } + + //larger image size + largeImage := &multipart.FileHeader{ + Size: 6 * 1024 * 1024, + } + + updatedArticle, err := articleService.UpdateArticle(mockArticleID, mockArticleInput, largeImage) + + assert.Error(t, err) + assert.Equal(t, entity.ArticleCore{}, updatedArticle) + assert.Contains(t, err.Error(), "ukuran file tidak boleh lebih dari 5 MB") +} + +func TestUpdateArticleRepositoryError(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "123" + mockArticleInput := entity.ArticleCore{ + Title: "Updated Title", + Content: "Updated Content", + Category_id: []string{"1", "2"}, + } + + mockImage := &multipart.FileHeader{ + Size: 1 * 1024 * 1024, + } + + repoData.On("UpdateArticle", mockArticleID, mockArticleInput, mockImage).Return(entity.ArticleCore{}, errors.New("repository error")) + updatedArticle, err := articleService.UpdateArticle(mockArticleID, mockArticleInput, mockImage) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "repository error") + assert.Equal(t, entity.ArticleCore{}, updatedArticle) +} + +func TestGetAllArticleInvalidLimit(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockPage := 1 + mockLimit := 15 + mockSearch := "Sample Search" + mockFilter := "Article" + + articles, pageInfo, count, err := articleService.GetAllArticle(mockPage, mockLimit, mockSearch, mockFilter) + + assert.Error(t, err) + assert.Empty(t, articles) + assert.Equal(t, pagination.PageInfo{}, pageInfo) + assert.Equal(t, 0, count) + assert.Contains(t, err.Error(), "limit tidak boleh lebih dari 10") +} + +func TestGetAllArticleInvalidCategory(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockPage := 1 + mockLimit := 5 + mockSearch := "Sample Search" + mockFilter := "Invalid Category" + + articles, pageInfo, count, err := articleService.GetAllArticle(mockPage, mockLimit, mockSearch, mockFilter) + + assert.Error(t, err) + assert.Empty(t, articles) + assert.Equal(t, pagination.PageInfo{}, pageInfo) + assert.Equal(t, 0, count) + assert.Contains(t, err.Error(), "error : kategori tidak valid") +} + +func TestGetAllArticleRepositoryError(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockPage := 1 + mockLimit := 5 + mockSearch := "Sample Search" + mockFilter := "Article" + + repoData.On("GetAllArticle", mockPage, mockLimit, mockSearch, mockFilter).Return([]entity.ArticleCore{}, pagination.PageInfo{}, 0, errors.New("repository error")) + + articles, pageInfo, count, err := articleService.GetAllArticle(mockPage, mockLimit, mockSearch, mockFilter) + + assert.Error(t, err) + assert.Empty(t, articles) + assert.Equal(t, pagination.PageInfo{}, pageInfo) + assert.Equal(t, 0, count) + assert.Contains(t, err.Error(), "kategori tidak valid") +} + +func TestCreateArticleSuccess(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleInput := entity.ArticleCore{ + Title: "Sample Title", + Content: "Sample Content", + Category_id: []string{"1", "2"}, + Image: "sample_image.jpg", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + mockImage := &multipart.FileHeader{ + Size: 1 * 1024 * 1024, + } + + repoData.On("CreateArticle", mockArticleInput, mockImage).Return(mockArticleInput, nil) + article, err := articleService.CreateArticle(mockArticleInput, mockImage) + + assert.NoError(t, err) + assert.Equal(t, mockArticleInput, article) +} + +func TestCreateArticleEmptyTitleAndContent(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleInput := entity.ArticleCore{} + + mockImage := &multipart.FileHeader{ + Size: 1 * 1024 * 1024, + } + + article, err := articleService.CreateArticle(mockArticleInput, mockImage) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "judul dan konten artikel tidak boleh kosong") + assert.Equal(t, entity.ArticleCore{}, article) +} + +func TestCreateArticleEmptyCategory(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleInput := entity.ArticleCore{ + Title: "Sample Title", + Content: "Sample Content", + } + + mockImage := &multipart.FileHeader{ + Size: 1 * 1024 * 1024, + } + + article, err := articleService.CreateArticle(mockArticleInput, mockImage) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "kategori tidak boleh kosong") + assert.Equal(t, entity.ArticleCore{}, article) +} + +func TestCreateArticleLargeImage(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleInput := entity.ArticleCore{ + Title: "Sample Title", + Content: "Sample Content", + Category_id: []string{"1", "2"}, + } + + mockImage := &multipart.FileHeader{ + Size: 6 * 1024 * 1024, + } + + article, err := articleService.CreateArticle(mockArticleInput, mockImage) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "ukuran file tidak boleh lebih dari 5 MB") + assert.Equal(t, entity.ArticleCore{}, article) +} + +func TestCreateArticleRepositoryError(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleInput := entity.ArticleCore{ + Title: "Updated Title", + Content: "Updated Content", + Category_id: []string{"1", "2"}, + } + + mockImage := &multipart.FileHeader{ + Size: 1 * 1024 * 1024, + } + + repoData.On("CreateArticle", mockArticleInput, mockImage).Return(entity.ArticleCore{}, errors.New("repository error")) + CreateArticle, err := articleService.CreateArticle(mockArticleInput, mockImage) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "repository error") + assert.Equal(t, entity.ArticleCore{}, CreateArticle) +} + +func TestPostLikeSuccess(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "123" + mockUserID := "456" + + repoData.On("PostLike", mockArticleID, mockUserID).Return(nil) + err := articleService.PostLike(mockArticleID, mockUserID) + + assert.NoError(t, err) +} + +func TestPostLikeEmptyArticleID(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockUserID := "456" + + err := articleService.PostLike("", mockUserID) + + assert.Error(t, err) + assert.Contains(t, err.Error(), constanta.ERROR_ID_INVALID) +} + +func TestPostLikeEmptyUserID(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "123" + + err := articleService.PostLike(mockArticleID, "") + + assert.Error(t, err) + assert.Contains(t, err.Error(), constanta.ERROR_ID_INVALID) +} + +func TestPostLikeRepositoryError(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "123" + mockUserID := "456" + + repoData.On("PostLike", mockArticleID, mockUserID).Return(errors.New("repository error")) + err := articleService.PostLike(mockArticleID, mockUserID) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "repository error") +} + +func TestPostShareSuccess(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "123" + + repoData.On("PostShare", mockArticleID).Return(nil) + err := articleService.PostShare(mockArticleID) + + assert.NoError(t, err) +} + +func TestPostShareEmptyArticleID(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + err := articleService.PostShare("") + + assert.Error(t, err) + assert.Contains(t, err.Error(), constanta.ERROR_ID_INVALID) +} + +func TestPostShareRepositoryError(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockArticleID := "123" + + repoData.On("PostShare", mockArticleID).Return(errors.New("repository error")) + err := articleService.PostShare(mockArticleID) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "repository error") +} + +func TestGetPopularArticleSuccess(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockSearch := "Sample Search" + + mockArticleList := []entity.ArticleCore{ + {ID: "1", Title: "Article 1"}, + {ID: "2", Title: "Article 2"}, + } + + repoData.On("GetPopularArticle", mockSearch).Return(mockArticleList, nil) + articles, err := articleService.GetPopularArticle(mockSearch) + + assert.NoError(t, err) + assert.Equal(t, mockArticleList, articles) +} + +func TestGetPopularArticleError(t *testing.T) { + repoData := new(mocks.ArticleRepositoryInterface) + articleService := service.NewArticleService(repoData) + + mockSearch := "Sample Search" + + repoData.On("GetPopularArticle", mockSearch).Return([]entity.ArticleCore{}, errors.New("repository error")) + articles, err := articleService.GetPopularArticle(mockSearch) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "repository error") + assert.Empty(t, articles) +} diff --git a/features/community/service/service_test.go b/features/community/service/service_test.go new file mode 100644 index 00000000..651f517f --- /dev/null +++ b/features/community/service/service_test.go @@ -0,0 +1,989 @@ +package service + +import ( + "errors" + "mime/multipart" + "recything/features/community/entity" + "recything/mocks" + "recything/utils/constanta" + "recything/utils/pagination" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestCreateCommunitySuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockImage := &multipart.FileHeader{} + mockCommunityData := entity.CommunityCore{ + Name: "Sample", + Description: "This is a test community", + Location: "Test Location", + MaxMembers: 100, + } + + // Set up the mock behavior for GetByName to return an error, indicating that the name is not taken + repoData.On("GetByName", mockCommunityData.Name).Return(entity.CommunityCore{}, errors.New("not found")) + + // Set up the mock behavior for CreateCommunity to succeed + repoData.On("CreateCommunity", mockImage, mockCommunityData).Return(nil) + + // Call method + err := communityService.CreateCommunity(mockImage, mockCommunityData) + + // Assertions + assert.NoError(t, err) +} + +func TestCreateCommunityNameTaken(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockImage := &multipart.FileHeader{} + mockCommunityData := entity.CommunityCore{ + Name: "Sample Community", + Description: "This is a test community", + Location: "Test Location", + MaxMembers: 100, + } + + // Set up the mock behavior for GetByName to return no error, indicating that the name is already taken + repoData.On("GetByName", mockCommunityData.Name).Return(entity.CommunityCore{}, nil) + + // Call the method + err := communityService.CreateCommunity(mockImage, mockCommunityData) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "nama community sudah digunakan") +} + +func TestCreateCommunityEmptyFields(t *testing.T) { + communityService := NewCommunityService(nil) + + // Call the method with empty fields + err := communityService.CreateCommunity(nil, entity.CommunityCore{}) + + // Assertions + assert.Error(t, err) +} + +func TestCreateCommunityRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockImage := &multipart.FileHeader{} + mockCommunityData := entity.CommunityCore{ + Name: "Sample", + Description: "This is a test community", + Location: "Test Location", + MaxMembers: 100, + } + + // Set up the mock behavior for GetByName to return an error, indicating that the name is not taken + repoData.On("GetByName", mockCommunityData.Name).Return(entity.CommunityCore{}, errors.New("not found")) + + // Set up the mock behavior for CreateCommunity to return an error + expectedError := errors.New("failed to create community") + repoData.On("CreateCommunity", mockImage, mockCommunityData).Return(expectedError) + + // Call the method + err := communityService.CreateCommunity(mockImage, mockCommunityData) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, expectedError.Error()) +} + +func TestDeleteCommunityByIdSuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + communityID := "community123" + + // Mock DeleteCommunityById to return nil + repoData.On("DeleteCommunityById", communityID).Return(nil) + + err := communityService.DeleteCommunityById(communityID) + + assert.NoError(t, err) +} + +func TestDeleteCommunityByIdInvalidID(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + communityID := "" + + err := communityService.DeleteCommunityById(communityID) + + assert.Error(t, err) + assert.Equal(t, constanta.ERROR_ID_INVALID, err.Error()) +} + +func TestDeleteCommunityByIdRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + communityID := "community123" + + // Mock DeleteCommunityById to return an error + repoData.On("DeleteCommunityById", communityID).Return(errors.New("repository error")) + + err := communityService.DeleteCommunityById(communityID) + + assert.Error(t, err) + assert.Equal(t, "repository error", err.Error()) +} + +func TestGetAllCommunitySuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + page := "1" + limit := "10" + search := "community" + + expectedCommunityCores := []entity.CommunityCore{ + {Id: "1", Name: "Community1", Description: "Description1", Location: "Location1", MaxMembers: 100}, + {Id: "2", Name: "Community2", Description: "Description2", Location: "Location2", MaxMembers: 150}, + {Id: "3", Name: "Community3", Description: "Description3", Location: "Location3", MaxMembers: 100}, + {Id: "4", Name: "Community4", Description: "Description4", Location: "Location4", MaxMembers: 150}, + {Id: "5", Name: "Community5", Description: "Description5", Location: "Location5", MaxMembers: 100}, + } + + expectedPageInfo := pagination.PageInfo{ + CurrentPage: 1, + Limit: 10, + LastPage: 4, + } + + expectedCount := 15 + + repoData.On("GetAllCommunity", 1, 10, "community").Return(expectedCommunityCores, expectedPageInfo, expectedCount, nil) + + communityCores, pageInfo, count, err := communityService.GetAllCommunity(page, limit, search) + + assert.NoError(t, err) + assert.Equal(t, expectedCommunityCores, communityCores) + assert.Equal(t, expectedPageInfo, pageInfo) + assert.Equal(t, expectedCount, count) +} + +func TestGetAllCommunityInvalidPaginationParameters(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + page := "invalid" + limit := "10" + search := "community" + + communityCores, pageInfo, count, err := communityService.GetAllCommunity(page, limit, search) + + assert.Error(t, err) + assert.Nil(t, communityCores) + assert.Equal(t, pagination.PageInfo{}, pageInfo) + assert.Equal(t, 0, count) +} + +func TestGetAllCommunityRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + page := "1" + limit := "10" + search := "community" + + repoData.On("GetAllCommunity", 1, 10, "community").Return(nil, pagination.PageInfo{}, 0, errors.New("repository error")) + + communityCores, pageInfo, count, err := communityService.GetAllCommunity(page, limit, search) + + assert.Error(t, err) + assert.Nil(t, communityCores) + assert.Equal(t, pagination.PageInfo{}, pageInfo) + assert.Equal(t, 0, count) + assert.Equal(t, "repository error", err.Error()) +} + +func TestGetCommunityByIdSuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockID := "community123" + + // Mock data for the community returned by the repository + mockCommunity := entity.CommunityCore{ + Id: mockID, + Name: "Sample Community", + Description: "This is a test community", + Location: "Test Location", + Members: 50, + MaxMembers: 100, + Image: "community_image.jpg", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + // Set up the mock behavior + repoData.On("GetCommunityById", mockID).Return(mockCommunity, nil) + + // Call the method + resultCommunity, err := communityService.GetCommunityById(mockID) + + // Assertions + assert.NoError(t, err) + assert.Equal(t, mockCommunity, resultCommunity) +} + +func TestGetCommunityByIdInvalidID(t *testing.T) { + communityService := NewCommunityService(nil) + + invalidID := "" + + // Call the method with an invalid ID + resultCommunity, err := communityService.GetCommunityById(invalidID) + + // Assertions + assert.Error(t, err) + assert.Equal(t, entity.CommunityCore{}, resultCommunity) + assert.EqualError(t, err, constanta.ERROR_ID_INVALID) +} + +func TestGetCommunityByIdRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockID := "community123" + + // Set up the mock behavior for repository error + repoData.On("GetCommunityById", mockID).Return(entity.CommunityCore{}, errors.New("repository error")) + + // Call the method + resultCommunity, err := communityService.GetCommunityById(mockID) + + // Assertions + assert.Error(t, err) + assert.Equal(t, entity.CommunityCore{}, resultCommunity) +} + +func TestUpdateCommunityByIdSuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockID := "community123" + mockImage := &multipart.FileHeader{ + Filename: "community_image.jpg", + Size: 1024, + } + + mockData := entity.CommunityCore{ + Name: "Updated Community", + Description: "Updated description", + Location: "Updated Location", + Members: 100, + MaxMembers: 150, + } + + // Set up the mock behavior for repository + repoData.On("GetByName", mockData.Name).Return(entity.CommunityCore{}, errors.New("not found")) + repoData.On("UpdateCommunityById", mockID, mockImage, mockData).Return(nil) + + // Call the method + err := communityService.UpdateCommunityById(mockID, mockImage, mockData) + + // Assertions + assert.NoError(t, err) +} + +func TestUpdateCommunityByIdEmptyFields(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockID := "community123" + mockImage := &multipart.FileHeader{ + Filename: "community_image.jpg", + Size: 1024, + } + + mockData := entity.CommunityCore{} // Empty fields + + // Call the method with empty fields + err := communityService.UpdateCommunityById(mockID, mockImage, mockData) + + // Assertions + assert.Error(t, err) +} + +func TestUpdateCommunityByIdDuplicateName(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockID := "community123" + mockImage := &multipart.FileHeader{ + Filename: "community_image.jpg", + Size: 1024, + } + + mockData := entity.CommunityCore{ + Name: "Updated Community", + Description: "Updated description", + Location: "Updated Location", + Members: 100, + MaxMembers: 150, + } + + // Set up the mock behavior for repository with duplicate name + repoData.On("GetByName", mockData.Name).Return(entity.CommunityCore{}, nil) + + // Call the method + err := communityService.UpdateCommunityById(mockID, mockImage, mockData) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "nama community sudah digunakan") +} + +func TestUpdateCommunityByIdRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockID := "community123" + mockImage := &multipart.FileHeader{ + Filename: "community_image.jpg", + Size: 1024, + } + + mockData := entity.CommunityCore{ + Name: "Updated Community", + Description: "Updated description", + Location: "Updated Location", + Members: 100, + MaxMembers: 150, + Id: "123de", + } + + // Set up the mock behavior for GetByName to return no error + repoData.On("GetByName", mockData.Name).Return(entity.CommunityCore{}, errors.New("not found")) + + // Set up the mock behavior for UpdateCommunityById with repository error + repoData.On("UpdateCommunityById", mockID, mockImage, mockData).Return(errors.New("repository error")) + + // Call the method + err := communityService.UpdateCommunityById(mockID, mockImage, mockData) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "repository error") +} + +func TestCreateEventSuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventInput := entity.CommunityEventCore{ + Title: "Sample Event", + Description: "This is a test event", + Date: "2023/12/25", + Quota: 50, + Location: "Test Location", + Status: "berjalan", + MapLink: "https://map-link.com", + FormLink: "https://form-link.com", + } + + mockImage := &multipart.FileHeader{ + Filename: "event_image.jpg", + Size: 1024, + } + + // Set up the mock behavior for repository + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + repoData.On("CreateEvent", mockCommunityID, mockEventInput, mockImage).Return(nil) + + // Call the method + err := communityService.CreateEvent(mockCommunityID, mockEventInput, mockImage) + + // Assertions + assert.NoError(t, err) +} + +func TestCreateEventCommunityNotFound(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "nonexistentCommunity" + mockEventInput := entity.CommunityEventCore{ + Title: "Sample Event", + Description: "This is a test event", + Date: "2023/12/25", + Quota: 50, + Location: "Test Location", + Status: "berjalan", + MapLink: "https://map-link.com", + FormLink: "https://form-link.com", + } + + // Set up the mock behavior for community not found + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, errors.New("community not found")) + + // Call the method + err := communityService.CreateEvent(mockCommunityID, mockEventInput, nil) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "community not found") +} + +func TestCreateEventEmptyFields(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventInput := entity.CommunityEventCore{} // Empty fields + + // Set up the expected behavior for GetCommunityById + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Call the method with empty fields + err := communityService.CreateEvent(mockCommunityID, mockEventInput, nil) + + // Assertions + assert.Error(t, err) +} + +func TestCreateEventInvalidDateFormat(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventInput := entity.CommunityEventCore{ + Title: "Sample Event", + Description: "This is a test event", + Date: "2023-12-25", + Quota: 50, + Location: "Test Location", + Status: "berjalan", + MapLink: "https://map-link.com", + FormLink: "https://form-link.com", + } + + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Call the method with invalid date format + err := communityService.CreateEvent(mockCommunityID, mockEventInput, nil) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "error, tanggal harus dalam format 'yyyy/mm/dd'") +} + +func TestCreateEventExceedFileSizeLimit(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventInput := entity.CommunityEventCore{ + Title: "Sample Event", + Description: "This is a test event", + Date: "2023/12/25", + Quota: 50, + Location: "Test Location", + Status: "berjalan", + MapLink: "https://map-link.com", + FormLink: "https://form-link.com", + } + + mockImage := &multipart.FileHeader{ + Filename: "event_image.jpg", + Size: 6 * 1024 * 1024, + } + + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Call the method with an image exceeding the file size limit + err := communityService.CreateEvent(mockCommunityID, mockEventInput, mockImage) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "ukuran file tidak boleh lebih dari 5 MB") +} + +func TestCreateEventRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventInput := entity.CommunityEventCore{ + Title: "Sample Event", + Description: "This is a test event", + Date: "2023/12/25", + Quota: 50, + Location: "Test Location", + Status: "berjalan", + MapLink: "https://map-link.com", + FormLink: "https://form-link.com", + } + + mockImage := &multipart.FileHeader{ + Filename: "event_image.jpg", + Size: 1024, + } + + // Set up the mock behavior for repository error + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + repoData.On("CreateEvent", mockCommunityID, mockEventInput, mockImage).Return(errors.New("repository error")) + + // Call the method + err := communityService.CreateEvent(mockCommunityID, mockEventInput, mockImage) + + // Assertions + assert.Error(t, err) +} + +func TestDeleteEventSuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + + // Set up the expected behavior for DeleteEvent + repoData.On("DeleteEvent", mockCommunityID, mockEventID).Return(nil) + + // Call the method + err := communityService.DeleteEvent(mockCommunityID, mockEventID) + + // Assertions + assert.NoError(t, err) +} + +func TestDeleteEventEmptyEventID(t *testing.T) { + communityService := NewCommunityService(nil) // No need for a repository mock in this case + + mockCommunityID := "community123" + mockEmptyEventID := "" + + // Call the method with an empty event ID + err := communityService.DeleteEvent(mockCommunityID, mockEmptyEventID) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "id event tidak ditemukan") +} + +func TestDeleteEventRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + + // Set up the expected behavior for DeleteEvent with repository error + repoData.On("DeleteEvent", mockCommunityID, mockEventID).Return(errors.New("repository error")) + + // Call the method + err := communityService.DeleteEvent(mockCommunityID, mockEventID) + + // Assertions + assert.Error(t, err) +} + +func TestReadAllEventSuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockStatus := "berjalan" + mockPage := "1" + mockLimit := "10" + mockSearch := "Sample Search" + mockCommunityID := "community123" + + // Set up the expected behavior for ReadAllEvent + repoData.On("ReadAllEvent", mockStatus, 1, 10, mockSearch, mockCommunityID).Return( + []entity.CommunityEventCore{ + { + Id: "event123", + Title: "Sample Event", + Description: "This is a test event", + Location: "Test Location", + MapLink: "https://maps.example.com", + FormLink: "https://form.example.com", + Quota: 50, + Date: "2023/12/31", + Status: "berjalan", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + }, + pagination.PageInfo{Limit: 10, CurrentPage: 1, LastPage: 5}, + pagination.CountEventInfo{TotalCount: 50, CountBerjalan: 20, CountBelumBerjalan: 15, CountSelesai: 15}, + nil, + ) + + // Call the method + data, pageInfo, count, err := communityService.ReadAllEvent(mockStatus, mockPage, mockLimit, mockSearch, mockCommunityID) + + // Assertions + assert.NoError(t, err) + assert.Len(t, data, 1) + assert.Equal(t, "Sample Event", data[0].Title) + assert.Equal(t, 10, pageInfo.Limit) + assert.Equal(t, 1, pageInfo.CurrentPage) + assert.Equal(t, 5, pageInfo.LastPage) + assert.Equal(t, 50, count.TotalCount) + assert.Equal(t, 20, count.CountBerjalan) + assert.Equal(t, 15, count.CountBelumBerjalan) + assert.Equal(t, 15, count.CountSelesai) +} + +func TestReadAllEventInvalidStatus(t *testing.T) { + communityService := NewCommunityService(nil) // No need for a repository mock in this case + + mockInvalidStatus := "invalid" + mockPage := "1" + mockLimit := "10" + mockSearch := "Sample Search" + mockCommunityID := "community123" + + // Call the method with an invalid status + data, pageInfo, count, err := communityService.ReadAllEvent(mockInvalidStatus, mockPage, mockLimit, mockSearch, mockCommunityID) + + // Assertions + assert.Error(t, err) + assert.Nil(t, data) + assert.EqualError(t, err, "status tidak valid") + assert.Equal(t, pagination.PageInfo{}, pageInfo) + assert.Equal(t, pagination.CountEventInfo{}, count) +} + +func TestReadAllEventValidationErr(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockStatus := "berjalan" + mockPage := "1" + mockLimit := "limit" + mockSearch := "Sample Search" + mockCommunityID := "community123" + + // Call the method + data, pageInfo, count, err := communityService.ReadAllEvent(mockStatus, mockPage, mockLimit, mockSearch, mockCommunityID) + + // Assertions + assert.Error(t, err) + assert.Nil(t, data) + assert.EqualError(t, err, "limit harus berupa angka") + assert.Equal(t, pagination.PageInfo{}, pageInfo) + assert.Equal(t, pagination.CountEventInfo{}, count) +} + +func TestReadAllEventRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockStatus := "berjalan" + mockPage := "1" + mockLimit := "10" + mockSearch := "Sample Search" + mockCommunityID := "community123" + + // Set up the expected behavior for ReadAllEvent with repository error + repoData.On("ReadAllEvent", mockStatus, 1, 10, mockSearch, mockCommunityID).Return( + nil, pagination.PageInfo{}, pagination.CountEventInfo{}, errors.New("repository error"), + ) + + // Call the method + data, pageInfo, count, err := communityService.ReadAllEvent(mockStatus, mockPage, mockLimit, mockSearch, mockCommunityID) + + // Assertions + assert.Error(t, err) + assert.Nil(t, data) + assert.EqualError(t, err, "repository error") + assert.Equal(t, pagination.PageInfo{}, pageInfo) + assert.Equal(t, pagination.CountEventInfo{}, count) +} + +func TestReadEventSuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + + // Set up the expected behavior for ReadEvent + repoData.On("ReadEvent", mockCommunityID, mockEventID).Return( + entity.CommunityEventCore{ + Id: mockEventID, + Title: "Sample Event", + Description: "This is a test event", + Location: "Test Location", + MapLink: "https://maps.example.com", + FormLink: "https://form.example.com", + Quota: 50, + Date: "2023/12/31", + Status: "berjalan", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + nil, + ) + + // Call the method + eventData, err := communityService.ReadEvent(mockCommunityID, mockEventID) + + // Assertions + assert.NoError(t, err) + assert.Equal(t, mockEventID, eventData.Id) + assert.Equal(t, "Sample Event", eventData.Title) +} + +func TestReadEventInvalidEventID(t *testing.T) { + communityService := NewCommunityService(nil) // No need for a repository mock in this case + + mockCommunityID := "community123" + mockInvalidEventID := "" + + // Call the method with an invalid event ID + eventData, err := communityService.ReadEvent(mockCommunityID, mockInvalidEventID) + + // Assertions + assert.Error(t, err) + assert.Equal(t, entity.CommunityEventCore{}, eventData) + assert.EqualError(t, err, "event tidak ditemukan") +} + +func TestReadEventRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + + // Set up the expected behavior for ReadEvent with repository error + repoData.On("ReadEvent", mockCommunityID, mockEventID).Return( + entity.CommunityEventCore{}, errors.New("repository error"), + ) + + // Call the method + eventData, err := communityService.ReadEvent(mockCommunityID, mockEventID) + + // Assertions + assert.Error(t, err) + assert.Equal(t, entity.CommunityEventCore{}, eventData) + assert.EqualError(t, err, "repository error") +} + +func TestUpdateEventSuccess(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + + mockImage := &multipart.FileHeader{ + Filename: "event_image.jpg", + Size: 1024, + } + + mockEventInput := entity.CommunityEventCore{ + Title: "Updated Event Title", + Description: "Updated event description", + Location: "Updated Location", + MapLink: "https://updated-maps.example.com", + FormLink: "https://updated-form.example.com", + Quota: 75, + Date: "2024/01/15", + Status: "selesai", + } + + // Set up the mock behavior for GetCommunityById + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Set up the mock behavior for UpdateEvent + repoData.On("UpdateEvent", mockCommunityID, mockEventID, mockEventInput, mockImage).Return(nil) + + // Call the method + err := communityService.UpdateEvent(mockCommunityID, mockEventID, mockEventInput, mockImage) + + // Assertions + assert.NoError(t, err) +} + +func TestUpdateEventInvalidEventID(t *testing.T) { + communityService := NewCommunityService(nil) // No need for a repository mock in this case + + mockCommunityID := "community123" + mockInvalidEventID := "" + + // Call the method with an invalid event ID + err := communityService.UpdateEvent(mockCommunityID, mockInvalidEventID, entity.CommunityEventCore{}, nil) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "event tidak ditemukan") +} + +func TestUpdateEventInvalidStatus(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + + mockImage := &multipart.FileHeader{ + Filename: "event_image.jpg", + Size: 1024, + } + + mockEventInput := entity.CommunityEventCore{ + Status: "invalid_status", + } + + // Set up the mock behavior for GetCommunityById + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Call the method with an invalid status + err := communityService.UpdateEvent(mockCommunityID, mockEventID, mockEventInput, mockImage) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "error : status input tidak valid") +} + +func TestUpdateEventEmptyFields(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + mockImage := &multipart.FileHeader{ + Filename: "event_image.jpg", + Size: 1024, + } + + mockEventInput := entity.CommunityEventCore{ + Description: "Updated event description", + Location: "Updated Location", + MapLink: "https://updated-maps.example.com", + FormLink: "https://updated-form.example.com", + Quota: 75, + Date: "2024/01/15", + Status: "selesai", + } + + // Set up the mock behavior for GetCommunityById + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Call the method with empty fields + err := communityService.UpdateEvent(mockCommunityID, mockEventID, mockEventInput, mockImage) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "error : harap lengkapi data dengan benar") +} + +func TestUpdateEventLargeImageSize(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + mockImage := &multipart.FileHeader{ + Filename: "large_image.jpg", + Size: 10 * 1024 * 1024, + } + + mockEventInput := entity.CommunityEventCore{ + Title: "Updated Event Title", + Description: "Updated event description", + Location: "Updated Location", + MapLink: "https://updated-maps.example.com", + FormLink: "https://updated-form.example.com", + Quota: 75, + Date: "2024/01/15", + Status: "selesai", + } + + // Set up the mock behavior for GetCommunityById + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Call the method with a large image size + err := communityService.UpdateEvent(mockCommunityID, mockEventID, mockEventInput, mockImage) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "ukuran file tidak boleh lebih dari 5 MB") +} + +func TestUpdateEventInvalidDateFormat(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + mockImage := &multipart.FileHeader{ + Filename: "event_image.jpg", + Size: 1024, + } + + mockEventInput := entity.CommunityEventCore{ + Title: "Updated Event Title", + Description: "Updated event description", + Location: "Updated Location", + MapLink: "https://updated-maps.example.com", + FormLink: "https://updated-form.example.com", + Quota: 75, + Date: "invalid_date_format", + Status: "selesai", + } + + // Set up the mock behavior for GetCommunityById + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Call the method with an invalid date format + err := communityService.UpdateEvent(mockCommunityID, mockEventID, mockEventInput, mockImage) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "error, tanggal harus dalam format 'yyyy/mm/dd'") +} + +func TestUpdateEventRepositoryError(t *testing.T) { + repoData := new(mocks.CommunityRepositoryInterface) + communityService := NewCommunityService(repoData) + + mockCommunityID := "community123" + mockEventID := "event123" + mockImage := &multipart.FileHeader{ + Filename: "event_image.jpg", + Size: 1024, + } + + mockEventInput := entity.CommunityEventCore{ + Title: "Updated Event Title", + Description: "Updated event description", + Location: "Updated Location", + MapLink: "https://updated-maps.example.com", + FormLink: "https://updated-form.example.com", + Quota: 75, + Date: "2024/01/15", + Status: "selesai", + } + + // Set up the mock behavior for GetCommunityById + repoData.On("GetCommunityById", mockCommunityID).Return(entity.CommunityCore{}, nil) + + // Set up the mock behavior for UpdateEvent with repository error + repoData.On("UpdateEvent", mockCommunityID, mockEventID, mockEventInput, mockImage).Return(errors.New("repository error")) + + // Call the method + err := communityService.UpdateEvent(mockCommunityID, mockEventID, mockEventInput, mockImage) + + // Assertions + assert.Error(t, err) + assert.EqualError(t, err, "repository error") +} diff --git a/features/dashboard/service/cover.out b/features/dashboard/service/cover.out new file mode 100644 index 00000000..ff8ec550 --- /dev/null +++ b/features/dashboard/service/cover.out @@ -0,0 +1,44 @@ +mode: set +recything/features/dashboard/service/service.go:13.110,17.2 1 1 +recything/features/dashboard/service/service.go:20.295,22.16 2 1 +recything/features/dashboard/service/service.go:22.16,24.3 1 1 +recything/features/dashboard/service/service.go:26.2,27.16 2 1 +recything/features/dashboard/service/service.go:27.16,29.3 1 1 +recything/features/dashboard/service/service.go:31.2,32.16 2 1 +recything/features/dashboard/service/service.go:32.16,34.3 1 0 +recything/features/dashboard/service/service.go:36.2,37.16 2 1 +recything/features/dashboard/service/service.go:37.16,39.3 1 1 +recything/features/dashboard/service/service.go:41.2,42.16 2 1 +recything/features/dashboard/service/service.go:42.16,44.3 1 1 +recything/features/dashboard/service/service.go:46.2,47.16 2 1 +recything/features/dashboard/service/service.go:47.16,49.3 1 1 +recything/features/dashboard/service/service.go:51.2,52.16 2 1 +recything/features/dashboard/service/service.go:52.16,54.3 1 1 +recything/features/dashboard/service/service.go:56.2,57.16 2 1 +recything/features/dashboard/service/service.go:57.16,59.3 1 0 +recything/features/dashboard/service/service.go:61.2,62.16 2 1 +recything/features/dashboard/service/service.go:62.16,64.3 1 1 +recything/features/dashboard/service/service.go:66.2,67.16 2 1 +recything/features/dashboard/service/service.go:67.16,69.3 1 0 +recything/features/dashboard/service/service.go:71.2,81.119 10 1 +recything/features/dashboard/service/service.go:85.294,87.16 2 1 +recything/features/dashboard/service/service.go:87.16,89.3 1 1 +recything/features/dashboard/service/service.go:91.2,92.16 2 1 +recything/features/dashboard/service/service.go:92.16,94.3 1 1 +recything/features/dashboard/service/service.go:96.2,97.16 2 1 +recything/features/dashboard/service/service.go:97.16,99.3 1 0 +recything/features/dashboard/service/service.go:101.2,102.16 2 1 +recything/features/dashboard/service/service.go:102.16,104.3 1 1 +recything/features/dashboard/service/service.go:106.2,107.16 2 1 +recything/features/dashboard/service/service.go:107.16,109.3 1 1 +recything/features/dashboard/service/service.go:111.2,112.16 2 1 +recything/features/dashboard/service/service.go:112.16,114.3 1 1 +recything/features/dashboard/service/service.go:116.2,117.16 2 1 +recything/features/dashboard/service/service.go:117.16,119.3 1 1 +recything/features/dashboard/service/service.go:121.2,122.16 2 1 +recything/features/dashboard/service/service.go:122.16,124.3 1 0 +recything/features/dashboard/service/service.go:126.2,127.16 2 1 +recything/features/dashboard/service/service.go:127.16,129.3 1 0 +recything/features/dashboard/service/service.go:131.2,132.16 2 1 +recything/features/dashboard/service/service.go:132.16,134.3 1 0 +recything/features/dashboard/service/service.go:137.2,149.120 11 1 diff --git a/features/dashboard/service/service.go b/features/dashboard/service/service.go index e7f0abed..8efcecd8 100644 --- a/features/dashboard/service/service.go +++ b/features/dashboard/service/service.go @@ -149,72 +149,3 @@ func (ds *dashboardService) DashboardYears() (dashboard.GetCountUser, dashboard. return userResult, voucherResult, reportResult, trashResult, scalaResult, userRanking, monthlyStats, incomeResult, nil } -// CountMonthlyTrashAndScalaTypesYear implements entity.DashboardServiceInterface. -// func (ds *dashboardService) CountMonthlyTrashAndScalaTypesYear() ([]dashboard.MonthlyStats, error) { -// trashAndScalaTypes, err := ds.dashboardRepository.CountWeeklyTrashAndScalaTypes() -// if err != nil { -// return nil, err -// } - -// // Menghitung jumlah bulan dalam setahun -// startOfYear := time.Now().AddDate(-1, 0, 0) // Mengubah ke -1 untuk mendapatkan awal tahun sekarang -// monthsInYear := 12 -// monthlyStats := make([]dashboard.MonthlyStats, monthsInYear) - -// for i := 0; i < monthsInYear; i++ { -// // Menghitung awal dan akhir bulan -// monthStartDate := startOfYear.AddDate(0, i, 0) -// monthEndDate := monthStartDate.AddDate(0, 1, -1) - -// // Filter data yang berada dalam rentang waktu bulan ini -// filteredData := dashboard.FilterDataByDate(trashAndScalaTypes, monthStartDate, monthEndDate) - -// // Hitung jumlah data trash_type dan scala_type -// trashCount, scalaCount := dashboard.CountTrashAndScalaTypes(filteredData) - -// // Set nilai MonthlyStats -// monthlyStats[i].Month = i + 1 -// monthlyStats[i].Trash = trashCount -// monthlyStats[i].Scala = scalaCount -// } - -// return monthlyStats, nil -// } - -// // CountWeeklyTrashAndScalaTypes implements entity.DashboardServiceInterface. -// func (ds *dashboardService) CountWeeklyTrashAndScalaTypes() ([]dashboard.WeeklyStats, error) { -// trashAndScalaTypes, err := ds.dashboardRepository.CountWeeklyTrashAndScalaTypes() -// if err != nil { -// return nil, err -// } - -// // Menghitung jumlah minggu dalam bulan ini -// startOfMonth := time.Now().AddDate(0, 0, -time.Now().Day()+1) -// year, month, _ := startOfMonth.Date() -// weeksInMonth := helper.GetWeeksInMonth(year, month) -// weeklyStats := make([]dashboard.WeeklyStats, weeksInMonth) - -// for i := 0; i < weeksInMonth; i++ { -// // Menghitung awal dan akhir minggu -// weekStartDate := startOfMonth.AddDate(0, 0, 7*i) -// weekEndDate := startOfMonth.AddDate(0, 0, 7*(i+1)-1) - -// if i == weeksInMonth-1 { -// lastDayOfMonth := time.Date(year, month+1, 0, 0, 0, 0, 0, time.UTC).Day() -// weekEndDate = startOfMonth.AddDate(0, 0, lastDayOfMonth-1) -// } -// log.Printf("Week %d: StartDate: %s, EndDate: %s\n", i+1, weekStartDate, weekEndDate) -// // Filter data yang berada dalam rentang waktu minggu ini -// filteredData := dashboard.FilterDataByDate(trashAndScalaTypes, weekStartDate, weekEndDate) - -// // Hitung jumlah data trash_type dan scala_type -// trashCount, scalaCount := dashboard.CountTrashAndScalaTypes(filteredData) - -// // Set nilai WeeklyStats -// weeklyStats[i].Week = i + 1 -// weeklyStats[i].Trash = trashCount -// weeklyStats[i].Scala = scalaCount -// } - -// return weeklyStats, nil -// } diff --git a/features/dashboard/service/service_test.go b/features/dashboard/service/service_test.go new file mode 100644 index 00000000..7d514ce8 --- /dev/null +++ b/features/dashboard/service/service_test.go @@ -0,0 +1,1050 @@ +package service + +import ( + "errors" + re "recything/features/report/entity" + te "recything/features/trash_exchange/entity" + ue "recything/features/user/entity" + ve "recything/features/voucher/entity" + "recything/mocks" + "recything/utils/dashboard" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDashboardMonthlySuccess(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + // Set up the expected behavior for CountUserActiveLastMonth + repoData.On("CountUserActiveLastMonth").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + // Set up the expected behavior for GetUserRanking + repoData.On("GetUserRanking").Return( + []ue.UsersCore{ + {Id: "user1", Point: 100}, + {Id: "user2", Point: 90}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchanges + repoData.On("CountVoucherExchanges").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + // Set up the expected behavior for CountReports + repoData.On("CountReports").Return( + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + []re.ReportCore{ + {ID: "report7"}, + {ID: "report8"}, + }, + nil, + ) + + // Set up the expected behavior for CountTrashExchanges + repoData.On("CountTrashExchanges").Return( + []te.TrashExchangeCore{ + {Id: "trash1"}, + {Id: "trash2"}, + }, + []te.TrashExchangeCore{ + {Id: "trash3"}, + {Id: "trash4"}, + }, + nil, + ) + + // Set up the expected behavior for CountCategory + repoData.On("CountCategory").Return( + []re.ReportCore{ + {ID: "category1"}, + {ID: "category2"}, + }, + []re.ReportCore{ + {ID: "category3"}, + {ID: "category4"}, + }, + nil, + ) + + // Set up the expected behavior for CountWeeklyTrashAndScalaTypes + repoData.On("CountWeeklyTrashAndScalaTypes").Return( + []re.ReportCore{ + {ID: "weekly1"}, + {ID: "weekly2"}, + }, + nil, + ) + + // Set up the expected behavior for CountTrashExchangesIncome + repoData.On("CountTrashExchangesIncome").Return( + dashboard.TrashIncomeStats{ + TotalIncomeThisMonth: 200, + TotalIncomeLastMonth: 180, + }, + nil, + ) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardMonthly() + + // Assertions + assert.NoError(t, err) + assert.Equal(t, 1, len(users.TotalPenggunaAktif)) + assert.Equal(t, 1, len(vouchers.TotalPenukaran)) + assert.Equal(t, 1, len(reports.TotalReporting)) // Sesuaikan panjang dengan jumlah laporan + assert.Equal(t, 1, len(trash.TotalTrashExchange)) + assert.Equal(t, 2, len(scaleTypes.Company)) + assert.Equal(t, 2, len(userRanking)) + assert.Equal(t, 5, len(weeklyStats)) // Sesuaikan panjang dengan jumlah minggu + assert.Equal(t, 200, income.TotalIncome) +} + +func TestDashboardMonthlyCountUserActiveLastMonthError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastMonth").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardMonthly() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardMonthlyCountVoucherActiveError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastMonth").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + repoData.On("CountVoucherExchanges").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardMonthly() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardMonthlyCountReportsError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastMonth").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchanges + repoData.On("CountVoucherExchanges").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + repoData.On("CountReports").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardMonthly() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardMonthlyCountCategoryError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastMonth").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchanges + repoData.On("CountVoucherExchanges").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + // Set up the expected behavior for CountReports + repoData.On("CountReports").Return( + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + []re.ReportCore{ + {ID: "report7"}, + {ID: "report8"}, + }, + nil, + ) + + // Set up the expected behavior for CountTrashExchanges + repoData.On("CountTrashExchanges").Return( + []te.TrashExchangeCore{ + {Id: "trash1"}, + {Id: "trash2"}, + }, + []te.TrashExchangeCore{ + {Id: "trash3"}, + {Id: "trash4"}, + }, + nil, + ) + + repoData.On("CountCategory").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardMonthly() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardMonthlyCountWeeklyTrashAndScalaTypesError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + // Set up the expected behavior for GetUserRanking + repoData.On("GetUserRanking").Return( + []ue.UsersCore{ + {Id: "user1", Point: 100}, + {Id: "user2", Point: 90}, + }, + nil, + ) + + repoData.On("CountUserActiveLastMonth").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchanges + repoData.On("CountVoucherExchanges").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + // Set up the expected behavior for CountReports + repoData.On("CountReports").Return( + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + []re.ReportCore{ + {ID: "report7"}, + {ID: "report8"}, + }, + nil, + ) + + // Set up the expected behavior for CountTrashExchanges + repoData.On("CountTrashExchanges").Return( + []te.TrashExchangeCore{ + {Id: "trash1"}, + {Id: "trash2"}, + }, + []te.TrashExchangeCore{ + {Id: "trash3"}, + {Id: "trash4"}, + }, + nil, + ) + + // Set up the expected behavior for CountCategory + repoData.On("CountCategory").Return( + []re.ReportCore{ + {ID: "category1"}, + {ID: "category2"}, + }, + []re.ReportCore{ + {ID: "category3"}, + {ID: "category4"}, + }, + nil, + ) + + // Set up the expected behavior for CountTrashExchangesIncome + repoData.On("CountTrashExchangesIncome").Return( + dashboard.TrashIncomeStats{ + TotalIncomeThisMonth: 200, + TotalIncomeLastMonth: 180, + }, + nil, + ) + + repoData.On("CountWeeklyTrashAndScalaTypes").Return(nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardMonthly() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardMonthlyCountTotalTrashActiveError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastMonth").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchanges + repoData.On("CountVoucherExchanges").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + // Set up the expected behavior for CountReports + repoData.On("CountReports").Return( + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + []re.ReportCore{ + {ID: "report7"}, + {ID: "report8"}, + }, + nil, + ) + + repoData.On("CountTrashExchanges").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardMonthly() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardMonthlyCountUserActiveError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardMonthly() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + + +//years + +func TestDashboardYearsSuccess(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActiveThisYear + repoData.On("CountUserActiveThisYear").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + // Set up the expected behavior for CountUserActiveLastYear + repoData.On("CountUserActiveLastYear").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + // Set up the expected behavior for GetUserRankingYear + repoData.On("GetUserRankingYear").Return( + []ue.UsersCore{ + {Id: "user1", Point: 100}, + {Id: "user2", Point: 90}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchangesYear + repoData.On("CountVoucherExchangesYear").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + // Set up the expected behavior for CountReportsYear + repoData.On("CountReportsYear").Return( + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + []re.ReportCore{ + {ID: "report7"}, + {ID: "report8"}, + }, + nil, + ) + + // Set up the expected behavior for CountTrashExchangesYear + repoData.On("CountTrashExchangesYear").Return( + []te.TrashExchangeCore{ + {Id: "trash1"}, + {Id: "trash2"}, + }, + []te.TrashExchangeCore{ + {Id: "trash3"}, + {Id: "trash4"}, + }, + nil, + ) + + // Set up the expected behavior for CountCategoryYear + repoData.On("CountCategoryYear").Return( + []re.ReportCore{ + {ID: "category1"}, + {ID: "category2"}, + }, + []re.ReportCore{ + {ID: "category3"}, + {ID: "category4"}, + }, + nil, + ) + + // Set up the expected behavior for GetUserRankingYear + repoData.On("GetUserRankingYear").Return( + []ue.UsersCore{ + {Id: "user1", Point: 100}, + {Id: "user2", Point: 90}, + }, + nil, + ) + + // Set up the expected behavior for CountWeeklyTrashAndScalaTypes + repoData.On("CountWeeklyTrashAndScalaTypes").Return( + []re.ReportCore{ + {ID: "weekly1"}, + {ID: "weekly2"}, + }, + nil, + ) + + // Set up the expected behavior for CountTrashExchangesIncomeYear + repoData.On("CountTrashExchangesIncomeYear").Return( + dashboard.TrashIncomeStats{ + TotalIncomeThisMonth: 200, + TotalIncomeLastMonth: 180, + }, + nil, + ) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, monthlyStats, income, err := dashboardService.DashboardYears() + + // Assertions + assert.NoError(t, err) + assert.Equal(t, 1, len(users.TotalPenggunaAktif)) + assert.Equal(t, 1, len(vouchers.TotalPenukaran)) + assert.Equal(t, 1, len(reports.TotalReporting)) + assert.Equal(t, 1, len(trash.TotalTrashExchange)) + assert.Equal(t, 2, len(scaleTypes.Company)) + assert.Equal(t, 2, len(userRanking)) + assert.Equal(t, 12, len(monthlyStats)) // Assuming 12 months + assert.Equal(t, 200, income.TotalIncome) +} + +func TestDashboardYearsCountUserActiveLastYearError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActiveThisYear").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastYear").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardYears() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardYearCountVoucherActiveError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveThisYear").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastYear").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + nil, + ) + + repoData.On("CountVoucherExchangesYear").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardYears() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardYearsCountReportsError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActiveThisYear").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastYear").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchanges + repoData.On("CountVoucherExchangesYear").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + repoData.On("CountReportsYear").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardYears() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardYearsCountCategoryError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActiveThisYear").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastYear").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchanges + repoData.On("CountVoucherExchangesYear").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + // Set up the expected behavior for CountReports + repoData.On("CountReportsYear").Return( + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + []re.ReportCore{ + {ID: "report7"}, + {ID: "report8"}, + }, + nil, + ) + + // Set up the expected behavior for CountTrashExchanges + repoData.On("CountTrashExchangesYear").Return( + []te.TrashExchangeCore{ + {Id: "trash1"}, + {Id: "trash2"}, + }, + []te.TrashExchangeCore{ + {Id: "trash3"}, + {Id: "trash4"}, + }, + nil, + ) + + repoData.On("CountCategoryYear").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardYears() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardYearCountTotalTrashActiveError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActive + repoData.On("CountUserActive").Return( + []ue.UsersCore{ + {Id: "user1"}, + {Id: "user2"}, + }, + []re.ReportCore{ + {ID: "report1"}, + {ID: "report2"}, + }, + nil, + ) + + repoData.On("CountUserActiveThisYear").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report3"}, + {ID: "report4"}, + }, + nil, + ) + + repoData.On("CountUserActiveLastYear").Return( + []ue.UsersCore{ + {Id: "user3"}, + {Id: "user4"}, + }, + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + nil, + ) + + // Set up the expected behavior for CountVoucherExchanges + repoData.On("CountVoucherExchangesYear").Return( + []ve.ExchangeVoucherCore{ + {Id: "voucher1"}, + {Id: "voucher2"}, + }, + []ve.ExchangeVoucherCore{ + {Id: "voucher3"}, + {Id: "voucher4"}, + }, + nil, + ) + + // Set up the expected behavior for CountReports + repoData.On("CountReportsYear").Return( + []re.ReportCore{ + {ID: "report5"}, + {ID: "report6"}, + }, + []re.ReportCore{ + {ID: "report7"}, + {ID: "report8"}, + }, + nil, + ) + + repoData.On("CountTrashExchangesYear").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, weeklyStats, income, err := dashboardService.DashboardYears() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t,"", users.TotalPenggunaAktif) + assert.Equal(t,"", vouchers.TotalPenukaran) + assert.Equal(t,"", reports.TotalReporting) + assert.Equal(t,"", trash.TotalTrashExchange) + assert.Equal(t,"", scaleTypes.Company) + assert.Nil(t,userRanking) + assert.Nil(t,weeklyStats) + assert.Equal(t,"", income.Persentase) +} + +func TestDashboardYearsCountUserActiveError(t *testing.T) { + repoData := new(mocks.DashboardRepositoryInterface) + dashboardService := NewDashboardService(repoData) + + // Set up the expected behavior for CountUserActiveThisYear with an error + repoData.On("CountUserActiveThisYear").Return(nil, nil, errors.New("some error")) + + // Call the method + users, vouchers, reports, trash, scaleTypes, userRanking, monthlyStats, income, err := dashboardService.DashboardYears() + + // Assertions for error case + assert.Error(t, err) + assert.Equal(t, "", users.TotalPenggunaAktif) + assert.Equal(t, "", vouchers.TotalPenukaran) + assert.Equal(t, "", reports.TotalReporting) + assert.Equal(t, "", trash.TotalTrashExchange) + assert.Equal(t, "", scaleTypes.Company) + assert.Nil(t, userRanking) + assert.Nil(t, monthlyStats) + assert.Equal(t, "", income.Persentase) +} diff --git a/features/faq/service/service_test.go b/features/faq/service/service_test.go new file mode 100644 index 00000000..fd518ba2 --- /dev/null +++ b/features/faq/service/service_test.go @@ -0,0 +1,83 @@ +package service + +import ( + "errors" + "testing" + "recything/features/faq/entity" + "recything/mocks" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestGetAllFaqs(t *testing.T) { + mockRepo := new(mocks.FaqRepositoryInterface) + faqService := NewFaqService(mockRepo) + + // Mock data + mockData := []entity.FaqCore{ + {Id: 1, Title: "Cara saya melakukan penukaran point", Description: "Berikut cara melakukan penukaran point"}, + {Id: 2, Title: "Cara saya bergabung ke dalam komunitas", Description: "Berikut cara bergabung ke dalam komunitas"}, + {Id: 3, Title: "Cara saya melaporkan sampah tidak pada tempatnya", Description: "Berikut cara melaporkan sampah tidak pada tempatnya"}, + } + + // Mock repository response + mockRepo.On("GetFaqs"). + Return(mockData, nil) + + // Test case + faqs, err := faqService.GetFaqs() + + assert.NoError(t, err) + assert.Len(t, faqs, len(mockData)) + mockRepo.AssertExpectations(t) +} + +func TestGetAllFaqsError(t *testing.T) { + mockRepo := new(mocks.FaqRepositoryInterface) + faqService := NewFaqService(mockRepo) + + // Mock repository response with an error + mockRepo.On("GetFaqs").Return(nil, errors.New("some error")) + + // Test case + faqs, err := faqService.GetFaqs() + + assert.Error(t, err) + assert.Nil(t, faqs) + mockRepo.AssertExpectations(t) +} + +func TestGetFaqById(t *testing.T) { + mockRepo := new(mocks.FaqRepositoryInterface) + faqService := NewFaqService(mockRepo) + + // Mock data + mockData := entity.FaqCore{ + Id: 1, Title: "Cara saya melakukan penukaran point", Description: "Berikut cara melakukan penukaran point", + } + + mockRepo.On("GetFaqsById", mock.AnythingOfType("uint")).Return(mockData, nil) + + faq, err := faqService.GetFaqsById(1) + + assert.NoError(t, err) + assert.Equal(t, mockData.Id, faq.Id) + mockRepo.AssertExpectations(t) +} + +func TestGetFaqByIdNonExistentId(t *testing.T) { + mockRepo := new(mocks.FaqRepositoryInterface) + faqService := NewFaqService(mockRepo) + + // Mock repository response with an error for a non-existent ID + mockRepo.On("GetFaqsById", mock.AnythingOfType("uint")).Return(entity.FaqCore{}, errors.New("not found")) + + // Test case + faq, err := faqService.GetFaqsById(999) + + assert.Error(t, err) + assert.EqualError(t, err, "not found") // Check for the specific error message + assert.Equal(t, entity.FaqCore{}, faq) // Check for the specific zero-value of FaqCore + mockRepo.AssertExpectations(t) +} diff --git a/features/recybot/service/service.go b/features/recybot/service/service.go index 81e63646..d4d238c1 100644 --- a/features/recybot/service/service.go +++ b/features/recybot/service/service.go @@ -3,13 +3,13 @@ package service import ( "context" "fmt" - "log" "os" "recything/features/recybot/entity" "recything/utils/constanta" "recything/utils/helper" "recything/utils/pagination" "recything/utils/validation" + "strings" "github.com/joho/godotenv" "github.com/sashabaranov/go-openai" @@ -46,7 +46,6 @@ func (rb *recybotService) CreateData(data entity.RecybotCore) (entity.RecybotCor return result, nil } - func (rb *recybotService) FindAllData(filter, search, page, limit string) ([]entity.RecybotCore, pagination.PageInfo, helper.CountPrompt, error) { pageInt, limitInt, err := validation.ValidateParamsPagination(page, limit) @@ -102,55 +101,66 @@ func (rb *recybotService) UpdateData(idData string, data entity.RecybotCore) (en } func (rb *recybotService) GetPrompt(question string) (string, error) { - err := godotenv.Load() - if err != nil { - log.Fatal("Error loading .env file") - } + godotenv.Load() - dataRecybot, err := rb.recybotRepository.GetAll() - if err != nil { - return "", err - } + resultChan := make(chan map[string][]string) + errChan := make(chan error) - output := make(map[string][]string) - for _, item := range dataRecybot { - output[item.Category] = append(output[item.Category], item.Question) - } + go func() { + dataRecybot, err := rb.recybotRepository.GetAll() + if err != nil { + errChan <- err + return + } - var prompt string - for category, questions := range output { - prompt += "\n" + fmt.Sprintf("kategori %s:\n", category) - for _, question := range questions { - prompt += fmt.Sprintf("%s\n", question) + output := make(map[string][]string) + for _, item := range dataRecybot { + output[item.Category] = append(output[item.Category], item.Question) } - } - log.Println(prompt) - ctx := context.Background() - client := openai.NewClient(os.Getenv("OPEN_AI_KEY")) - model := openai.GPT3Dot5Turbo - messages := []openai.ChatCompletionMessage{ - { - Role: "system", - Content: prompt, - }, - { - Role: "user", - Content: question, - }, - } + resultChan <- output + }() + + select { + case output := <-resultChan: + var prompt strings.Builder + for category, questions := range output { + prompt.WriteString(fmt.Sprintln(" ")) + prompt.WriteString(fmt.Sprintf("kategori %s:\n", category)) + for _, question := range questions { + prompt.WriteString(fmt.Sprintf("%s\n", question)) + } + } - response, err := client.CreateChatCompletion( - ctx, - openai.ChatCompletionRequest{ - Model: model, - Messages: messages, - }, - ) - if err != nil { + ctx := context.Background() + client := openai.NewClient(os.Getenv("OPEN_AI_KEY")) + model := openai.GPT3Dot5Turbo + messages := []openai.ChatCompletionMessage{ + { + Role: "system", + Content: prompt.String(), + }, + { + Role: "user", + Content: question, + }, + } + + response, err := client.CreateChatCompletion( + ctx, + openai.ChatCompletionRequest{ + Model: model, + Messages: messages, + }, + ) + if err != nil { + return "", err + } + + answer := response.Choices[0].Message.Content + return answer, nil + + case err := <-errChan: return "", err } - - answer := response.Choices[0].Message.Content - return answer, nil } diff --git a/features/recybot/service/service_test.go b/features/recybot/service/service_test.go new file mode 100644 index 00000000..52ed9ddc --- /dev/null +++ b/features/recybot/service/service_test.go @@ -0,0 +1,298 @@ +package service + +import ( + "errors" + entity "recything/features/recybot/entity" + "recything/mocks" + "recything/utils/constanta" + "recything/utils/helper" + "recything/utils/pagination" + + "github.com/stretchr/testify/assert" + + "testing" +) + +var dataPrompt = []entity.RecybotCore{ + {ID: "1", Category: "informasi", Question: "jakarta ada di pulau jawa"}, + {ID: "2", Category: "batasan", Question: "tidak boleh berkata kasar"}, + {ID: "3", Category: "sampah organik", Question: "daun merupakan sampah organik"}, +} + +func TestCreateData(t *testing.T) { + t.Run("Succes Create", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + requestBody := entity.RecybotCore{ + Category: "informasi", + Question: "matahari terbit di timur", + } + mockRepo.On("Create", requestBody).Return(requestBody, nil) + + data, err := recybotService.CreateData(requestBody) + + assert.NoError(t, err) + assert.NotNil(t, data) + mockRepo.AssertExpectations(t) + + }) + t.Run("Data Empty", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + requestBody := entity.RecybotCore{ + Category: "", + Question: "", + } + + data, err := recybotService.CreateData(requestBody) + + assert.Error(t, err) + assert.Empty(t, data) + mockRepo.AssertExpectations(t) + }) + t.Run("Equal Data Category", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + requestBody := entity.RecybotCore{ + Category: "robot", + Question: "robot itu menggunakan baterai", + } + + data, err := recybotService.CreateData(requestBody) + + assert.Error(t, err) + assert.Empty(t, data) + assert.NotEqualValues(t, []string{"sampah anorganik", "sampah organik", "informasi", "batasan"}, requestBody.Category) + mockRepo.AssertExpectations(t) + }) + t.Run("Repository Error", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + requestBody := entity.RecybotCore{ + Category: "informasi", + Question: "matahari terbit di timur", + } + + mockRepo.On("Create", requestBody).Return(entity.RecybotCore{}, errors.New("Repository error")) + + data, err := recybotService.CreateData(requestBody) + + assert.Error(t, err) + assert.Empty(t, data) + + mockRepo.AssertExpectations(t) + }) +} + +func TestFindAllData(t *testing.T) { + + t.Run("Success FindAll", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + mockRepo.On("FindAll", 1, 10, "", "").Return(dataPrompt, pagination.PageInfo{}, helper.CountPrompt{}, nil) + + data, pageInfo, count, err := recybotService.FindAllData("", "", "", "") + + assert.NoError(t, err) + assert.NotNil(t, data) + assert.NotNil(t, count) + assert.NotNil(t, pageInfo) + mockRepo.AssertExpectations(t) + }) + + t.Run("Wrong Limit", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + data, _, _, err := recybotService.FindAllData("", "", "", "50") + + assert.Error(t, err) + assert.Empty(t, data) + mockRepo.AssertExpectations(t) + }) + + t.Run("Repository Error", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + mockRepo.On("FindAll", 1, 10, "", "").Return(nil, pagination.PageInfo{}, helper.CountPrompt{}, errors.New("Repository error")) + + data, _, _, err := recybotService.FindAllData("", "", "1", "10") + + assert.Error(t, err) + assert.Empty(t, data) + mockRepo.AssertExpectations(t) + }) +} + +func TestGetById(t *testing.T) { + t.Run("Succes GetById", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + recybotID := "1" + + mockRepo.On("GetById", recybotID).Return(dataPrompt[0], nil) + + result, err := recybotService.GetById(recybotID) + + assert.NoError(t, err) + assert.Equal(t, recybotID, dataPrompt[0].ID) + assert.NotNil(t, result) + mockRepo.AssertExpectations(t) + }) + + t.Run("Data Not Found", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + recybotID := "2" + mockRepo.On("GetById", recybotID).Return(entity.RecybotCore{}, errors.New(constanta.ERROR_RECORD_NOT_FOUND)) + + result, err := recybotService.GetById(recybotID) + + assert.Error(t, err) + assert.NotEqual(t, recybotID, dataPrompt[0].ID) + assert.Empty(t, result) + mockRepo.AssertExpectations(t) + }) +} + +func TestDeleteData(t *testing.T) { + t.Run("Succes DeleteData", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + recybotID := "1" + + mockRepo.On("Delete", recybotID).Return(nil) + + err := recybotService.DeleteData(recybotID) + + assert.NoError(t, err) + assert.Equal(t, recybotID, dataPrompt[0].ID) + mockRepo.AssertExpectations(t) + }) + + t.Run("Data Not Found", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + recybotID := "2" + mockRepo.On("Delete", recybotID).Return(errors.New(constanta.ERROR_RECORD_NOT_FOUND)) + + err := recybotService.DeleteData(recybotID) + + assert.Error(t, err) + assert.NotEqual(t, recybotID, dataPrompt[0].ID) + mockRepo.AssertExpectations(t) + }) +} + +func TestUpdateData(t *testing.T) { + t.Run("Succes UpdateData", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + requestBody := entity.RecybotCore{ + Category: "informasi", + Question: "mobil beroda empat", + } + + recybotID := "2" + mockRepo.On("Update", recybotID, requestBody).Return(requestBody, nil) + + data, err := recybotService.UpdateData(recybotID, requestBody) + + assert.NoError(t, err) + assert.NotNil(t, data) + assert.Equal(t, recybotID, dataPrompt[1].ID) + mockRepo.AssertExpectations(t) + + }) + t.Run("Data Empty", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + requestBody := entity.RecybotCore{ + Category: "", + Question: "", + } + recybotID := "2" + data, err := recybotService.UpdateData(recybotID, requestBody) + + assert.Error(t, err) + assert.Empty(t, data) + mockRepo.AssertExpectations(t) + }) + t.Run("Equal Data Category", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + requestBody := entity.RecybotCore{ + Category: "robot", + Question: "robot itu menggunakan baterai", + } + + recybotID := "2" + data, err := recybotService.UpdateData(recybotID, requestBody) + + assert.Error(t, err) + assert.Empty(t, data) + assert.NotEqualValues(t, []string{"sampah anorganik", "sampah organik", "informasi", "batasan"}, requestBody.Category) + mockRepo.AssertExpectations(t) + }) + t.Run("Repository Error", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + requestBody := entity.RecybotCore{ + Category: "informasi", + Question: "sampah", + } + recybotID := "2" + mockRepo.On("Update", recybotID, requestBody).Return(entity.RecybotCore{}, errors.New("Repository error")) + + data, err := recybotService.UpdateData(recybotID, requestBody) + + assert.Error(t, err) + assert.Empty(t, data) + + mockRepo.AssertExpectations(t) + }) +} + +func TestGetPrompt(t *testing.T) { + t.Run("Error API Key", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + question := "contoh 3 sampah organik" + mockRepo.On("GetAll").Return(dataPrompt, nil) + + result, err := recybotService.GetPrompt(question) + + assert.Error(t, err) + assert.Empty(t,result) + mockRepo.AssertExpectations(t) + }) + + t.Run("Error Get All Prompt", func(t *testing.T) { + mockRepo := new(mocks.RecybotRepositoryInterface) + recybotService := NewRecybotService(mockRepo) + + question := "contoh 3 sampah organik" + mockRepo.On("GetAll").Return(dataPrompt, errors.New("Failed Get Data")) + + result, err := recybotService.GetPrompt(question) + + assert.Error(t, err) + assert.Empty(t, result) + mockRepo.AssertExpectations(t) + }) +} diff --git a/features/report/service/service_test.go b/features/report/service/service_test.go new file mode 100644 index 00000000..e926641d --- /dev/null +++ b/features/report/service/service_test.go @@ -0,0 +1,334 @@ +package service + +import ( + "errors" + "mime/multipart" + "recything/features/report/entity" + "recything/mocks" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestReadAllReportSuccess(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReports := []entity.ReportCore{ + {ID: "report1", UserId: mockUserID, Description: "Report 1"}, + {ID: "report2", UserId: mockUserID, Description: "Report 2"}, + + } + + repoData.On("ReadAllReport", mockUserID).Return(mockReports, nil) + reports, err := reportService.ReadAllReport(mockUserID) + + assert.NoError(t, err) + assert.Equal(t, mockReports, reports) +} + +func TestReadAllReportEmptyUserID(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + reports, err := reportService.ReadAllReport("") + + assert.Error(t, err) + assert.Contains(t, err.Error(), "pengguna tidak ditemukan") + assert.Empty(t, reports) +} + +func TestReadAllReportRepositoryError(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + + repoData.On("ReadAllReport", mockUserID).Return([]entity.ReportCore{}, errors.New("repository error")) + reports, err := reportService.ReadAllReport(mockUserID) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "gagal mendapatkan data") + assert.Empty(t, reports) +} + +func TestSelectByIdSuccess(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReports := entity.ReportCore{ + ID: "report1", UserId: mockUserID, Description: "Report 1", + } + + repoData.On("SelectById", mockUserID).Return(mockReports, nil) + reports, err := reportService.SelectById(mockUserID) + + assert.NoError(t, err) + assert.Equal(t, mockReports, reports) +} + +func TestSelectByIdEmptyUserID(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + reports, err := reportService.SelectById("") + + assert.Error(t, err) + assert.Contains(t, err.Error(), "id tidak cocok") + assert.Empty(t, reports) +} + +func TestSelectByIdRepositoryError(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + + repoData.On("SelectById", mockUserID).Return(entity.ReportCore{}, errors.New("repository error")) + reports, err := reportService.SelectById(mockUserID) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "repository error") + assert.Empty(t, reports) +} + +func TestCreateReportSuccess(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReportInput := entity.ReportCore{ + ReportType: "pelanggaran sampah", + ScaleType: "skala besar", + InsidentDate: "2023-12-25", + InsidentTime: "12:45", + Location: "jl nias", + AddressPoint: "didepan rumah", + TrashType: "sampah kering", + Description: "didepan rumah pak rt ada yang buang sampah sembarangan", + Status: "perlu ditinjau", + + } + + mockImages := []*multipart.FileHeader{ + { + Filename: "image1.jpg", + Size: 1024, + + }, + + } + + expectedCreatedReport := entity.ReportCore{ + ID: "report123", + UserId: mockUserID, + ReportType: mockReportInput.ReportType, + ScaleType: mockReportInput.ScaleType, + InsidentDate: mockReportInput.InsidentDate, + InsidentTime: mockReportInput.InsidentTime, + Location: mockReportInput.Location, + AddressPoint: mockReportInput.AddressPoint, + TrashType: mockReportInput.TrashType, + Description: mockReportInput.Description, + Status: mockReportInput.Status, + + } + + repoData.On("Insert", mock.AnythingOfType("entity.ReportCore"), mock.AnythingOfType("[]*multipart.FileHeader")).Return(expectedCreatedReport, nil) + + createdReport, err := reportService.Create(mockReportInput, mockUserID, mockImages) + + assert.NoError(t, err) + assert.Equal(t, expectedCreatedReport, createdReport) +} + +func TestCreateReportInvalidImageSize(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReportInput := entity.ReportCore{ + ReportType: "pelanggaran sampah", + ScaleType: "skala besar", + InsidentDate: "2023-12-25", + InsidentTime: "12:45", + Location: "jl nias", + AddressPoint: "didepan rumah", + TrashType: "sampah kering", + Description: "didepan rumah pak rt ada yang buang sampah sembarangan", + Status: "perlu ditinjau", + + } + + mockImages := []*multipart.FileHeader{ + { + Filename: "large_image.jpg", + Size: 30 * 1024 * 1024, + + }, + + } + + expectedError := "ukuran file tidak boleh lebih dari 20 MB" + _, err := reportService.Create(mockReportInput, mockUserID, mockImages) + + assert.Error(t, err) + assert.Equal(t, expectedError, err.Error()) +} + +func TestCreateReportInvalidReportType(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReportInput := entity.ReportCore{ + ReportType: "invalid_report_type", + + } + + mockImages := []*multipart.FileHeader{ + + } + + createdReport, err := reportService.Create(mockReportInput, mockUserID, mockImages) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "error : report type tidak sesuai") + assert.Equal(t, entity.ReportCore{}, createdReport) +} + +func TestCreateReportInvalidScaleType(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReportInput := entity.ReportCore{ + ReportType: "pelanggaran sampah", + ScaleType: "invalid_scale_type", + + } + + mockImages := []*multipart.FileHeader{ + + } + + createdReport, err := reportService.Create(mockReportInput, mockUserID, mockImages) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "error : scale type tidak sesuai") + assert.Equal(t, entity.ReportCore{}, createdReport) +} + +func TestCreateReportInvalidIncidentDate(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReportInput := entity.ReportCore{ + ReportType: "pelanggaran sampah", + ScaleType: "skala besar", + InsidentDate: "invalid_date", + + } + + mockImages := []*multipart.FileHeader{ + + } + + createdReport, err := reportService.Create(mockReportInput, mockUserID, mockImages) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "error, tanggal harus dalam format 'yyyy-mm-dd'") + assert.Equal(t, entity.ReportCore{}, createdReport) +} + +func TestCreateReportInvalidIncidentTime(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReportInput := entity.ReportCore{ + ReportType: "pelanggaran sampah", + ScaleType: "skala besar", + InsidentDate: "2023-01-01", + InsidentTime: "invalid_time", + + } + + mockImages := []*multipart.FileHeader{ + + } + + createdReport, err := reportService.Create(mockReportInput, mockUserID, mockImages) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "error, jam harus dalam format 'hh:mm'") + assert.Equal(t, entity.ReportCore{}, createdReport) +} + +func TestCreateReportImageSizeExceedsLimit(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReportInput := entity.ReportCore{ + ReportType: "pelanggaran sampah", + ScaleType: "skala besar", + InsidentDate: "2023-01-01", + InsidentTime: "12:00", + + } + + mockLargeImage := &multipart.FileHeader{ + Size: 21 * 1024 * 1024, + + } + + mockImages := []*multipart.FileHeader{mockLargeImage} + + createdReport, err := reportService.Create(mockReportInput, mockUserID, mockImages) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "ukuran file tidak boleh lebih dari 20 MB") + assert.Equal(t, entity.ReportCore{}, createdReport) +} + +func TestCreateReportRepositoryError(t *testing.T) { + repoData := new(mocks.ReportRepositoryInterface) + reportService := NewReportService(repoData) + + mockUserID := "user123" + mockReportInput := entity.ReportCore{ + ReportType: "pelanggaran sampah", + ScaleType: "skala besar", + InsidentDate: "2023-12-25", + InsidentTime: "12:45", + Location: "jl nias", + AddressPoint: "didepan rumah", + TrashType: "sampah kering", + Description: "didepan rumah pak rt ada yang buang sampah sembarangan", + Status: "perlu ditinjau", + + } + + mockImages := []*multipart.FileHeader{ + { + Filename: "image1.jpg", + Size: 1024, + + }, + + } + + expectedError := errors.New("repository error message") + repoData.On("Insert", mock.AnythingOfType("entity.ReportCore"), mock.AnythingOfType("[]*multipart.FileHeader")).Return(entity.ReportCore{}, expectedError) + + createdReport, err := reportService.Create(mockReportInput, mockUserID, mockImages) + + assert.Error(t, err) + assert.Equal(t, expectedError, err) + assert.Equal(t, entity.ReportCore{}, createdReport) +} \ No newline at end of file diff --git a/go.mod b/go.mod index 838b0fdf..347ecbe6 100644 --- a/go.mod +++ b/go.mod @@ -65,6 +65,7 @@ require ( github.com/joho/godotenv v1.5.1 github.com/labstack/echo-jwt/v4 v4.2.0 github.com/sashabaranov/go-openai v1.17.9 + github.com/stretchr/testify v1.8.4 golang.org/x/sys v0.15.0 // indirect gorm.io/driver/mysql v1.5.2 ) diff --git a/utils/constanta/constanta.go b/utils/constanta/constanta.go index cf0f7e61..9e515dad 100644 --- a/utils/constanta/constanta.go +++ b/utils/constanta/constanta.go @@ -21,6 +21,7 @@ const ( //VERIFICATION_URL = "http://localhost:8080/verify-token?token=" VERIFICATION_URL = "https://api.recything.my.id/verify-token?token=" EMAIL_NOT_REGISTER = "email belum terdaftar" + IMAGE_ADMIN = "https://ui-avatars.com/api/?background=56cc33&color=fff&name=" ) // Constanta For Error @@ -112,7 +113,7 @@ const ( GOLD = "gold" ) -const( +const ( ASIABANGKOK = "Asia/Bangkok" )