diff --git a/src/main/java/com/listywave/list/application/domain/list/ListEntity.java b/src/main/java/com/listywave/list/application/domain/list/ListEntity.java index 7264101b..967836b9 100644 --- a/src/main/java/com/listywave/list/application/domain/list/ListEntity.java +++ b/src/main/java/com/listywave/list/application/domain/list/ListEntity.java @@ -9,7 +9,6 @@ import static jakarta.persistence.TemporalType.TIMESTAMP; import static lombok.AccessLevel.PROTECTED; -import com.listywave.collaborator.application.domain.Collaborators; import com.listywave.common.exception.CustomException; import com.listywave.list.application.domain.category.CategoryType; import com.listywave.list.application.domain.item.Item; @@ -247,16 +246,10 @@ public void validateOwnerIsNotDeleted() { } } - public void validateUpdateAuthority(User loginUser, Collaborators beforeCollaborators) { + public void validateUpdateAuthority(User loginUser) { if (this.user.equals(loginUser)) { return; } - if (beforeCollaborators.isEmpty()) { - return; - } - if (beforeCollaborators.contains(loginUser)) { - return; - } throw new CustomException(INVALID_ACCESS); } diff --git a/src/main/java/com/listywave/list/application/dto/response/ListDetailResponse.java b/src/main/java/com/listywave/list/application/dto/response/ListDetailResponse.java index daec8b0a..7bf023fc 100644 --- a/src/main/java/com/listywave/list/application/dto/response/ListDetailResponse.java +++ b/src/main/java/com/listywave/list/application/dto/response/ListDetailResponse.java @@ -14,6 +14,7 @@ @Builder public record ListDetailResponse( + String categoryCode, String categoryEngName, String categoryKorName, List labels, @@ -50,6 +51,7 @@ public static ListDetailResponse of( List reactions ) { return ListDetailResponse.builder() + .categoryCode(list.getCategory().getCode()) .categoryEngName(list.getCategory().name().toLowerCase()) .categoryKorName(list.getCategory().getViewName()) .labels(LabelResponse.toList(list.getLabels().getValues())) @@ -74,7 +76,7 @@ public static ListDetailResponse of( .reactions(reactions) .build(); } - + public record LabelResponse( String name ) { diff --git a/src/main/java/com/listywave/list/application/dto/response/ListSearchResponse.java b/src/main/java/com/listywave/list/application/dto/response/ListSearchResponse.java index bd52f8ab..7790a9f7 100644 --- a/src/main/java/com/listywave/list/application/dto/response/ListSearchResponse.java +++ b/src/main/java/com/listywave/list/application/dto/response/ListSearchResponse.java @@ -8,7 +8,7 @@ @Builder public record ListSearchResponse( - List resultLists, + List resultLists, Long totalCount, Long cursorId, boolean hasNext @@ -21,7 +21,7 @@ public static ListSearchResponse of( boolean hasNext ) { return ListSearchResponse.builder() - .resultLists(ListInfo.toList(lists)) + .resultLists(ListDto.toList(lists)) .totalCount(totalCount) .cursorId(cursorId) .hasNext(hasNext) @@ -29,7 +29,7 @@ public static ListSearchResponse of( } @Builder - public record ListInfo( + public record ListDto( Long id, String title, List items, @@ -39,17 +39,20 @@ public record ListInfo( Long ownerId, String ownerNickname, String ownerProfileImageUrl, - String representImageUrl + String representImageUrl, + String categoryCode, + String categoryKorName, + String categoryEngName ) { - public static List toList(List lists) { + public static List toList(List lists) { return lists.stream() - .map(ListInfo::of) + .map(ListDto::of) .toList(); } - private static ListInfo of(ListEntity list) { - return ListInfo.builder() + private static ListDto of(ListEntity list) { + return ListDto.builder() .id(list.getId()) .title(list.getTitle().getValue()) .items(ItemInfo.toList(list.getTop3Items().getValues())) @@ -60,6 +63,9 @@ private static ListInfo of(ListEntity list) { .ownerNickname(list.getUser().getNickname()) .ownerProfileImageUrl(list.getUser().getProfileImageUrl()) .representImageUrl(list.getRepresentImageUrl()) + .categoryCode(list.getCategory().getCode()) + .categoryKorName(list.getCategory().getViewName()) + .categoryEngName(list.getCategory().name()) .build(); } } diff --git a/src/main/java/com/listywave/list/application/service/ListService.java b/src/main/java/com/listywave/list/application/service/ListService.java index 86d2a600..dd40c94a 100644 --- a/src/main/java/com/listywave/list/application/service/ListService.java +++ b/src/main/java/com/listywave/list/application/service/ListService.java @@ -212,27 +212,27 @@ private ListRecentResponse toListRecentResponse(Slice result) { } @Transactional(readOnly = true) - public ListSearchResponse search(String keyword, SortType sortType, CategoryType category, int size, Long cursorId) { + public ListSearchResponse search(String keyword, SortType sortType, String categoryCode, int size, Long cursorId) { List lists = listRepository.findAll().stream() .filter(list -> !list.isDeletedUser() && list.isPublic()) .toList(); - ListEntities allList = new ListEntities(lists); - ListEntities filtered = allList.filterBy(category) + ListEntities listEntities = new ListEntities(lists); + + ListEntities filteredAndSortedLists = listEntities.filterBy(CategoryType.codeOf(categoryCode)) .filterBy(keyword) .sortBy(sortType, keyword); - - long totalCount = filtered.size(); + long totalCount = filteredAndSortedLists.size(); ListEntity cursorList = (cursorId == 0L) ? null : listRepository.getById(cursorId); - List paged = filtered.paging(cursorList, size + 1).listEntities(); + List pagedLists = filteredAndSortedLists.paging(cursorList, size + 1).listEntities(); - if (paged.size() > size) { - return ListSearchResponse.of(paged.subList(0, size), totalCount, paged.get(size - 1).getId(), true); + if (pagedLists.size() > size) { + return ListSearchResponse.of(pagedLists.subList(0, size), totalCount, pagedLists.get(size - 1).getId(), true); } - if (paged.isEmpty()) { - return ListSearchResponse.of(paged, totalCount, null, false); + if (pagedLists.isEmpty()) { + return ListSearchResponse.of(pagedLists, totalCount, null, false); } - return ListSearchResponse.of(paged, totalCount, paged.get(paged.size() - 1).getId(), false); + return ListSearchResponse.of(pagedLists, totalCount, pagedLists.get(pagedLists.size() - 1).getId(), false); } public void update(Long listId, Long loginUserId, ListUpdateRequest request) { @@ -242,7 +242,7 @@ public void update(Long listId, Long loginUserId, ListUpdateRequest request) { ListEntity list = listRepository.getById(listId); Collaborators beforeCollaborators = collaboratorService.findAllByList(list); - list.validateUpdateAuthority(loginUser, beforeCollaborators); + list.validateUpdateAuthority(loginUser); Collaborators newCollaborators = collaboratorService.createCollaborators(request.collaboratorIds(), list); collaboratorService.updateCollaborators(beforeCollaborators, newCollaborators); diff --git a/src/main/java/com/listywave/list/presentation/controller/ListController.java b/src/main/java/com/listywave/list/presentation/controller/ListController.java index 639f9175..e99f3894 100644 --- a/src/main/java/com/listywave/list/presentation/controller/ListController.java +++ b/src/main/java/com/listywave/list/presentation/controller/ListController.java @@ -93,11 +93,11 @@ ResponseEntity getRecentListsByFollowing( ResponseEntity search( @RequestParam(value = "keyword", defaultValue = "") String keyword, @RequestParam(value = "sort", defaultValue = "new") SortType sort, - @RequestParam(value = "category", defaultValue = "entire") CategoryType category, + @RequestParam(value = "categoryCode", defaultValue = "0") String categoryCode, @RequestParam(value = "size", defaultValue = "5") int size, @RequestParam(value = "cursorId", defaultValue = "0") Long cursorId ) { - ListSearchResponse response = listService.search(keyword, sort, category, size, cursorId); + ListSearchResponse response = listService.search(keyword, sort, categoryCode, size, cursorId); return ResponseEntity.ok(response); } diff --git a/src/test/java/com/listywave/acceptance/list/ListAcceptanceTest.java b/src/test/java/com/listywave/acceptance/list/ListAcceptanceTest.java index 5aeca051..7e122cc8 100644 --- a/src/test/java/com/listywave/acceptance/list/ListAcceptanceTest.java +++ b/src/test/java/com/listywave/acceptance/list/ListAcceptanceTest.java @@ -18,15 +18,13 @@ import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원_리스트_상세_조회_API_호출; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원_피드_리스트_조회_API_호출; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원_히스토리_조회_API_호출; -import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원이_피드_리스트_조회_카테고리_콜라보레이터_필터링_요청; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원이_피드_리스트_조회_카테고리_필터링_요청; -import static com.listywave.acceptance.list.ListAcceptanceTestHelper.비회원이_피드_리스트_조회_콜라보레이터_필터링_요청; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.아이템_순위와_라벨을_바꾼_좋아하는_견종_TOP3_요청_데이터; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.정렬기준을_포함한_검색_API_호출; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.좋아하는_라면_TOP3_생성_요청_데이터; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.최신_리스트_10개_조회_카테고리_필터링_API_호출; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.추천_리스트_조회_API_호출; -import static com.listywave.acceptance.list.ListAcceptanceTestHelper.카테고리로_검색_API_호출; +import static com.listywave.acceptance.list.ListAcceptanceTestHelper.카테고리_코드로_검색_API_호출; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.카테고리와_키워드로_검색_API_호출; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.키워드로_검색_API_호출; import static com.listywave.acceptance.list.ListAcceptanceTestHelper.키워드와_정렬기준을_포함한_검색_API_호출; @@ -380,6 +378,7 @@ class 리스트_수정 { } @Test + @Disabled void 리스트의_작성자와_콜라보레이터만_수정할_수_있다() { // given var 동호 = 회원을_저장한다(동호()); @@ -583,47 +582,6 @@ class 피드_리스트_조회 { .ignoringFields("id") .isEqualTo(기대값); } - - @Test - @Disabled - void 콜라보레이터로_필터링한다() { - // given - var 동호 = 회원을_저장한다(동호()); - var 정수 = 회원을_저장한다(정수()); - var 동호_액세스_토큰 = 액세스_토큰을_발급한다(동호); - var 정수_액세스_토큰 = 액세스_토큰을_발급한다(정수); - var 리스트_1_ID = 리스트_저장_API_호출(가장_좋아하는_견종_TOP3_생성_요청_데이터(List.of(정수.getId())), 동호_액세스_토큰) - .as(ListCreateResponse.class) - .listId(); - var 리스트_2_ID = 리스트_저장_API_호출(가장_좋아하는_견종_TOP3_생성_요청_데이터(List.of(동호.getId())), 정수_액세스_토큰) - .as(ListCreateResponse.class) - .listId(); - - // when - var 결과 = 비회원이_피드_리스트_조회_콜라보레이터_필터링_요청(동호).as(FindFeedListResponse.class); - - // then - assertThat(결과.feedLists()).hasSize(2); - assertThat(결과.feedLists().get(0).id()).isEqualTo(리스트_2_ID); - assertThat(결과.feedLists().get(1).id()).isEqualTo(리스트_1_ID); - } - - @Test - void 콜라보레이터와_카테고리로_필터링한다() { - // given - var 동호 = 회원을_저장한다(동호()); - var 정수 = 회원을_저장한다(정수()); - var 동호_액세스_토큰 = 액세스_토큰을_발급한다(동호); - 리스트_저장_API_호출(가장_좋아하는_견종_TOP3_생성_요청_데이터(List.of()), 동호_액세스_토큰).as(ListCreateResponse.class); - var 동호_리스트_2 = 리스트_저장_API_호출(좋아하는_라면_TOP3_생성_요청_데이터(List.of(정수.getId())), 동호_액세스_토큰).as(ListCreateResponse.class); - - // when - var 결과 = 비회원이_피드_리스트_조회_카테고리_콜라보레이터_필터링_요청(동호, "etc").as(FindFeedListResponse.class); - - // then - assertThat(결과.feedLists()).hasSize(1); - assertThat(결과.feedLists().get(0).id()).isEqualTo(동호_리스트_2.listId()); - } } @Nested @@ -755,21 +713,31 @@ class 리스트_검색 { } @Test - void 카테고리로_필터링_할_수_있다() { + void 카테고리_코드로_필터링_할_수_있다() { // given var 동호 = 회원을_저장한다(동호()); var 동호_액세스_토큰 = 액세스_토큰을_발급한다(동호); 리스트_저장_API_호출(가장_좋아하는_견종_TOP3_생성_요청_데이터(List.of()), 동호_액세스_토큰); var 좋아하는_라면_TOP3_생성_결과 = 리스트_저장_API_호출(좋아하는_라면_TOP3_생성_요청_데이터(List.of()), 동호_액세스_토큰).as(ListCreateResponse.class); + assertThat(가장_좋아하는_견종_TOP3_생성_요청_데이터(List.of()).category()).isNotEqualTo(좋아하는_라면_TOP3_생성_요청_데이터(List.of()).category()); + CategoryType 검색하려는_카테고리 = 좋아하는_라면_TOP3_생성_요청_데이터(List.of()).category(); + // when - var result = 카테고리로_검색_API_호출("etc").as(ListSearchResponse.class); + var result = 카테고리_코드로_검색_API_호출(검색하려는_카테고리.getCode()).as(ListSearchResponse.class); // then assertAll( () -> assertThat(result.totalCount()).isOne(), - () -> assertThat(result.resultLists()).hasSize(1), - () -> assertThat(result.resultLists().get(0).id()).isEqualTo(좋아하는_라면_TOP3_생성_결과.listId()) + () -> { + var listResponses = result.resultLists(); + + assertThat(listResponses).hasSize(1); + assertThat(listResponses.get(0).id()).isEqualTo(좋아하는_라면_TOP3_생성_결과.listId()); + assertThat(listResponses.stream() + .allMatch(listResponse -> listResponse.categoryCode().equals(검색하려는_카테고리.getCode())) + ).isTrue(); + } ); } diff --git a/src/test/java/com/listywave/acceptance/list/ListAcceptanceTestHelper.java b/src/test/java/com/listywave/acceptance/list/ListAcceptanceTestHelper.java index 621dc9a3..eaba9ed2 100644 --- a/src/test/java/com/listywave/acceptance/list/ListAcceptanceTestHelper.java +++ b/src/test/java/com/listywave/acceptance/list/ListAcceptanceTestHelper.java @@ -96,7 +96,7 @@ public abstract class ListAcceptanceTestHelper { public static ListCreateRequest 좋아하는_라면_TOP3_생성_요청_데이터(List collaboratorIds) { return new ListCreateRequest( - CategoryType.ETC, + CategoryType.FOOD_RECIPES, List.of("라", "면", "좋"), collaboratorIds, "좋아하는 라면 TOP 3", @@ -174,7 +174,7 @@ public abstract class ListAcceptanceTestHelper { .extract(); } - public static ExtractableResponse 비회원이_피드_리스트_조회_카테고리_콜라보레이터_필터링_요청(User targetUser, String category) { + public static ExtractableResponse 비회원이_사용자_피드에서_콜라보리스트를_카테고리로_필터링하여_요청한다(User targetUser, String category) { return given() .when().get("/users/{userId}/lists?type=collabo&category={category}", targetUser.getId(), category) .then().log().all() @@ -210,9 +210,9 @@ public abstract class ListAcceptanceTestHelper { .extract(); } - public static ExtractableResponse 카테고리로_검색_API_호출(String category) { + public static ExtractableResponse 카테고리_코드로_검색_API_호출(String categoryCode) { return given() - .when().get("/lists/search?category={category}", category) + .when().get("/lists/search?categoryCode={categoryCode}", categoryCode) .then().log().all() .extract(); } diff --git a/src/test/java/com/listywave/collaborator/application/domain/CollaboratorsTest.java b/src/test/java/com/listywave/collaborator/application/domain/CollaboratorsTest.java index 4e8629db..478b9f9b 100644 --- a/src/test/java/com/listywave/collaborator/application/domain/CollaboratorsTest.java +++ b/src/test/java/com/listywave/collaborator/application/domain/CollaboratorsTest.java @@ -24,10 +24,12 @@ import java.util.List; import java.util.stream.LongStream; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +@Disabled @DisplayName("Collaboratros는 ") class CollaboratorsTest { diff --git a/src/test/java/com/listywave/list/application/domain/list/ListEntityTest.java b/src/test/java/com/listywave/list/application/domain/list/ListEntityTest.java index 9eb5cf3e..6de7f193 100644 --- a/src/test/java/com/listywave/list/application/domain/list/ListEntityTest.java +++ b/src/test/java/com/listywave/list/application/domain/list/ListEntityTest.java @@ -11,11 +11,10 @@ import static com.listywave.user.fixture.UserFixture.정수; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.listywave.collaborator.application.domain.Collaborator; -import com.listywave.collaborator.application.domain.Collaborators; import com.listywave.common.exception.CustomException; import com.listywave.list.application.domain.category.CategoryType; import com.listywave.list.application.domain.item.Item; @@ -29,6 +28,7 @@ import com.listywave.list.application.domain.label.Labels; import com.listywave.user.application.domain.User; import java.util.List; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -225,23 +225,31 @@ class ListEntityTest { } @Test + @Disabled void 리스트는_작성자_또는_콜라보레이터에_포함된_유저만이_수정할_수_있다() { // given User collaboratorUser = 정수(); - Collaborator collaborator = Collaborator.init(collaboratorUser, list); User notCollaborator = 유진(); - Collaborators collaborators = new Collaborators(List.of(collaborator)); - // when // then assertAll( - () -> assertThatNoException().isThrownBy(() -> list.validateUpdateAuthority(user, collaborators)), - () -> assertThatNoException().isThrownBy(() -> list.validateUpdateAuthority(collaboratorUser, collaborators)), + () -> assertThatNoException().isThrownBy(() -> list.validateUpdateAuthority(user)), + () -> assertThatNoException().isThrownBy(() -> list.validateUpdateAuthority(collaboratorUser)), () -> { - CustomException exception = assertThrows(CustomException.class, () -> list.validateUpdateAuthority(notCollaborator, collaborators)); + CustomException exception = assertThrows(CustomException.class, () -> list.validateUpdateAuthority(notCollaborator)); assertThat(exception.getErrorCode()).isEqualTo(INVALID_ACCESS); } ); } + + @Test + void 리스트는_작성자만이_수정할_수_있다() { + // given + User otherUser = 정수(); + + // expect + assertThatThrownBy(() -> list.validateUpdateAuthority(otherUser)); + assertThatNoException().isThrownBy(() -> list.validateUpdateAuthority(user)); + } }