From 4f479b240f0acb89c41ed13d17a8dfe704f6d128 Mon Sep 17 00:00:00 2001 From: jiyunio Date: Sun, 23 Feb 2025 02:03:55 +0900 Subject: [PATCH] =?UTF-8?q?[Feat]=20=EC=A4=91=EA=B3=A0=EC=83=81=ED=92=88?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=EC=97=90=20=EB=8C=80=ED=95=9C=20api=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=EC=84=9C=20=EC=9E=91=EC=84=B1=20#106?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/usedItem/usedItem.adoc | 26 ++- .../evc/domain/useditem/dto/ItemRequest.java | 40 ----- .../usedItem/UsedItemControllerDocsTest.java | 170 ++++++++++++++---- 3 files changed, 161 insertions(+), 75 deletions(-) delete mode 100644 src/main/java/com/yzgeneration/evc/domain/useditem/dto/ItemRequest.java diff --git a/src/docs/asciidoc/usedItem/usedItem.adoc b/src/docs/asciidoc/usedItem/usedItem.adoc index caa8c18..36c85d0 100644 --- a/src/docs/asciidoc/usedItem/usedItem.adoc +++ b/src/docs/asciidoc/usedItem/usedItem.adoc @@ -7,4 +7,28 @@ include::{snippets}/usedItem-create/request-part-createUsedItem-fields.adoc[] === HTTP Response include::{snippets}/usedItem-create/http-response.adoc[] -include::{snippets}/usedItem-create/response-fields.adoc[] + + +[[usedItems-get]] +== 중고상품들 조회 (슬라이드 형태) + +=== HTTP Request +include::{snippets}/usedItems-get/http-request.adoc[] +include::{snippets}/usedItems-get/query-parameters.adoc[] + +=== HTTP Response +include::{snippets}/usedItems-get/http-response.adoc[] +include::{snippets}/usedItems-get/response-fields.adoc[] + +[[usedItem-get]] +== 개별 중고상품 조회 + +=== HTTP Request +include::{snippets}/usedItem-get/http-request.adoc[] +include::{snippets}/usedItem-get/path-parameters.adoc[] +include::{snippets}/usedItem-get/query-parameters.adoc[] + +=== HTTP Response +include::{snippets}/usedItem-get/http-response.adoc[] +include::{snippets}/usedItem-get/response-fields.adoc[] + diff --git a/src/main/java/com/yzgeneration/evc/domain/useditem/dto/ItemRequest.java b/src/main/java/com/yzgeneration/evc/domain/useditem/dto/ItemRequest.java deleted file mode 100644 index 834a7fb..0000000 --- a/src/main/java/com/yzgeneration/evc/domain/useditem/dto/ItemRequest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.yzgeneration.evc.domain.useditem.dto; - -import com.yzgeneration.evc.domain.useditem.enums.TransactionMode; -import com.yzgeneration.evc.domain.useditem.enums.TransactionType; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.*; - -public class ItemRequest { - - @Getter - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class CreateItemDetails { - @NotBlank(message = "제목은 필수항목입니다.") - private String title; - - @NotBlank(message = "카테고리는 필수항목입니다.") - private String category; - - @NotBlank(message = "내용은 필수항목입니다.") - private String content; - - @NotNull(message = "가격은 필수항목입니다.") - private int price; - } - - @Getter - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class CreateTransaction { - @NotNull(message = "거래유형을 선택해주세요.") - private String transactionType; - - @NotNull(message = "거래방법을 선택해주세요.") - private String transactionMode; - } -} diff --git a/src/test/java/com/yzgeneration/evc/docs/usedItem/UsedItemControllerDocsTest.java b/src/test/java/com/yzgeneration/evc/docs/usedItem/UsedItemControllerDocsTest.java index fb76f0e..8742d0b 100644 --- a/src/test/java/com/yzgeneration/evc/docs/usedItem/UsedItemControllerDocsTest.java +++ b/src/test/java/com/yzgeneration/evc/docs/usedItem/UsedItemControllerDocsTest.java @@ -2,12 +2,15 @@ import com.yzgeneration.evc.docs.RestDocsSupport; import com.yzgeneration.evc.domain.useditem.controller.UsedItemController; -import com.yzgeneration.evc.domain.useditem.dto.UsedItemRequest.CreateUsedItem; -import com.yzgeneration.evc.domain.useditem.dto.UsedItemResponse; +import com.yzgeneration.evc.domain.useditem.dto.UsedItemRequest.CreateUsedItemRequest; +import com.yzgeneration.evc.domain.useditem.dto.UsedItemResponse.CreateUsedItemResponse; +import com.yzgeneration.evc.domain.useditem.dto.UsedItemResponse.LoadUsedItemResponse; +import com.yzgeneration.evc.domain.useditem.dto.UsedItemResponse.LoadUsedItemsDetails; +import com.yzgeneration.evc.domain.useditem.dto.UsedItemResponse.LoadUsedItemsResponse; +import com.yzgeneration.evc.domain.useditem.enums.TransactionMode; +import com.yzgeneration.evc.domain.useditem.enums.TransactionStatue; +import com.yzgeneration.evc.domain.useditem.enums.TransactionType; import com.yzgeneration.evc.domain.useditem.enums.UsedItemStatus; -import com.yzgeneration.evc.domain.useditem.model.ItemDetails; -import com.yzgeneration.evc.domain.useditem.model.ItemStats; -import com.yzgeneration.evc.domain.useditem.model.UsedItemTransaction; import com.yzgeneration.evc.domain.useditem.service.UsedItemService; import com.yzgeneration.evc.fixture.usedItem.UsedItemFixture; import com.yzgeneration.evc.mock.usedItem.MockUsedItemImageFile; @@ -20,7 +23,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.time.LocalDateTime; -import java.util.ArrayList; +import java.util.List; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; @@ -29,6 +32,7 @@ import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.operation.preprocess.Preprocessors.*; import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class UsedItemControllerDocsTest extends RestDocsSupport { @@ -44,23 +48,13 @@ protected Object initController() { @DisplayName("중고상품 등록") void createUsedItem() throws Exception { - CreateUsedItem usedItem = UsedItemFixture.fixCreateUsedItem(); // 실제 값 넣기 - MockMultipartFile usedItemReq = new MockMultipartFile("createUsedItem", "", "application/json", objectMapper.writeValueAsBytes(usedItem)); + CreateUsedItemRequest usedItem = UsedItemFixture.fixCreateUsedItemRequest(); + MockMultipartFile usedItemReq = new MockMultipartFile("createUsedItemRequest", "", "application/json", objectMapper.writeValueAsBytes(usedItem)); - UsedItemResponse usedItemResponse = UsedItemResponse.builder() - .memberId(1L) - .itemDetails(ItemDetails.create(usedItem.getCreateItemDetails())) - .usedItemTransaction(UsedItemTransaction.create(usedItem.getCreateTransaction())) - .usedItemStatus(UsedItemStatus.ACTIVE) - .itemStats(ItemStats.create()) - .imageURLs(new ArrayList<>()) - .createAt(LocalDateTime.now()) - .build(); + CreateUsedItemResponse createUsedItemResponse = new CreateUsedItemResponse(usedItem.getMemberId(), 1L); -// when(usedItemService.createUsedItem(any(Long.class), any(CreateUsedItem.class), anyList())) -// .thenReturn(usedItemResponse); - when(usedItemService.createUsedItem(any(CreateUsedItem.class), anyList())) - .thenReturn(usedItemResponse); + when(usedItemService.createUsedItem(any(CreateUsedItemRequest.class), anyList())) + .thenReturn(createUsedItemResponse); mockMvc.perform(MockMvcRequestBuilders.multipart("/api/useditems") @@ -72,7 +66,7 @@ void createUsedItem() throws Exception { .andDo(document("usedItem-create", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), - requestPartFields("createUsedItem", + requestPartFields("createUsedItemRequest", fieldWithPath("memberId").type(JsonFieldType.NUMBER) .description("회원 Id"), fieldWithPath("title").type(JsonFieldType.STRING) @@ -84,13 +78,116 @@ void createUsedItem() throws Exception { fieldWithPath("price").type(JsonFieldType.NUMBER) .description("중고상품 가격"), fieldWithPath("transactionType").type(JsonFieldType.STRING) - .description("중고상품 거래유형"), + .description("중고상품 거래유형 (DIRECT, DELIVERY)"), fieldWithPath("transactionMode").type(JsonFieldType.STRING) - .description("중고상품 거래방법") + .description("중고상품 거래방법 (SELL, BUY, AUCTION)") ), responseFields( fieldWithPath("memberId").type(JsonFieldType.NUMBER) - .description("회원의 memberId"), + .description("회원의 id"), + fieldWithPath("usedItemId").type(JsonFieldType.NUMBER) + .description("중고상품의 id") + ))); + } + + @Test + @WithMockUser + @DisplayName("중고상품들 조회 (메인페이지)") + void loadUsedItems() throws Exception { + LoadUsedItemsDetails loadUsedItemsDetails1 = LoadUsedItemsDetails.builder() + .usedItemId(1L) + .title("중고상품이요~") + .price(10000) + .transactionMode(TransactionMode.BUY) + .imageURLs(List.of("https://domain/asdfasdfasdf")) + .likeCount(0) + .createAt(LocalDateTime.now()) + .usedItemStatus(UsedItemStatus.ACTIVE) + .build(); + LoadUsedItemsDetails loadUsedItemsDetails2 = LoadUsedItemsDetails.builder() + .usedItemId(2L) + .title("중고상품이요~ 22") + .price(20000) + .transactionMode(TransactionMode.AUCTION) + .imageURLs(List.of("https://domain/asdfasdfasdf")) + .likeCount(0) + .createAt(LocalDateTime.now()) + .usedItemStatus(UsedItemStatus.ACTIVE) + .build(); + LoadUsedItemsResponse loadUsedItemsResponse = LoadUsedItemsResponse.builder() + .loadUsedItemDetails(List.of(loadUsedItemsDetails1, loadUsedItemsDetails2)) + .isLast(false) + .build(); + + when(usedItemService.loadUsedItems(0)) + .thenReturn(loadUsedItemsResponse); + + mockMvc.perform(MockMvcRequestBuilders.get("/api/useditems") + .param("page", "0")) + .andExpect(status().isOk()) + .andDo(document("usedItems-get", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + queryParameters(parameterWithName("page").description("출력 페이지 번호 / 0부터 시작 / 10개씩 뽑아줌")), + responseFields( + fieldWithPath("loadUsedItemDetails").type(JsonFieldType.ARRAY) + .description("중고상품 리스트"), + fieldWithPath("loadUsedItemDetails[].usedItemId").type(JsonFieldType.NUMBER) + .description("중고상품 id"), + fieldWithPath("loadUsedItemDetails[].title").type(JsonFieldType.STRING) + .description("중고상품 제목"), + fieldWithPath("loadUsedItemDetails[].price").type(JsonFieldType.NUMBER) + .description("중고상품 가격"), + fieldWithPath("loadUsedItemDetails[].transactionMode").type(JsonFieldType.STRING) + .description("중고상품 거래방법 (SELL, BUY, AUCTION)"), + fieldWithPath("loadUsedItemDetails[].imageURLs").type(JsonFieldType.ARRAY) + .description("중고상품 이미지 리스트"), + fieldWithPath("loadUsedItemDetails[].likeCount").type(JsonFieldType.NUMBER) + .description("게시물 좋아요수"), + fieldWithPath("loadUsedItemDetails[].createAt").type(JsonFieldType.ARRAY) + .description("중고상품 게시시간 (createAt과 현재시간과의 차이값을 프론트 화면에 렌더링)"), + fieldWithPath("loadUsedItemDetails[].usedItemStatus").type(JsonFieldType.STRING) + .description("중고상품 상태"), + fieldWithPath("isLast").type(JsonFieldType.BOOLEAN) + .description("페이지 마지막 유무 (false == 상품 더 있음 / true == 상품 없음") + ))); + } + + @Test + @WithMockUser + @DisplayName("개별 중고상품 조회 (상세페이지)") + void loadUsedItem() throws Exception { + LoadUsedItemResponse loadUsedItemResponse = LoadUsedItemResponse.builder() + .title("중고상품이요") + .category("윗도리") + .content("강매는 아닌데 사십쇼.") + .price(10000) + .transactionType(TransactionType.DIRECT) + .transactionMode(TransactionMode.BUY) + .transactionStatue(TransactionStatue.ONGOING) + .imageURLs(List.of("https://domain/asdfasdfasdf")) + .viewCount(0) + .likeCount(0) + .chattingCount(0) + .memberId(1L) + .nickName("highyun") + .isOwned(true) + .createAt(LocalDateTime.now()) + .usedItemStatus(UsedItemStatus.ACTIVE) + .build(); + + when(usedItemService.loadUsedItem(any(), any())) + .thenReturn(loadUsedItemResponse); + + mockMvc.perform(MockMvcRequestBuilders.get("/api/useditems/{usedItemId}", 1L) + .param("memberId", "0")) + .andExpect(status().isOk()) + .andDo(document("usedItem-get", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters(parameterWithName("usedItemId").description("중고상품의 id")), + queryParameters(parameterWithName("memberId").description("회원의 id")), + responseFields( fieldWithPath("title").type(JsonFieldType.STRING) .description("중고상품 제목"), fieldWithPath("category").type(JsonFieldType.STRING) @@ -100,24 +197,29 @@ void createUsedItem() throws Exception { fieldWithPath("price").type(JsonFieldType.NUMBER) .description("중고상품 가격"), fieldWithPath("transactionType").type(JsonFieldType.STRING) - .description("중고상품 거래유형"), + .description("중고상품 거래유형 (DIRECT, DELIVERY)"), fieldWithPath("transactionMode").type(JsonFieldType.STRING) - .description("중고상품 거래방법"), + .description("중고상품 거래방법 (SELL, BUY, AUCTION)"), fieldWithPath("transactionStatue").type(JsonFieldType.STRING) - .description("중고상품 거래상태"), - fieldWithPath("usedItemStatus").type(JsonFieldType.STRING) - .description("중고상품 게시상태"), + .description("중고상품 거래상태 (ONGOING, RESERVE, COMPLETE)"), + fieldWithPath("imageURLs").type(JsonFieldType.ARRAY) + .description("중고상품 이미지 리스트"), fieldWithPath("viewCount").type(JsonFieldType.NUMBER) .description("게시물 조회수"), fieldWithPath("likeCount").type(JsonFieldType.NUMBER) .description("게시물 좋아요수"), fieldWithPath("chattingCount").type(JsonFieldType.NUMBER) .description("게시물 채팅수"), - fieldWithPath("imageURLs").type(JsonFieldType.ARRAY) - .description("중고상품 이미지 리스트"), + fieldWithPath("memberId").type(JsonFieldType.NUMBER) + .description("상점 주인의 id (상점 주인 상세페이지 이동에서 사용될 수 있으니 추가함)"), + fieldWithPath("nickName").type(JsonFieldType.STRING) + .description("상점 주인 nickname"), + fieldWithPath("isOwned").type(JsonFieldType.BOOLEAN) + .description("내가 작성한 글인지 유무"), fieldWithPath("createAt").type(JsonFieldType.ARRAY) - .description("중고상품 게시시간") + .description("중고상품 게시시간"), + fieldWithPath("usedItemStatus").type(JsonFieldType.STRING) + .description("중고상품 게시상태 (ACTIVE, DELETED, BAN)") ))); - } }