From b173d86f2300e717cbd4131b299d86b5d156520f Mon Sep 17 00:00:00 2001 From: JesseBrault0709 <62299747+JesseBrault0709@users.noreply.github.com> Date: Mon, 8 Jul 2024 09:46:29 +0200 Subject: [PATCH] Wrote tests for adding and deleting recipe stars. --- .../api/recipe/RecipeServiceTests.java | 43 +++++++++++++++++-- .../api/recipe/RecipeRepository.java | 7 +++ .../api/recipe/RecipeService.java | 2 + .../api/recipe/RecipeServiceImpl.java | 11 ++++- .../api/recipe/star/RecipeStar.java | 1 + .../api/recipe/star/RecipeStarEntity.java | 8 +++- .../api/matchers/ContainsStarsMatcher.java | 43 +++++++++++++++++++ .../api/matchers/IsRecipeMatcher.java | 27 ++++++++++++ .../mealsmadeeasy/api/matchers/Matchers.java | 9 ++++ 9 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 src/testFixtures/java/app/mealsmadeeasy/api/matchers/ContainsStarsMatcher.java create mode 100644 src/testFixtures/java/app/mealsmadeeasy/api/matchers/IsRecipeMatcher.java diff --git a/src/integrationTest/java/app/mealsmadeeasy/api/recipe/RecipeServiceTests.java b/src/integrationTest/java/app/mealsmadeeasy/api/recipe/RecipeServiceTests.java index 9384c67..8b9dd1f 100644 --- a/src/integrationTest/java/app/mealsmadeeasy/api/recipe/RecipeServiceTests.java +++ b/src/integrationTest/java/app/mealsmadeeasy/api/recipe/RecipeServiceTests.java @@ -1,6 +1,7 @@ package app.mealsmadeeasy.api.recipe; import app.mealsmadeeasy.api.matchers.Matchers; +import app.mealsmadeeasy.api.recipe.star.RecipeStar; import app.mealsmadeeasy.api.user.User; import app.mealsmadeeasy.api.user.UserEntity; import app.mealsmadeeasy.api.user.UserRepository; @@ -11,8 +12,9 @@ import org.springframework.test.annotation.DirtiesContext; import java.util.List; -import static app.mealsmadeeasy.api.matchers.Matchers.isUser; +import static app.mealsmadeeasy.api.matchers.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.is; @SpringBootTest @@ -32,7 +34,7 @@ public class RecipeServiceTests { return this.userRepository.save(draft); } - private Recipe createTestRecipe(User owner) throws RecipeException { + private Recipe createTestRecipe(User owner) { return this.recipeService.create(owner, "My Recipe" , "Hello!"); } @@ -48,7 +50,7 @@ public class RecipeServiceTests { @Test @DirtiesContext - public void createViaUser() throws RecipeException { + public void createViaUser() { final User user = this.createTestUser("recipeOwner"); final Recipe recipe = this.recipeService.create(user, "My Recipe", "Hello!"); assertThat(recipe.getOwner().getUsername(), is(user.getUsername())); @@ -66,6 +68,16 @@ public class RecipeServiceTests { assertThat(byId.getRawText(), is("Hello!")); } + @Test + @DirtiesContext + public void getByIdWithStars() throws RecipeException { + final User owner = this.createTestUser("recipeOwner"); + final Recipe recipe = this.createTestRecipe(owner); + final RecipeStar star = this.recipeService.addStar(recipe, owner); + final Recipe byIdWithStars = this.recipeService.getByIdWithStars(recipe.getId()); + assertThat(byIdWithStars.getStars(), containsStars(star)); + } + @Test @DirtiesContext public void getByMinimumStars() throws RecipeException { @@ -181,4 +193,29 @@ public class RecipeServiceTests { assertThat(recipe.getOwner(), isUser(secondOwner)); } + @Test + @DirtiesContext + public void addStar() throws RecipeException { + final User owner = this.createTestUser("recipeOwner"); + final User starer = this.createTestUser("starer"); + Recipe recipe = this.createTestRecipe(owner); + recipe = this.recipeService.addViewer(recipe, starer); + final RecipeStar star = this.recipeService.addStar(recipe, starer); + assertThat(star.getRecipe(), isRecipe(recipe)); + assertThat(star.getOwner(), isUser(starer)); + } + + @Test + @DirtiesContext + public void deleteStar() throws RecipeException { + final User owner = this.createTestUser("recipeOwner"); + final User starer = this.createTestUser("starer"); + Recipe recipe = this.createTestRecipe(owner); + recipe = this.recipeService.addViewer(recipe, starer); + final RecipeStar star = this.recipeService.addStar(recipe, starer); + this.recipeService.deleteStar(star); + recipe = this.recipeService.getByIdWithStars(recipe.getId()); + assertThat(recipe.getStars(), is(empty())); + } + } diff --git a/src/main/java/app/mealsmadeeasy/api/recipe/RecipeRepository.java b/src/main/java/app/mealsmadeeasy/api/recipe/RecipeRepository.java index 1c10ead..c5dcd3b 100644 --- a/src/main/java/app/mealsmadeeasy/api/recipe/RecipeRepository.java +++ b/src/main/java/app/mealsmadeeasy/api/recipe/RecipeRepository.java @@ -6,8 +6,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import java.util.List; +import java.util.Optional; public interface RecipeRepository extends JpaRepository { + List findAllByIsPublicIsTrue(); List findAllByViewersContaining(UserEntity viewer); List findAllByOwner(UserEntity owner); @@ -18,4 +20,9 @@ public interface RecipeRepository extends JpaRepository { @Query("SELECT r FROM Recipe r WHERE r.id = ?1") @EntityGraph(attributePaths = { "viewers" }) RecipeEntity getByIdWithViewers(long id); + + @Query("SELECT r FROM Recipe r WHERE r.id = ?1") + @EntityGraph(attributePaths = { "stars" }) + Optional findByIdWithStars(long id); + } diff --git a/src/main/java/app/mealsmadeeasy/api/recipe/RecipeService.java b/src/main/java/app/mealsmadeeasy/api/recipe/RecipeService.java index 280c9f1..bdb9d76 100644 --- a/src/main/java/app/mealsmadeeasy/api/recipe/RecipeService.java +++ b/src/main/java/app/mealsmadeeasy/api/recipe/RecipeService.java @@ -12,6 +12,8 @@ public interface RecipeService { Recipe create(User user, String title, String rawText); Recipe getById(long id) throws RecipeException; + Recipe getByIdWithStars(long id) throws RecipeException; + List getByMinimumStars(long minimumStars); List getPublicRecipes(); List getRecipesViewableBy(User user); diff --git a/src/main/java/app/mealsmadeeasy/api/recipe/RecipeServiceImpl.java b/src/main/java/app/mealsmadeeasy/api/recipe/RecipeServiceImpl.java index ef5bec7..c395519 100644 --- a/src/main/java/app/mealsmadeeasy/api/recipe/RecipeServiceImpl.java +++ b/src/main/java/app/mealsmadeeasy/api/recipe/RecipeServiceImpl.java @@ -17,6 +17,7 @@ import org.springframework.stereotype.Service; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; @Service @@ -78,6 +79,14 @@ public final class RecipeServiceImpl implements RecipeService { )); } + @Override + public Recipe getByIdWithStars(long id) throws RecipeException { + return this.recipeRepository.findByIdWithStars(id).orElseThrow(() -> new RecipeException( + RecipeException.Type.INVALID_ID, + "No such recipe for id " + id + )); + } + @Override public List getByMinimumStars(long minimumStars) { return List.copyOf(this.recipeRepository.findAllByStarsGreaterThanEqual(minimumStars)); @@ -138,7 +147,7 @@ public final class RecipeServiceImpl implements RecipeService { @Override public RecipeStar addStar(Recipe recipe, User giver) throws RecipeException { boolean viewable = false; - if (recipe.isPublic()) { + if (recipe.isPublic() || Objects.equals(recipe.getOwner().getId(), giver.getId())) { viewable = true; } else { final RecipeEntity withViewers = this.recipeRepository.getByIdWithViewers(recipe.getId()); diff --git a/src/main/java/app/mealsmadeeasy/api/recipe/star/RecipeStar.java b/src/main/java/app/mealsmadeeasy/api/recipe/star/RecipeStar.java index 0d57b6e..e850568 100644 --- a/src/main/java/app/mealsmadeeasy/api/recipe/star/RecipeStar.java +++ b/src/main/java/app/mealsmadeeasy/api/recipe/star/RecipeStar.java @@ -6,6 +6,7 @@ import app.mealsmadeeasy.api.user.User; import java.time.LocalDateTime; public interface RecipeStar { + Long getId(); User getOwner(); LocalDateTime getDate(); Recipe getRecipe(); diff --git a/src/main/java/app/mealsmadeeasy/api/recipe/star/RecipeStarEntity.java b/src/main/java/app/mealsmadeeasy/api/recipe/star/RecipeStarEntity.java index 6b1ee39..f3d2a4f 100644 --- a/src/main/java/app/mealsmadeeasy/api/recipe/star/RecipeStarEntity.java +++ b/src/main/java/app/mealsmadeeasy/api/recipe/star/RecipeStarEntity.java @@ -25,7 +25,8 @@ public final class RecipeStarEntity implements RecipeStar { @JoinColumn(name = "recipe_id", nullable = false, updatable = false) private RecipeEntity recipe; - public long getId() { + @Override + public Long getId() { return this.id; } @@ -60,4 +61,9 @@ public final class RecipeStarEntity implements RecipeStar { this.recipe = recipe; } + @Override + public String toString() { + return "RecipeStarEntity(" + this.id + ")"; + } + } diff --git a/src/testFixtures/java/app/mealsmadeeasy/api/matchers/ContainsStarsMatcher.java b/src/testFixtures/java/app/mealsmadeeasy/api/matchers/ContainsStarsMatcher.java new file mode 100644 index 0000000..068343e --- /dev/null +++ b/src/testFixtures/java/app/mealsmadeeasy/api/matchers/ContainsStarsMatcher.java @@ -0,0 +1,43 @@ +package app.mealsmadeeasy.api.matchers; + +import app.mealsmadeeasy.api.recipe.star.RecipeStar; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; + +import java.util.Objects; +import java.util.Set; + +public class ContainsStarsMatcher extends BaseMatcher> { + + private final RecipeStar[] allExpected; + + public ContainsStarsMatcher(RecipeStar[] allExpected) { + this.allExpected = allExpected; + } + + @Override + public boolean matches(Object actual) { + if (actual instanceof Set set) { + checkExpected: + for (final RecipeStar expected : allExpected) { + for (final Object item : set) { + if (item instanceof RecipeStar o && Objects.equals(o.getId(), expected.getId())) { + continue checkExpected; + } + } + // Did not find the expected in the set + return false; + } + // Found all expected in set + return true; + } + // actual is not a Set + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("Expected ").appendValue(Set.of(this.allExpected)); + } + +} diff --git a/src/testFixtures/java/app/mealsmadeeasy/api/matchers/IsRecipeMatcher.java b/src/testFixtures/java/app/mealsmadeeasy/api/matchers/IsRecipeMatcher.java new file mode 100644 index 0000000..6360590 --- /dev/null +++ b/src/testFixtures/java/app/mealsmadeeasy/api/matchers/IsRecipeMatcher.java @@ -0,0 +1,27 @@ +package app.mealsmadeeasy.api.matchers; + +import app.mealsmadeeasy.api.recipe.Recipe; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; + +import java.util.Objects; + +public class IsRecipeMatcher extends BaseMatcher { + + private final Recipe expected; + + public IsRecipeMatcher(Recipe expected) { + this.expected = expected; + } + + @Override + public boolean matches(Object actual) { + return actual instanceof Recipe o && Objects.equals(this.expected.getId(), o.getId()); + } + + @Override + public void describeTo(Description description) { + description.appendText("Expected ").appendValue(this.expected); + } + +} diff --git a/src/testFixtures/java/app/mealsmadeeasy/api/matchers/Matchers.java b/src/testFixtures/java/app/mealsmadeeasy/api/matchers/Matchers.java index 477ded5..eb33422 100644 --- a/src/testFixtures/java/app/mealsmadeeasy/api/matchers/Matchers.java +++ b/src/testFixtures/java/app/mealsmadeeasy/api/matchers/Matchers.java @@ -1,6 +1,7 @@ package app.mealsmadeeasy.api.matchers; import app.mealsmadeeasy.api.recipe.Recipe; +import app.mealsmadeeasy.api.recipe.star.RecipeStar; import app.mealsmadeeasy.api.user.User; public final class Matchers { @@ -9,6 +10,14 @@ public final class Matchers { return new ContainsRecipesMatcher(expected); } + public static ContainsStarsMatcher containsStars(RecipeStar... expected) { + return new ContainsStarsMatcher(expected); + } + + public static IsRecipeMatcher isRecipe(Recipe expected) { + return new IsRecipeMatcher(expected); + } + public static IsUserMatcher isUser(User expected) { return new IsUserMatcher(expected); }