diff --git a/src/main/java/com/funeat/product/application/ProductService.java b/src/main/java/com/funeat/product/application/ProductService.java index 84859fc5..7efa1781 100644 --- a/src/main/java/com/funeat/product/application/ProductService.java +++ b/src/main/java/com/funeat/product/application/ProductService.java @@ -1,9 +1,14 @@ package com.funeat.product.application; +import static com.funeat.member.exception.MemberErrorCode.MEMBER_NOT_FOUND; import static com.funeat.product.exception.CategoryErrorCode.CATEGORY_NOT_FOUND; import static com.funeat.product.exception.ProductErrorCode.PRODUCT_NOT_FOUND; import com.funeat.common.dto.PageDto; +import com.funeat.member.domain.Member; +import com.funeat.member.exception.MemberException.MemberNotFoundException; +import com.funeat.member.persistence.MemberRepository; +import com.funeat.member.persistence.RecipeFavoriteRepository; import com.funeat.product.domain.Category; import com.funeat.product.domain.Product; import com.funeat.product.dto.ProductInCategoryDto; @@ -51,6 +56,7 @@ public class ProductService { private static final int RANKING_SIZE = 3; private static final int DEFAULT_PAGE_SIZE = 10; private static final int DEFAULT_CURSOR_PAGINATION_SIZE = 11; + private static final long GUEST_ID = -1L; private final CategoryRepository categoryRepository; private final ProductRepository productRepository; @@ -59,12 +65,15 @@ public class ProductService { private final ProductRecipeRepository productRecipeRepository; private final RecipeImageRepository recipeImageRepository; private final RecipeRepository recipeRepository; + private final MemberRepository memberRepository; + private final RecipeFavoriteRepository recipeFavoriteRepository; public ProductService(final CategoryRepository categoryRepository, final ProductRepository productRepository, final ReviewTagRepository reviewTagRepository, final ReviewRepository reviewRepository, final ProductRecipeRepository productRecipeRepository, final RecipeImageRepository recipeImageRepository, - final RecipeRepository recipeRepository) { + final RecipeRepository recipeRepository, final MemberRepository memberRepository, + final RecipeFavoriteRepository recipeFavoriteRepository) { this.categoryRepository = categoryRepository; this.productRepository = productRepository; this.reviewTagRepository = reviewTagRepository; @@ -72,6 +81,8 @@ public ProductService(final CategoryRepository categoryRepository, final Product this.productRecipeRepository = productRecipeRepository; this.recipeImageRepository = recipeImageRepository; this.recipeRepository = recipeRepository; + this.memberRepository = memberRepository; + this.recipeFavoriteRepository = recipeFavoriteRepository; } public ProductsInCategoryResponse getAllProductsInCategory(final Long categoryId, final Long lastProductId, @@ -174,7 +185,7 @@ private List findAllWithReviewCountByNameContaining(final return productRepository.findAllWithReviewCountByNameContaining(query, lastProductId, size); } - public SortingRecipesResponse getProductRecipes(final Long productId, final Pageable pageable) { + public SortingRecipesResponse getProductRecipes(final Long memberId, final Long productId, final Pageable pageable) { final Product product = productRepository.findById(productId) .orElseThrow(() -> new ProductNotFoundException(PRODUCT_NOT_FOUND, productId)); @@ -182,12 +193,22 @@ public SortingRecipesResponse getProductRecipes(final Long productId, final Page final PageDto pageDto = PageDto.toDto(recipes); final List recipeDtos = recipes.stream() - .map(recipe -> { - final List images = recipeImageRepository.findByRecipe(recipe); - final List products = productRecipeRepository.findProductByRecipe(recipe); - return RecipeDto.toDto(recipe, images, products); - }) - .collect(Collectors.toList()); + .map(recipe -> createRecipeDto(memberId, recipe)) + .toList(); return SortingRecipesResponse.toResponse(pageDto, recipeDtos); } + + private RecipeDto createRecipeDto(final Long memberId, final Recipe recipe) { + final List images = recipeImageRepository.findByRecipe(recipe); + final List products = productRecipeRepository.findProductByRecipe(recipe); + + if (memberId == GUEST_ID) { + return RecipeDto.toDto(recipe, images, products, false); + } + + final Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND, memberId)); + final Boolean favorite = recipeFavoriteRepository.existsByMemberAndRecipeAndFavoriteTrue(member, recipe); + return RecipeDto.toDto(recipe, images, products, favorite); + } } diff --git a/src/main/java/com/funeat/product/presentation/ProductApiController.java b/src/main/java/com/funeat/product/presentation/ProductApiController.java index 2d2ee6ca..cfdd20dc 100644 --- a/src/main/java/com/funeat/product/presentation/ProductApiController.java +++ b/src/main/java/com/funeat/product/presentation/ProductApiController.java @@ -1,5 +1,7 @@ package com.funeat.product.presentation; +import com.funeat.auth.dto.LoginInfo; +import com.funeat.auth.util.AuthenticationPrincipal; import com.funeat.product.application.ProductService; import com.funeat.product.dto.ProductResponse; import com.funeat.product.dto.ProductSortCondition; @@ -8,7 +10,6 @@ import com.funeat.product.dto.SearchProductResultsResponse; import com.funeat.product.dto.SearchProductsResponse; import com.funeat.recipe.dto.SortingRecipesResponse; -import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; @@ -64,9 +65,10 @@ public ResponseEntity getSearchResults(@RequestPar } @GetMapping("/products/{productId}/recipes") - public ResponseEntity getProductRecipes(@PathVariable final Long productId, + public ResponseEntity getProductRecipes(@AuthenticationPrincipal final LoginInfo loginInfo, + @PathVariable final Long productId, @PageableDefault final Pageable pageable) { - final SortingRecipesResponse response = productService.getProductRecipes(productId, pageable); + final SortingRecipesResponse response = productService.getProductRecipes(loginInfo.getId(), productId, pageable); return ResponseEntity.ok(response); } } diff --git a/src/main/java/com/funeat/product/presentation/ProductController.java b/src/main/java/com/funeat/product/presentation/ProductController.java index a5b2e791..87065f24 100644 --- a/src/main/java/com/funeat/product/presentation/ProductController.java +++ b/src/main/java/com/funeat/product/presentation/ProductController.java @@ -1,5 +1,7 @@ package com.funeat.product.presentation; +import com.funeat.auth.dto.LoginInfo; +import com.funeat.auth.util.AuthenticationPrincipal; import com.funeat.product.dto.ProductResponse; import com.funeat.product.dto.ProductsInCategoryResponse; import com.funeat.product.dto.RankingProductsResponse; @@ -71,6 +73,7 @@ ResponseEntity getSearchResults(@RequestParam fina description = "해당 상품 꿀조합 목록 조회 성공." ) @GetMapping - ResponseEntity getProductRecipes(@PathVariable final Long productId, + ResponseEntity getProductRecipes(@AuthenticationPrincipal final LoginInfo loginInfo, + @PathVariable final Long productId, @PageableDefault final Pageable pageable); } diff --git a/src/main/java/com/funeat/recipe/application/RecipeService.java b/src/main/java/com/funeat/recipe/application/RecipeService.java index 100c708c..59fda3e3 100644 --- a/src/main/java/com/funeat/recipe/application/RecipeService.java +++ b/src/main/java/com/funeat/recipe/application/RecipeService.java @@ -156,21 +156,31 @@ public MemberRecipesResponse findRecipeByMember(final Long memberId, final Pagea return MemberRecipesResponse.toResponse(page, dtos); } - public SortingRecipesResponse getSortingRecipes(final Pageable pageable) { + public SortingRecipesResponse getSortingRecipes(final Long memberId, final Pageable pageable) { final Page pages = recipeRepository.findAll(pageable); final PageDto page = PageDto.toDto(pages); final List recipes = pages.getContent().stream() - .map(recipe -> { - final List images = recipeImageRepository.findByRecipe(recipe); - final List products = productRecipeRepository.findProductByRecipe(recipe); - return RecipeDto.toDto(recipe, images, products); - }) - .collect(Collectors.toList()); + .map(recipe -> createRecipeDto(memberId, recipe)) + .toList(); return SortingRecipesResponse.toResponse(page, recipes); } + private RecipeDto createRecipeDto(final Long memberId, final Recipe recipe) { + final List images = recipeImageRepository.findByRecipe(recipe); + final List products = productRecipeRepository.findProductByRecipe(recipe); + + if (memberId == GUEST_ID) { + return RecipeDto.toDto(recipe, images, products, false); + } + + final Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND, memberId)); + final Boolean favorite = recipeFavoriteRepository.existsByMemberAndRecipeAndFavoriteTrue(member, recipe); + return RecipeDto.toDto(recipe, images, products, favorite); + } + @Transactional public void likeRecipe(final Long memberId, final Long recipeId, final RecipeFavoriteRequest request) { final Member member = memberRepository.findById(memberId) diff --git a/src/main/java/com/funeat/recipe/dto/ProductRecipeDto.java b/src/main/java/com/funeat/recipe/dto/ProductRecipeDto.java index 60ab88ea..f1d09e7c 100644 --- a/src/main/java/com/funeat/recipe/dto/ProductRecipeDto.java +++ b/src/main/java/com/funeat/recipe/dto/ProductRecipeDto.java @@ -7,15 +7,21 @@ public class ProductRecipeDto { private final Long id; private final String name; private final Long price; + private final String image; + private final Double averageRating; - private ProductRecipeDto(final Long id, final String name, final Long price) { + private ProductRecipeDto(final Long id, final String name, final Long price, final String image, + final Double averageRating) { this.id = id; this.name = name; this.price = price; + this.image = image; + this.averageRating = averageRating; } public static ProductRecipeDto toDto(final Product product) { - return new ProductRecipeDto(product.getId(), product.getName(), product.getPrice()); + return new ProductRecipeDto(product.getId(), product.getName(), product.getPrice(), product.getImage(), + product.getAverageRating()); } public Long getId() { @@ -29,4 +35,12 @@ public String getName() { public Long getPrice() { return price; } + + public String getImage() { + return image; + } + + public Double getAverageRating() { + return averageRating; + } } diff --git a/src/main/java/com/funeat/recipe/dto/RecipeDto.java b/src/main/java/com/funeat/recipe/dto/RecipeDto.java index 51cd78fc..2c140ace 100644 --- a/src/main/java/com/funeat/recipe/dto/RecipeDto.java +++ b/src/main/java/com/funeat/recipe/dto/RecipeDto.java @@ -5,42 +5,44 @@ import com.funeat.recipe.domain.RecipeImage; import java.time.LocalDateTime; import java.util.List; -import java.util.stream.Collectors; public class RecipeDto { private final Long id; private final String image; private final String title; + private final String content; private final RecipeAuthorDto author; private final List products; - private final Long favoriteCount; + private final Boolean favorite; private final LocalDateTime createdAt; - public RecipeDto(final Long id, final String image, final String title, final RecipeAuthorDto author, - final List products, - final Long favoriteCount, final LocalDateTime createdAt) { + public RecipeDto(final Long id, final String image, final String title, final String content, + final RecipeAuthorDto author, final List products, final Boolean favorite, + final LocalDateTime createdAt) { this.id = id; this.image = image; this.title = title; + this.content = content; this.author = author; this.products = products; - this.favoriteCount = favoriteCount; + this.favorite = favorite; this.createdAt = createdAt; } public static RecipeDto toDto(final Recipe recipe, final List recipeImages, - final List products) { + final List products, final Boolean favorite) { final RecipeAuthorDto authorDto = RecipeAuthorDto.toDto(recipe.getMember()); final List productDtos = products.stream() .map(ProductRecipeDto::toDto) - .collect(Collectors.toList()); + .toList(); + if (recipeImages.isEmpty()) { - return new RecipeDto(recipe.getId(), null, recipe.getTitle(), authorDto, productDtos, - recipe.getFavoriteCount(), recipe.getCreatedAt()); + return new RecipeDto(recipe.getId(), null, recipe.getTitle(), recipe.getContent(), authorDto, + productDtos, favorite, recipe.getCreatedAt()); } - return new RecipeDto(recipe.getId(), recipeImages.get(0).getImage(), recipe.getTitle(), authorDto, productDtos, - recipe.getFavoriteCount(), recipe.getCreatedAt()); + return new RecipeDto(recipe.getId(), recipeImages.get(0).getImage(), recipe.getTitle(), recipe.getContent(), + authorDto, productDtos, favorite, recipe.getCreatedAt()); } public Long getId() { @@ -55,6 +57,10 @@ public String getTitle() { return title; } + public String getContent() { + return content; + } + public RecipeAuthorDto getAuthor() { return author; } @@ -63,8 +69,8 @@ public List getProducts() { return products; } - public Long getFavoriteCount() { - return favoriteCount; + public Boolean getFavorite() { + return favorite; } public LocalDateTime getCreatedAt() { diff --git a/src/main/java/com/funeat/recipe/presentation/RecipeApiController.java b/src/main/java/com/funeat/recipe/presentation/RecipeApiController.java index 4a0fe7ef..07a0540a 100644 --- a/src/main/java/com/funeat/recipe/presentation/RecipeApiController.java +++ b/src/main/java/com/funeat/recipe/presentation/RecipeApiController.java @@ -60,8 +60,9 @@ public ResponseEntity getRecipeDetail(@AuthenticationPrinc } @GetMapping(value = "/api/recipes") - public ResponseEntity getSortingRecipes(@PageableDefault final Pageable pageable) { - final SortingRecipesResponse response = recipeService.getSortingRecipes(pageable); + public ResponseEntity getSortingRecipes(@AuthenticationPrincipal final LoginInfo loginInfo, + @PageableDefault final Pageable pageable) { + final SortingRecipesResponse response = recipeService.getSortingRecipes(loginInfo.getId(), pageable); return ResponseEntity.ok(response); } diff --git a/src/main/java/com/funeat/recipe/presentation/RecipeController.java b/src/main/java/com/funeat/recipe/presentation/RecipeController.java index 0e04232b..2ec5ca3e 100644 --- a/src/main/java/com/funeat/recipe/presentation/RecipeController.java +++ b/src/main/java/com/funeat/recipe/presentation/RecipeController.java @@ -56,7 +56,8 @@ ResponseEntity getRecipeDetail(@AuthenticationPrincipal fi description = "꿀조합 목록 조회 성공." ) @GetMapping - ResponseEntity getSortingRecipes(@PageableDefault final Pageable pageable); + ResponseEntity getSortingRecipes(@AuthenticationPrincipal final LoginInfo loginInfo, + @PageableDefault final Pageable pageable); @Operation(summary = "꿀조합 좋아요", description = "꿀조합에 좋아요 또는 취소를 한다.") @ApiResponse( diff --git a/src/test/java/com/funeat/acceptance/recipe/RecipeAcceptanceTest.java b/src/test/java/com/funeat/acceptance/recipe/RecipeAcceptanceTest.java index ef0ffff1..77713967 100644 --- a/src/test/java/com/funeat/acceptance/recipe/RecipeAcceptanceTest.java +++ b/src/test/java/com/funeat/acceptance/recipe/RecipeAcceptanceTest.java @@ -472,7 +472,7 @@ class getSortingRecipes_성공_테스트 { // then STATUS_CODE를_검증한다(응답, 정상_처리); 페이지를_검증한다(응답, 예상_응답_페이지); - 레시피_목록_조회_결과를_검증한다(응답, List.of(레시피2, 레시피1, 레시피3)); + 레시피_목록_조회_결과를_검증한다(응답, List.of(레시피2, 레시피1, 레시피3), List.of(false, false, false)); } @Test @@ -494,7 +494,7 @@ class getSortingRecipes_성공_테스트 { // then STATUS_CODE를_검증한다(응답, 정상_처리); 페이지를_검증한다(응답, 예상_응답_페이지); - 레시피_목록_조회_결과를_검증한다(응답, List.of(레시피3, 레시피2, 레시피1)); + 레시피_목록_조회_결과를_검증한다(응답, List.of(레시피3, 레시피2, 레시피1), List.of(false, false, false)); } @Test @@ -516,7 +516,31 @@ class getSortingRecipes_성공_테스트 { // then STATUS_CODE를_검증한다(response, 정상_처리); 페이지를_검증한다(response, 예상_응답_페이지); - 레시피_목록_조회_결과를_검증한다(response, List.of(레시피1, 레시피2, 레시피3)); + 레시피_목록_조회_결과를_검증한다(response, List.of(레시피1, 레시피2, 레시피3), List.of(false, false, false)); + } + + @Test + void 로그인_후_꿀조합을_좋아요가_많은_순으로_정렬할_수_있다() { + // given + final var 카테고리 = 카테고리_간편식사_생성(); + 단일_카테고리_저장(카테고리); + final var 상품 = 단일_상품_저장(상품_삼각김밥_가격1000원_평점5점_생성(카테고리)); + + 레시피_작성_요청(로그인_쿠키_획득(멤버1), 여러개_사진_명세_요청(이미지1), 레시피추가요청_생성(상품)); + 레시피_작성_요청(로그인_쿠키_획득(멤버1), 여러개_사진_명세_요청(이미지2), 레시피추가요청_생성(상품)); + 레시피_작성_요청(로그인_쿠키_획득(멤버1), 여러개_사진_명세_요청(이미지3), 레시피추가요청_생성(상품)); + 여러명이_레시피_좋아요_요청(List.of(멤버1), 레시피1, 좋아요O); + 여러명이_레시피_좋아요_요청(List.of(멤버1, 멤버2), 레시피2, 좋아요O); + + final var 예상_응답_페이지 = 응답_페이지_생성(총_데이터_개수(3L), 총_페이지(1L), 첫페이지O, 마지막페이지O, FIRST_PAGE, PAGE_SIZE); + + // when + final var 응답 = 레시피_목록_요청(로그인_쿠키_획득(멤버2), 좋아요수_내림차순, FIRST_PAGE); + + // then + STATUS_CODE를_검증한다(응답, 정상_처리); + 페이지를_검증한다(응답, 예상_응답_페이지); + 레시피_목록_조회_결과를_검증한다(응답, List.of(레시피2, 레시피1, 레시피3), List.of(true, false, false)); } } @@ -755,11 +779,14 @@ class getRecipeComment_실패_테스트 { } } - private void 레시피_목록_조회_결과를_검증한다(final ExtractableResponse response, final List recipeIds) { + private void 레시피_목록_조회_결과를_검증한다(final ExtractableResponse response, final List recipeIds, + final List favorites) { final var actual = response.jsonPath().getList("recipes", RecipeDto.class); assertThat(actual).extracting(RecipeDto::getId) .containsExactlyElementsOf(recipeIds); + assertThat(actual).extracting(RecipeDto::getFavorite) + .containsExactlyElementsOf(favorites); } private void 레시피_상세_정보_조회_결과를_검증한다(final ExtractableResponse response) { diff --git a/src/test/java/com/funeat/acceptance/recipe/RecipeSteps.java b/src/test/java/com/funeat/acceptance/recipe/RecipeSteps.java index cac33e0e..b8bc49e0 100644 --- a/src/test/java/com/funeat/acceptance/recipe/RecipeSteps.java +++ b/src/test/java/com/funeat/acceptance/recipe/RecipeSteps.java @@ -54,6 +54,17 @@ public class RecipeSteps { .extract(); } + public static ExtractableResponse 레시피_목록_요청(final String loginCookie, final String sort, final Long page) { + return given() + .queryParam("sort", sort) + .queryParam("page", page) + .cookie("SESSION", loginCookie) + .when() + .get("/api/recipes") + .then() + .extract(); + } + public static ExtractableResponse 레시피_좋아요_요청(final String loginCookie, final Long recipeId, final RecipeFavoriteRequest request) { return given() diff --git a/src/test/java/com/funeat/recipe/application/RecipeServiceTest.java b/src/test/java/com/funeat/recipe/application/RecipeServiceTest.java index 205388ca..3c7acc0a 100644 --- a/src/test/java/com/funeat/recipe/application/RecipeServiceTest.java +++ b/src/test/java/com/funeat/recipe/application/RecipeServiceTest.java @@ -275,156 +275,277 @@ class findRecipeByMember_실패_테스트 { @Nested class getSortingRecipes_성공_테스트 { - @Test - void 꿀조합을_좋아요가_많은_순으로_정렬할_수_있다() { - // given - final var member1 = 멤버_멤버1_생성(); - final var member2 = 멤버_멤버2_생성(); - final var member3 = 멤버_멤버3_생성(); - 복수_멤버_저장(member1, member2, member3); - - final var category = 카테고리_간편식사_생성(); - 단일_카테고리_저장(category); - - final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); - final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); - final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); - 복수_상품_저장(product1, product2, product3); - - final var recipe1_1 = 레시피_생성(member1, 1L); - final var recipe1_2 = 레시피_생성(member1, 3L); - final var recipe1_3 = 레시피_생성(member1, 2L); - 복수_꿀조합_저장(recipe1_1, recipe1_2, recipe1_3); - - final var product_recipe_1_1_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_1); - final var product_recipe_1_1_2 = 레시피_안에_들어가는_상품_생성(product2, recipe1_1); - final var product_recipe_1_1_3 = 레시피_안에_들어가는_상품_생성(product3, recipe1_1); - final var product_recipe_1_2_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_2); - final var product_recipe_1_2_2 = 레시피_안에_들어가는_상품_생성(product3, recipe1_2); - 복수_꿀조합_상품_저장(product_recipe_1_1_1, product_recipe_1_1_2, product_recipe_1_1_3, product_recipe_1_2_1, - product_recipe_1_2_2); - - final var recipeImage1_1_1 = 레시피이미지_생성(recipe1_1); - final var recipeImage1_2_1 = 레시피이미지_생성(recipe1_2); - final var recipeImage1_2_2 = 레시피이미지_생성(recipe1_2); - 복수_꿀조합_이미지_저장(recipeImage1_1_1, recipeImage1_2_1); - - final var page = 페이지요청_생성(0, 10, 좋아요수_내림차순); - - // when - final var actual = recipeService.getSortingRecipes(page).getRecipes(); - final var expected = List.of( - RecipeDto.toDto(recipe1_2, List.of(recipeImage1_2_1, recipeImage1_2_2), - List.of(product1, product3)), - RecipeDto.toDto(recipe1_3, List.of(), List.of()), - RecipeDto.toDto(recipe1_1, List.of(recipeImage1_1_1), List.of(product1, product2, product3))); - - // then - assertThat(actual) - .usingRecursiveComparison() - .isEqualTo(expected); - } + @Nested + class 정렬_기준에_따른_테스트 { - @Test - void 꿀조합을_최신순으로_정렬할_수_있다() throws InterruptedException { - // given - final var member1 = 멤버_멤버1_생성(); - final var member2 = 멤버_멤버2_생성(); - final var member3 = 멤버_멤버3_생성(); - 복수_멤버_저장(member1, member2, member3); + @Test + void 꿀조합을_좋아요가_많은_순으로_정렬할_수_있다() { + // given + final var loginId = -1L; + final var member1 = 멤버_멤버1_생성(); + final var member2 = 멤버_멤버2_생성(); + final var member3 = 멤버_멤버3_생성(); + 복수_멤버_저장(member1, member2, member3); + + final var category = 카테고리_간편식사_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); + final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); + final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); + 복수_상품_저장(product1, product2, product3); + + final var recipe1_1 = 레시피_생성(member1, 1L); + final var recipe1_2 = 레시피_생성(member1, 3L); + final var recipe1_3 = 레시피_생성(member1, 2L); + 복수_꿀조합_저장(recipe1_1, recipe1_2, recipe1_3); + + final var product_recipe_1_1_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_1); + final var product_recipe_1_1_2 = 레시피_안에_들어가는_상품_생성(product2, recipe1_1); + final var product_recipe_1_1_3 = 레시피_안에_들어가는_상품_생성(product3, recipe1_1); + final var product_recipe_1_2_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_2); + final var product_recipe_1_2_2 = 레시피_안에_들어가는_상품_생성(product3, recipe1_2); + 복수_꿀조합_상품_저장(product_recipe_1_1_1, product_recipe_1_1_2, product_recipe_1_1_3, product_recipe_1_2_1, + product_recipe_1_2_2); + + final var recipeImage1_1_1 = 레시피이미지_생성(recipe1_1); + final var recipeImage1_2_1 = 레시피이미지_생성(recipe1_2); + final var recipeImage1_2_2 = 레시피이미지_생성(recipe1_2); + 복수_꿀조합_이미지_저장(recipeImage1_1_1, recipeImage1_2_1); + + final var page = 페이지요청_생성(0, 10, 좋아요수_내림차순); - final var category = 카테고리_간편식사_생성(); - 단일_카테고리_저장(category); + // when + final var actual = recipeService.getSortingRecipes(loginId, page).getRecipes(); + final var expected = List.of( + RecipeDto.toDto(recipe1_2, List.of(recipeImage1_2_1, recipeImage1_2_2), + List.of(product1, product3), false), + RecipeDto.toDto(recipe1_3, List.of(), List.of(), false), + RecipeDto.toDto(recipe1_1, List.of(recipeImage1_1_1), List.of(product1, product2, product3), + false)); - final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); - final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); - final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); - 복수_상품_저장(product1, product2, product3); + // then + assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } - final var recipe1_1 = 레시피_생성(member1, 1L); - Thread.sleep(100); - final var recipe1_2 = 레시피_생성(member1, 3L); - Thread.sleep(100); - final var recipe1_3 = 레시피_생성(member1, 2L); - 복수_꿀조합_저장(recipe1_1, recipe1_2, recipe1_3); + @Test + void 꿀조합을_최신순으로_정렬할_수_있다() throws InterruptedException { + // given + final var loginId = -1L; + final var member1 = 멤버_멤버1_생성(); + final var member2 = 멤버_멤버2_생성(); + final var member3 = 멤버_멤버3_생성(); + 복수_멤버_저장(member1, member2, member3); + + final var category = 카테고리_간편식사_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); + final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); + final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); + 복수_상품_저장(product1, product2, product3); + + final var recipe1_1 = 레시피_생성(member1, 1L); + Thread.sleep(100); + final var recipe1_2 = 레시피_생성(member1, 3L); + Thread.sleep(100); + final var recipe1_3 = 레시피_생성(member1, 2L); + 복수_꿀조합_저장(recipe1_1, recipe1_2, recipe1_3); + + final var product_recipe_1_1_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_1); + final var product_recipe_1_1_2 = 레시피_안에_들어가는_상품_생성(product2, recipe1_1); + final var product_recipe_1_1_3 = 레시피_안에_들어가는_상품_생성(product3, recipe1_1); + final var product_recipe_1_2_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_2); + final var product_recipe_1_2_2 = 레시피_안에_들어가는_상품_생성(product3, recipe1_2); + 복수_꿀조합_상품_저장(product_recipe_1_1_1, product_recipe_1_1_2, product_recipe_1_1_3, product_recipe_1_2_1, + product_recipe_1_2_2); + + final var recipeImage1_1_1 = 레시피이미지_생성(recipe1_1); + final var recipeImage1_2_1 = 레시피이미지_생성(recipe1_2); + final var recipeImage1_2_2 = 레시피이미지_생성(recipe1_2); + 복수_꿀조합_이미지_저장(recipeImage1_1_1, recipeImage1_2_1); + + final var page = 페이지요청_생성(0, 10, 최신순); - final var product_recipe_1_1_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_1); - final var product_recipe_1_1_2 = 레시피_안에_들어가는_상품_생성(product2, recipe1_1); - final var product_recipe_1_1_3 = 레시피_안에_들어가는_상품_생성(product3, recipe1_1); - final var product_recipe_1_2_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_2); - final var product_recipe_1_2_2 = 레시피_안에_들어가는_상품_생성(product3, recipe1_2); - 복수_꿀조합_상품_저장(product_recipe_1_1_1, product_recipe_1_1_2, product_recipe_1_1_3, product_recipe_1_2_1, - product_recipe_1_2_2); + // when + final var actual = recipeService.getSortingRecipes(loginId, page).getRecipes(); + final var expected = List.of( + RecipeDto.toDto(recipe1_3, List.of(), List.of(), false), + RecipeDto.toDto(recipe1_2, List.of(recipeImage1_2_1, recipeImage1_2_2), + List.of(product1, product3), false), + RecipeDto.toDto(recipe1_1, List.of(recipeImage1_1_1), List.of(product1, product2, product3), + false)); - final var recipeImage1_1_1 = 레시피이미지_생성(recipe1_1); - final var recipeImage1_2_1 = 레시피이미지_생성(recipe1_2); - final var recipeImage1_2_2 = 레시피이미지_생성(recipe1_2); - 복수_꿀조합_이미지_저장(recipeImage1_1_1, recipeImage1_2_1); + // then + assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } - final var page = 페이지요청_생성(0, 10, 최신순); + @Test + void 꿀조합을_오래된순으로_정렬할_수_있다() { + // given + final var loginId = -1L; + final var member1 = 멤버_멤버1_생성(); + final var member2 = 멤버_멤버2_생성(); + final var member3 = 멤버_멤버3_생성(); + 복수_멤버_저장(member1, member2, member3); + + final var category = 카테고리_간편식사_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); + final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); + final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); + 복수_상품_저장(product1, product2, product3); + + final var recipe1_1 = 레시피_생성(member1, 1L); + final var recipe1_2 = 레시피_생성(member1, 3L); + final var recipe1_3 = 레시피_생성(member1, 2L); + 복수_꿀조합_저장(recipe1_1, recipe1_2, recipe1_3); + + final var product_recipe_1_1_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_1); + final var product_recipe_1_1_2 = 레시피_안에_들어가는_상품_생성(product2, recipe1_1); + final var product_recipe_1_1_3 = 레시피_안에_들어가는_상품_생성(product3, recipe1_1); + final var product_recipe_1_2_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_2); + final var product_recipe_1_2_2 = 레시피_안에_들어가는_상품_생성(product3, recipe1_2); + 복수_꿀조합_상품_저장(product_recipe_1_1_1, product_recipe_1_1_2, product_recipe_1_1_3, product_recipe_1_2_1, + product_recipe_1_2_2); + + final var recipeImage1_1_1 = 레시피이미지_생성(recipe1_1); + final var recipeImage1_2_1 = 레시피이미지_생성(recipe1_2); + final var recipeImage1_2_2 = 레시피이미지_생성(recipe1_2); + 복수_꿀조합_이미지_저장(recipeImage1_1_1, recipeImage1_2_1); + + final var page = 페이지요청_생성(0, 10, 과거순); - // when - final var actual = recipeService.getSortingRecipes(page).getRecipes(); - final var expected = List.of( - RecipeDto.toDto(recipe1_3, List.of(), List.of()), - RecipeDto.toDto(recipe1_2, List.of(recipeImage1_2_1, recipeImage1_2_2), - List.of(product1, product3)), - RecipeDto.toDto(recipe1_1, List.of(recipeImage1_1_1), List.of(product1, product2, product3))); + // when + final var actual = recipeService.getSortingRecipes(loginId, page).getRecipes(); + final var expected = List.of( + RecipeDto.toDto(recipe1_1, List.of(recipeImage1_1_1), List.of(product1, product2, product3), + false), + RecipeDto.toDto(recipe1_2, List.of(recipeImage1_2_1, recipeImage1_2_2), + List.of(product1, product3), false), + RecipeDto.toDto(recipe1_3, List.of(), List.of(), false)); - // then - assertThat(actual) - .usingRecursiveComparison() - .isEqualTo(expected); + // then + assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } } - @Test - void 꿀조합을_오래된순으로_정렬할_수_있다() { - // given - final var member1 = 멤버_멤버1_생성(); - final var member2 = 멤버_멤버2_생성(); - final var member3 = 멤버_멤버3_생성(); - 복수_멤버_저장(member1, member2, member3); - - final var category = 카테고리_간편식사_생성(); - 단일_카테고리_저장(category); + @Nested + class 로그인_여부_응답_테스트 { - final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); - final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); - final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); - 복수_상품_저장(product1, product2, product3); + @Test + void 로그인_안한_경우_모든_꿀조합의_좋아요는_false로_반환한다() { + // given + final var loginId = -1L; + final var member1 = 멤버_멤버1_생성(); + final var member2 = 멤버_멤버2_생성(); + final var member3 = 멤버_멤버3_생성(); + 복수_멤버_저장(member1, member2, member3); + + final var category = 카테고리_간편식사_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); + final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); + final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); + 복수_상품_저장(product1, product2, product3); + + final var recipe1_1 = 레시피_생성(member1, 1L); + final var recipe1_2 = 레시피_생성(member1, 3L); + final var recipe1_3 = 레시피_생성(member1, 2L); + 복수_꿀조합_저장(recipe1_1, recipe1_2, recipe1_3); + + final var product_recipe_1_1_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_1); + final var product_recipe_1_1_2 = 레시피_안에_들어가는_상품_생성(product2, recipe1_1); + final var product_recipe_1_1_3 = 레시피_안에_들어가는_상품_생성(product3, recipe1_1); + final var product_recipe_1_2_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_2); + final var product_recipe_1_2_2 = 레시피_안에_들어가는_상품_생성(product3, recipe1_2); + 복수_꿀조합_상품_저장(product_recipe_1_1_1, product_recipe_1_1_2, product_recipe_1_1_3, product_recipe_1_2_1, + product_recipe_1_2_2); + + final var recipeImage1_1_1 = 레시피이미지_생성(recipe1_1); + final var recipeImage1_2_1 = 레시피이미지_생성(recipe1_2); + final var recipeImage1_2_2 = 레시피이미지_생성(recipe1_2); + 복수_꿀조합_이미지_저장(recipeImage1_1_1, recipeImage1_2_1); + + final var page = 페이지요청_생성(0, 10, 좋아요수_내림차순); - final var recipe1_1 = 레시피_생성(member1, 1L); - final var recipe1_2 = 레시피_생성(member1, 3L); - final var recipe1_3 = 레시피_생성(member1, 2L); - 복수_꿀조합_저장(recipe1_1, recipe1_2, recipe1_3); + // when + final var actual = recipeService.getSortingRecipes(loginId, page).getRecipes(); + final var expected = List.of( + RecipeDto.toDto(recipe1_2, List.of(recipeImage1_2_1, recipeImage1_2_2), + List.of(product1, product3), false), + RecipeDto.toDto(recipe1_3, List.of(), List.of(), false), + RecipeDto.toDto(recipe1_1, List.of(recipeImage1_1_1), List.of(product1, product2, product3), + false)); - final var product_recipe_1_1_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_1); - final var product_recipe_1_1_2 = 레시피_안에_들어가는_상품_생성(product2, recipe1_1); - final var product_recipe_1_1_3 = 레시피_안에_들어가는_상품_생성(product3, recipe1_1); - final var product_recipe_1_2_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_2); - final var product_recipe_1_2_2 = 레시피_안에_들어가는_상품_생성(product3, recipe1_2); - 복수_꿀조합_상품_저장(product_recipe_1_1_1, product_recipe_1_1_2, product_recipe_1_1_3, product_recipe_1_2_1, - product_recipe_1_2_2); + // then + assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } - final var recipeImage1_1_1 = 레시피이미지_생성(recipe1_1); - final var recipeImage1_2_1 = 레시피이미지_생성(recipe1_2); - final var recipeImage1_2_2 = 레시피이미지_생성(recipe1_2); - 복수_꿀조합_이미지_저장(recipeImage1_1_1, recipeImage1_2_1); + @Test + void 로그인_한_경우_각_꿀조합의_좋아요는_로그인_사용자의_좋아요_여부로_반환한다() { + // given + final var member1 = 멤버_멤버1_생성(); + final var member2 = 멤버_멤버2_생성(); + final var member3 = 멤버_멤버3_생성(); + 복수_멤버_저장(member1, member2, member3); + final var loginId = member1.getId(); + + final var category = 카테고리_간편식사_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); + final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); + final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); + 복수_상품_저장(product1, product2, product3); + + final var recipe1_1 = 레시피_생성(member1, 1L); + final var recipe1_2 = 레시피_생성(member1, 3L); + final var recipe1_3 = 레시피_생성(member1, 2L); + 복수_꿀조합_저장(recipe1_1, recipe1_2, recipe1_3); + + final var product_recipe_1_1_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_1); + final var product_recipe_1_1_2 = 레시피_안에_들어가는_상품_생성(product2, recipe1_1); + final var product_recipe_1_1_3 = 레시피_안에_들어가는_상품_생성(product3, recipe1_1); + final var product_recipe_1_2_1 = 레시피_안에_들어가는_상품_생성(product1, recipe1_2); + final var product_recipe_1_2_2 = 레시피_안에_들어가는_상품_생성(product3, recipe1_2); + 복수_꿀조합_상품_저장(product_recipe_1_1_1, product_recipe_1_1_2, product_recipe_1_1_3, product_recipe_1_2_1, + product_recipe_1_2_2); + + final var recipeImage1_1_1 = 레시피이미지_생성(recipe1_1); + final var recipeImage1_2_1 = 레시피이미지_생성(recipe1_2); + final var recipeImage1_2_2 = 레시피이미지_생성(recipe1_2); + 복수_꿀조합_이미지_저장(recipeImage1_1_1, recipeImage1_2_1); + + final var recipeFavorite = 레시피_좋아요_생성(member1, recipe1_1, true); + 단일_꿀조합_좋아요_저장(recipeFavorite); - final var page = 페이지요청_생성(0, 10, 과거순); + final var page = 페이지요청_생성(0, 10, 좋아요수_내림차순); - // when - final var actual = recipeService.getSortingRecipes(page).getRecipes(); - final var expected = List.of( - RecipeDto.toDto(recipe1_1, List.of(recipeImage1_1_1), List.of(product1, product2, product3)), - RecipeDto.toDto(recipe1_2, List.of(recipeImage1_2_1, recipeImage1_2_2), - List.of(product1, product3)), - RecipeDto.toDto(recipe1_3, List.of(), List.of())); + // when + final var actual = recipeService.getSortingRecipes(loginId, page).getRecipes(); + final var expected = List.of( + RecipeDto.toDto(recipe1_2, List.of(recipeImage1_2_1, recipeImage1_2_2), + List.of(product1, product3), false), + RecipeDto.toDto(recipe1_3, List.of(), List.of(), false), + RecipeDto.toDto(recipe1_1, List.of(recipeImage1_1_1), List.of(product1, product2, product3), + true)); - // then - assertThat(actual) - .usingRecursiveComparison() - .isEqualTo(expected); + // then + assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } } }