diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 050ab36..c793b8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,9 +66,11 @@ jobs: java-version: "21" cache: "gradle" + - name: Make gradlew executable run: chmod +x ./gradlew + - name: Cache Gradle dependencies uses: actions/cache@v4 with: diff --git a/src/main/java/snackscription/review/repository/ReviewRepository.java b/src/main/java/snackscription/review/repository/ReviewRepository.java index f0f025e..19b3c56 100644 --- a/src/main/java/snackscription/review/repository/ReviewRepository.java +++ b/src/main/java/snackscription/review/repository/ReviewRepository.java @@ -6,6 +6,7 @@ import io.micrometer.common.lang.Nullable; import snackscription.review.model.Review; import snackscription.review.model.ReviewId; +import snackscription.review.model.ReviewId; import snackscription.review.model.ReviewState; public interface ReviewRepository extends JpaRepository { diff --git a/src/main/java/snackscription/review/service/ReviewServiceImpl.java b/src/main/java/snackscription/review/service/ReviewServiceImpl.java index 4b0006c..34dd81c 100644 --- a/src/main/java/snackscription/review/service/ReviewServiceImpl.java +++ b/src/main/java/snackscription/review/service/ReviewServiceImpl.java @@ -3,9 +3,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; import io.micrometer.core.instrument.composite.CompositeMeterRegistry; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @@ -20,9 +22,11 @@ @Component public class ReviewServiceImpl implements ReviewService { private final ReviewRepository reviewRepository; + private final SentimentAnalysisService sentimentAnalysisService; - public ReviewServiceImpl (ReviewRepository reviewRepository) { + public ReviewServiceImpl (ReviewRepository reviewRepository, SentimentAnalysisService sentimentAnalysisService) { this.reviewRepository = reviewRepository; + this.sentimentAnalysisService = sentimentAnalysisService; } public boolean reviewExist(String subsbox, String user) { @@ -104,4 +108,10 @@ public void deleteReview(String subsbox, String user) throws Exception { reviewRepository.delete(review); } + + @Async + public CompletableFuture analyzeSentimentAsync(String reviewText) { + String sentiment = sentimentAnalysisService.analyze(reviewText); + return CompletableFuture.completedFuture(sentiment); + } } diff --git a/src/main/java/snackscription/review/service/SentimentAnalysisService.java b/src/main/java/snackscription/review/service/SentimentAnalysisService.java new file mode 100644 index 0000000..d09357b --- /dev/null +++ b/src/main/java/snackscription/review/service/SentimentAnalysisService.java @@ -0,0 +1,14 @@ +package snackscription.review.service; + +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +@Service +@Component +public class SentimentAnalysisService { + public String analyze(String reviewText) { + // do analysis + return "positive"; + } + +} diff --git a/src/test/java/snackscription/review/controller/ReviewControllerTest.java b/src/test/java/snackscription/review/controller/ReviewControllerTest.java index edf1599..edcda83 100644 --- a/src/test/java/snackscription/review/controller/ReviewControllerTest.java +++ b/src/test/java/snackscription/review/controller/ReviewControllerTest.java @@ -19,9 +19,12 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; + import static org.junit.jupiter.api.Assertions.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.mockito.Mockito.when; @@ -71,27 +74,27 @@ public void testCreateSubsboxReview() throws Exception{ ResultActions result = mockMvc.perform(post("/subscription-boxes/{subsbox}/users/self", review.getSubsbox()) .contentType(MediaType.APPLICATION_JSON) - .content("{\"rating\": 5, \"content\": \"I love it\", \"author\": \"user_123\"}")) + .content("{\"rating\": 5, \"content\": \"I love it\", \"author\": \"user_123\"}")) .andExpect(status().isCreated()) .andExpect(jsonPath("$.rating", is(5))) .andExpect(jsonPath("$.content", is("I love it"))) .andExpect(jsonPath("$.author", is("user_123"))) - .andExpect(jsonPath("$.subsbox", is("subsbox_123"))); + .andExpect(jsonPath("$.subsbox", is("subsbox_123"))); - verify(reviewService).createReview(review.getRating(), review.getContent(), review.getSubsbox(), review.getAuthor()); + verify(reviewService).createReview(review.getRating(), review.getContent(), review.getSubsbox(), review.getAuthor()); } @Test public void testReadAllPublicSubsboxReviews() throws Exception { List approvedReviews = new ArrayList<>(); String subsbox = "subsbox_124"; - for (Review review : reviews) { + for (Review review : reviews) { if (review.getSubsbox().equals(subsbox) && review.getState().equals(ReviewState.APPROVED)) { approvedReviews.add(review); } } - when(reviewService.getSubsboxReview(subsbox, "APPROVED")).thenReturn(approvedReviews); + when(reviewService.getSubsboxReview(subsbox, "APPROVED")).thenReturn(approvedReviews); String result = mockMvc.perform(get("/subscription-boxes/{subsbox}", subsbox)) .andExpect(status().isOk()) @@ -100,17 +103,17 @@ public void testReadAllPublicSubsboxReviews() throws Exception { .getResponse() .getContentAsString(); - List foundReviews = new ArrayList(); - for (int i=0; i foundReviews = new ArrayList(); + for (int i=0; i cmp = Comparator.comparing(Review::getAuthor); approvedReviews.sort(cmp); @@ -120,10 +123,10 @@ public void testReadAllPublicSubsboxReviews() throws Exception { assertEquals(approvedReviews.get(i).getRating(), foundReviews.get(i).getRating()); assertEquals(approvedReviews.get(i).getContent(), foundReviews.get(i).getContent()); assertEquals(approvedReviews.get(i).getAuthor(), foundReviews.get(i).getAuthor()); - assertEquals(approvedReviews.get(i).getSubsbox(), foundReviews.get(i).getSubsbox()); + assertEquals(approvedReviews.get(i).getSubsbox(), foundReviews.get(i).getSubsbox()); } - verify(reviewService).getSubsboxReview(subsbox, "APPROVED"); + verify(reviewService).getSubsboxReview(subsbox, "APPROVED"); } @Test @@ -132,7 +135,7 @@ public void testReadSelfSubsboxReview() throws Exception { String subsbox = review.getSubsbox(); String author = review.getAuthor(); - when(reviewService.getReview(subsbox, author)).thenReturn(review); + when(reviewService.getReview(subsbox, author)).thenReturn(review); ResultActions result = mockMvc.perform(get("/subscription-boxes/{subscriptionBoxId}/users/self", subsbox, author) .contentType(MediaType.APPLICATION_JSON) @@ -174,6 +177,7 @@ public void testDeleteSelfSubsboxReview() throws Exception { String subsbox = review.getSubsbox(); String author = review.getAuthor(); + doNothing().when(reviewService).deleteReview(subsbox, author); doNothing().when(reviewService).deleteReview(subsbox, author); ResultActions result = mockMvc.perform(delete("/subscription-boxes/{subsbox}/users/self", subsbox) diff --git a/src/test/java/snackscription/review/service/ReviewServiceTest.java b/src/test/java/snackscription/review/service/ReviewServiceTest.java index 3cacbff..edd0b7a 100644 --- a/src/test/java/snackscription/review/service/ReviewServiceTest.java +++ b/src/test/java/snackscription/review/service/ReviewServiceTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; @@ -24,7 +25,9 @@ @ExtendWith(MockitoExtension.class) public class ReviewServiceTest { - + + @Mock + SentimentAnalysisService sentimentAnalysisService; @Mock ReviewRepository reviewRepo; @@ -34,7 +37,8 @@ public class ReviewServiceTest { @BeforeEach public void setUp() { - reviewService = new ReviewServiceImpl(reviewRepo); + sentimentAnalysisService = new SentimentAnalysisService(); + reviewService = new ReviewServiceImpl(reviewRepo, sentimentAnalysisService); Review review1 = new Review(5, "I love it", "subsbox_123", "user_123"); Review review2 = new Review(1, "I hate it", "subsbox_123", "user_124"); @@ -56,10 +60,10 @@ public void setUp() { @Test - public void testGetSubsboxReview() throws Exception { + public void testGetSubsboxReview() throws Exception { String subscriptionBoxId = this.reviews.getFirst().getSubsbox(); List curReviews = new ArrayList<>(); - for (Review review : this.reviews) { + for (Review review : this.reviews) { if (review.getSubsbox().equals(subscriptionBoxId)) { curReviews.add(review); } @@ -67,14 +71,14 @@ public void testGetSubsboxReview() throws Exception { when(reviewRepo.findByIdSubsbox(subscriptionBoxId)).thenReturn(curReviews); - List foundReviews = reviewService.getSubsboxReview(subscriptionBoxId, null); + List foundReviews = reviewService.getSubsboxReview(subscriptionBoxId, null); assertEquals(curReviews, foundReviews); verify(reviewRepo).findByIdSubsbox(subscriptionBoxId); } - @Test + @Test public void testGetSubsboxReviewNotFound() throws Exception { String subscriptionBoxId = "nonexistent_subsbox_id"; @@ -83,13 +87,13 @@ public void testGetSubsboxReviewNotFound() throws Exception { List foundReviews = reviewService.getSubsboxReview(subscriptionBoxId, null); assertNotNull(foundReviews); - assertEquals(0, foundReviews.size()); + assertEquals(0, foundReviews.size()); verify(reviewRepo).findByIdSubsbox(subscriptionBoxId); } @Test - public void testGetSubsboxReviewApproved() throws Exception { + public void testGetSubsboxReviewApproved() throws Exception { String subscriptionBoxId = this.reviews.getFirst().getSubsbox(); List cuReviews = new ArrayList<>(); @@ -128,7 +132,7 @@ public void testCreateReview() throws Exception { review.getRating(), review.getContent(), review.getSubsbox(), - review.getAuthor()); + review.getAuthor()); assertEqualReview(review, savedReview); @@ -163,18 +167,21 @@ public void testEditReview() throws Exception { int newRating = 1; String newContent = "Changed content"; - Review newReview = new Review(newRating, newContent, author, subsbox); + Review newReview = new Review(newRating, newContent, author, subsbox); newReview.setId(review.getId()); + when(reviewRepo.findByIdSubsboxAndIdAuthor(subsbox, author)).thenReturn(review); when(reviewRepo.findByIdSubsboxAndIdAuthor(subsbox, author)).thenReturn(review); when(reviewRepo.save(any(Review.class))).thenReturn(newReview); - Review editedReview = reviewService.editReview(newRating, newContent, subsbox, author); + Review editedReview = reviewService.editReview(newRating, newContent, subsbox, author); assertEquals(newRating, editedReview.getRating()); assertEquals(newContent, editedReview.getContent()); assertEquals(subsbox, editedReview.getSubsbox()); assertEquals(author, editedReview.getAuthor()); + assertEquals(subsbox, editedReview.getSubsbox()); + assertEquals(author, editedReview.getAuthor()); assertEquals(review.getId(), editedReview.getId()); } @@ -199,7 +206,7 @@ public void testEditReviewNotFound() throws Exception { @Test public void testDeleteReview() throws Exception { String subsbox = this.reviews.getFirst().getSubsbox(); - String author = this.reviews.getFirst().getAuthor(); + String author = this.reviews.getFirst().getAuthor(); Review review = reviews.getFirst();