diff --git a/src/main/java/com/kustacks/kuring/common/exception/code/ErrorCode.java b/src/main/java/com/kustacks/kuring/common/exception/code/ErrorCode.java index 99895f77..d7004411 100644 --- a/src/main/java/com/kustacks/kuring/common/exception/code/ErrorCode.java +++ b/src/main/java/com/kustacks/kuring/common/exception/code/ErrorCode.java @@ -62,7 +62,7 @@ public enum ErrorCode { LIB_BAD_RESPONSE("도서관 공지 요청에 대한 응답이 비정상적입니다."), LIB_CANNOT_PARSE_JSON("도서관 공지를 POJO로 변환할 수 없습니다."), - CAT_NOT_EXIST_CATEGORY("서버에서 지원하지 않는 카테고리입니다."), + CAT_NOT_EXIST_CATEGORY(HttpStatus.BAD_REQUEST, "서버에서 지원하지 않는 카테고리입니다."), // STAFF_SCRAPER_TAG_NOT_EXIST("Jsoup - 찾고자 하는 태그가 존재하지 않습니다."), STAFF_SCRAPER_EXCEED_RETRY_LIMIT("교직원 업데이트 재시도 횟수를 초과했습니다."), diff --git a/src/main/java/com/kustacks/kuring/common/interceptor/AuthInterceptor.java b/src/main/java/com/kustacks/kuring/common/interceptor/AuthInterceptor.java deleted file mode 100644 index ca8ef358..00000000 --- a/src/main/java/com/kustacks/kuring/common/interceptor/AuthInterceptor.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.kustacks.kuring.common.interceptor; - -import com.kustacks.kuring.common.annotation.CheckSession; -import lombok.extern.slf4j.Slf4j; -import org.springframework.lang.Nullable; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.IOException; - -@Slf4j -public class AuthInterceptor implements HandlerInterceptor { - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { - - if(!(handler instanceof HandlerMethod)) { - // return true이면 Controller에 있는 메서드가 아니므로, 그대로 컨트롤러로 진행 - return true; - } - - HandlerMethod handlerMethod = (HandlerMethod) handler; - - CheckSession checkSession = handlerMethod.getMethodAnnotation(CheckSession.class); - if(checkSession == null) { - return true; - } - - HttpSession session = request.getSession(false); - if(session != null) { - log.info("sessionId = {}", session.getId()); - log.info("lastAccessedTime = {}", session.getLastAccessedTime()); - } - - boolean isSessionFromCookie = session != null; - boolean isSessionRequired = checkSession.isSessionRequired(); - - // 세션이 있어야 하는 경우 - 없으면 로그인 페이지로 이동 - if(isSessionRequired) { - log.info("isSessionFromCookie = {}", isSessionFromCookie); - if(isSessionFromCookie) { - return true; - } else { - response.sendRedirect("/admin/login"); - return false; - } - } - // 세션이 없어야 하는 경우(로그인 페이지) - 있으면 이전 페이지로 이동 - else { - if(isSessionFromCookie) { - response.setStatus(401); - response.sendRedirect("/admin/dashboard"); - return false; - } else { - return true; - } - } - } - - @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, - @Nullable ModelAndView modelAndView) throws Exception { - } - - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, - @Nullable Exception ex) throws Exception { - } -} diff --git a/src/main/java/com/kustacks/kuring/config/WebMvcConfig.java b/src/main/java/com/kustacks/kuring/config/WebMvcConfig.java deleted file mode 100644 index a73f43f9..00000000 --- a/src/main/java/com/kustacks/kuring/config/WebMvcConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.kustacks.kuring.config; - -import com.kustacks.kuring.common.interceptor.AuthInterceptor; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@Configuration -public class WebMvcConfig implements WebMvcConfigurer { - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(new AuthInterceptor()) - .addPathPatterns("/admin/**") // 해당 경로에 접근하기 전에 인터셉터가 가로챈다. - .excludePathPatterns("/admin/api/**") // 해당 경로는 인터셉터가 가로채지 않는다. - .excludePathPatterns("/api/**"); - } -} diff --git a/src/main/java/com/kustacks/kuring/notice/business/NoticeService.java b/src/main/java/com/kustacks/kuring/notice/business/NoticeService.java index 794f03ec..10bbcf0b 100644 --- a/src/main/java/com/kustacks/kuring/notice/business/NoticeService.java +++ b/src/main/java/com/kustacks/kuring/notice/business/NoticeService.java @@ -26,7 +26,7 @@ public class NoticeService { private final NoticeRepository noticeRepository; private final DepartmentNoticeRepository departmentNoticeRepository; - private final CategoryName[] categoryNames; + private final CategoryName[] supportedCategoryNameList; private final DepartmentName[] supportedDepartmentNameList; private final String SPACE_REGEX = "[\\s+]"; @@ -39,7 +39,7 @@ public class NoticeService { public NoticeService(NoticeRepository noticeRepository, DepartmentNoticeRepository departmentNoticeRepository) { this.noticeRepository = noticeRepository; this.departmentNoticeRepository = departmentNoticeRepository; - this.categoryNames = CategoryName.values(); + this.supportedCategoryNameList = CategoryName.values(); this.supportedDepartmentNameList = DepartmentName.values(); } @@ -102,7 +102,7 @@ private List noticeCategoryNameConvertEnglish(String[] splitedKeywords) } private String convertEnglish(String keyword) { - for (CategoryName categoryName : categoryNames) { + for (CategoryName categoryName : supportedCategoryNameList) { if (categoryName.isSameKorName(keyword)) { return categoryName.getName(); } @@ -111,7 +111,7 @@ private String convertEnglish(String keyword) { } private String convertShortNameIntoLongName(String typeShortName) { - return Arrays.stream(categoryNames) + return Arrays.stream(supportedCategoryNameList) .filter(categoryName -> categoryName.isSameShortName(typeShortName)) .findFirst() .map(CategoryName::getName) diff --git a/src/main/java/com/kustacks/kuring/notice/presentation/NoticeControllerV1.java b/src/main/java/com/kustacks/kuring/notice/presentation/NoticeControllerV1.java deleted file mode 100644 index 9854bfaf..00000000 --- a/src/main/java/com/kustacks/kuring/notice/presentation/NoticeControllerV1.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.kustacks.kuring.notice.presentation; - -import com.kustacks.kuring.notice.presentation.dto.CategoryListResponse; -import com.kustacks.kuring.notice.presentation.dto.SubscribeCategoriesV1Request; -import com.kustacks.kuring.notice.presentation.dto.SubscribeCategoriesResponse; -import com.kustacks.kuring.notice.domain.CategoryName; -import com.kustacks.kuring.message.firebase.FirebaseService; -import com.kustacks.kuring.notice.business.NoticeService; -import com.kustacks.kuring.notice.common.dto.NoticeListResponse; -import com.kustacks.kuring.user.business.UserService; -import com.kustacks.kuring.user.facade.UserCommandFacade; -import lombok.RequiredArgsConstructor; -import org.springframework.http.MediaType; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Validated -@RestController -@RequiredArgsConstructor -@RequestMapping(value = "/api/v1/notice", produces = MediaType.APPLICATION_JSON_VALUE) -public class NoticeControllerV1 { - - private final NoticeService noticeService; - private final FirebaseService firebaseService; - private final UserService userService; - private final UserCommandFacade userCommandFacade; - - @GetMapping - public NoticeListResponse getNotices( - @RequestParam(name = "type") String type, - @RequestParam(name = "offset") @Min(0) int offset, - @RequestParam(name = "max") @Min(1) @Max(30) int max) { - return noticeService.getNotices(type, offset, max); - } - - @GetMapping("/categories") - public CategoryListResponse getSupportedCategories() { - List categoryNames = Stream.of(CategoryName.values()) - .map(CategoryName::getName) - .collect(Collectors.toList()); - - return new CategoryListResponse(categoryNames); - } - - @GetMapping("/subscribe") - public CategoryListResponse getUserCategories(@RequestParam("id") @NotBlank String token) { - firebaseService.validationToken(token); - List categoryNames = userService.lookUpUserCategories(token) - .stream() - .map(CategoryName::getName) - .collect(Collectors.toList()); - - return new CategoryListResponse(categoryNames); - } - - @PostMapping(value = "/subscribe", consumes = MediaType.APPLICATION_JSON_VALUE) - public SubscribeCategoriesResponse editUserSubscribeCategories(@Valid @RequestBody SubscribeCategoriesV1Request request) { - userCommandFacade.editSubscribeCategories(request.getId(), request.getCategories()); - return new SubscribeCategoriesResponse(); - } -} diff --git a/src/main/java/com/kustacks/kuring/notice/presentation/dto/CategoryListResponse.java b/src/main/java/com/kustacks/kuring/notice/presentation/dto/CategoryListResponse.java deleted file mode 100644 index b287eb48..00000000 --- a/src/main/java/com/kustacks/kuring/notice/presentation/dto/CategoryListResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.kustacks.kuring.notice.presentation.dto; - -import com.kustacks.kuring.common.dto.ResponseDto; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class CategoryListResponse extends ResponseDto { - - private List categories; - - public CategoryListResponse(List categories) { - super(true, "성공", 200); - this.categories = categories; - } -} diff --git a/src/main/java/com/kustacks/kuring/notice/presentation/dto/SubscribeCategoriesResponse.java b/src/main/java/com/kustacks/kuring/notice/presentation/dto/SubscribeCategoriesResponse.java deleted file mode 100644 index f396aa23..00000000 --- a/src/main/java/com/kustacks/kuring/notice/presentation/dto/SubscribeCategoriesResponse.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.kustacks.kuring.notice.presentation.dto; - -import com.kustacks.kuring.common.dto.ResponseDto; -import lombok.Getter; - -@Getter -public class SubscribeCategoriesResponse extends ResponseDto { - - public SubscribeCategoriesResponse() { - super(true, "성공", 201); - } -} diff --git a/src/main/java/com/kustacks/kuring/notice/presentation/dto/SubscribeCategoriesV1Request.java b/src/main/java/com/kustacks/kuring/notice/presentation/dto/SubscribeCategoriesV1Request.java deleted file mode 100644 index 1facff40..00000000 --- a/src/main/java/com/kustacks/kuring/notice/presentation/dto/SubscribeCategoriesV1Request.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.kustacks.kuring.notice.presentation.dto; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.util.List; - - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class SubscribeCategoriesV1Request { - - @NotBlank - private String id; - - @NotNull - private List categories; -} diff --git a/src/main/java/com/kustacks/kuring/user/common/SubscribeCategoriesRequest.java b/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCategoriesRequest.java similarity index 88% rename from src/main/java/com/kustacks/kuring/user/common/SubscribeCategoriesRequest.java rename to src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCategoriesRequest.java index d5301877..ec25e72a 100644 --- a/src/main/java/com/kustacks/kuring/user/common/SubscribeCategoriesRequest.java +++ b/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCategoriesRequest.java @@ -1,4 +1,4 @@ -package com.kustacks.kuring.user.common; +package com.kustacks.kuring.user.common.dto; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/kustacks/kuring/user/common/SubscribeDepartmentsRequest.java b/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeDepartmentsRequest.java similarity index 88% rename from src/main/java/com/kustacks/kuring/user/common/SubscribeDepartmentsRequest.java rename to src/main/java/com/kustacks/kuring/user/common/dto/SubscribeDepartmentsRequest.java index f861da02..964c4114 100644 --- a/src/main/java/com/kustacks/kuring/user/common/SubscribeDepartmentsRequest.java +++ b/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeDepartmentsRequest.java @@ -1,4 +1,4 @@ -package com.kustacks.kuring.user.common; +package com.kustacks.kuring.user.common.dto; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/kustacks/kuring/user/presentation/UserCommandApiV2.java b/src/main/java/com/kustacks/kuring/user/presentation/UserCommandApiV2.java index f54fe6a6..01144206 100644 --- a/src/main/java/com/kustacks/kuring/user/presentation/UserCommandApiV2.java +++ b/src/main/java/com/kustacks/kuring/user/presentation/UserCommandApiV2.java @@ -1,8 +1,8 @@ package com.kustacks.kuring.user.presentation; import com.kustacks.kuring.common.dto.BaseResponse; -import com.kustacks.kuring.user.common.SubscribeCategoriesRequest; -import com.kustacks.kuring.user.common.SubscribeDepartmentsRequest; +import com.kustacks.kuring.user.common.dto.SubscribeCategoriesRequest; +import com.kustacks.kuring.user.common.dto.SubscribeDepartmentsRequest; import com.kustacks.kuring.user.common.dto.SaveFeedbackRequest; import com.kustacks.kuring.user.facade.UserCommandFacade; import lombok.RequiredArgsConstructor; diff --git a/src/test/java/com/kustacks/kuring/acceptance/AdminAcceptanceTest.java b/src/test/java/com/kustacks/kuring/acceptance/AdminAcceptanceTest.java index 87287d10..c0b9bd9f 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/AdminAcceptanceTest.java +++ b/src/test/java/com/kustacks/kuring/acceptance/AdminAcceptanceTest.java @@ -30,7 +30,7 @@ class AdminAcceptanceTest extends AcceptanceTest { * when : 어드민이 피드백 조회시 * then : 성공적으로 조회된다 */ - @DisplayName("사용자 피드백 조회") + @DisplayName("[v2] 사용자 피드백 조회") @Test void role_root_admin_search_feedbacks() { // given @@ -48,7 +48,7 @@ void role_root_admin_search_feedbacks() { * when : 테스트 공지를 발송하면 * then : 성공적으로 발송된다. */ - @DisplayName("테스트 공지 발송") + @DisplayName("[v2] 테스트 공지 발송") @Test void role_root_admin_create_test_notification() { // given @@ -80,7 +80,7 @@ void role_root_admin_create_test_notification() { * When : ROLE_ROOT의 API에 접근시 * Then : 응답받을 수 있다 */ - @DisplayName("Root -> Root API 접근 테스트") + @DisplayName("[v2] Root -> Root API 접근 테스트") @Test void role_root_admin_call_root_api_test() { // given @@ -109,7 +109,7 @@ void role_root_admin_call_root_api_test() { * When : ROLE_CLIENT의 API에 접근시 * Then : 응답받을 수 있다 */ - @DisplayName("Root -> Client API 접근 테스트") + @DisplayName("[v2] Root -> Client API 접근 테스트") @Test void role_root_admin_call_client_api_test() { // given @@ -138,7 +138,7 @@ void role_root_admin_call_client_api_test() { * When : ROLE_CLIENT의 API에 접근시 * Then : 응답받을 수 있다 */ - @DisplayName("Client -> Client API 접근 테스트") + @DisplayName("[v2] Client -> Client API 접근 테스트") @Test void role_client_admin_call_client_api_test() { // given @@ -167,7 +167,7 @@ void role_client_admin_call_client_api_test() { * When : ROLE_ROOT의 API에 접근시 * Then : 응답받을 수 없다 */ - @DisplayName("Client -> Root API 접근 테스트") + @DisplayName("[v2] Client -> Root API 접근 테스트") @Test void role_client_admin_call_root_api_test() { // given diff --git a/src/test/java/com/kustacks/kuring/acceptance/AuthAcceptanceTest.java b/src/test/java/com/kustacks/kuring/acceptance/AuthAcceptanceTest.java index 64c2c2a0..f98dfd67 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/AuthAcceptanceTest.java +++ b/src/test/java/com/kustacks/kuring/acceptance/AuthAcceptanceTest.java @@ -11,7 +11,7 @@ @DisplayName("인수 : 인증") class AuthAcceptanceTest extends AcceptanceTest { - @DisplayName("Bearer Auth login") + @DisplayName("[v2] Bearer Auth login") @Test void bearer_auth_login_success() { // given @@ -22,7 +22,7 @@ void bearer_auth_login_success() { } - @DisplayName("존재하지 않는 id, password 로그인을 시도한다") + @DisplayName("[v2] 존재하지 않는 id, password 로그인을 시도한다") @Test void bearer_auth_login_fail() { // given diff --git a/src/test/java/com/kustacks/kuring/acceptance/CategoryAcceptanceTest.java b/src/test/java/com/kustacks/kuring/acceptance/CategoryAcceptanceTest.java index 2ec8bfa5..c0581daa 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/CategoryAcceptanceTest.java +++ b/src/test/java/com/kustacks/kuring/acceptance/CategoryAcceptanceTest.java @@ -1,9 +1,9 @@ package com.kustacks.kuring.acceptance; import com.google.firebase.messaging.FirebaseMessagingException; -import com.kustacks.kuring.message.firebase.exception.FirebaseInvalidTokenException; -import com.kustacks.kuring.notice.presentation.dto.SubscribeCategoriesV1Request; import com.kustacks.kuring.message.firebase.FirebaseService; +import com.kustacks.kuring.message.firebase.exception.FirebaseInvalidTokenException; +import com.kustacks.kuring.user.common.dto.SubscribeCategoriesRequest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -11,14 +11,7 @@ import java.util.List; -import static com.kustacks.kuring.acceptance.CategoryStep.사용자_카테고리_목록_조회_요청; -import static com.kustacks.kuring.acceptance.CategoryStep.카테고리_구독_요청; -import static com.kustacks.kuring.acceptance.CategoryStep.카테고리_구독_요청_응답_확인; -import static com.kustacks.kuring.acceptance.CategoryStep.카테고리_수정_요청; -import static com.kustacks.kuring.acceptance.CategoryStep.카테고리_조회_요청; -import static com.kustacks.kuring.acceptance.CategoryStep.카테고리_조회_요청_응답_확인; -import static com.kustacks.kuring.acceptance.CategoryStep.학과_조회_요청; -import static com.kustacks.kuring.acceptance.CategoryStep.학과_조회_응답_확인; +import static com.kustacks.kuring.acceptance.CategoryStep.*; import static com.kustacks.kuring.acceptance.CommonStep.실패_응답_확인; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doNothing; @@ -35,14 +28,15 @@ public class CategoryAcceptanceTest extends AcceptanceTest { * When : 첫 로딩화면 로딩시 * Then : 상단에 카테고리 목록을 보여준다 */ - @DisplayName("서버가 지원하는 카테고리 목록을 조회한다") + @DisplayName("[v2] 서버가 지원하는 카테고리 목록을 조회한다") @Test void look_up_category_list() { // when - var 카테고리_조회_요청_응답 = 카테고리_조회_요청(); + var 카테고리_조회_요청_응답 = 지원하는_카테고리_조회_요청(); // then - 카테고리_조회_요청_응답_확인(카테고리_조회_요청_응답, "student", "bachelor", "employment"); + 카테고리_조회_요청_응답_확인(카테고리_조회_요청_응답, "bachelor", "scholarship", "employment", "national", + "student", "industry_university", "normal", "library", "department"); } @@ -66,14 +60,14 @@ void look_up_department_list() { * When : 사용자가 카테고리 구독 요청을 요청한다 * Then : 성공 유무를 반환한다 */ - @DisplayName("사용자가 카테고리를 구독한다") + @DisplayName("[v2] 사용자가 카테고리를 구독한다") @Test void user_subscribe_category() throws FirebaseMessagingException { // given doNothing().when(firebaseService).subscribe(anyString(), anyString()); // when - var 카테고리_구독_요청_응답 = 카테고리_구독_요청(new SubscribeCategoriesV1Request(USER_FCM_TOKEN, List.of("student", "employment"))); + var 카테고리_구독_요청_응답 = 카테고리_구독_요청(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("student", "employment"))); // then 카테고리_구독_요청_응답_확인(카테고리_구독_요청_응답); @@ -84,7 +78,7 @@ void user_subscribe_category() throws FirebaseMessagingException { * When : 사용자가 비정상 토큰과 함께 카테고리 구독을 요청한다 * Then : 실패코드를 반환한다 */ - @DisplayName("사용자가 잘못된 토큰과 함께 카테고리 구독시 실패한다") + @DisplayName("[v2] 사용자가 잘못된 토큰과 함께 카테고리 구독시 실패한다") @Test void user_subscribe_category_with_invalid_token() { // given @@ -92,7 +86,7 @@ void user_subscribe_category_with_invalid_token() { doThrow(new FirebaseInvalidTokenException()).when(firebaseService).validationToken(anyString()); // when - var response = 카테고리_구독_요청(new SubscribeCategoriesV1Request(INVALID_USER_FCM_TOKEN, List.of("student", "employment"))); + var response = 카테고리_구독_요청(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("student", "employment"))); // then 실패_응답_확인(response, HttpStatus.UNAUTHORIZED); @@ -103,15 +97,15 @@ void user_subscribe_category_with_invalid_token() { * When : 사용자가 구독한 카테고리 목록을 요청한다 * Then : 구독한 카테고리 목록을 반환한다 */ - @DisplayName("사용자가 구독한 카테고리 목록을 조회한다") + @DisplayName("[v2] 사용자가 구독한 카테고리 목록을 조회한다") @Test void look_up_user_subscribe_category() { // given doNothing().when(firebaseService).validationToken(anyString()); - 카테고리_구독_요청(new SubscribeCategoriesV1Request(USER_FCM_TOKEN, List.of("student", "employment"))); + 카테고리_구독_요청(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("student", "employment"))); // when - var 조회_응답 = 사용자_카테고리_목록_조회_요청(USER_FCM_TOKEN); + var 조회_응답 = 사용자가_구독한_카테고리_목록_조회_요청(USER_FCM_TOKEN); // then 카테고리_조회_요청_응답_확인(조회_응답, "student", "employment"); @@ -124,7 +118,7 @@ void look_up_user_subscribe_category() { * When : 사용자가 구독한 카테고리 목록을 요청한다 * Then : 구독한 카테고리 목록을 반환한다 */ - @DisplayName("사용자가 구독한 카테고리 목록을 수정한다") + @DisplayName("[v2] 사용자가 구독한 카테고리 목록을 수정한다") @Test void edit_user_subscribe_category() throws FirebaseMessagingException { // given @@ -132,42 +126,42 @@ void edit_user_subscribe_category() throws FirebaseMessagingException { doNothing().when(firebaseService).subscribe(anyString(), anyString()); doNothing().when(firebaseService).unsubscribe(anyString(), anyString()); - 카테고리_구독_요청(new SubscribeCategoriesV1Request(USER_FCM_TOKEN, List.of("student", "employment"))); + 카테고리_구독_요청(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("student", "employment"))); // when - var 카테고리_구독_요청_응답 = 카테고리_수정_요청(new SubscribeCategoriesV1Request(USER_FCM_TOKEN, List.of("student", "library"))); + var 카테고리_구독_요청_응답 = 카테고리_수정_요청(new SubscribeCategoriesRequest(List.of("student", "library"))); // then 카테고리_구독_요청_응답_확인(카테고리_구독_요청_응답); // when - var 조회_응답 = 사용자_카테고리_목록_조회_요청(USER_FCM_TOKEN); + var 조회_응답 = 사용자가_구독한_카테고리_목록_조회_요청(USER_FCM_TOKEN); // then 카테고리_조회_요청_응답_확인(조회_응답, "student", "library"); } - @DisplayName("요청 JSON body 필드 누락시 예외 발생") + @DisplayName("[v2] 요청 JSON body 필드 누락시 예외 발생") @Test void json_body_miss() throws FirebaseMessagingException { // given doNothing().when(firebaseService).subscribe(anyString(), anyString()); // when - var 카테고리_구독_요청_응답 = 카테고리_구독_요청(new SubscribeCategoriesV1Request(null, List.of("student", "employment"))); + var 카테고리_구독_요청_응답 = 카테고리_구독_요청(USER_FCM_TOKEN, new SubscribeCategoriesRequest(null)); // then 실패_응답_확인(카테고리_구독_요청_응답, HttpStatus.BAD_REQUEST); } - @DisplayName("잘못된 카테고리 구독 요청시 예외 발생") + @DisplayName("[v2] 잘못된 카테고리 구독 요청시 예외 발생") @Test void user_subscribe_invalid_category() throws FirebaseMessagingException { // given doNothing().when(firebaseService).subscribe(anyString(), anyString()); // when - var 카테고리_구독_요청_응답 = 카테고리_구독_요청(new SubscribeCategoriesV1Request(null, List.of("invalid-category"))); + var 카테고리_구독_요청_응답 = 카테고리_구독_요청(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("invalid-category"))); // then 실패_응답_확인(카테고리_구독_요청_응답, HttpStatus.BAD_REQUEST); diff --git a/src/test/java/com/kustacks/kuring/acceptance/CategoryStep.java b/src/test/java/com/kustacks/kuring/acceptance/CategoryStep.java index eb5a56a2..4847112f 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/CategoryStep.java +++ b/src/test/java/com/kustacks/kuring/acceptance/CategoryStep.java @@ -1,81 +1,68 @@ package com.kustacks.kuring.acceptance; -import com.kustacks.kuring.notice.presentation.dto.SubscribeCategoriesV1Request; +import com.kustacks.kuring.user.common.dto.SubscribeCategoriesRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import static com.kustacks.kuring.acceptance.AcceptanceTest.USER_FCM_TOKEN; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; public class CategoryStep { - public static void 카테고리_조회_요청_응답_확인(ExtractableResponse response, String... categories) { - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), - () -> assertThat(response.jsonPath().getBoolean("isSuccess")).isTrue(), - () -> assertThat(response.jsonPath().getString("resultMsg")).isEqualTo("성공"), - () -> assertThat(response.jsonPath().getInt("resultCode")).isEqualTo(200), - () -> assertThat(response.jsonPath().getList("categories")).contains(categories) - ); - } - - public static void 카테고리_조회_요청_응답_확인_v2(ExtractableResponse response, String... categories) { - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), - () -> assertThat(response.jsonPath().getInt("code")).isEqualTo(200), - () -> assertThat(response.jsonPath().getString("message")).isEqualTo("지원하는 학교 공지 카테고리 조회에 성공하였습니다"), - () -> assertThat(response.jsonPath().getList("data.name")).contains(categories) - ); - } - - public static ExtractableResponse 카테고리_조회_요청() { + public static ExtractableResponse 지원하는_카테고리_조회_요청() { return RestAssured .given().log().all() - .when().get("/api/v1/notice/categories") + .when().get("/api/v2/notices/categories") .then().log().all() .extract(); } - public static ExtractableResponse 카테고리_조회_요청_v2() { + public static ExtractableResponse 사용자가_구독한_카테고리_목록_조회_요청(String userFcmToken) { return RestAssured .given().log().all() - .when().get("/api/v2/notices/categories") + .header("User-Token", userFcmToken) + .accept(MediaType.APPLICATION_JSON_VALUE) + .when().get("/api/v2/users/subscriptions/categories") .then().log().all() .extract(); } - public static void 카테고리_구독_요청_응답_확인(ExtractableResponse response) { + public static void 카테고리_조회_요청_응답_확인(ExtractableResponse response, String... categories) { assertAll( - () -> assertThat(response.jsonPath().getBoolean("isSuccess")).isTrue(), - () -> assertThat(response.jsonPath().getString("resultMsg")).isEqualTo("성공"), - () -> assertThat(response.jsonPath().getInt("resultCode")).isEqualTo(201) + () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), + () -> assertThat(response.jsonPath().getInt("code")).isEqualTo(200), + () -> assertThat(response.jsonPath().getList("data.name")).contains(categories) ); } - public static ExtractableResponse 카테고리_구독_요청(SubscribeCategoriesV1Request reqeust) { + public static ExtractableResponse 카테고리_구독_요청(String userFcmToken, SubscribeCategoriesRequest reqeust) { return RestAssured .given().log().all() + .header("User-Token", userFcmToken) .contentType(MediaType.APPLICATION_JSON_VALUE) .accept(MediaType.APPLICATION_JSON_VALUE) .body(reqeust) - .when().post("/api/v1/notice/subscribe") + .when().post("/api/v2/users/subscriptions/categories") .then().log().all() .extract(); } - public static ExtractableResponse 카테고리_수정_요청(SubscribeCategoriesV1Request request) { - return 카테고리_구독_요청(request); + public static void 카테고리_구독_요청_응답_확인(ExtractableResponse response) { + assertAll( + () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), + () -> assertThat(response.jsonPath().getInt("code")).isEqualTo(200), + () -> assertThat(response.jsonPath().getString("message")).isEqualTo("사용자의 학교 공지 카테고리 구독에 성공하였습니다") + ); } - public static ExtractableResponse 사용자_카테고리_목록_조회_요청(String id) { + public static ExtractableResponse 학과_조회_요청() { return RestAssured .given().log().all() - .accept(MediaType.APPLICATION_JSON_VALUE) - .pathParam("id", id) - .when().get("/api/v1/notice/subscribe?id={id}") + .when().get("/api/v2/notices/departments") .then().log().all() .extract(); } @@ -89,11 +76,7 @@ public class CategoryStep { ); } - public static ExtractableResponse 학과_조회_요청() { - return RestAssured - .given().log().all() - .when().get("/api/v2/notices/departments") - .then().log().all() - .extract(); + public static ExtractableResponse 카테고리_수정_요청(SubscribeCategoriesRequest request) { + return 카테고리_구독_요청(USER_FCM_TOKEN, request); } } diff --git a/src/test/java/com/kustacks/kuring/acceptance/FeedbackAcceptanceTest.java b/src/test/java/com/kustacks/kuring/acceptance/FeedbackAcceptanceTest.java index b412b55b..22f4ef9f 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/FeedbackAcceptanceTest.java +++ b/src/test/java/com/kustacks/kuring/acceptance/FeedbackAcceptanceTest.java @@ -24,7 +24,7 @@ public class FeedbackAcceptanceTest extends AcceptanceTest { * When : 피드백 전송을 누르면 * Then : 성공적으로 서버에 저장된다 */ - @DisplayName("사용자의 피드백을 저장한다") + @DisplayName("[v2] 사용자의 피드백을 저장한다") @Test public void request_feedback() throws FirebaseMessagingException { // given @@ -37,7 +37,7 @@ public void request_feedback() throws FirebaseMessagingException { 피드백_요청_응답_확인(피드백_요청_응답); } - @DisplayName("잘못된 길이의 피드백을 요청시 예외가 발생한다") + @DisplayName("[v2] 잘못된 길이의 피드백을 요청시 예외가 발생한다") @Test public void request_invalid_length_feedback() throws FirebaseMessagingException { // given diff --git a/src/test/java/com/kustacks/kuring/acceptance/NoticeAcceptanceTest.java b/src/test/java/com/kustacks/kuring/acceptance/NoticeAcceptanceTest.java index 13fe83d5..491f55bf 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/NoticeAcceptanceTest.java +++ b/src/test/java/com/kustacks/kuring/acceptance/NoticeAcceptanceTest.java @@ -4,17 +4,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static com.kustacks.kuring.acceptance.CategoryStep.카테고리_조회_요청_v2; -import static com.kustacks.kuring.acceptance.CategoryStep.카테고리_조회_요청_응답_확인_v2; -import static com.kustacks.kuring.acceptance.NoticeStep.공지_조회_요청; -import static com.kustacks.kuring.acceptance.NoticeStep.공지_조회_응답_확인; -import static com.kustacks.kuring.acceptance.NoticeStep.공지사항_조회_요청; -import static com.kustacks.kuring.acceptance.NoticeStep.공지사항_조회_요청_실패_응답_확인; -import static com.kustacks.kuring.acceptance.NoticeStep.공지사항_조회_요청_응답_확인; -import static com.kustacks.kuring.acceptance.NoticeStep.공지사항_조회_요청_응답_확인_v2; -import static com.kustacks.kuring.acceptance.NoticeStep.페이지_번호와_함께_공지사항_조회_요청; -import static com.kustacks.kuring.acceptance.NoticeStep.페이지_번호와_함께_학교_공지사항_조회_요청; -import static com.kustacks.kuring.acceptance.NoticeStep.학교_공지_조회_응답_확인; +import static com.kustacks.kuring.acceptance.CategoryStep.지원하는_카테고리_조회_요청; +import static com.kustacks.kuring.acceptance.CategoryStep.카테고리_조회_요청_응답_확인; +import static com.kustacks.kuring.acceptance.NoticeStep.*; @DisplayName("인수 : 공지사항") class NoticeAcceptanceTest extends AcceptanceTest { @@ -24,7 +16,7 @@ class NoticeAcceptanceTest extends AcceptanceTest { * When : 학생 공지페이지 요청시 * Then : 학생 공지 목록이 성공적으로 조회된다 */ - @DisplayName("학생 공지사항을 성공적으로 조회한다") + @DisplayName("[v2] 학생 공지사항을 성공적으로 조회한다") @Test void look_up_university_notice() { // when @@ -38,10 +30,10 @@ void look_up_university_notice() { @Test void look_up_support_university_category() { // when - var 카테고리_조회_요청_응답 = 카테고리_조회_요청_v2(); + var 카테고리_조회_요청_응답 = 지원하는_카테고리_조회_요청(); // then - 카테고리_조회_요청_응답_확인_v2(카테고리_조회_요청_응답, "student", "bachelor", "employment", "department", "library"); + 카테고리_조회_요청_응답_확인(카테고리_조회_요청_응답, "student", "bachelor", "employment", "department", "library"); } /** @@ -56,7 +48,7 @@ void look_up_notice_v2() { var 공지사항_조회_요청_응답 = 페이지_번호와_함께_학교_공지사항_조회_요청("stu", "", Boolean.FALSE, 0); // then - 공지사항_조회_요청_응답_확인_v2(공지사항_조회_요청_응답, "student"); + 공지사항_조회_요청_응답_확인(공지사항_조회_요청_응답, "student"); } /** @@ -94,7 +86,7 @@ void look_up_department_normal_notice_v2() { * When : 잘못된 카테고리를 요청시 * Then : 실패 코드를 반환한다 */ - @DisplayName("잘못된 카테고리를 요청한다") + @DisplayName("[v2] 잘못된 카테고리를 요청한다") @Test void invalid_category_request() { // when @@ -109,7 +101,7 @@ void invalid_category_request() { * When : 잘못된 페이지 넘버 요청시 * Then : 실패 코드를 반환한다 */ - @DisplayName("잘못된 offset을 요청한다") + @DisplayName("[v2] 잘못된 offset을 요청한다") @Test void invalid_offset_request() { // when @@ -124,6 +116,7 @@ void invalid_offset_request() { * When : 키워드로 검색하면 * Then : 해당하는 공지들이 조회된다 */ + @DisplayName("[v2] 키워드로 검색을 요청한다") @Test void search_notice_by_keyword() { // when diff --git a/src/test/java/com/kustacks/kuring/acceptance/NoticeStep.java b/src/test/java/com/kustacks/kuring/acceptance/NoticeStep.java index 62f605bb..2b2aa74b 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/NoticeStep.java +++ b/src/test/java/com/kustacks/kuring/acceptance/NoticeStep.java @@ -11,19 +11,6 @@ public class NoticeStep { public static void 공지사항_조회_요청_응답_확인(ExtractableResponse response, String category) { - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), - () -> assertThat(response.jsonPath().getBoolean("isSuccess")).isTrue(), - () -> assertThat(response.jsonPath().getString("resultMsg")).isEqualTo("성공"), - () -> assertThat(response.jsonPath().getInt("resultCode")).isEqualTo(200), - () -> assertThat(response.jsonPath().getString("noticeList[0].articleId")).isNotBlank(), - () -> assertThat(response.jsonPath().getString("noticeList[0].postedDate")).isNotBlank(), - () -> assertThat(response.jsonPath().getString("noticeList[0].subject")).isNotBlank(), - () -> assertThat(response.jsonPath().getString("noticeList[0].category")).isEqualTo(category) - ); - } - - public static void 공지사항_조회_요청_응답_확인_v2(ExtractableResponse response, String category) { assertAll( () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), () -> assertThat(response.jsonPath().getInt("code")).isEqualTo(200), @@ -40,13 +27,13 @@ public class NoticeStep { return 페이지_번호와_함께_공지사항_조회_요청(category, 0); } - public static ExtractableResponse 페이지_번호와_함께_공지사항_조회_요청(String category, int offset) { + public static ExtractableResponse 페이지_번호와_함께_공지사항_조회_요청(String category, int page) { return RestAssured .given().log().all() .pathParam("type", category) - .pathParam("offset", String.valueOf(offset)) - .pathParam("max", "10") - .when().get("/api/v1/notice?type={type}&offset={offset}&max={max}") + .pathParam("page", String.valueOf(page)) + .pathParam("size", "10") + .when().get("/api/v2/notices?type={type}&page={page}&size={size}") .then().log().all() .extract(); } diff --git a/src/test/java/com/kustacks/kuring/acceptance/UserAcceptanceTest.java b/src/test/java/com/kustacks/kuring/acceptance/UserAcceptanceTest.java index 610e1d95..c4349043 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/UserAcceptanceTest.java +++ b/src/test/java/com/kustacks/kuring/acceptance/UserAcceptanceTest.java @@ -2,7 +2,7 @@ import com.kustacks.kuring.auth.exception.RegisterException; import com.kustacks.kuring.message.firebase.FirebaseService; -import com.kustacks.kuring.user.common.SubscribeCategoriesRequest; +import com.kustacks.kuring.user.common.dto.SubscribeCategoriesRequest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -29,7 +29,7 @@ class UserAcceptanceTest extends AcceptanceTest { * When: 토큰과 함께 가입 요청을 보내온다 * Then: 성공적으로 가입한다 */ - @DisplayName("[V2] 사용자 가입 성공") + @DisplayName("[v2] 사용자 가입 성공") @Test void user_register_success() { // given @@ -41,7 +41,7 @@ void user_register_success() { assertThat(회원_가입_응답.statusCode()).isEqualTo(HttpStatus.OK.value()); } - @DisplayName("[V2] 사용자 가입 실패") + @DisplayName("[v2] 사용자 가입 실패") @Test void user_register_fail() { // given @@ -65,10 +65,10 @@ void user_subscribe_category() { doNothing().when(firebaseService).subscribe(anyString(), anyString()); // when - var 카테고리_구독_요청_응답 = 카테고리_구독_요청_v2(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("student", "employment"))); + var 카테고리_구독_요청_응답 = 카테고리_구독_요청(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("student", "employment"))); // then - 카테고리_구독_요청_응답_확인_v2(카테고리_구독_요청_응답); + 카테고리_구독_요청_응답_확인(카테고리_구독_요청_응답); } /** @@ -81,13 +81,13 @@ void user_subscribe_category() { void look_up_user_subscribe_category() { // given doNothing().when(firebaseService).validationToken(anyString()); - 카테고리_구독_요청_v2(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("student", "employment"))); + 카테고리_구독_요청(USER_FCM_TOKEN, new SubscribeCategoriesRequest(List.of("student", "employment"))); // when - var 조회_응답 = 사용자_카테고리_구독_목록_조회_요청_v2(USER_FCM_TOKEN); + var 조회_응답 = 사용자_카테고리_구독_목록_조회_요청(USER_FCM_TOKEN); // then - 카테고리_구독_목록_조회_요청_응답_확인_v2(조회_응답, List.of("student", "employment")); + 카테고리_구독_목록_조회_요청_응답_확인(조회_응답, List.of("student", "employment")); } /** diff --git a/src/test/java/com/kustacks/kuring/acceptance/UserStep.java b/src/test/java/com/kustacks/kuring/acceptance/UserStep.java index 74c28147..eeb4326b 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/UserStep.java +++ b/src/test/java/com/kustacks/kuring/acceptance/UserStep.java @@ -1,8 +1,8 @@ package com.kustacks.kuring.acceptance; import com.kustacks.kuring.auth.dto.UserRegisterRequest; -import com.kustacks.kuring.user.common.SubscribeCategoriesRequest; -import com.kustacks.kuring.user.common.SubscribeDepartmentsRequest; +import com.kustacks.kuring.user.common.dto.SubscribeCategoriesRequest; +import com.kustacks.kuring.user.common.dto.SubscribeDepartmentsRequest; import com.kustacks.kuring.user.common.dto.SaveFeedbackRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; @@ -26,7 +26,7 @@ public class UserStep { .extract(); } - public static ExtractableResponse 카테고리_구독_요청_v2(String token, SubscribeCategoriesRequest reqeust) { + public static ExtractableResponse 카테고리_구독_요청(String token, SubscribeCategoriesRequest reqeust) { return RestAssured .given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) @@ -38,7 +38,7 @@ public class UserStep { .extract(); } - public static void 카테고리_구독_요청_응답_확인_v2(ExtractableResponse response) { + public static void 카테고리_구독_요청_응답_확인(ExtractableResponse response) { assertAll( () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), () -> assertThat(response.jsonPath().getInt("code")).isEqualTo(200), @@ -46,7 +46,7 @@ public class UserStep { ); } - public static ExtractableResponse 사용자_카테고리_구독_목록_조회_요청_v2(String id) { + public static ExtractableResponse 사용자_카테고리_구독_목록_조회_요청(String id) { return RestAssured .given().log().all() .accept(MediaType.APPLICATION_JSON_VALUE) @@ -56,7 +56,7 @@ public class UserStep { .extract(); } - public static void 카테고리_구독_목록_조회_요청_응답_확인_v2(ExtractableResponse response, List departments) { + public static void 카테고리_구독_목록_조회_요청_응답_확인(ExtractableResponse response, List departments) { assertAll( () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), () -> assertThat(response.jsonPath().getInt("code")).isEqualTo(200), diff --git a/src/test/java/com/kustacks/kuring/controller/NoticeControllerTest.java b/src/test/java/com/kustacks/kuring/controller/NoticeControllerTest.java deleted file mode 100644 index a0125584..00000000 --- a/src/test/java/com/kustacks/kuring/controller/NoticeControllerTest.java +++ /dev/null @@ -1,493 +0,0 @@ -package com.kustacks.kuring.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.firebase.messaging.FirebaseMessagingException; -import com.kustacks.kuring.auth.AuthConfig; -import com.kustacks.kuring.common.exception.NotFoundException; -import com.kustacks.kuring.common.exception.code.ErrorCode; -import com.kustacks.kuring.message.firebase.FirebaseService; -import com.kustacks.kuring.message.firebase.exception.FirebaseInvalidTokenException; -import com.kustacks.kuring.message.firebase.exception.FirebaseSubscribeException; -import com.kustacks.kuring.notice.business.NoticeService; -import com.kustacks.kuring.notice.common.dto.NoticeDto; -import com.kustacks.kuring.notice.common.dto.NoticeListResponse; -import com.kustacks.kuring.notice.domain.CategoryName; -import com.kustacks.kuring.notice.presentation.NoticeControllerV1; -import com.kustacks.kuring.notice.presentation.dto.SubscribeCategoriesV1Request; -import com.kustacks.kuring.user.business.UserService; -import com.kustacks.kuring.user.facade.UserCommandFacade; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.FilterType; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.restdocs.RestDocumentationContextProvider; -import org.springframework.restdocs.RestDocumentationExtension; -import org.springframework.restdocs.payload.JsonFieldType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.ResultActions; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; - -import java.nio.charset.StandardCharsets; -import java.util.LinkedList; -import java.util.List; - -import static com.kustacks.kuring.ApiDocumentUtils.getDocumentRequest; -import static com.kustacks.kuring.ApiDocumentUtils.getDocumentResponse; -import static org.hamcrest.Matchers.hasSize; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.payload.PayloadDocumentation.*; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; -import static org.springframework.restdocs.snippet.Attributes.key; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@ExtendWith(RestDocumentationExtension.class) -@WebMvcTest(controllers = NoticeControllerV1.class, excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AuthConfig.class)}) -public class NoticeControllerTest { - - private MockMvc mockMvc; - - @MockBean - private NoticeService noticeService; - - @MockBean - private FirebaseService firebaseService; - - @MockBean - private UserService userService; - - @MockBean - private UserCommandFacade userCommandFacade; - - @Mock - private FirebaseMessagingException firebaseMessagingException; - - @Autowired - private WebApplicationContext webApplicationContext; - - @Autowired - private ObjectMapper objectMapper; - - private final String articleId = "5cw2e1"; - private final String postedDate = "20211016"; - private final String subject = "[학사] 2021년 학사 관련 공지"; - private final String categoryName = "bachelor"; - - private String type; - private int offset; - private int max; - - @BeforeEach - void setUp(RestDocumentationContextProvider restDocumentation) { - this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext) - .apply(documentationConfiguration(restDocumentation)) - .build(); - } - - @DisplayName("공지 API - 성공") - @Test - void getNoticesSuccessTest() throws Exception { - - type = "bch"; - offset = 0; - max = 10; - - List noticeDtoList = new LinkedList<>(); - noticeDtoList.add(NoticeDto.builder() - .articleId(articleId) - .postedDate(postedDate) - .subject(subject) - .url("url") - .category(categoryName) - .important(false) - .build()); - - NoticeListResponse noticeListResponse = new NoticeListResponse("https://www.konkuk.ac.kr/do/MessageBoard/ArticleRead.do", noticeDtoList); - - given(noticeService.getNotices(type, offset, max)).willReturn(noticeListResponse); - - // when - ResultActions result = mockMvc.perform(get("/api/v1/notice") - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .queryParam("type", type) - .queryParam("offset", String.valueOf(offset)) - .queryParam("max", String.valueOf(max))); - - // then - result.andExpect(status().isOk()) - .andExpect(jsonPath("isSuccess").value(true)) - .andExpect(jsonPath("resultMsg").value("성공")) - .andExpect(jsonPath("resultCode").value(200)) - .andExpect(jsonPath("baseUrl").exists()) - .andExpect(jsonPath("noticeList").exists()) - .andDo(document("notice-success", - getDocumentRequest(), - getDocumentResponse(), - requestParameters( - parameterWithName("type").description("공지 카테고리 키워드") - .attributes(key("Constraints").value("bch, sch, emp, nat, stu, ind, nor, lib")), - parameterWithName("offset").description("가져올 공지의 시작 인덱스") - .attributes(key("Constraints").value("0 이상의 정수")), - parameterWithName("max").description("가져올 공지 최대 개수") - .attributes(key("Constraints").value("1 이상 30 이하의 정수")) - ), - responseFields( - fieldWithPath("isSuccess").type(JsonFieldType.BOOLEAN).description("성공 여부"), - fieldWithPath("resultMsg").type(JsonFieldType.STRING).description("결과 메세지"), - fieldWithPath("resultCode").type(JsonFieldType.NUMBER).description("결과 코드"), - fieldWithPath("baseUrl").type(JsonFieldType.STRING).description("공지 확인할 수 있는 url의 공통 부분"), - fieldWithPath("noticeList[].articleId").type(JsonFieldType.STRING).description("공지 ID"), - fieldWithPath("noticeList[].postedDate").type(JsonFieldType.STRING).description("공지 게시일"), - fieldWithPath("noticeList[].subject").type(JsonFieldType.STRING).description("공지 제목"), - fieldWithPath("noticeList[].category").type(JsonFieldType.STRING).description("공지 카테고리명"), - fieldWithPath("noticeList[].important").type(JsonFieldType.BOOLEAN).description("공지 중요 유무"), - fieldWithPath("noticeList[].url").type(JsonFieldType.STRING).description("공지 주소") - )) - - ); - } - - @DisplayName("공지 API - 실패 - 잘못된 공지 카테고리") - @Test - void getNoticesFailByInvalidTypeTest() throws Exception { - type = "invalid-type"; - offset = 0; - max = 20; - - given(noticeService.getNotices(type, offset, max)).willThrow(new NotFoundException(ErrorCode.API_NOTICE_NOT_EXIST_CATEGORY)); - - // when - ResultActions result = mockMvc.perform(get("/api/v1/notice") - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .queryParam("type", type) - .queryParam("offset", String.valueOf(offset)) - .queryParam("max", String.valueOf(max))); - - // then - result.andExpect(status().isBadRequest()) - .andExpect(jsonPath("isSuccess").value(false)) - .andExpect(jsonPath("resultMsg").value(ErrorCode.API_NOTICE_NOT_EXIST_CATEGORY.getMessage())) - .andExpect(jsonPath("resultCode").value(HttpStatus.BAD_REQUEST.value())) - .andDo(document("notice-fail-invalid-category", - getDocumentRequest(), - getDocumentResponse()) - ); - } - - @DisplayName("공지 API - 실패 - 잘못된 offset 혹은 max 파라미터 값") - @Test - void getNoticesFailByInvalidOffsetTest() throws Exception { - type = "bch"; - offset = -1; - max = 20; - - // when - ResultActions result = mockMvc.perform(get("/api/v1/notice") - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .queryParam("type", type) - .queryParam("offset", String.valueOf(offset)) - .queryParam("max", String.valueOf(max))); - - // then - result.andExpect(status().isBadRequest()) - .andExpect(jsonPath("isSuccess").value(false)) - .andExpect(jsonPath("resultMsg").value(ErrorCode.API_INVALID_PARAM.getMessage())) - .andExpect(jsonPath("resultCode").value(HttpStatus.BAD_REQUEST.value())) - .andDo(document("notice-fail-invalid-param", - getDocumentRequest(), - getDocumentResponse()) - ); - } - - - @DisplayName("서버에서 제공하는 공지 카테고리 목록 제공 API - 성공") - @Test - void getSupportedCategoriesSuccessTest() throws Exception { - - // when - ResultActions result = mockMvc.perform(get("/api/v1/notice/categories") - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON)); - - result.andExpect(status().isOk()) - .andExpect(jsonPath("isSuccess").value(true)) - .andExpect(jsonPath("resultMsg").value("성공")) - .andExpect(jsonPath("resultCode").value(200)) - .andExpect(jsonPath("categories", hasSize(9))) - .andDo(document("category-get-all-success", - getDocumentRequest(), - getDocumentResponse(), - requestParameters(), - responseFields( - fieldWithPath("isSuccess").type(JsonFieldType.BOOLEAN).description("성공 여부"), - fieldWithPath("resultMsg").type(JsonFieldType.STRING).description("결과 메세지"), - fieldWithPath("resultCode").type(JsonFieldType.NUMBER).description("결과 코드"), - fieldWithPath("categories").type(JsonFieldType.ARRAY).description("서버에서 지원하는 공지 카테고리 목록") - )) - ); - } - - @DisplayName("특정 회원이 구독한 카테고리 목록 제공 API - 성공") - @Test - void getUserCategoriesSuccessTest() throws Exception { - String token = "TEST_TOKEN"; - - List categoryNames = new LinkedList<>(); - categoryNames.add(CategoryName.BACHELOR); - categoryNames.add(CategoryName.EMPLOYMENT); - - // given - given(userService.lookUpUserCategories(token)).willReturn(categoryNames); - - // when - ResultActions result = mockMvc.perform(get("/api/v1/notice/subscribe") - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .queryParam("id", token)); - - // then - result.andExpect(status().isOk()) - .andExpect(jsonPath("isSuccess").value(true)) - .andExpect(jsonPath("resultMsg").value("성공")) - .andExpect(jsonPath("resultCode").value(200)) - .andExpect(jsonPath("categories", hasSize(2))) - .andExpect(jsonPath("categories[0]").value(categoryNames.get(0).getName())) - .andExpect(jsonPath("categories[1]").value(categoryNames.get(1).getName())) - .andDo(document("category-get-user-categories-success", - getDocumentRequest(), - getDocumentResponse(), - requestParameters( - parameterWithName("id").description("유효한 FCM 토큰") - .attributes(key("Constraints").value("")) - ), - responseFields( - fieldWithPath("isSuccess").type(JsonFieldType.BOOLEAN).description("성공 여부"), - fieldWithPath("resultMsg").type(JsonFieldType.STRING).description("결과 메세지"), - fieldWithPath("resultCode").type(JsonFieldType.NUMBER).description("결과 코드"), - fieldWithPath("categories").type(JsonFieldType.ARRAY).description("해당 회원이 구독한 카테고리 목록") - )) - ); - } - - @DisplayName("특정 회원이 구독한 카테고리 목록 제공 API - 실패 - 유효하지 않은 FCM 토큰") - @Test - void getUserCategoriesFailByInvalidTokenTest() throws Exception { - // given - String token = "INVALID_TOKEN"; - doThrow(new FirebaseInvalidTokenException()).when(firebaseService).validationToken(token); - - // when - ResultActions result = mockMvc.perform(get("/api/v1/notice/subscribe") - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON) - .queryParam("id", token)); - - // then - result.andExpect(status().isUnauthorized()) - .andExpect(jsonPath("isSuccess").value(false)) - .andExpect(jsonPath("resultMsg").value(ErrorCode.API_FB_INVALID_TOKEN.getMessage())) - .andExpect(jsonPath("resultCode").value(ErrorCode.API_FB_INVALID_TOKEN.getHttpStatus().value())) - .andExpect(jsonPath("categories").doesNotExist()) - .andDo(document("category-get-user-categories-fail-invalid-token", - getDocumentRequest(), - getDocumentResponse() - )); - } - - @DisplayName("특정 회원이 구독한 카테고리 목록 제공 API - 실패 - 필수 파라미터 누락") - @Test - void getUserCategoriesFailByMissingParamTest() throws Exception { - - // when - ResultActions result = mockMvc.perform(get("/api/v1/notice/subscribe") - .characterEncoding(StandardCharsets.UTF_8) - .accept(MediaType.APPLICATION_JSON)); - - // then - result.andExpect(status().isBadRequest()) - .andExpect(jsonPath("isSuccess").value(false)) - .andExpect(jsonPath("resultMsg").value(ErrorCode.API_MISSING_PARAM.getMessage())) - .andExpect(jsonPath("resultCode").value(ErrorCode.API_MISSING_PARAM.getHttpStatus().value())) - .andExpect(jsonPath("categories").doesNotExist()) - .andDo(document("category-get-user-categories-fail-missing-param", - getDocumentRequest(), - getDocumentResponse() - )); - } - - @DisplayName("특정 회원의 구독 카테고리 편집 API - 성공") - @Test - void subscribeCategoriesSuccessTest() throws Exception { - // given - SubscribeCategoriesV1Request subscribeCategoriesRequest = new SubscribeCategoriesV1Request("TEST_TOKEN", List.of("bachelor", "student")); - doNothing().when(firebaseService).validationToken(anyString()); - doNothing().when(userCommandFacade).editSubscribeCategories(anyString(), any()); - - // when - ResultActions result = mockMvc.perform(post("/api/v1/notice/subscribe") - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(subscribeCategoriesRequest))); - - // then - result.andExpect(status().isOk()) - .andExpect(jsonPath("isSuccess").value(true)) - .andExpect(jsonPath("resultMsg").value("성공")) - .andExpect(jsonPath("resultCode").value(201)) - .andDo(document("category-subscribe-categories-success", - getDocumentRequest(), - getDocumentResponse(), - requestFields( - fieldWithPath("id").type(JsonFieldType.STRING).description("FCM 토큰"), - fieldWithPath("categories").type(JsonFieldType.ARRAY).description("알림을 받을 공지 카테고리 목록") - ), - responseFields( - fieldWithPath("isSuccess").type(JsonFieldType.BOOLEAN).description("성공 여부"), - fieldWithPath("resultMsg").type(JsonFieldType.STRING).description("결과 메세지"), - fieldWithPath("resultCode").type(JsonFieldType.NUMBER).description("결과 코드") - )) - ); - } - - @DisplayName("특정 회원의 구독 카테고리 편집 API - 실패 - 유효하지 않은 토큰") - @Test - void subscribeCategoriesFailByInvalidToken() throws Exception { - - String token = "INVALID_TOKEN"; - - List categories = new LinkedList<>(); - categories.add("bachelor"); - categories.add("student"); - - SubscribeCategoriesV1Request requestDTO = new SubscribeCategoriesV1Request(token, categories); - - // given - given(userService.getUserByToken(token)).willReturn(null); - doThrow(new FirebaseInvalidTokenException()).when(userCommandFacade).editSubscribeCategories(anyString(), any()); - - // when - ResultActions result = mockMvc.perform(post("/api/v1/notice/subscribe") - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(requestDTO))); - - // then - result.andExpect(status().isUnauthorized()) - .andExpect(jsonPath("isSuccess").value(false)) - .andExpect(jsonPath("resultMsg").value(ErrorCode.API_FB_INVALID_TOKEN.getMessage())) - .andExpect(jsonPath("resultCode").value(ErrorCode.API_FB_INVALID_TOKEN.getHttpStatus().value())) - .andDo(document("category-subscribe-categories-fail-invalid-token", - getDocumentRequest(), - getDocumentResponse()) - ); - } - - @DisplayName("특정 회원의 구독 카테고리 편집 API - 실패 - 요청 body에 필수 json 필드 누락") - @Test - void subscribeCategoriesFailByMissingJsonField() throws Exception { - // given - String requestBody = "{\"categories\": [\"bachelor\", \"student\"]}"; - - // when - ResultActions result = mockMvc.perform(post("/api/v1/notice/subscribe") - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .content(requestBody)); - - // then - result.andExpect(status().isBadRequest()) - .andExpect(jsonPath("isSuccess").value(false)) - .andExpect(jsonPath("resultMsg").value(ErrorCode.API_MISSING_PARAM.getMessage())) - .andExpect(jsonPath("resultCode").value(ErrorCode.API_MISSING_PARAM.getHttpStatus().value())) - .andDo(document("category-subscribe-categories-fail-missing-json-field", - getDocumentRequest(), - getDocumentResponse()) - ); - } - - @DisplayName("특정 회원의 구독 카테고리 편집 API - 실패 - 서버에서 지원하지 않는 카테고리를 수신") - @Test - void subscribeCategoriesFailByNotSupportedCategory() throws Exception { - - String token = "TEST_TOKEN"; - - List categories = new LinkedList<>(); - categories.add("bachelor"); - categories.add("invalid-category"); - - SubscribeCategoriesV1Request requestDTO = new SubscribeCategoriesV1Request(token, categories); - - // given - doThrow(new FirebaseSubscribeException()).when(userCommandFacade).editSubscribeCategories(any(), any()); - - // when - ResultActions result = mockMvc.perform(post("/api/v1/notice/subscribe") - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(requestDTO))); - - // then - result.andExpect(status().isInternalServerError()) - .andExpect(jsonPath("isSuccess").value(false)) - .andExpect(jsonPath("resultMsg").value(ErrorCode.FB_FAIL_SUBSCRIBE.getMessage())) - .andExpect(jsonPath("resultCode").value(ErrorCode.FB_FAIL_SUBSCRIBE.getHttpStatus().value())) - .andDo(document("category-subscribe-categories-fail-not-supported-category", - getDocumentRequest(), - getDocumentResponse()) - ); - - } - - @DisplayName("특정 회원의 구독 카테고리 편집 API - 실패 - FCM 오류로 인한 구독 및 구독 취소 실패") - @Test - void subscribeCategoriesFailByFCMError() throws Exception { - - String token = "TEST_TOKEN"; - - List categories = new LinkedList<>(); - categories.add("bachelor"); - categories.add("student"); - - SubscribeCategoriesV1Request request = new SubscribeCategoriesV1Request(token, categories); - - // given - doThrow(new FirebaseSubscribeException()).when(userCommandFacade).editSubscribeCategories(any(), any()); - - // when - ResultActions result = mockMvc.perform(post("/api/v1/notice/subscribe") - .contentType(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))); - - // then - result.andExpect(status().isInternalServerError()) - .andExpect(jsonPath("isSuccess").value(false)) - .andExpect(jsonPath("resultMsg").value(ErrorCode.FB_FAIL_SUBSCRIBE.getMessage())) - .andExpect(jsonPath("resultCode").value(ErrorCode.FB_FAIL_SUBSCRIBE.getHttpStatus().value())) - .andDo(document("category-subscribe-categories-fail-firebase-error", - getDocumentRequest(), - getDocumentResponse()) - ); - } -}