Skip to content

Commit

Permalink
feat: 리스트 검색, 리스트 상세 조회 API 요청 및 응답값 수정 (#340)
Browse files Browse the repository at this point in the history
* feat: 리스트 검색, 리스트 상세 조회 API 요청 및 응답값 수정

- 리스트 검색: Category의 영어 이름으로 검색 -> CategoryCode를 이용해 검색, 검색 응답 시에 카테고리 정보 포함
- 리스트 상세 조회: 응답에 카테고리 코드 포함 (#336)

* test: 콜라보레이터 관련 테스트 비활성화 (#336)
  • Loading branch information
kdkdhoho committed Jan 20, 2025
1 parent 434bada commit 1224455
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

@Builder
public record ListDetailResponse(
String categoryCode,
String categoryEngName,
String categoryKorName,
List<LabelResponse> labels,
Expand Down Expand Up @@ -50,6 +51,7 @@ public static ListDetailResponse of(
List<ReactionResponse> reactions
) {
return ListDetailResponse.builder()
.categoryCode(list.getCategory().getCode())
.categoryEngName(list.getCategory().name().toLowerCase())
.categoryKorName(list.getCategory().getViewName())
.labels(LabelResponse.toList(list.getLabels().getValues()))
Expand All @@ -74,7 +76,7 @@ public static ListDetailResponse of(
.reactions(reactions)
.build();
}

public record LabelResponse(
String name
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

@Builder
public record ListSearchResponse(
List<ListInfo> resultLists,
List<ListDto> resultLists,
Long totalCount,
Long cursorId,
boolean hasNext
Expand All @@ -21,15 +21,15 @@ public static ListSearchResponse of(
boolean hasNext
) {
return ListSearchResponse.builder()
.resultLists(ListInfo.toList(lists))
.resultLists(ListDto.toList(lists))
.totalCount(totalCount)
.cursorId(cursorId)
.hasNext(hasNext)
.build();
}

@Builder
public record ListInfo(
public record ListDto(
Long id,
String title,
List<ItemInfo> items,
Expand All @@ -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<ListInfo> toList(List<ListEntity> lists) {
public static List<ListDto> toList(List<ListEntity> 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()))
Expand All @@ -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();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,27 +212,27 @@ private ListRecentResponse toListRecentResponse(Slice<ListEntity> 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<ListEntity> 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<ListEntity> paged = filtered.paging(cursorList, size + 1).listEntities();
List<ListEntity> 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) {
Expand All @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ ResponseEntity<ListRecentResponse> getRecentListsByFollowing(
ResponseEntity<ListSearchResponse> 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);
}

Expand Down
64 changes: 16 additions & 48 deletions src/test/java/com/listywave/acceptance/list/ListAcceptanceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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_호출;
Expand Down Expand Up @@ -380,6 +378,7 @@ class 리스트_수정 {
}

@Test
@Disabled
void 리스트의_작성자와_콜라보레이터만_수정할_수_있다() {
// given
var 동호 = 회원을_저장한다(동호());
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public abstract class ListAcceptanceTestHelper {

public static ListCreateRequest 좋아하는_라면_TOP3_생성_요청_데이터(List<Long> collaboratorIds) {
return new ListCreateRequest(
CategoryType.ETC,
CategoryType.FOOD_RECIPES,
List.of("라", "면", "좋"),
collaboratorIds,
"좋아하는 라면 TOP 3",
Expand Down Expand Up @@ -174,7 +174,7 @@ public abstract class ListAcceptanceTestHelper {
.extract();
}

public static ExtractableResponse<Response> 비회원이_피드_리스트_조회_카테고리_콜라보레이터_필터링_요청(User targetUser, String category) {
public static ExtractableResponse<Response> 비회원이_사용자_피드에서_콜라보리스트를_카테고리로_필터링하여_요청한다(User targetUser, String category) {
return given()
.when().get("/users/{userId}/lists?type=collabo&category={category}", targetUser.getId(), category)
.then().log().all()
Expand Down Expand Up @@ -210,9 +210,9 @@ public abstract class ListAcceptanceTestHelper {
.extract();
}

public static ExtractableResponse<Response> 카테고리로_검색_API_호출(String category) {
public static ExtractableResponse<Response> 카테고리_코드로_검색_API_호출(String categoryCode) {
return given()
.when().get("/lists/search?category={category}", category)
.when().get("/lists/search?categoryCode={categoryCode}", categoryCode)
.then().log().all()
.extract();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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));
}
}

0 comments on commit 1224455

Please sign in to comment.