diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/category/CategoryAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/category/CategoryAdminRepository.java index 7bd01c701..9f506092c 100644 --- a/gg-admin-repo/src/main/java/gg/admin/repo/category/CategoryAdminRepository.java +++ b/gg-admin-repo/src/main/java/gg/admin/repo/category/CategoryAdminRepository.java @@ -6,4 +6,6 @@ public interface CategoryAdminRepository extends JpaRepository { Boolean existsByName(String categoryName); + + Category findByName(String categoryName); } diff --git a/gg-pingpong-api/src/main/java/gg/party/api/admin/category/controller/CategoryAdminController.java b/gg-pingpong-api/src/main/java/gg/party/api/admin/category/controller/CategoryAdminController.java index 36065dc20..a93e36e24 100644 --- a/gg-pingpong-api/src/main/java/gg/party/api/admin/category/controller/CategoryAdminController.java +++ b/gg-pingpong-api/src/main/java/gg/party/api/admin/category/controller/CategoryAdminController.java @@ -1,5 +1,7 @@ package gg.party.api.admin.category.controller; +import javax.validation.Valid; + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -25,7 +27,7 @@ public class CategoryAdminController { * @return 추가 성공 여부 */ @PostMapping - public ResponseEntity categoryAdd(@RequestBody CategoryAddAdminReqDto reqDto) { + public ResponseEntity categoryAdd(@RequestBody @Valid CategoryAddAdminReqDto reqDto) { categoryAdminService.addCategory(reqDto); return ResponseEntity.status(HttpStatus.CREATED).build(); } diff --git a/gg-pingpong-api/src/main/java/gg/party/api/admin/category/controller/request/CategoryAddAdminReqDto.java b/gg-pingpong-api/src/main/java/gg/party/api/admin/category/controller/request/CategoryAddAdminReqDto.java index e154c0f20..043053450 100644 --- a/gg-pingpong-api/src/main/java/gg/party/api/admin/category/controller/request/CategoryAddAdminReqDto.java +++ b/gg-pingpong-api/src/main/java/gg/party/api/admin/category/controller/request/CategoryAddAdminReqDto.java @@ -1,10 +1,19 @@ package gg.party.api.admin.category.controller.request; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + import lombok.Getter; import lombok.NoArgsConstructor; @Getter -@NoArgsConstructor +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) public class CategoryAddAdminReqDto { + @NotBlank(message = "카테고리 이름은 비어 있을 수 없습니다.") + @Size(min = 1, max = 10, message = "카테고리 이름은 1자 이상 10자 이하이어야 합니다.") private String categoryName; + + public CategoryAddAdminReqDto(String category) { + this.categoryName = category; + } } diff --git a/gg-pingpong-api/src/main/java/gg/party/api/admin/category/service/CategoryAdminService.java b/gg-pingpong-api/src/main/java/gg/party/api/admin/category/service/CategoryAdminService.java index 48acb1608..2718508ea 100644 --- a/gg-pingpong-api/src/main/java/gg/party/api/admin/category/service/CategoryAdminService.java +++ b/gg-pingpong-api/src/main/java/gg/party/api/admin/category/service/CategoryAdminService.java @@ -21,7 +21,7 @@ public class CategoryAdminService { /** * 카테고리 추가 * @param reqDto 추가할 카테고리 이름 - * @exception CategoryDuplicateException 중복된 카테고리 + * @exception CategoryDuplicateException 중복된 카테고리 - 409 */ @Transactional public void addCategory(CategoryAddAdminReqDto reqDto) { @@ -35,20 +35,20 @@ public void addCategory(CategoryAddAdminReqDto reqDto) { /** * 카테고리 삭제 - * 삭제 시 기존에 room에 연결되어 있던 카테고리는 default(1) 로 변경 + * 삭제 시 기존에 room에 연결되어 있던 카테고리는 etc 로 변경 * @param categoryId 삭제할 카테고리 id - * @exception CategoryNotFoundException 유효하지 않은 카테고리 - * @exception DefaultCategoryNeedException default 카테고리 존재 x 또는 default 카테고리 삭제 요청 + * @exception CategoryNotFoundException 유효하지 않은 카테고리 - 404 + * @exception DefaultCategoryNeedException default 카테고리 존재 x 또는 default 카테고리 삭제 요청 - 400 */ @Transactional public void removeCategory(Long categoryId) { Category category = categoryAdminRepository.findById(categoryId) .orElseThrow(CategoryNotFoundException::new); - Category defaultCategory = categoryAdminRepository.findById(DefaultCategoryNeedException.DEFAULT_CATEGORY_ID) - .orElseThrow(DefaultCategoryNeedException::new); + Category defaultCategory = categoryAdminRepository.findByName( + DefaultCategoryNeedException.DEFAULT_CATEGORY_NAME); - if (category.equals(defaultCategory)) { + if (defaultCategory == null || category.equals(defaultCategory)) { throw new DefaultCategoryNeedException(); } diff --git a/gg-pingpong-api/src/test/java/gg/party/api/admin/category/CategoryAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/party/api/admin/category/CategoryAdminControllerTest.java new file mode 100644 index 000000000..e6f2af8b6 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/party/api/admin/category/CategoryAdminControllerTest.java @@ -0,0 +1,163 @@ +package gg.party.api.admin.category; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.auth.utils.AuthTokenProvider; +import gg.data.party.Category; +import gg.data.party.Room; +import gg.data.party.type.RoomType; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.party.api.admin.category.controller.request.CategoryAddAdminReqDto; +import gg.repo.party.CategoryRepository; +import gg.repo.party.RoomRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +@RequiredArgsConstructor +@Slf4j +public class CategoryAdminControllerTest { + @Autowired + MockMvc mockMvc; + @Autowired + TestDataUtils testDataUtils; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + RoomRepository roomRepository; + @Autowired + CategoryRepository categoryRepository; + User userTester; + String userAccessToken; + Category defaultCategory; + Category testCategory; + Room testRoom; + + @Nested + @DisplayName("카테고리 추가 테스트") + class CategoryAdd { + @BeforeEach + void beforeEach() { + userTester = testDataUtils.createNewUser("adminTester", "adminTester", + RacketType.DUAL, SnsType.SLACK, RoleType.ADMIN); + userAccessToken = tokenProvider.createToken(userTester.getId()); + defaultCategory = testDataUtils.createNewCategory("etc"); + } + + @Test + @DisplayName("카테고리 추가 성공 201") + public void success() throws Exception { + //given + String url = "/party/admin/categories"; + CategoryAddAdminReqDto categoryAddAdminReqDto = new CategoryAddAdminReqDto("category"); + String jsonRequest = objectMapper.writeValueAsString(categoryAddAdminReqDto); + //when + String contentAsString = mockMvc.perform(post(url) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonRequest) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + userAccessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + //then + assertThat(categoryRepository.findAll()).size().isEqualTo(2); + } + + @Test + @DisplayName("이미 존재하는 카테고리로 인한 에러 409") + public void fail() throws Exception { + //given + String url = "/party/admin/categories"; + testDataUtils.createNewCategory("category"); + CategoryAddAdminReqDto categoryAddAdminReqDto = new CategoryAddAdminReqDto("category"); + String jsonRequest = objectMapper.writeValueAsString(categoryAddAdminReqDto); + //when & then + String contentAsString = mockMvc.perform(post(url) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonRequest) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + userAccessToken)) + .andExpect(status().isConflict()).toString(); + } + } + + @Nested + @DisplayName("카테고리 삭제 테스트") + class CategoryRemove { + @BeforeEach + void beforeEach() { + userTester = testDataUtils.createNewUser("adminTester", "adminTester", + RacketType.DUAL, SnsType.SLACK, RoleType.ADMIN); + userAccessToken = tokenProvider.createToken(userTester.getId()); + testCategory = testDataUtils.createNewCategory("test"); + testRoom = testDataUtils.createNewRoom(userTester, userTester, testCategory, 1, 1, + 3, 2, 180, RoomType.OPEN); + defaultCategory = testDataUtils.createNewCategory("etc"); + } + + @Test + @DisplayName("카테고리 삭제 성공 204") + public void success() throws Exception { + //given + String categoryID = testCategory.getId().toString(); + String url = "/party/admin/categories/" + categoryID; + //when + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + userAccessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + //then + assertThat(categoryRepository.findAll()).size().isEqualTo(1); + assertThat(roomRepository.findById(testRoom.getId()).get().getCategory().getName()).isEqualTo("etc"); + } + + @Test + @DisplayName("존재하지 않는 카테고리로 인한 에러 404") + public void noCategoryFail() throws Exception { + //given + String categoryID = "10"; + String url = "/party/admin/categories/" + categoryID; + //when & then + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + userAccessToken)) + .andExpect(status().isNotFound()).toString(); + } + + @Test + @DisplayName("default 카테고리 삭제 요청에 대한 에러 400") + public void fail() throws Exception { + //given + String categoryID = defaultCategory.getId().toString(); + String url = "/party/admin/categories/" + categoryID; + //when & then + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + userAccessToken)) + .andExpect(status().isBadRequest()).toString(); + } + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java b/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java index 0db612d88..c896b7703 100644 --- a/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java +++ b/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java @@ -179,11 +179,11 @@ public enum ErrorCode { ROOM_SAME_STATUS(400, "PT204", "이미 처리된 방 입니다."), ROOM_NOT_OPEN(400, "PT205", "모집중인 방이 아닙니다."), ROOM_NOT_PARTICIPANT(400, "PT206", "참여하지 않은 방 입니다."), - CATEGORY_DUPLICATE(400, "PT207", "중복된 카테고리 입니다."), - ROOM_MIN_MAX_PEOPLE(400, "PT208", "최소인원이 최대인원보다 큽니다."), + ROOM_MIN_MAX_PEOPLE(400, "PT207", "최소인원이 최대인원보다 큽니다."), USER_ALREADY_IN_ROOM(409, "PT301", "이미 참여한 방 입니다."), ALREADY_REPORTED(409, "PT302", "이미 신고한 요청입니다."), SELF_REPORT(409, "PT303", "자신을 신고할 수 없습니다."), + CATEGORY_DUPLICATE(409, "PT304", "중복된 카테고리 입니다."), ON_PENALTY(403, "PT501", "패널티 상태입니다."); private final int status; diff --git a/gg-utils/src/main/java/gg/utils/exception/party/DefaultCategoryNeedException.java b/gg-utils/src/main/java/gg/utils/exception/party/DefaultCategoryNeedException.java index 642528de4..d0b193f17 100644 --- a/gg-utils/src/main/java/gg/utils/exception/party/DefaultCategoryNeedException.java +++ b/gg-utils/src/main/java/gg/utils/exception/party/DefaultCategoryNeedException.java @@ -1,10 +1,10 @@ package gg.utils.exception.party; import gg.utils.exception.ErrorCode; -import gg.utils.exception.custom.NotExistException; +import gg.utils.exception.custom.BusinessException; -public class DefaultCategoryNeedException extends NotExistException { - public static final Long DEFAULT_CATEGORY_ID = 1L; +public class DefaultCategoryNeedException extends BusinessException { + public static final String DEFAULT_CATEGORY_NAME = "etc"; public DefaultCategoryNeedException() { super(ErrorCode.DEFAULT_CATEGORY_NEED.getMessage(), ErrorCode.DEFAULT_CATEGORY_NEED);