Added starred to FullRecipeView and related query/service implementation.
This commit is contained in:
parent
941acf7f2b
commit
73fdced131
@ -16,6 +16,7 @@ import org.springframework.test.annotation.DirtiesContext;
|
|||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.hasSize;
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
@ -74,7 +75,9 @@ public class RecipeControllerTests {
|
|||||||
public void getRecipePageViewByIdPublicRecipeNoPrincipal() throws Exception {
|
public void getRecipePageViewByIdPublicRecipeNoPrincipal() throws Exception {
|
||||||
final User owner = this.createTestUser("owner");
|
final User owner = this.createTestUser("owner");
|
||||||
final Recipe recipe = this.createTestRecipe(owner, true);
|
final Recipe recipe = this.createTestRecipe(owner, true);
|
||||||
this.mockMvc.perform(get("/recipes/{username}/{slug}", recipe.getOwner().getUsername(), recipe.getSlug()))
|
this.mockMvc.perform(
|
||||||
|
get("/recipes/{username}/{slug}", recipe.getOwner().getUsername(), recipe.getSlug())
|
||||||
|
)
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.id").value(1))
|
.andExpect(jsonPath("$.id").value(1))
|
||||||
.andExpect(jsonPath("$.created").exists()) // TODO: better matching of exact LocalDateTime
|
.andExpect(jsonPath("$.created").exists()) // TODO: better matching of exact LocalDateTime
|
||||||
@ -88,10 +91,39 @@ public class RecipeControllerTests {
|
|||||||
.andExpect(jsonPath("$.owner.id").value(owner.getId()))
|
.andExpect(jsonPath("$.owner.id").value(owner.getId()))
|
||||||
.andExpect(jsonPath("$.owner.username").value(owner.getUsername()))
|
.andExpect(jsonPath("$.owner.username").value(owner.getUsername()))
|
||||||
.andExpect(jsonPath("$.starCount").value(0))
|
.andExpect(jsonPath("$.starCount").value(0))
|
||||||
|
.andExpect(jsonPath("$.isStarred").value(nullValue()))
|
||||||
.andExpect(jsonPath("$.viewerCount").value(0))
|
.andExpect(jsonPath("$.viewerCount").value(0))
|
||||||
.andExpect(jsonPath("$.isPublic").value(true));
|
.andExpect(jsonPath("$.isPublic").value(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DirtiesContext
|
||||||
|
public void getFullRecipeViewPrincipalIsStarer() throws Exception {
|
||||||
|
final User owner = this.createTestUser("owner");
|
||||||
|
final Recipe recipe = this.createTestRecipe(owner, false);
|
||||||
|
this.recipeStarService.create(recipe.getId(), owner.getUsername());
|
||||||
|
final String accessToken = this.getAccessToken(owner);
|
||||||
|
this.mockMvc.perform(
|
||||||
|
get("/recipes/{username}/{slug}", recipe.getOwner().getUsername(), recipe.getSlug())
|
||||||
|
.header("Authorization", "Bearer " + accessToken)
|
||||||
|
)
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.isStarred").value(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFullRecipeViewPrincipalIsNotStarer() throws Exception {
|
||||||
|
final User owner = this.createTestUser("owner");
|
||||||
|
final Recipe recipe = this.createTestRecipe(owner, false);
|
||||||
|
final String accessToken = this.getAccessToken(owner);
|
||||||
|
this.mockMvc.perform(
|
||||||
|
get("/recipes/{username}/{slug}", recipe.getOwner().getUsername(), recipe.getSlug())
|
||||||
|
.header("Authorization", "Bearer " + accessToken)
|
||||||
|
)
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.isStarred").value(false));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DirtiesContext
|
@DirtiesContext
|
||||||
public void getRecipeInfoViewsNoPrincipal() throws Exception {
|
public void getRecipeInfoViewsNoPrincipal() throws Exception {
|
||||||
|
@ -4,6 +4,7 @@ import app.mealsmadeeasy.api.recipe.spec.RecipeCreateSpec;
|
|||||||
import app.mealsmadeeasy.api.recipe.spec.RecipeUpdateSpec;
|
import app.mealsmadeeasy.api.recipe.spec.RecipeUpdateSpec;
|
||||||
import app.mealsmadeeasy.api.recipe.star.RecipeStar;
|
import app.mealsmadeeasy.api.recipe.star.RecipeStar;
|
||||||
import app.mealsmadeeasy.api.recipe.star.RecipeStarService;
|
import app.mealsmadeeasy.api.recipe.star.RecipeStarService;
|
||||||
|
import app.mealsmadeeasy.api.recipe.view.FullRecipeView;
|
||||||
import app.mealsmadeeasy.api.recipe.view.RecipeInfoView;
|
import app.mealsmadeeasy.api.recipe.view.RecipeInfoView;
|
||||||
import app.mealsmadeeasy.api.user.User;
|
import app.mealsmadeeasy.api.user.User;
|
||||||
import app.mealsmadeeasy.api.user.UserEntity;
|
import app.mealsmadeeasy.api.user.UserEntity;
|
||||||
@ -23,6 +24,7 @@ import static app.mealsmadeeasy.api.recipe.ContainsRecipeInfoViewsForRecipesMatc
|
|||||||
import static app.mealsmadeeasy.api.recipe.ContainsRecipesMatcher.containsRecipes;
|
import static app.mealsmadeeasy.api.recipe.ContainsRecipesMatcher.containsRecipes;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
@ -350,4 +352,44 @@ public class RecipeServiceTests {
|
|||||||
assertThrows(AccessDeniedException.class, () -> this.recipeService.deleteRecipe(toDelete.getId(), notOwner));
|
assertThrows(AccessDeniedException.class, () -> this.recipeService.deleteRecipe(toDelete.getId(), notOwner));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DirtiesContext
|
||||||
|
public void getFullViewByUsernameAndSlugIncludesStarredFalseWhenViewerNotNullButNotStarer() throws RecipeException {
|
||||||
|
final User owner = this.createTestUser("recipeOwner");
|
||||||
|
final Recipe recipe = this.createTestRecipe(owner);
|
||||||
|
final FullRecipeView view = this.recipeService.getFullViewByUsernameAndSlug(
|
||||||
|
owner.getUsername(),
|
||||||
|
recipe.getSlug(),
|
||||||
|
owner
|
||||||
|
);
|
||||||
|
assertThat(view.getIsStarred(), is(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DirtiesContext
|
||||||
|
public void getFullViewByUsernameAndSlugIncludesStarredTrueWhenViewerNotNullAndStarer() throws RecipeException {
|
||||||
|
final User owner = this.createTestUser("recipeOwner");
|
||||||
|
final Recipe recipe = this.createTestRecipe(owner);
|
||||||
|
this.recipeStarService.create(recipe.getId(), owner.getUsername());
|
||||||
|
final FullRecipeView view = this.recipeService.getFullViewByUsernameAndSlug(
|
||||||
|
owner.getUsername(),
|
||||||
|
recipe.getSlug(),
|
||||||
|
owner
|
||||||
|
);
|
||||||
|
assertThat(view.getIsStarred(), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DirtiesContext
|
||||||
|
public void getFullViewByUsernameIncludesStarredNullWhenViewerNull() throws RecipeException {
|
||||||
|
final User owner = this.createTestUser("recipeOwner");
|
||||||
|
final Recipe recipe = this.createTestRecipe(owner, true);
|
||||||
|
final FullRecipeView view = this.recipeService.getFullViewByUsernameAndSlug(
|
||||||
|
owner.getUsername(),
|
||||||
|
recipe.getSlug(),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
assertThat(view.getIsStarred(), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package app.mealsmadeeasy.api.recipe.star;
|
||||||
|
|
||||||
|
import app.mealsmadeeasy.api.recipe.RecipeEntity;
|
||||||
|
import app.mealsmadeeasy.api.recipe.RecipeRepository;
|
||||||
|
import app.mealsmadeeasy.api.user.UserEntity;
|
||||||
|
import app.mealsmadeeasy.api.user.UserRepository;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
public class RecipeStarRepositoryTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RecipeStarRepository recipeStarRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RecipeRepository recipeRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
private UserEntity getOwnerUser() {
|
||||||
|
final UserEntity draft = UserEntity.getDefaultDraft();
|
||||||
|
draft.setUsername("test-user");
|
||||||
|
draft.setEmail("test-user@test.com");
|
||||||
|
draft.setPassword("test");
|
||||||
|
return this.userRepository.save(draft);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecipeEntity getTestRecipe(UserEntity owner) {
|
||||||
|
final RecipeEntity recipeDraft = new RecipeEntity();
|
||||||
|
recipeDraft.setCreated(LocalDateTime.now());
|
||||||
|
recipeDraft.setSlug("test-recipe");
|
||||||
|
recipeDraft.setOwner(owner);
|
||||||
|
recipeDraft.setTitle("Test Recipe");
|
||||||
|
recipeDraft.setRawText("Hello, World!");
|
||||||
|
return this.recipeRepository.save(recipeDraft);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DirtiesContext
|
||||||
|
public void returnsTrueIfStarer() {
|
||||||
|
final UserEntity owner = this.getOwnerUser();
|
||||||
|
final RecipeEntity recipe = this.getTestRecipe(owner);
|
||||||
|
|
||||||
|
final RecipeStarEntity starDraft = new RecipeStarEntity();
|
||||||
|
final RecipeStarId starId = new RecipeStarId();
|
||||||
|
starId.setRecipeId(recipe.getId());
|
||||||
|
starId.setOwnerUsername(owner.getUsername());
|
||||||
|
starDraft.setId(starId);
|
||||||
|
this.recipeStarRepository.save(starDraft);
|
||||||
|
|
||||||
|
assertThat(this.recipeStarRepository.isStarer(recipe.getId(), owner.getUsername()), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DirtiesContext
|
||||||
|
public void returnsFalseIfNotStarer() {
|
||||||
|
final UserEntity owner = this.getOwnerUser();
|
||||||
|
final RecipeEntity recipe = this.getTestRecipe(owner);
|
||||||
|
assertThat(this.recipeStarRepository.isStarer(recipe.getId(), owner.getUsername()), is(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,6 +6,7 @@ import app.mealsmadeeasy.api.image.S3ImageEntity;
|
|||||||
import app.mealsmadeeasy.api.image.view.ImageView;
|
import app.mealsmadeeasy.api.image.view.ImageView;
|
||||||
import app.mealsmadeeasy.api.recipe.spec.RecipeCreateSpec;
|
import app.mealsmadeeasy.api.recipe.spec.RecipeCreateSpec;
|
||||||
import app.mealsmadeeasy.api.recipe.spec.RecipeUpdateSpec;
|
import app.mealsmadeeasy.api.recipe.spec.RecipeUpdateSpec;
|
||||||
|
import app.mealsmadeeasy.api.recipe.star.RecipeStarRepository;
|
||||||
import app.mealsmadeeasy.api.recipe.view.FullRecipeView;
|
import app.mealsmadeeasy.api.recipe.view.FullRecipeView;
|
||||||
import app.mealsmadeeasy.api.recipe.view.RecipeInfoView;
|
import app.mealsmadeeasy.api.recipe.view.RecipeInfoView;
|
||||||
import app.mealsmadeeasy.api.user.User;
|
import app.mealsmadeeasy.api.user.User;
|
||||||
@ -40,11 +41,16 @@ public class RecipeServiceImpl implements RecipeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final RecipeRepository recipeRepository;
|
private final RecipeRepository recipeRepository;
|
||||||
|
private final RecipeStarRepository recipeStarRepository;
|
||||||
private final ImageService imageService;
|
private final ImageService imageService;
|
||||||
|
|
||||||
|
public RecipeServiceImpl(
|
||||||
public RecipeServiceImpl(RecipeRepository recipeRepository, ImageService imageService) {
|
RecipeRepository recipeRepository,
|
||||||
|
RecipeStarRepository recipeStarRepository,
|
||||||
|
ImageService imageService
|
||||||
|
) {
|
||||||
this.recipeRepository = recipeRepository;
|
this.recipeRepository = recipeRepository;
|
||||||
|
this.recipeStarRepository = recipeStarRepository;
|
||||||
this.imageService = imageService;
|
this.imageService = imageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +130,9 @@ public class RecipeServiceImpl implements RecipeService {
|
|||||||
recipe,
|
recipe,
|
||||||
this.getRenderedMarkdown(recipe),
|
this.getRenderedMarkdown(recipe),
|
||||||
this.getStarCount(recipe),
|
this.getStarCount(recipe),
|
||||||
|
viewer != null
|
||||||
|
? this.recipeStarRepository.isStarer(recipe.getId(), viewer.getUsername())
|
||||||
|
: null,
|
||||||
this.getViewerCount(recipe.getId()),
|
this.getViewerCount(recipe.getId()),
|
||||||
this.getImageView(recipe.getMainImage(), viewer)
|
this.getImageView(recipe.getMainImage(), viewer)
|
||||||
);
|
);
|
||||||
|
@ -12,6 +12,9 @@ public interface RecipeStarRepository extends JpaRepository<RecipeStarEntity, Lo
|
|||||||
@Query("SELECT star FROM RecipeStar star WHERE star.id.recipeId = ?1 AND star.id.ownerUsername = ?2")
|
@Query("SELECT star FROM RecipeStar star WHERE star.id.recipeId = ?1 AND star.id.ownerUsername = ?2")
|
||||||
Optional<RecipeStarEntity> findByRecipeIdAndOwnerUsername(Long recipeId, String username);
|
Optional<RecipeStarEntity> findByRecipeIdAndOwnerUsername(Long recipeId, String username);
|
||||||
|
|
||||||
|
@Query("SELECT count(rs) > 0 FROM RecipeStar rs WHERE rs.id.recipeId = ?1 AND rs.id.ownerUsername = ?2")
|
||||||
|
boolean isStarer(long recipeId, String username);
|
||||||
|
|
||||||
@Modifying
|
@Modifying
|
||||||
@Transactional
|
@Transactional
|
||||||
@Query("DELETE FROM RecipeStar star WHERE star.id.recipeId = ?1 AND star.id.ownerUsername = ?2")
|
@Query("DELETE FROM RecipeStar star WHERE star.id.recipeId = ?1 AND star.id.ownerUsername = ?2")
|
||||||
|
@ -13,6 +13,7 @@ public class FullRecipeView {
|
|||||||
Recipe recipe,
|
Recipe recipe,
|
||||||
String renderedText,
|
String renderedText,
|
||||||
int starCount,
|
int starCount,
|
||||||
|
Boolean starred,
|
||||||
int viewerCount,
|
int viewerCount,
|
||||||
ImageView mainImage
|
ImageView mainImage
|
||||||
) {
|
) {
|
||||||
@ -28,6 +29,7 @@ public class FullRecipeView {
|
|||||||
view.setText(renderedText);
|
view.setText(renderedText);
|
||||||
view.setOwner(UserInfoView.from(recipe.getOwner()));
|
view.setOwner(UserInfoView.from(recipe.getOwner()));
|
||||||
view.setStarCount(starCount);
|
view.setStarCount(starCount);
|
||||||
|
view.setIsStarred(starred);
|
||||||
view.setViewerCount(viewerCount);
|
view.setViewerCount(viewerCount);
|
||||||
view.setMainImage(mainImage);
|
view.setMainImage(mainImage);
|
||||||
view.setIsPublic(recipe.isPublic());
|
view.setIsPublic(recipe.isPublic());
|
||||||
@ -45,6 +47,7 @@ public class FullRecipeView {
|
|||||||
private String text;
|
private String text;
|
||||||
private UserInfoView owner;
|
private UserInfoView owner;
|
||||||
private int starCount;
|
private int starCount;
|
||||||
|
private @Nullable Boolean starred;
|
||||||
private int viewerCount;
|
private int viewerCount;
|
||||||
private ImageView mainImage;
|
private ImageView mainImage;
|
||||||
private boolean isPublic;
|
private boolean isPublic;
|
||||||
@ -137,6 +140,14 @@ public class FullRecipeView {
|
|||||||
this.starCount = starCount;
|
this.starCount = starCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @Nullable Boolean getIsStarred() {
|
||||||
|
return this.starred;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsStarred(@Nullable Boolean starred) {
|
||||||
|
this.starred = starred;
|
||||||
|
}
|
||||||
|
|
||||||
public int getViewerCount() {
|
public int getViewerCount() {
|
||||||
return this.viewerCount;
|
return this.viewerCount;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user