Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 리스트 검색, 리스트 상세 조회 API 요청 및 응답값 수정 #340

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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));
}
}
Loading