diff --git a/store-service/src/docs/asciidoc/api-docs.adoc b/store-service/src/docs/asciidoc/api-docs.adoc new file mode 100644 index 0000000..0ad9197 --- /dev/null +++ b/store-service/src/docs/asciidoc/api-docs.adoc @@ -0,0 +1,73 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: left +:toclevels: 2 +:sectlinks: + + +[[overview]] += 개요 + +[[overview-http-verbs]] +== HTTP 동사 + +본 REST API에서 사용하는 HTTP 동사(verbs)는 가능한한 표준 HTTP와 REST 규약을 따릅니다. + +|=== +| 동사 | 용례 + +| `GET` +| 리소스를 가져올 때 사용 + +| `POST` +| 새 리소스를 만들 때 사용 + +| `PUT` +| 기존 리소스를 수정할 때 사용 + +| `PATCH` +| 기존 리소스의 일부를 수정할 때 사용 + +| `DELETE` +| 기존 리소스를 삭제할 떄 사용 +|=== + +[[overview-http-status-codes]] +== HTTP 상태 코드 + +본 REST API에서 사용하는 HTTP 상태 코드는 가능한 표준 HTTP와 REST 규약을 따릅니다. + +|=== +| 상태 코드 | 용례 + +| `200 OK` +| 요청을 성공적으로 처리함 + +| `201 Created` +| 새 리소스를 성공적으로 생성함. 응답의 `Location` 헤더에 해당 리소스의 URI가 담겨있다. + +| `204 No Content` +| 기존 리소스를 성공적으로 수정함. + +| `400 Bad Request` +| 잘못된 요청을 보낸 경우. 응답 본문에 더 오류에 대한 정보가 담겨있다. + +| `404 Not Found` +| 요청한 리소스가 없음. + +| `409 Conflict` +| 클라이언트의 요청이 서버의 상태와 충돌이 발생한 경우. +|=== + +[[snippets-write-convention]] +== snippets 작성 컨벤션 +domain-httpRequestCode-etc + +== 주문 +=== 점주 서비스 - 카테고리 페이지 +- 페이지 offset : 6 + +operation::get-categoryList[snippets='curl-request,http-request,http-response,request-parameters,response-fields'] + +operation::put-categoryList[snippets='curl-request,http-request,http-response,request-parameters,response-fields'] diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/category/web/CategoryController.java b/store-service/src/main/java/com/justpickup/storeservice/domain/category/web/CategoryController.java index 0e189fd..c18b90f 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/category/web/CategoryController.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/category/web/CategoryController.java @@ -65,13 +65,16 @@ public class CategoryController { .body(Result.createSuccessResult(null)); } - @Data @NoArgsConstructor @AllArgsConstructor + @Data @NoArgsConstructor @AllArgsConstructor @Builder public static class PutCategoryRequest{ private Long storeId; private List categoryList; private List deletedList; @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor public static class Category{ private Long categoryId; private String name; diff --git a/store-service/src/test/java/com/justpickup/storeservice/config/TestConfig.java b/store-service/src/test/java/com/justpickup/storeservice/config/TestConfig.java new file mode 100644 index 0000000..045c78f --- /dev/null +++ b/store-service/src/test/java/com/justpickup/storeservice/config/TestConfig.java @@ -0,0 +1,18 @@ +package com.justpickup.storeservice.config; + +import org.springframework.boot.test.autoconfigure.restdocs.RestDocsMockMvcConfigurationCustomizer; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; + +@TestConfiguration +public class TestConfig { + + @Bean + public RestDocsMockMvcConfigurationCustomizer restDocsMockMvcConfigurationCustomizer() { + return configurer -> configurer.operationPreprocessors() + .withRequestDefaults(prettyPrint()) + .withResponseDefaults(prettyPrint()); + } +} \ No newline at end of file diff --git a/store-service/src/test/java/com/justpickup/storeservice/domain/category/web/CategoryControllerTest.java b/store-service/src/test/java/com/justpickup/storeservice/domain/category/web/CategoryControllerTest.java new file mode 100644 index 0000000..82fa310 --- /dev/null +++ b/store-service/src/test/java/com/justpickup/storeservice/domain/category/web/CategoryControllerTest.java @@ -0,0 +1,163 @@ +package com.justpickup.storeservice.domain.category.web; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.justpickup.storeservice.config.TestConfig; +import com.justpickup.storeservice.domain.category.dto.CategoryDto; +import com.justpickup.storeservice.domain.category.service.CategoryService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.BDDMockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.request.RequestDocumentation; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; + +@WebMvcTest(CategoryController.class) +@Import(TestConfig.class) +@AutoConfigureRestDocs(uriHost = "127.0.0.1",uriPort = 8001) +class CategoryControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private CategoryService categoryService; + + @Test + @DisplayName("카테고리리스트_가져오기_성공") + void getCategoryList_success() throws Exception { + + //given + Long storeId = 1L; + List categoryDtoList = new ArrayList<>(); + categoryDtoList.add(CategoryDto.builder() + .id(10L) + .name("카테고리1") + .order(1) + .build()); + + categoryDtoList.add(CategoryDto.builder() + .id(11L) + .name("카테고리2") + .order(2) + .build()); + + BDDMockito.given(categoryService.getCategoryList(1L)).willReturn(categoryDtoList); + //when + + ResultActions actions = mockMvc.perform(MockMvcRequestBuilders + .get("/category") + .param("storeId",String.valueOf(storeId)) + ); + + //then + + actions.andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("data[0].categoryId").value("10")) + .andExpect(MockMvcResultMatchers.jsonPath("data[0].name").value("카테고리1")) + .andExpect(MockMvcResultMatchers.jsonPath("data[1].categoryId").value("11")) + .andExpect(MockMvcResultMatchers.jsonPath("data[1].name").value("카테고리2")) + .andDo(MockMvcResultHandlers.print()) + .andDo(MockMvcRestDocumentation.document("get-categoryList", + requestParameters( + parameterWithName("storeId").description("매장 고유 번호") + ), + responseFields( + fieldWithPath("code").description("결과 코드 SUCCESS/ERROR"), + fieldWithPath("message").description("메시지"), + fieldWithPath("data[*].categoryId").description("카테고리 고유 번호"), + fieldWithPath("data[*].name").description("카테고리 명"), + fieldWithPath("data[*].order").description("순서") + ) + )); + + } + + + @Test + @DisplayName("카테고리리스트_수정_성공") + void putCategoryList_success() throws Exception { + + //given + Long storeId = 1L; + List categoryList = new ArrayList<>(); + categoryList.add(CategoryController.PutCategoryRequest.Category.builder() + .categoryId(10L) + .name("카테고리1") + .order(2) + .build()); + + categoryList.add(CategoryController.PutCategoryRequest.Category.builder() + .categoryId(11L) + .name("카테고리2") + .order(1) + .build()); + + List deletedList = new ArrayList<>(); + + deletedList.add(CategoryController.PutCategoryRequest.Category.builder() + .categoryId(11L) + .name("Non Coffee") + .order(3) + .build()); + + + CategoryController.PutCategoryRequest putCategoryRequest = + CategoryController.PutCategoryRequest.builder() + .storeId(storeId) + .categoryList(categoryList) + .deletedList(deletedList) + .build(); + + //when + ResultActions actions = mockMvc.perform( + MockMvcRequestBuilders + .put("/category") + .content(objectMapper.writeValueAsString(putCategoryRequest) ) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + ); + //then + + actions.andExpect(MockMvcResultMatchers.status().isNoContent()) + .andDo(MockMvcResultHandlers.print()) + .andDo(MockMvcRestDocumentation.document("put-categoryList", + requestFields( + fieldWithPath("storeId").description("매장 고유 번호"), + fieldWithPath("categoryList").description("수정된 카테고리 리스트"), + fieldWithPath("categoryList[*].categoryId").description("카테고리 고유 번호"), + fieldWithPath("categoryList[*].name").description("카테고리명"), + fieldWithPath("categoryList[*].order").description("순서"), + fieldWithPath("deletedList").description("삭제된 카테고리 리스트"), + fieldWithPath("deletedList[*].categoryId").description("카테고리 고유 번호"), + fieldWithPath("deletedList[*].name").description("카테고리명"), + fieldWithPath("deletedList[*].order").description("순서") + ) + )); + } + + + + +} \ No newline at end of file