From 2402ddded3beda26a2df14429f7b3c8abd9d5461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=98=EC=A0=9C?= Date: Tue, 22 Aug 2023 18:22:21 +0900 Subject: [PATCH 01/41] =?UTF-8?q?YEL-132=20[hotfix]=20if=EB=AC=B8=EC=97=90?= =?UTF-8?q?=EC=84=9C=20case=EB=AC=B8=EC=9C=BC=EB=A1=9C=20=EB=B0=94?= =?UTF-8?q?=EA=BF=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../purchase/service/PurchaseService.java | 65 ++++++++++--------- .../yello/server/global/common/ErrorCode.java | 1 + 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java b/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java index c28e8e1e..28c80df4 100644 --- a/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java +++ b/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java @@ -4,6 +4,7 @@ import static com.yello.server.global.common.ErrorCode.GOOGLE_SUBSCRIPTIONS_FORBIDDEN_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_SUBSCRIPTION_DUPLICATED_CANCEL_EXCEPTION; +import static com.yello.server.global.common.ErrorCode.GOOGLE_SUBSCRIPTION_TRANSACTION_EXPIRED_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_SUBSCRIPTION_USED_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_TOKEN_FIELD_NOT_FOUND_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_TOKEN_FORBIDDEN_EXCEPTION; @@ -76,7 +77,7 @@ public UserSubscribeNeededResponse getUserSubscribe(User user, LocalDateTime tim final Optional mostRecentPurchase = purchaseRepository.findTopByUserAndProductTypeOrderByCreatedAtDesc( user, ProductType.YELLO_PLUS); - final Boolean isSubscribeNeeded = user.getSubscribe()==Subscribe.CANCELED + final Boolean isSubscribeNeeded = user.getSubscribe() == Subscribe.CANCELED && mostRecentPurchase.isPresent() && Duration.between(mostRecentPurchase.get().getCreatedAt(), time).getSeconds() < 1 * 24 * 60 * 60; @@ -93,7 +94,7 @@ public void verifyAppleSubscriptionTransaction(Long userId, purchaseManager.handleAppleTransactionError(verifyReceiptResponse, request.transactionId()); - if (user.getSubscribe()==Subscribe.ACTIVE) { + if (user.getSubscribe() == Subscribe.ACTIVE) { throw new SubscriptionConflictException(SUBSCRIBE_ACTIVE_EXCEPTION); } @@ -115,13 +116,11 @@ public void verifyAppleTicketTransaction(Long userId, AppleTransaction request) switch (request.productId()) { case ONE_TICKET_ID: - purchaseManager.createTicket(user, ProductType.ONE_TICKET, Gateway.APPLE, - request.transactionId()); + purchaseManager.createTicket(user, ProductType.ONE_TICKET, Gateway.APPLE, request.transactionId()); user.changeTicketCount(1); break; case TWO_TICKET_ID: - purchaseManager.createTicket(user, ProductType.TWO_TICKET, Gateway.APPLE, - request.transactionId()); + purchaseManager.createTicket(user, ProductType.TWO_TICKET, Gateway.APPLE, request.transactionId()); user.changeTicketCount(2); break; case FIVE_TICKET_ID: @@ -140,13 +139,13 @@ public GoogleSubscriptionV2GetResponse verifyGoogleSubscriptionTransaction(Long User user = userRepository.getById(userId); // exception - if (user.getSubscribe()!=Subscribe.NORMAL) { + if (user.getSubscribe() != Subscribe.NORMAL) { throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_FORBIDDEN_EXCEPTION); } - purchaseRepository.findByTransactionId(request.orderId()) + purchaseRepository.findByTransactionId(request.orderId().toString()) .ifPresent(action -> { - throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION); + throw new PurchaseConflictException(GOOGLE_SUBSCRIPTION_USED_EXCEPTION); }); final GoogleToken googleToken = @@ -176,28 +175,33 @@ public GoogleSubscriptionV2GetResponse verifyGoogleSubscriptionTransaction(Long Gson gson = new Gson(); JsonObject object = gson.fromJson(subscribeResponse.getBody(), JsonObject.class); - String subscriptionState = object.get("subscriptionState").toString(); - - if (subscriptionState.equals(ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_EXPIRED)) { - throw new GoogleBadRequestException(GOOGLE_SUBSCRIPTION_USED_EXCEPTION); - } else if (subscriptionState.equals(ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_CANCELED)) { - if (user.getSubscribe()==Subscribe.CANCELED) { - throw new GoogleBadRequestException( - GOOGLE_SUBSCRIPTION_DUPLICATED_CANCEL_EXCEPTION); + final String subscriptionState = object.get("subscriptionState").toString().replaceAll("\"", ""); + + switch (subscriptionState) { + case ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_EXPIRED -> { + user.setSubscribe(Subscribe.NORMAL); + throw new GoogleBadRequestException(GOOGLE_SUBSCRIPTION_TRANSACTION_EXPIRED_EXCEPTION); + } + case ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_CANCELED -> { + if (user.getSubscribe() == Subscribe.CANCELED) { + throw new GoogleBadRequestException(GOOGLE_SUBSCRIPTION_DUPLICATED_CANCEL_EXCEPTION); + } else { + // TODO messageQueue 를 이용한 결제 만료일 도달 시, 유저 구독 상태 변경하기 + user.setSubscribe(Subscribe.CANCELED); + } + } + case ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_ACTIVE -> { + final Purchase subscribe = + purchaseManager.createSubscribe(user, Gateway.GOOGLE, request.orderId()); + subscribe.setTransactionId(request.orderId()); } - } else if (subscriptionState.equals(ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_ACTIVE)) { - final Purchase subscribe = - purchaseManager.createSubscribe(user, Gateway.GOOGLE, request.orderId()); - user.changeTicketCount(3); - subscribe.setTransactionId(request.orderId()); } return GoogleSubscriptionV2GetResponse.of(request.productId()); } @Transactional - public GoogleInAppV1GetResponse verifyGoogleInAppTransaction(Long userId, - GoogleInAppGetRequest request) + public GoogleInAppV1GetResponse verifyGoogleInAppTransaction(Long userId, GoogleInAppGetRequest request) throws IOException { final User user = userRepository.getById(userId); @@ -206,8 +210,7 @@ public GoogleInAppV1GetResponse verifyGoogleInAppTransaction(Long userId, throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION); }); - final GoogleToken googleToken = - googleTokenRepository.getById(googleTokenRepository.tokenId); + final GoogleToken googleToken = googleTokenRepository.getById(googleTokenRepository.tokenId); if (googleToken.getAccessToken().isEmpty() || googleToken.getRefreshToken().isEmpty()) { throw new GoogleTokenNotFoundException(GOOGLE_TOKEN_FIELD_NOT_FOUND_EXCEPTION); } @@ -230,16 +233,14 @@ public GoogleInAppV1GetResponse verifyGoogleInAppTransaction(Long userId, throw new GoogleTokenServerErrorException(GOOGLE_TOKEN_SERVER_EXCEPTION); } - if (inAppResponse.getBody().purchaseState()==0) { + if (inAppResponse.getBody().purchaseState() == 0) { purchaseRepository.findByTransactionId(inAppResponse.getBody().orderId()) .ifPresent(action -> { - throw new PurchaseConflictException( - GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION); + throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION); }); - Purchase ticket = - purchaseManager.createTicket(user, getProductType(request.productId()), - Gateway.GOOGLE, request.orderId()); + Purchase ticket = purchaseManager.createTicket(user, getProductType(request.productId()), + Gateway.GOOGLE, request.orderId()); user.changeTicketCount(getTicketAmount(request.productId()) * request.quantity()); ticket.setTransactionId(inAppResponse.getBody().orderId()); } else { diff --git a/src/main/java/com/yello/server/global/common/ErrorCode.java b/src/main/java/com/yello/server/global/common/ErrorCode.java index 1d21a625..ce6a4b5b 100644 --- a/src/main/java/com/yello/server/global/common/ErrorCode.java +++ b/src/main/java/com/yello/server/global/common/ErrorCode.java @@ -59,6 +59,7 @@ public enum ErrorCode { GOOGLE_TOKEN_FORBIDDEN_EXCEPTION(FORBIDDEN, "유효하지 않는 Google OAuth 2.0 refreshToken입니다. DBA에게 문의해주세요."), GOOGLE_SUBSCRIPTIONS_FORBIDDEN_EXCEPTION(FORBIDDEN, "이미 YELLO: PLUS를 구독한 상태입니다."), + GOOGLE_SUBSCRIPTION_TRANSACTION_EXPIRED_EXCEPTION(FORBIDDEN, "이미 만료된 결제 내역의 영수증입니다."), /** * 404 NOT FOUND From 32b9de7b9910e27acd636ef82d0d0c27f9c7ec1a Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:30:37 +0900 Subject: [PATCH 02/41] =?UTF-8?q?YEL-139=20[test]=20restdocs=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 27 ++ src/docs/asciidoc/add-friend.adoc | 0 src/docs/asciidoc/apple.adoc | 0 src/docs/asciidoc/check-keyword.adoc | 0 src/docs/asciidoc/check-user-by-id.adoc | 0 src/docs/asciidoc/check-user.adoc | 0 src/docs/asciidoc/check-vote-available.adoc | 0 src/docs/asciidoc/create-vote.adoc | 0 src/docs/asciidoc/delete-friend.adoc | 0 src/docs/asciidoc/delete-user.adoc | 0 src/docs/asciidoc/device-token.adoc | 0 src/docs/asciidoc/find-friend-votes.adoc | 0 src/docs/asciidoc/find-friends.adoc | 0 src/docs/asciidoc/find-group-friends.adoc | 0 src/docs/asciidoc/find-kakao-friends.adoc | 0 .../asciidoc/find-onboarding-friends.adoc | 0 src/docs/asciidoc/find-question.adoc | 0 src/docs/asciidoc/find-vote.adoc | 0 src/docs/asciidoc/find-votes.adoc | 0 src/docs/asciidoc/get-unread-vote.adoc | 0 src/docs/asciidoc/google.adoc | 0 src/docs/asciidoc/index.adoc | 0 src/docs/asciidoc/login.adoc | 0 src/docs/asciidoc/overview.adoc | 0 src/docs/asciidoc/pay.adoc | 11 + src/docs/asciidoc/purchase-check.adoc | 0 src/docs/asciidoc/reissue-token.adoc | 0 src/docs/asciidoc/reveal-full-name.adoc | 0 src/docs/asciidoc/reveal-name.adoc | 0 src/docs/asciidoc/search-department.adoc | 0 src/docs/asciidoc/search-friend.adoc | 0 src/docs/asciidoc/search-school.adoc | 0 src/docs/asciidoc/shuffle-friends.adoc | 0 src/docs/asciidoc/signup.adoc | 0 src/docs/asciidoc/sub-check.adoc | 0 src/docs/asciidoc/validate-yelloid.adoc | 0 ...java => GoogleSubscriptionGetRequest.java} | 2 +- ...quest.java => GoogleTicketGetRequest.java} | 2 +- ...ava => GoogleSubscriptionGetResponse.java} | 6 +- ...onse.java => GoogleTicketGetResponse.java} | 6 +- .../medium/PurchaseControllerTest.java | 302 ++++++++++++++++++ 41 files changed, 348 insertions(+), 8 deletions(-) create mode 100644 src/docs/asciidoc/add-friend.adoc create mode 100644 src/docs/asciidoc/apple.adoc create mode 100644 src/docs/asciidoc/check-keyword.adoc create mode 100644 src/docs/asciidoc/check-user-by-id.adoc create mode 100644 src/docs/asciidoc/check-user.adoc create mode 100644 src/docs/asciidoc/check-vote-available.adoc create mode 100644 src/docs/asciidoc/create-vote.adoc create mode 100644 src/docs/asciidoc/delete-friend.adoc create mode 100644 src/docs/asciidoc/delete-user.adoc create mode 100644 src/docs/asciidoc/device-token.adoc create mode 100644 src/docs/asciidoc/find-friend-votes.adoc create mode 100644 src/docs/asciidoc/find-friends.adoc create mode 100644 src/docs/asciidoc/find-group-friends.adoc create mode 100644 src/docs/asciidoc/find-kakao-friends.adoc create mode 100644 src/docs/asciidoc/find-onboarding-friends.adoc create mode 100644 src/docs/asciidoc/find-question.adoc create mode 100644 src/docs/asciidoc/find-vote.adoc create mode 100644 src/docs/asciidoc/find-votes.adoc create mode 100644 src/docs/asciidoc/get-unread-vote.adoc create mode 100644 src/docs/asciidoc/google.adoc create mode 100644 src/docs/asciidoc/index.adoc create mode 100644 src/docs/asciidoc/login.adoc create mode 100644 src/docs/asciidoc/overview.adoc create mode 100644 src/docs/asciidoc/pay.adoc create mode 100644 src/docs/asciidoc/purchase-check.adoc create mode 100644 src/docs/asciidoc/reissue-token.adoc create mode 100644 src/docs/asciidoc/reveal-full-name.adoc create mode 100644 src/docs/asciidoc/reveal-name.adoc create mode 100644 src/docs/asciidoc/search-department.adoc create mode 100644 src/docs/asciidoc/search-friend.adoc create mode 100644 src/docs/asciidoc/search-school.adoc create mode 100644 src/docs/asciidoc/shuffle-friends.adoc create mode 100644 src/docs/asciidoc/signup.adoc create mode 100644 src/docs/asciidoc/sub-check.adoc create mode 100644 src/docs/asciidoc/validate-yelloid.adoc rename src/main/java/com/yello/server/domain/purchase/dto/request/{GoogleSubscriptionV2GetRequest.java => GoogleSubscriptionGetRequest.java} (87%) rename src/main/java/com/yello/server/domain/purchase/dto/request/{GoogleInAppGetRequest.java => GoogleTicketGetRequest.java} (88%) rename src/main/java/com/yello/server/domain/purchase/dto/response/{GoogleSubscriptionV2GetResponse.java => GoogleSubscriptionGetResponse.java} (62%) rename src/main/java/com/yello/server/domain/purchase/dto/response/{GoogleInAppV1GetResponse.java => GoogleTicketGetResponse.java} (63%) create mode 100644 src/test/java/com/yello/server/domain/purchase/medium/PurchaseControllerTest.java diff --git a/build.gradle b/build.gradle index 5098fcf6..87c76027 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,15 @@ plugins { id 'org.springframework.boot' version '2.7.4' id 'io.spring.dependency-management' version '1.0.15.RELEASE' id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' + id "org.asciidoctor.jvm.convert" version "3.3.2" +} + +ext { + snippetsDir = file('build/generated-snippets') +} + +test { + outputs.dir snippetsDir } group = 'com.yello' @@ -19,6 +28,7 @@ java { } configurations { + asciidoctorExt compileOnly { extendsFrom annotationProcessor } @@ -34,6 +44,9 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.4.2' + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' + testImplementation 'org.springframework.security:spring-security-test' // JPA & Database implementation 'org.springframework.boot:spring-boot-starter-data-jpa' @@ -118,4 +131,18 @@ compileQuerydsl { jar { enabled = false +} + +asciidoctor { + inputs.dir snippetsDir + configurations 'asciidoctorExt' + dependsOn test +} +asciidoctor.doFirst { + delete file('src/docs/asciidocs') +} +task copyDocument(type: Copy) { + dependsOn asciidoctor + from file("build/docs/asciidoc") + into file("src/main/resources/static/docs") } \ No newline at end of file diff --git a/src/docs/asciidoc/add-friend.adoc b/src/docs/asciidoc/add-friend.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/apple.adoc b/src/docs/asciidoc/apple.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/check-keyword.adoc b/src/docs/asciidoc/check-keyword.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/check-user-by-id.adoc b/src/docs/asciidoc/check-user-by-id.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/check-user.adoc b/src/docs/asciidoc/check-user.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/check-vote-available.adoc b/src/docs/asciidoc/check-vote-available.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/create-vote.adoc b/src/docs/asciidoc/create-vote.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/delete-friend.adoc b/src/docs/asciidoc/delete-friend.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/delete-user.adoc b/src/docs/asciidoc/delete-user.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/device-token.adoc b/src/docs/asciidoc/device-token.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/find-friend-votes.adoc b/src/docs/asciidoc/find-friend-votes.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/find-friends.adoc b/src/docs/asciidoc/find-friends.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/find-group-friends.adoc b/src/docs/asciidoc/find-group-friends.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/find-kakao-friends.adoc b/src/docs/asciidoc/find-kakao-friends.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/find-onboarding-friends.adoc b/src/docs/asciidoc/find-onboarding-friends.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/find-question.adoc b/src/docs/asciidoc/find-question.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/find-vote.adoc b/src/docs/asciidoc/find-vote.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/find-votes.adoc b/src/docs/asciidoc/find-votes.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/get-unread-vote.adoc b/src/docs/asciidoc/get-unread-vote.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/google.adoc b/src/docs/asciidoc/google.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/login.adoc b/src/docs/asciidoc/login.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/overview.adoc b/src/docs/asciidoc/overview.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/pay.adoc b/src/docs/asciidoc/pay.adoc new file mode 100644 index 00000000..1fd03e8d --- /dev/null +++ b/src/docs/asciidoc/pay.adoc @@ -0,0 +1,11 @@ += Friend API + +== 친구 추가하기 + +=== 요청 + +include::{snippets}/api/v1/pay/postPayCount/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/pay/postPayCount/http-response.adoc[] diff --git a/src/docs/asciidoc/purchase-check.adoc b/src/docs/asciidoc/purchase-check.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/reissue-token.adoc b/src/docs/asciidoc/reissue-token.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/reveal-full-name.adoc b/src/docs/asciidoc/reveal-full-name.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/reveal-name.adoc b/src/docs/asciidoc/reveal-name.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/search-department.adoc b/src/docs/asciidoc/search-department.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/search-friend.adoc b/src/docs/asciidoc/search-friend.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/search-school.adoc b/src/docs/asciidoc/search-school.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/shuffle-friends.adoc b/src/docs/asciidoc/shuffle-friends.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/signup.adoc b/src/docs/asciidoc/signup.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/sub-check.adoc b/src/docs/asciidoc/sub-check.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/docs/asciidoc/validate-yelloid.adoc b/src/docs/asciidoc/validate-yelloid.adoc new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/com/yello/server/domain/purchase/dto/request/GoogleSubscriptionV2GetRequest.java b/src/main/java/com/yello/server/domain/purchase/dto/request/GoogleSubscriptionGetRequest.java similarity index 87% rename from src/main/java/com/yello/server/domain/purchase/dto/request/GoogleSubscriptionV2GetRequest.java rename to src/main/java/com/yello/server/domain/purchase/dto/request/GoogleSubscriptionGetRequest.java index 112d0070..a0322d12 100644 --- a/src/main/java/com/yello/server/domain/purchase/dto/request/GoogleSubscriptionV2GetRequest.java +++ b/src/main/java/com/yello/server/domain/purchase/dto/request/GoogleSubscriptionGetRequest.java @@ -3,7 +3,7 @@ import lombok.Builder; @Builder -public record GoogleSubscriptionV2GetRequest( +public record GoogleSubscriptionGetRequest( String orderId, String packageName, String productId, diff --git a/src/main/java/com/yello/server/domain/purchase/dto/request/GoogleInAppGetRequest.java b/src/main/java/com/yello/server/domain/purchase/dto/request/GoogleTicketGetRequest.java similarity index 88% rename from src/main/java/com/yello/server/domain/purchase/dto/request/GoogleInAppGetRequest.java rename to src/main/java/com/yello/server/domain/purchase/dto/request/GoogleTicketGetRequest.java index 42c968b8..fc447186 100644 --- a/src/main/java/com/yello/server/domain/purchase/dto/request/GoogleInAppGetRequest.java +++ b/src/main/java/com/yello/server/domain/purchase/dto/request/GoogleTicketGetRequest.java @@ -3,7 +3,7 @@ import lombok.Builder; @Builder -public record GoogleInAppGetRequest( +public record GoogleTicketGetRequest( String orderId, String packageName, String productId, diff --git a/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleSubscriptionV2GetResponse.java b/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleSubscriptionGetResponse.java similarity index 62% rename from src/main/java/com/yello/server/domain/purchase/dto/response/GoogleSubscriptionV2GetResponse.java rename to src/main/java/com/yello/server/domain/purchase/dto/response/GoogleSubscriptionGetResponse.java index 3565692a..765615ee 100644 --- a/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleSubscriptionV2GetResponse.java +++ b/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleSubscriptionGetResponse.java @@ -4,13 +4,13 @@ import lombok.Builder; @Builder -public record GoogleSubscriptionV2GetResponse( +public record GoogleSubscriptionGetResponse( String productId, String expiredAt ) { - public static GoogleSubscriptionV2GetResponse of(String productId) { - return GoogleSubscriptionV2GetResponse.builder() + public static GoogleSubscriptionGetResponse of(String productId) { + return GoogleSubscriptionGetResponse.builder() .productId(productId) .expiredAt(LocalDateTime.now().toString()) .build(); diff --git a/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleInAppV1GetResponse.java b/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleTicketGetResponse.java similarity index 63% rename from src/main/java/com/yello/server/domain/purchase/dto/response/GoogleInAppV1GetResponse.java rename to src/main/java/com/yello/server/domain/purchase/dto/response/GoogleTicketGetResponse.java index bb77670d..c9051493 100644 --- a/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleInAppV1GetResponse.java +++ b/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleTicketGetResponse.java @@ -4,13 +4,13 @@ import lombok.Builder; @Builder -public record GoogleInAppV1GetResponse( +public record GoogleTicketV1GetResponse( String productId, Integer ticketCount ) { - public static GoogleInAppV1GetResponse of(String productId, User user) { - return GoogleInAppV1GetResponse.builder() + public static GoogleTicketV1GetResponse of(String productId, User user) { + return GoogleTicketV1GetResponse.builder() .productId(productId) .ticketCount(user.getTicketCount()) .build(); diff --git a/src/test/java/com/yello/server/domain/purchase/medium/PurchaseControllerTest.java b/src/test/java/com/yello/server/domain/purchase/medium/PurchaseControllerTest.java new file mode 100644 index 00000000..7a2c9b4d --- /dev/null +++ b/src/test/java/com/yello/server/domain/purchase/medium/PurchaseControllerTest.java @@ -0,0 +1,302 @@ +package com.yello.server.domain.authorization.medium; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yello.server.domain.authorization.controller.AuthController; +import com.yello.server.domain.authorization.dto.ServiceTokenVO; +import com.yello.server.domain.authorization.dto.request.OAuthRequest; +import com.yello.server.domain.authorization.dto.request.OnBoardingFriendRequest; +import com.yello.server.domain.authorization.dto.request.SignUpRequest; +import com.yello.server.domain.authorization.dto.response.DepartmentSearchResponse; +import com.yello.server.domain.authorization.dto.response.GroupNameSearchResponse; +import com.yello.server.domain.authorization.dto.response.OAuthResponse; +import com.yello.server.domain.authorization.dto.response.OnBoardingFriendResponse; +import com.yello.server.domain.authorization.dto.response.SignUpResponse; +import com.yello.server.domain.authorization.filter.JwtExceptionFilter; +import com.yello.server.domain.authorization.filter.JwtFilter; +import com.yello.server.domain.authorization.service.AuthService; +import com.yello.server.domain.user.entity.Gender; +import com.yello.server.domain.user.entity.Social; +import com.yello.server.domain.user.entity.User; +import com.yello.server.global.exception.ControllerExceptionAdvice; +import com.yello.server.util.TestDataEntityUtil; +import com.yello.server.util.TestDataUtil; +import com.yello.server.util.WithAccessTokenUser; +import java.util.Arrays; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +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.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@AutoConfigureRestDocs +@WebMvcTest( + controllers = AuthController.class, + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ControllerExceptionAdvice.class) + }) +@WithAccessTokenUser +@DisplayNameGeneration(ReplaceUnderscores.class) +@DisplayName("Auth 컨트롤러에서") +class AuthControllerTest { + + final String[] excludeRequestHeaders = {"X-CSRF-TOKEN", "Host"}; + final String[] excludeResponseHeaders = {"X-Content-Type-Options", "X-XSS-Protection", "Cache-Control", "Pragma", + "Expires", "X-Frame-Options", "Content-Length"}; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private AuthService authService; + + private TestDataUtil testDataUtil = new TestDataEntityUtil(); + private User user; + private User target; + + @BeforeEach + void init() { + user = testDataUtil.generateUser(1L, 1L); + target = testDataUtil.generateUser(2L, 1L); + } + + @Test + void 소셜_로그인에_성공합니다() throws Exception { + // given + final OAuthRequest oAuthRequest = OAuthRequest.builder() + .accessToken("accessToken") + .deviceToken("deviceToken") + .social("social") + .build(); + + final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( + "serviceAccessToken", + "serviceRefreshToken" + ); + + final OAuthResponse oAuthResponse = OAuthResponse.of(false, serviceTokenVO); + + given(authService.oauthLogin(oAuthRequest)) + .willReturn(oAuthResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/oauth") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(oAuthRequest))) + .andDo(print()) + .andDo(document("api/v1/auth/oauthLogin", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 옐로_아이디_중복_확인에_성공합니다() throws Exception { + // given + given(authService.isYelloIdDuplicated(anyString())) + .willReturn(false); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/valid") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .param("yelloId", "yelloId here")) + .andDo(print()) + .andDo(document("api/v1/auth/getYelloIdValidation", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("yelloId").description("중복 체크할 yelloId"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 회원_가입에_성공합니다() throws Exception { + // given + final SignUpRequest signUpRequest = SignUpRequest.builder() + .social(Social.KAKAO) + .uuid("uuid") + .deviceToken("deviceToken") + .email("email@emall.com") + .profileImage("profileImage") + .groupId(1L) + .groupAdmissionYear(20) + .name("name") + .yelloId("yelloId") + .gender(Gender.MALE) + .friends(Arrays.asList(1L)) + .recommendId("recommendId") + .build(); + + final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( + "serviceAccessToken", + "serviceRefreshToken" + ); + + final SignUpResponse signUpResponse = SignUpResponse.of("yelloId", serviceTokenVO); + + given(authService.signUp(signUpRequest)) + .willReturn(signUpResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/signup") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(signUpRequest))) + .andDo(print()) + .andDo(document("api/v1/auth/postSignUp", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 가입한_친구_불러오기에_성공합니다() throws Exception { + // given + final OnBoardingFriendRequest onBoardingFriendRequest = OnBoardingFriendRequest.builder() + .friendKakaoId(Arrays.asList("friendKakaoId")) + .build(); + + final OnBoardingFriendResponse onBoardingFriendResponse = OnBoardingFriendResponse.of(0, Arrays.asList(user)); + + given(authService.findOnBoardingFriends(any(OnBoardingFriendRequest.class), any(Pageable.class))) + .willReturn(onBoardingFriendResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/friend") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(onBoardingFriendRequest)) + .param("page", "0")) + .andDo(print()) + .andDo(document("api/v1/auth/findOnBoardingFriends", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("page").description("페이지네이션 페이지 번호"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 대학교_이름_검색에_성공합니다() throws Exception { + // given + final GroupNameSearchResponse groupNameSearchResponse = GroupNameSearchResponse.of( + 0, + Arrays.asList("groupName") + ); + + given(authService.findSchoolsByKeyword(anyString(), any(Pageable.class))) + .willReturn(groupNameSearchResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/school") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .param("page", "0") + .param("keyword", "keyword here") + ) + .andDo(print()) + .andDo(document("api/v1/auth/findSchoolsByKeyword", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters( + parameterWithName("page").description("페이지네이션 페이지 번호"), + parameterWithName("keyword").description("검색할 쿼리"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 학과_이름_검색에_성공합니다() throws Exception { + // given + final DepartmentSearchResponse departmentSearchResponse = DepartmentSearchResponse.of( + 0, + Arrays.asList(testDataUtil.generateSchool(1L)) + ); + + given(authService.findDepartmentsByKeyword(anyString(), anyString(), any(Pageable.class))) + .willReturn(departmentSearchResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/school/department") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .param("page", "0") + .param("school", "school name here") + .param("keyword", "keyword here") + ) + .andDo(print()) + .andDo(document("api/v1/auth/findDepartmentsByKeyword", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters( + parameterWithName("page").description("페이지네이션 페이지 번호"), + parameterWithName("school").description("학교 이름"), + parameterWithName("keyword").description("검색할 쿼리"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 토큰_재발급에_성공합니다() throws Exception { + // given + final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( + "new accessToken", + "new refreshToken" + ); + + given(authService.reIssueToken(any(ServiceTokenVO.class))) + .willReturn(serviceTokenVO); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/token/issue") + .with(csrf().asHeader()) + .header("X-ACCESS-AUTH", "Bearer your-access-token") + .header("X-REFRESH-AUTH", "Bearer your-refresh-token") + ) + .andDo(print()) + .andDo(document("api/v1/auth/reIssueToken", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } +} From b0eed804478db75c2303f0ec2cb1d765e6ca5e1f Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:31:02 +0900 Subject: [PATCH 03/41] =?UTF-8?q?YEL-139=20[test]=20restdoc=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/add-friend.adoc | 13 +++ src/docs/asciidoc/apple.adoc | 29 +++++++ src/docs/asciidoc/check-keyword.adoc | 13 +++ src/docs/asciidoc/check-user-by-id.adoc | 9 ++ src/docs/asciidoc/check-user.adoc | 9 ++ src/docs/asciidoc/check-vote-available.adoc | 9 ++ src/docs/asciidoc/create-vote.adoc | 10 +++ src/docs/asciidoc/delete-friend.adoc | 13 +++ src/docs/asciidoc/delete-user.adoc | 9 ++ src/docs/asciidoc/device-token.adoc | 9 ++ src/docs/asciidoc/find-friend-votes.adoc | 13 +++ src/docs/asciidoc/find-friends.adoc | 14 +++ src/docs/asciidoc/find-group-friends.adoc | 13 +++ src/docs/asciidoc/find-kakao-friends.adoc | 13 +++ .../asciidoc/find-onboarding-friends.adoc | 13 +++ src/docs/asciidoc/find-question.adoc | 9 ++ src/docs/asciidoc/find-vote.adoc | 13 +++ src/docs/asciidoc/find-votes.adoc | 13 +++ src/docs/asciidoc/get-unread-vote.adoc | 9 ++ src/docs/asciidoc/google.adoc | 19 ++++ src/docs/asciidoc/index.adoc | 86 +++++++++++++++++++ src/docs/asciidoc/login.adoc | 11 +++ src/docs/asciidoc/overview.adoc | 40 +++++++++ src/docs/asciidoc/pay.adoc | 2 - src/docs/asciidoc/purchase-check.adoc | 9 ++ src/docs/asciidoc/reissue-token.adoc | 12 +++ src/docs/asciidoc/reveal-full-name.adoc | 13 +++ src/docs/asciidoc/reveal-name.adoc | 13 +++ src/docs/asciidoc/search-department.adoc | 13 +++ src/docs/asciidoc/search-friend.adoc | 15 ++++ src/docs/asciidoc/search-school.adoc | 13 +++ src/docs/asciidoc/shuffle-friends.adoc | 9 ++ src/docs/asciidoc/signup.adoc | 9 ++ src/docs/asciidoc/sub-check.adoc | 9 ++ src/docs/asciidoc/validate-yelloid.adoc | 13 +++ 35 files changed, 517 insertions(+), 2 deletions(-) diff --git a/src/docs/asciidoc/add-friend.adoc b/src/docs/asciidoc/add-friend.adoc index e69de29b..aaa42bf8 100644 --- a/src/docs/asciidoc/add-friend.adoc +++ b/src/docs/asciidoc/add-friend.adoc @@ -0,0 +1,13 @@ +== 친구 추가하기 + +=== 요청 + +include::{snippets}/api/v1/friend/addFriend/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/friend/addFriend/path-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/friend/addFriend/http-response.adoc[] diff --git a/src/docs/asciidoc/apple.adoc b/src/docs/asciidoc/apple.adoc index e69de29b..086e50a4 100644 --- a/src/docs/asciidoc/apple.adoc +++ b/src/docs/asciidoc/apple.adoc @@ -0,0 +1,29 @@ +== Apple 구독 구매 검증하기 + +=== 요청 + +include::{snippets}/api/v1/purchase/verifyAppleSubscriptionTransaction/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/purchase/verifyAppleSubscriptionTransaction/http-response.adoc[] + +== Apple 열람권 구매 검증하기 + +=== 요청 + +include::{snippets}/api/v1/purchase/verifyAppleTicketTransaction/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/purchase/verifyAppleTicketTransaction/http-response.adoc[] + +== Apple 환불하기 + +=== 요청 + +include::{snippets}/api/v1/purchase/refundInAppApple/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/purchase/refundInAppApple/http-response.adoc[] diff --git a/src/docs/asciidoc/check-keyword.adoc b/src/docs/asciidoc/check-keyword.adoc index e69de29b..9a9e6107 100644 --- a/src/docs/asciidoc/check-keyword.adoc +++ b/src/docs/asciidoc/check-keyword.adoc @@ -0,0 +1,13 @@ +== 투표 키워드 확인하기 + +=== 요청 + +include::{snippets}/api/v1/vote/checkKeyword/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/vote/checkKeyword/path-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/checkKeyword/http-response.adoc[] diff --git a/src/docs/asciidoc/check-user-by-id.adoc b/src/docs/asciidoc/check-user-by-id.adoc index e69de29b..941d2a53 100644 --- a/src/docs/asciidoc/check-user-by-id.adoc +++ b/src/docs/asciidoc/check-user-by-id.adoc @@ -0,0 +1,9 @@ +== 유저 정보 조회하기 + +=== 요청 + +include::{snippets}/api/v1/user/findUserById/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/user/findUserById/http-response.adoc[] diff --git a/src/docs/asciidoc/check-user.adoc b/src/docs/asciidoc/check-user.adoc index e69de29b..f51ef64f 100644 --- a/src/docs/asciidoc/check-user.adoc +++ b/src/docs/asciidoc/check-user.adoc @@ -0,0 +1,9 @@ +== 내 정보 조회하기 + +=== 요청 + +include::{snippets}/api/v1/user/findUser/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/user/findUser/http-response.adoc[] diff --git a/src/docs/asciidoc/check-vote-available.adoc b/src/docs/asciidoc/check-vote-available.adoc index e69de29b..0d67b25f 100644 --- a/src/docs/asciidoc/check-vote-available.adoc +++ b/src/docs/asciidoc/check-vote-available.adoc @@ -0,0 +1,9 @@ +== 투표 가능 여부 조회 + +=== 요청 + +include::{snippets}/api/v1/vote/checkVoteAvailable/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/checkVoteAvailable/http-response.adoc[] diff --git a/src/docs/asciidoc/create-vote.adoc b/src/docs/asciidoc/create-vote.adoc index e69de29b..fb2b9761 100644 --- a/src/docs/asciidoc/create-vote.adoc +++ b/src/docs/asciidoc/create-vote.adoc @@ -0,0 +1,10 @@ +== 투표 생성하기 + +=== 요청 + +include::{snippets}/api/v1/vote/createVote/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/createVote/http-response.adoc[] + diff --git a/src/docs/asciidoc/delete-friend.adoc b/src/docs/asciidoc/delete-friend.adoc index e69de29b..dd560fa5 100644 --- a/src/docs/asciidoc/delete-friend.adoc +++ b/src/docs/asciidoc/delete-friend.adoc @@ -0,0 +1,13 @@ +== 친구 삭제하기 + +=== 요청 + +include::{snippets}/api/v1/friend/deleteFriend/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/friend/deleteFriend/path-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/friend/deleteFriend/http-response.adoc[] diff --git a/src/docs/asciidoc/delete-user.adoc b/src/docs/asciidoc/delete-user.adoc index e69de29b..910ab4bc 100644 --- a/src/docs/asciidoc/delete-user.adoc +++ b/src/docs/asciidoc/delete-user.adoc @@ -0,0 +1,9 @@ +== 유저 탈퇴하기 + +=== 요청 + +include::{snippets}/api/v1/user/deleteUser/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/user/deleteUser/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/device-token.adoc b/src/docs/asciidoc/device-token.adoc index e69de29b..6185c3da 100644 --- a/src/docs/asciidoc/device-token.adoc +++ b/src/docs/asciidoc/device-token.adoc @@ -0,0 +1,9 @@ +== 디바이스 토큰 수정하기 + +=== 요청 + +include::{snippets}/api/v1/user/updateUserDeviceToken/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/user/updateUserDeviceToken/http-response.adoc[] diff --git a/src/docs/asciidoc/find-friend-votes.adoc b/src/docs/asciidoc/find-friend-votes.adoc index e69de29b..c6bbe0d4 100644 --- a/src/docs/asciidoc/find-friend-votes.adoc +++ b/src/docs/asciidoc/find-friend-votes.adoc @@ -0,0 +1,13 @@ +== 친구 투표 전체 조회 + +=== 요청 + +include::{snippets}/api/v1/vote/findAllFriendVotes/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/vote/findAllFriendVotes/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/findAllFriendVotes/http-response.adoc[] diff --git a/src/docs/asciidoc/find-friends.adoc b/src/docs/asciidoc/find-friends.adoc index e69de29b..6e1584ff 100644 --- a/src/docs/asciidoc/find-friends.adoc +++ b/src/docs/asciidoc/find-friends.adoc @@ -0,0 +1,14 @@ + +== 내 친구 전체 조회하기 + +=== 요청 + +include::{snippets}/api/v1/friend/findAllFriend/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/friend/findAllFriend/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/friend/findAllFriend/http-response.adoc[] diff --git a/src/docs/asciidoc/find-group-friends.adoc b/src/docs/asciidoc/find-group-friends.adoc index e69de29b..d252c9a1 100644 --- a/src/docs/asciidoc/find-group-friends.adoc +++ b/src/docs/asciidoc/find-group-friends.adoc @@ -0,0 +1,13 @@ +== 그룹 추천 친구 조회하기 + +=== 요청 + +include::{snippets}/api/v1/friend/findAllRecommendSchoolFriends/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/friend/findAllRecommendSchoolFriends/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/friend/findAllRecommendSchoolFriends/http-response.adoc[] diff --git a/src/docs/asciidoc/find-kakao-friends.adoc b/src/docs/asciidoc/find-kakao-friends.adoc index e69de29b..16b4ced0 100644 --- a/src/docs/asciidoc/find-kakao-friends.adoc +++ b/src/docs/asciidoc/find-kakao-friends.adoc @@ -0,0 +1,13 @@ +== 카카오 추천 친구 조회하기 + +=== 요청 + +include::{snippets}/api/v1/friend/findAllRecommendKakaoFriends/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/friend/findAllRecommendKakaoFriends/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/friend/findAllRecommendKakaoFriends/http-response.adoc[] diff --git a/src/docs/asciidoc/find-onboarding-friends.adoc b/src/docs/asciidoc/find-onboarding-friends.adoc index e69de29b..f332948a 100644 --- a/src/docs/asciidoc/find-onboarding-friends.adoc +++ b/src/docs/asciidoc/find-onboarding-friends.adoc @@ -0,0 +1,13 @@ +== 가입한 친구 목록 불러오기 + +=== 요청 + +include::{snippets}/api/v1/auth/findOnBoardingFriends/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/auth/findOnBoardingFriends/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/auth/findOnBoardingFriends/http-response.adoc[] diff --git a/src/docs/asciidoc/find-question.adoc b/src/docs/asciidoc/find-question.adoc index e69de29b..587fefec 100644 --- a/src/docs/asciidoc/find-question.adoc +++ b/src/docs/asciidoc/find-question.adoc @@ -0,0 +1,9 @@ +== 투표 질문 조회하기 + +=== 요청 + +include::{snippets}/api/v1/vote/findVoteQuestions/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/findVoteQuestions/http-response.adoc[] diff --git a/src/docs/asciidoc/find-vote.adoc b/src/docs/asciidoc/find-vote.adoc index e69de29b..8b546e30 100644 --- a/src/docs/asciidoc/find-vote.adoc +++ b/src/docs/asciidoc/find-vote.adoc @@ -0,0 +1,13 @@ +== 투표 상세 조회 + +=== 요청 + +include::{snippets}/api/v1/vote/findVoteById/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/vote/findVoteById/path-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/findVoteById/http-response.adoc[] diff --git a/src/docs/asciidoc/find-votes.adoc b/src/docs/asciidoc/find-votes.adoc index e69de29b..93df21d4 100644 --- a/src/docs/asciidoc/find-votes.adoc +++ b/src/docs/asciidoc/find-votes.adoc @@ -0,0 +1,13 @@ +== 내 투표 전체 조회 + +=== 요청 + +include::{snippets}/api/v1/vote/findAllMyVotes/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/vote/findAllMyVotes/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/findAllMyVotes/http-response.adoc[] diff --git a/src/docs/asciidoc/get-unread-vote.adoc b/src/docs/asciidoc/get-unread-vote.adoc index e69de29b..f8ddebda 100644 --- a/src/docs/asciidoc/get-unread-vote.adoc +++ b/src/docs/asciidoc/get-unread-vote.adoc @@ -0,0 +1,9 @@ +== 읽지 않은 쪽지 개수 조회 + +=== 요청 + +include::{snippets}/api/v1/vote/getUnreadVoteCount/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/getUnreadVoteCount/http-response.adoc[] diff --git a/src/docs/asciidoc/google.adoc b/src/docs/asciidoc/google.adoc index e69de29b..1d208f6c 100644 --- a/src/docs/asciidoc/google.adoc +++ b/src/docs/asciidoc/google.adoc @@ -0,0 +1,19 @@ +== Google 구독 구매 검증하기 + +=== 요청 + +include::{snippets}/api/v1/purchase/verifyGoogleSubscriptionTransaction/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/purchase/verifyGoogleSubscriptionTransaction/http-response.adoc[] + +== Google 열람권 구매 검증하기 + +=== 요청 + +include::{snippets}/api/v1/friend/findAllRecommendSchoolFriends/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/purchase/verifyAppleTicketTransaction/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index e69de29b..6e491286 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -0,0 +1,86 @@ += YELL:O API 문서 +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: left +:toclevels: 3 +:sectlinks: + +테스트테스트 + +[[API-List]] +== APIs + +=== Auth API + +* link:login.html[로그인] + +* link:signup.html[회원가입] + +* link:find-onboarding-friends.html[가입한 친구 목록 불러오기] + +* link:search-school.html[대학교 검색하기] + +* link:search-department.html[대학교 학과 검색하기] + +* link:reissue-token.html[토큰 재발급] + +=== User API + +* link:check-user.html[내 정보 조회하기] + +* link:check-user-by-id.html[특정 유저 정보 조회하기] + +* link:device-token.html[디바이스 토큰 수정하기] + +* link:delete-user.html[유저 탈퇴] + +=== Vote API + +* link:find-votes.html[내 투표 전체 조회하기] + +* link:find-friend-votes.html[친구 투표 전체 조회하기] + +* link:find-friend-votes.html[읽지 않은 쪽지 개수 조회하기] + +* link:find-vote.html[투표 상세 조회하기] + +* link:find-question.html[투표 질문 조회하기] + +* link:check-vote-available.html[투표 가능 여부 조회하기] + +* link:create-vote.html[투표 생성하기] + +* link:reveal-name.html[투표 이름 부분 조회하기] + +* link:reveal-full-name.html[투표 이름 전체 조회하기] + +=== Friend API + +* link:add-friend.html[친구 추가하기] + +* link:find-friends.html[친구 전체 조회하기] + +* link:shuffle-friends.html[셔플된 친구 조회하기] + +* link:find-group-friends.html[그룹 추천 친구 조회하기] + +* link:find-kakao-friends.html[카카오 추천 친구 조회하기] + +* link:delete-friend.html[친구 끊기] + +* link:search-friend.html[친구 검색하기] + +=== Purchase API + +* link:apple.html[Apple 결제 관련 API] + +* link:google.html[Google 결제 관련 API] + +* link:sub-check.html[구독 연장 유도 필요 여부 확인하기] + +* link:purchase-check.html[구독 상태 및 열람권 개수 조회하기] + +=== Pay API + +* link:pay.html[결제 전환율 체크] diff --git a/src/docs/asciidoc/login.adoc b/src/docs/asciidoc/login.adoc index e69de29b..76d52f76 100644 --- a/src/docs/asciidoc/login.adoc +++ b/src/docs/asciidoc/login.adoc @@ -0,0 +1,11 @@ +== 소셜 로그인 + +=== 요청 + +include::{snippets}/api/v1/auth/oauthLogin/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/auth/oauthLogin/http-response.adoc[] + + diff --git a/src/docs/asciidoc/overview.adoc b/src/docs/asciidoc/overview.adoc index e69de29b..09d6069a 100644 --- a/src/docs/asciidoc/overview.adoc +++ b/src/docs/asciidoc/overview.adoc @@ -0,0 +1,40 @@ +[[overview]] +== Overview + +[[overview-host]] +=== Host + +|=== +| 환경 | Host + +| Development +| `BE팀에게 문의` + +| Production +| `BE팀에게 문의` +|=== + +[[overview-http-status-codes]] +=== HTTP status codes + +|=== +| 상태 코드 | 설명 + +| `200 OK` +| 성공 + +| `400 Bad Request` +| 잘못된 요청 + +| `401 Unauthorized` +| 비인증 상태 + +| `403 Forbidden` +| 권한 거부 + +| `404 Not Found` +| 존재하지 않는 요청 리소스 + +| `500 Internal Server Error` +| 서버 에러 +|=== diff --git a/src/docs/asciidoc/pay.adoc b/src/docs/asciidoc/pay.adoc index 1fd03e8d..e20bec39 100644 --- a/src/docs/asciidoc/pay.adoc +++ b/src/docs/asciidoc/pay.adoc @@ -1,5 +1,3 @@ -= Friend API - == 친구 추가하기 === 요청 diff --git a/src/docs/asciidoc/purchase-check.adoc b/src/docs/asciidoc/purchase-check.adoc index e69de29b..43c648dd 100644 --- a/src/docs/asciidoc/purchase-check.adoc +++ b/src/docs/asciidoc/purchase-check.adoc @@ -0,0 +1,9 @@ +== 구독 상태 및 열람권 개수 조회하기 + +=== 요청 + +include::{snippets}/api/v1/purchase/getUserPurchaseInfo/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/purchase/getUserPurchaseInfo/http-response.adoc[] diff --git a/src/docs/asciidoc/reissue-token.adoc b/src/docs/asciidoc/reissue-token.adoc index e69de29b..663fb5b8 100644 --- a/src/docs/asciidoc/reissue-token.adoc +++ b/src/docs/asciidoc/reissue-token.adoc @@ -0,0 +1,12 @@ + +== 토큰 재발급 + +operation::api/v1/auth/reIssueToken[snippets='http-request,http-response'] + +=== 요청 + +include::{snippets}/api/v1/auth/reIssueToken/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/auth/reIssueToken/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/reveal-full-name.adoc b/src/docs/asciidoc/reveal-full-name.adoc index e69de29b..c98234c9 100644 --- a/src/docs/asciidoc/reveal-full-name.adoc +++ b/src/docs/asciidoc/reveal-full-name.adoc @@ -0,0 +1,13 @@ +== 투표 이름 전체 조회 + +=== 요청 + +include::{snippets}/api/v1/vote/revealFullName/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/vote/revealFullName/path-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/revealFullName/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/reveal-name.adoc b/src/docs/asciidoc/reveal-name.adoc index e69de29b..d40c61fa 100644 --- a/src/docs/asciidoc/reveal-name.adoc +++ b/src/docs/asciidoc/reveal-name.adoc @@ -0,0 +1,13 @@ +== 투표 이름 부분 조회 + +=== 요청 + +include::{snippets}/api/v1/vote/revealNameHint/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/vote/revealNameHint/path-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/vote/revealNameHint/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/search-department.adoc b/src/docs/asciidoc/search-department.adoc index e69de29b..467e457a 100644 --- a/src/docs/asciidoc/search-department.adoc +++ b/src/docs/asciidoc/search-department.adoc @@ -0,0 +1,13 @@ +== 대학교 학과 검색하기 + +=== 요청 + +include::{snippets}/api/v1/auth/findDepartmentsByKeyword/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/auth/findDepartmentsByKeyword/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/auth/findDepartmentsByKeyword/http-response.adoc[] diff --git a/src/docs/asciidoc/search-friend.adoc b/src/docs/asciidoc/search-friend.adoc index e69de29b..f2cef4f3 100644 --- a/src/docs/asciidoc/search-friend.adoc +++ b/src/docs/asciidoc/search-friend.adoc @@ -0,0 +1,15 @@ + + +== 친구 검색하기 + +=== 요청 + +include::{snippets}/api/v1/friend/searchFriend/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/friend/searchFriend/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/friend/searchFriend/http-response.adoc[] diff --git a/src/docs/asciidoc/search-school.adoc b/src/docs/asciidoc/search-school.adoc index e69de29b..e3713fa6 100644 --- a/src/docs/asciidoc/search-school.adoc +++ b/src/docs/asciidoc/search-school.adoc @@ -0,0 +1,13 @@ +== 대학교 검색하기 + +=== 요청 + +include::{snippets}/api/v1/auth/findSchoolsByKeyword/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/auth/findSchoolsByKeyword/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/auth/findSchoolsByKeyword/http-response.adoc[] diff --git a/src/docs/asciidoc/shuffle-friends.adoc b/src/docs/asciidoc/shuffle-friends.adoc index e69de29b..77b77bac 100644 --- a/src/docs/asciidoc/shuffle-friends.adoc +++ b/src/docs/asciidoc/shuffle-friends.adoc @@ -0,0 +1,9 @@ +== 셔플한 친구 조회하기 + +=== 요청 + +include::{snippets}/api/v1/friend/findShuffledFriend/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/friend/findShuffledFriend/http-response.adoc[] diff --git a/src/docs/asciidoc/signup.adoc b/src/docs/asciidoc/signup.adoc index e69de29b..bd5481cb 100644 --- a/src/docs/asciidoc/signup.adoc +++ b/src/docs/asciidoc/signup.adoc @@ -0,0 +1,9 @@ +== 회원가입 + +=== 요청 + +include::{snippets}/api/v1/auth/postSignUp/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/auth/postSignUp/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/sub-check.adoc b/src/docs/asciidoc/sub-check.adoc index e69de29b..00a19bdf 100644 --- a/src/docs/asciidoc/sub-check.adoc +++ b/src/docs/asciidoc/sub-check.adoc @@ -0,0 +1,9 @@ +== 구독 연장 유도 필요 여부 확인하기 + +=== 요청 + +include::{snippets}/api/v1/purchase/getUserSubscribeNeeded/http-request.adoc[] + +=== 응답 + +include::{snippets}/api/v1/purchase/getUserSubscribeNeeded/http-response.adoc[] diff --git a/src/docs/asciidoc/validate-yelloid.adoc b/src/docs/asciidoc/validate-yelloid.adoc index e69de29b..a917061b 100644 --- a/src/docs/asciidoc/validate-yelloid.adoc +++ b/src/docs/asciidoc/validate-yelloid.adoc @@ -0,0 +1,13 @@ +== 옐로 아이디 중복 확인 + +=== 요청 + +include::{snippets}/api/v1/auth/getYelloIdValidation/http-request.adoc[] + +=== 요청 파라미터 + +include::{snippets}/api/v1/auth/getYelloIdValidation/request-parameters.adoc[] + +=== 응답 + +include::{snippets}/api/v1/auth/getYelloIdValidation/http-response.adoc[] From 5d955358d63af9603cbbc658a2c8027530473c20 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:38:05 +0900 Subject: [PATCH 04/41] =?UTF-8?q?YEL-139=20[test]=20API=20url=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EC=9D=BC=EB=B6=80=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/authorization/FakeAuthManager.java | 2 +- .../authorization/FakeConnectionManager.java | 2 +- .../authorization/small}/AuthManagerTest.java | 18 ++--- .../authorization/small}/AuthServiceTest.java | 32 +++++---- .../cooldown/FakeCooldownRepository.java | 2 +- .../domain/friend/FakeFriendManager.java | 2 +- .../domain/friend/FakeFriendRepository.java | 20 +++--- .../friend/small}/FriendManagerTest.java | 4 +- .../friend/small}/FriendServiceTest.java | 13 ++-- .../domain/group/FakeSchoolRepository.java | 2 +- .../domain/keyword/FakeKeywordRepository.java | 2 +- .../purchase/FakePurchaseRepository.java | 6 +- .../purchase/small}/PurchaseServiceTest.java | 5 +- .../question/FakeQuestionRepository.java | 4 +- .../domain/user/FakeUserManager.java | 2 +- .../domain/user/FakeUserRepository.java | 2 +- .../user/small}/UserManagerTest.java | 3 +- .../user/small}/UserServiceTest.java | 17 ++--- .../domain/vote/FakeVoteManager.java | 2 +- .../domain/vote/FakeVoteRepository.java | 2 +- .../vote/small}/VoteManagerTest.java | 15 ++-- .../vote/small}/VoteServiceTest.java | 24 ++++--- .../firebase/FakeFcmManger.java | 4 +- .../firebase/FcmManagerTest.java | 71 +++++++++++++++++++ .../firebase/NotificationFcmServiceTest.java | 6 +- .../rabbitmq/FakeMessageQueueRepository.java | 2 +- .../rabbitmq/FakeProducerService.java | 2 +- .../redis/FakeTokenRepository.java | 2 +- 28 files changed, 174 insertions(+), 94 deletions(-) rename src/test/java/com/yello/server/{small => }/domain/authorization/FakeAuthManager.java (98%) rename src/test/java/com/yello/server/{small => }/domain/authorization/FakeConnectionManager.java (87%) rename src/test/java/com/yello/server/{small/domain/authorization => domain/authorization/small}/AuthManagerTest.java (89%) rename src/test/java/com/yello/server/{small/domain/authorization => domain/authorization/small}/AuthServiceTest.java (92%) rename src/test/java/com/yello/server/{small => }/domain/cooldown/FakeCooldownRepository.java (96%) rename src/test/java/com/yello/server/{small => }/domain/friend/FakeFriendManager.java (95%) rename src/test/java/com/yello/server/{small => }/domain/friend/FakeFriendRepository.java (89%) rename src/test/java/com/yello/server/{small/domain/friend => domain/friend/small}/FriendManagerTest.java (95%) rename src/test/java/com/yello/server/{small/domain/friend => domain/friend/small}/FriendServiceTest.java (95%) rename src/test/java/com/yello/server/{small => }/domain/group/FakeSchoolRepository.java (97%) rename src/test/java/com/yello/server/{small => }/domain/keyword/FakeKeywordRepository.java (94%) rename src/test/java/com/yello/server/{small => }/domain/purchase/FakePurchaseRepository.java (92%) rename src/test/java/com/yello/server/{small/domain/purchase => domain/purchase/small}/PurchaseServiceTest.java (94%) rename src/test/java/com/yello/server/{small => }/domain/question/FakeQuestionRepository.java (95%) rename src/test/java/com/yello/server/{small => }/domain/user/FakeUserManager.java (97%) rename src/test/java/com/yello/server/{small => }/domain/user/FakeUserRepository.java (99%) rename src/test/java/com/yello/server/{small/domain/user => domain/user/small}/UserManagerTest.java (97%) rename src/test/java/com/yello/server/{small/domain/user => domain/user/small}/UserServiceTest.java (86%) rename src/test/java/com/yello/server/{small => }/domain/vote/FakeVoteManager.java (99%) rename src/test/java/com/yello/server/{small => }/domain/vote/FakeVoteRepository.java (99%) rename src/test/java/com/yello/server/{small/domain/vote => domain/vote/small}/VoteManagerTest.java (88%) rename src/test/java/com/yello/server/{small/domain/vote => domain/vote/small}/VoteServiceTest.java (91%) rename src/test/java/com/yello/server/{small/global => infrastructure}/firebase/FakeFcmManger.java (94%) create mode 100644 src/test/java/com/yello/server/infrastructure/firebase/FcmManagerTest.java rename src/test/java/com/yello/server/{small/global => infrastructure}/firebase/NotificationFcmServiceTest.java (96%) rename src/test/java/com/yello/server/{small/global => infrastructure}/rabbitmq/FakeMessageQueueRepository.java (88%) rename src/test/java/com/yello/server/{small/global => infrastructure}/rabbitmq/FakeProducerService.java (92%) rename src/test/java/com/yello/server/{small/global => infrastructure}/redis/FakeTokenRepository.java (91%) diff --git a/src/test/java/com/yello/server/small/domain/authorization/FakeAuthManager.java b/src/test/java/com/yello/server/domain/authorization/FakeAuthManager.java similarity index 98% rename from src/test/java/com/yello/server/small/domain/authorization/FakeAuthManager.java rename to src/test/java/com/yello/server/domain/authorization/FakeAuthManager.java index b7e82fea..1c99dee5 100644 --- a/src/test/java/com/yello/server/small/domain/authorization/FakeAuthManager.java +++ b/src/test/java/com/yello/server/domain/authorization/FakeAuthManager.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.authorization; +package com.yello.server.domain.authorization; import static com.yello.server.global.common.ErrorCode.NOT_SIGNIN_USER_EXCEPTION; import static com.yello.server.global.common.ErrorCode.UUID_CONFLICT_USER_EXCEPTION; diff --git a/src/test/java/com/yello/server/small/domain/authorization/FakeConnectionManager.java b/src/test/java/com/yello/server/domain/authorization/FakeConnectionManager.java similarity index 87% rename from src/test/java/com/yello/server/small/domain/authorization/FakeConnectionManager.java rename to src/test/java/com/yello/server/domain/authorization/FakeConnectionManager.java index cdf97787..7a3e3ec2 100644 --- a/src/test/java/com/yello/server/small/domain/authorization/FakeConnectionManager.java +++ b/src/test/java/com/yello/server/domain/authorization/FakeConnectionManager.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.authorization; +package com.yello.server.domain.authorization; import com.yello.server.domain.authorization.dto.kakao.KakaoTokenInfo; import com.yello.server.global.common.manager.ConnectionManager; diff --git a/src/test/java/com/yello/server/small/domain/authorization/AuthManagerTest.java b/src/test/java/com/yello/server/domain/authorization/small/AuthManagerTest.java similarity index 89% rename from src/test/java/com/yello/server/small/domain/authorization/AuthManagerTest.java rename to src/test/java/com/yello/server/domain/authorization/small/AuthManagerTest.java index 7844df19..45372428 100644 --- a/src/test/java/com/yello/server/small/domain/authorization/AuthManagerTest.java +++ b/src/test/java/com/yello/server/domain/authorization/small/AuthManagerTest.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.authorization; +package com.yello.server.domain.authorization.small; import static com.yello.server.global.common.ErrorCode.NOT_SIGNIN_USER_EXCEPTION; import static org.assertj.core.api.Assertions.assertThat; @@ -10,20 +10,20 @@ import com.yello.server.domain.authorization.service.AuthManagerImpl; import com.yello.server.domain.authorization.service.TokenJwtProvider; import com.yello.server.domain.authorization.service.TokenProvider; +import com.yello.server.domain.cooldown.FakeCooldownRepository; import com.yello.server.domain.cooldown.repository.CooldownRepository; +import com.yello.server.domain.friend.FakeFriendRepository; import com.yello.server.domain.friend.repository.FriendRepository; +import com.yello.server.domain.question.FakeQuestionRepository; import com.yello.server.domain.question.repository.QuestionRepository; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserRepository; +import com.yello.server.domain.vote.FakeVoteRepository; import com.yello.server.domain.vote.repository.VoteRepository; +import com.yello.server.infrastructure.redis.FakeTokenRepository; import com.yello.server.infrastructure.redis.repository.TokenRepository; -import com.yello.server.small.domain.cooldown.FakeCooldownRepository; -import com.yello.server.small.domain.friend.FakeFriendRepository; -import com.yello.server.small.domain.question.FakeQuestionRepository; -import com.yello.server.small.domain.user.FakeUserRepository; -import com.yello.server.small.domain.vote.FakeVoteRepository; -import com.yello.server.small.global.redis.FakeTokenRepository; -import com.yello.server.util.TestDataUtil; +import com.yello.server.util.TestDataRepositoryUtil; import java.util.Base64; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -40,7 +40,7 @@ public class AuthManagerTest { private final QuestionRepository questionRepository = new FakeQuestionRepository(); private final VoteRepository voteRepository = new FakeVoteRepository(); - private final TestDataUtil testDataUtil = new TestDataUtil( + private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil( userRepository, voteRepository, questionRepository, diff --git a/src/test/java/com/yello/server/small/domain/authorization/AuthServiceTest.java b/src/test/java/com/yello/server/domain/authorization/small/AuthServiceTest.java similarity index 92% rename from src/test/java/com/yello/server/small/domain/authorization/AuthServiceTest.java rename to src/test/java/com/yello/server/domain/authorization/small/AuthServiceTest.java index cfc01289..8bcd38c5 100644 --- a/src/test/java/com/yello/server/small/domain/authorization/AuthServiceTest.java +++ b/src/test/java/com/yello/server/domain/authorization/small/AuthServiceTest.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.authorization; +package com.yello.server.domain.authorization.small; import static com.yello.server.global.common.ErrorCode.GROUPID_NOT_FOUND_GROUP_EXCEPTION; import static com.yello.server.global.common.ErrorCode.UUID_CONFLICT_USER_EXCEPTION; @@ -7,6 +7,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.yello.server.domain.authorization.FakeAuthManager; +import com.yello.server.domain.authorization.FakeConnectionManager; import com.yello.server.domain.authorization.dto.request.OnBoardingFriendRequest; import com.yello.server.domain.authorization.dto.request.SignUpRequest; import com.yello.server.domain.authorization.dto.response.OnBoardingFriend; @@ -17,41 +19,41 @@ import com.yello.server.domain.authorization.service.AuthService; import com.yello.server.domain.authorization.service.TokenJwtProvider; import com.yello.server.domain.authorization.service.TokenProvider; +import com.yello.server.domain.cooldown.FakeCooldownRepository; import com.yello.server.domain.cooldown.entity.Cooldown; import com.yello.server.domain.cooldown.repository.CooldownRepository; +import com.yello.server.domain.friend.FakeFriendManager; +import com.yello.server.domain.friend.FakeFriendRepository; import com.yello.server.domain.friend.repository.FriendRepository; import com.yello.server.domain.friend.service.FriendManager; +import com.yello.server.domain.group.FakeSchoolRepository; import com.yello.server.domain.group.exception.GroupNotFoundException; import com.yello.server.domain.group.repository.SchoolRepository; +import com.yello.server.domain.question.FakeQuestionRepository; import com.yello.server.domain.question.repository.QuestionRepository; +import com.yello.server.domain.user.FakeUserManager; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.Social; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.exception.UserConflictException; import com.yello.server.domain.user.repository.UserRepository; import com.yello.server.domain.user.service.UserManager; +import com.yello.server.domain.vote.FakeVoteManager; +import com.yello.server.domain.vote.FakeVoteRepository; import com.yello.server.domain.vote.repository.VoteRepository; import com.yello.server.domain.vote.service.VoteManager; import com.yello.server.global.common.factory.PaginationFactory; import com.yello.server.global.common.manager.ConnectionManager; +import com.yello.server.infrastructure.firebase.FakeFcmManger; import com.yello.server.infrastructure.firebase.manager.FCMManager; import com.yello.server.infrastructure.firebase.service.NotificationFcmService; import com.yello.server.infrastructure.firebase.service.NotificationService; +import com.yello.server.infrastructure.rabbitmq.FakeMessageQueueRepository; import com.yello.server.infrastructure.rabbitmq.repository.MessageQueueRepository; +import com.yello.server.infrastructure.redis.FakeTokenRepository; import com.yello.server.infrastructure.redis.repository.TokenRepository; -import com.yello.server.small.domain.cooldown.FakeCooldownRepository; -import com.yello.server.small.domain.friend.FakeFriendManager; -import com.yello.server.small.domain.friend.FakeFriendRepository; -import com.yello.server.small.domain.group.FakeSchoolRepository; -import com.yello.server.small.domain.question.FakeQuestionRepository; -import com.yello.server.small.domain.user.FakeUserManager; -import com.yello.server.small.domain.user.FakeUserRepository; -import com.yello.server.small.domain.vote.FakeVoteManager; -import com.yello.server.small.domain.vote.FakeVoteRepository; -import com.yello.server.small.global.firebase.FakeFcmManger; -import com.yello.server.small.global.rabbitmq.FakeMessageQueueRepository; -import com.yello.server.small.global.redis.FakeTokenRepository; -import com.yello.server.util.TestDataUtil; +import com.yello.server.util.TestDataRepositoryUtil; import java.util.ArrayList; import java.util.Base64; import java.util.List; @@ -75,7 +77,7 @@ public class AuthServiceTest { private final VoteRepository voteRepository = new FakeVoteRepository(); private final MessageQueueRepository messageQueueRepository = new FakeMessageQueueRepository(); - private final TestDataUtil testDataUtil = new TestDataUtil( + private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil( userRepository, voteRepository, questionRepository, diff --git a/src/test/java/com/yello/server/small/domain/cooldown/FakeCooldownRepository.java b/src/test/java/com/yello/server/domain/cooldown/FakeCooldownRepository.java similarity index 96% rename from src/test/java/com/yello/server/small/domain/cooldown/FakeCooldownRepository.java rename to src/test/java/com/yello/server/domain/cooldown/FakeCooldownRepository.java index 2060341e..24d62ca9 100644 --- a/src/test/java/com/yello/server/small/domain/cooldown/FakeCooldownRepository.java +++ b/src/test/java/com/yello/server/domain/cooldown/FakeCooldownRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.cooldown; +package com.yello.server.domain.cooldown; import com.yello.server.domain.cooldown.entity.Cooldown; import com.yello.server.domain.cooldown.repository.CooldownRepository; diff --git a/src/test/java/com/yello/server/small/domain/friend/FakeFriendManager.java b/src/test/java/com/yello/server/domain/friend/FakeFriendManager.java similarity index 95% rename from src/test/java/com/yello/server/small/domain/friend/FakeFriendManager.java rename to src/test/java/com/yello/server/domain/friend/FakeFriendManager.java index dada4dd2..912532e8 100644 --- a/src/test/java/com/yello/server/small/domain/friend/FakeFriendManager.java +++ b/src/test/java/com/yello/server/domain/friend/FakeFriendManager.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.friend; +package com.yello.server.domain.friend; import com.yello.server.domain.friend.service.FriendManager; import com.yello.server.domain.user.entity.User; diff --git a/src/test/java/com/yello/server/small/domain/friend/FakeFriendRepository.java b/src/test/java/com/yello/server/domain/friend/FakeFriendRepository.java similarity index 89% rename from src/test/java/com/yello/server/small/domain/friend/FakeFriendRepository.java rename to src/test/java/com/yello/server/domain/friend/FakeFriendRepository.java index dfac562b..ec14dd32 100644 --- a/src/test/java/com/yello/server/small/domain/friend/FakeFriendRepository.java +++ b/src/test/java/com/yello/server/domain/friend/FakeFriendRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.friend; +package com.yello.server.domain.friend; import static com.yello.server.global.common.ErrorCode.NOT_FOUND_FRIEND_EXCEPTION; @@ -19,12 +19,12 @@ public class FakeFriendRepository implements FriendRepository { @Override public Friend save(Friend friend) { - if (friend.getId() != null && friend.getId() > id) { + if (friend.getId()!=null && friend.getId() > id) { id = friend.getId(); } Friend newFriend = Friend.builder() - .id(friend.getId() == null ? ++id : friend.getId()) + .id(friend.getId()==null ? ++id : friend.getId()) .user(friend.getUser()) .target(friend.getTarget()) .deletedAt(null) @@ -43,7 +43,7 @@ public void delete(Friend friend) { public Integer countAllByUserId(Long userId) { return data.stream() .filter( - friend -> friend.getUser().getId().equals(userId) && friend.getDeletedAt() == null) + friend -> friend.getUser().getId().equals(userId) && friend.getDeletedAt()==null) .toList() .size(); } @@ -53,7 +53,7 @@ public Optional findByUserAndTarget(Long userId, Long targetId) { return data.stream() .filter(friend -> friend.getUser().getId().equals(userId) && friend.getTarget().getId() .equals(targetId) - && friend.getDeletedAt() == null) + && friend.getDeletedAt()==null) .findFirst(); } @@ -70,7 +70,7 @@ public Friend getByUserAndTarget(Long userId, Long targetId) { return data.stream() .filter(friend -> friend.getUser().getId().equals(userId) && friend.getTarget().getId().equals(targetId) - && friend.getDeletedAt() == null) + && friend.getDeletedAt()==null) .findFirst() .orElseThrow(() -> new FriendNotFoundException(NOT_FOUND_FRIEND_EXCEPTION)); } @@ -80,14 +80,14 @@ public boolean existsByUserAndTarget(Long userId, Long targetId) { return data.stream() .anyMatch(friend -> friend.getUser().getId().equals(userId) && friend.getTarget().getId().equals(targetId) - && friend.getDeletedAt() == null); + && friend.getDeletedAt()==null); } @Override public Page findAllFriendsByUserId(Pageable pageable, Long userId) { final List friends = data.stream() .filter( - friend -> friend.getUser().getId().equals(userId) && friend.getDeletedAt() == null) + friend -> friend.getUser().getId().equals(userId) && friend.getDeletedAt()==null) .toList(); final int start = (int) pageable.getOffset(); @@ -99,7 +99,7 @@ public Page findAllFriendsByUserId(Pageable pageable, Long userId) { public List findAllByUserId(Long userId) { return data.stream() .filter( - friend -> friend.getUser().getId().equals(userId) && friend.getDeletedAt() == null) + friend -> friend.getUser().getId().equals(userId) && friend.getDeletedAt()==null) .toList(); } @@ -108,7 +108,7 @@ public List findAllByTargetId(Long targetId) { return data.stream() .filter( friend -> friend.getTarget().getId().equals(targetId) - && friend.getDeletedAt() == null) + && friend.getDeletedAt()==null) .toList(); } diff --git a/src/test/java/com/yello/server/small/domain/friend/FriendManagerTest.java b/src/test/java/com/yello/server/domain/friend/small/FriendManagerTest.java similarity index 95% rename from src/test/java/com/yello/server/small/domain/friend/FriendManagerTest.java rename to src/test/java/com/yello/server/domain/friend/small/FriendManagerTest.java index 92d2b971..6074bf04 100644 --- a/src/test/java/com/yello/server/small/domain/friend/FriendManagerTest.java +++ b/src/test/java/com/yello/server/domain/friend/small/FriendManagerTest.java @@ -1,15 +1,15 @@ -package com.yello.server.small.domain.friend; +package com.yello.server.domain.friend.small; import static org.assertj.core.api.Assertions.assertThat; import com.yello.server.domain.friend.service.FriendManager; import com.yello.server.domain.friend.service.FriendManagerImpl; import com.yello.server.domain.group.entity.School; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.Social; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserRepository; -import com.yello.server.small.domain.user.FakeUserRepository; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.BeforeEach; diff --git a/src/test/java/com/yello/server/small/domain/friend/FriendServiceTest.java b/src/test/java/com/yello/server/domain/friend/small/FriendServiceTest.java similarity index 95% rename from src/test/java/com/yello/server/small/domain/friend/FriendServiceTest.java rename to src/test/java/com/yello/server/domain/friend/small/FriendServiceTest.java index d5ed5251..d013e4ad 100644 --- a/src/test/java/com/yello/server/small/domain/friend/FriendServiceTest.java +++ b/src/test/java/com/yello/server/domain/friend/small/FriendServiceTest.java @@ -1,10 +1,11 @@ -package com.yello.server.small.domain.friend; +package com.yello.server.domain.friend.small; import static com.yello.server.global.common.factory.PaginationFactory.createPageable; import static com.yello.server.global.common.factory.PaginationFactory.createPageableLimitTen; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.yello.server.domain.friend.FakeFriendRepository; import com.yello.server.domain.friend.dto.request.KakaoRecommendRequest; import com.yello.server.domain.friend.dto.response.FriendShuffleResponse; import com.yello.server.domain.friend.dto.response.FriendsResponse; @@ -15,15 +16,15 @@ import com.yello.server.domain.friend.exception.FriendNotFoundException; import com.yello.server.domain.friend.repository.FriendRepository; import com.yello.server.domain.friend.service.FriendService; +import com.yello.server.domain.question.FakeQuestionRepository; import com.yello.server.domain.question.repository.QuestionRepository; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.exception.UserNotFoundException; import com.yello.server.domain.user.repository.UserRepository; +import com.yello.server.domain.vote.FakeVoteRepository; import com.yello.server.domain.vote.repository.VoteRepository; -import com.yello.server.small.domain.question.FakeQuestionRepository; -import com.yello.server.small.domain.user.FakeUserRepository; -import com.yello.server.small.domain.vote.FakeVoteRepository; -import com.yello.server.util.TestDataUtil; +import com.yello.server.util.TestDataRepositoryUtil; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; @@ -37,7 +38,7 @@ class FriendServiceTest { private final FriendRepository friendRepository = new FakeFriendRepository(); private final VoteRepository voteRepository = new FakeVoteRepository(); private final QuestionRepository questionRepository = new FakeQuestionRepository(); - private final TestDataUtil testDataUtil = new TestDataUtil( + private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil( userRepository, voteRepository, questionRepository, diff --git a/src/test/java/com/yello/server/small/domain/group/FakeSchoolRepository.java b/src/test/java/com/yello/server/domain/group/FakeSchoolRepository.java similarity index 97% rename from src/test/java/com/yello/server/small/domain/group/FakeSchoolRepository.java rename to src/test/java/com/yello/server/domain/group/FakeSchoolRepository.java index e4cb1c71..d1c3cbbc 100644 --- a/src/test/java/com/yello/server/small/domain/group/FakeSchoolRepository.java +++ b/src/test/java/com/yello/server/domain/group/FakeSchoolRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.group; +package com.yello.server.domain.group; import static com.yello.server.global.common.ErrorCode.GROUPID_NOT_FOUND_GROUP_EXCEPTION; diff --git a/src/test/java/com/yello/server/small/domain/keyword/FakeKeywordRepository.java b/src/test/java/com/yello/server/domain/keyword/FakeKeywordRepository.java similarity index 94% rename from src/test/java/com/yello/server/small/domain/keyword/FakeKeywordRepository.java rename to src/test/java/com/yello/server/domain/keyword/FakeKeywordRepository.java index 26cc4a49..a9c3640b 100644 --- a/src/test/java/com/yello/server/small/domain/keyword/FakeKeywordRepository.java +++ b/src/test/java/com/yello/server/domain/keyword/FakeKeywordRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.keyword; +package com.yello.server.domain.keyword; import com.yello.server.domain.keyword.entity.Keyword; import com.yello.server.domain.keyword.repository.KeywordRepository; diff --git a/src/test/java/com/yello/server/small/domain/purchase/FakePurchaseRepository.java b/src/test/java/com/yello/server/domain/purchase/FakePurchaseRepository.java similarity index 92% rename from src/test/java/com/yello/server/small/domain/purchase/FakePurchaseRepository.java rename to src/test/java/com/yello/server/domain/purchase/FakePurchaseRepository.java index 7a571aa3..4fe49ea4 100644 --- a/src/test/java/com/yello/server/small/domain/purchase/FakePurchaseRepository.java +++ b/src/test/java/com/yello/server/domain/purchase/FakePurchaseRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.purchase; +package com.yello.server.domain.purchase; import com.yello.server.domain.purchase.entity.ProductType; import com.yello.server.domain.purchase.entity.Purchase; @@ -18,12 +18,12 @@ public class FakePurchaseRepository implements PurchaseRepository { @Override public Purchase save(Purchase purchase) { - if (purchase.getId() != null && purchase.getId() > id) { + if (purchase.getId()!=null && purchase.getId() > id) { id = purchase.getId(); } final Purchase newPurchase = Purchase.builder() - .id(purchase.getId() == null ? ++id : purchase.getId()) + .id(purchase.getId()==null ? ++id : purchase.getId()) .price(purchase.getPrice()) .user(purchase.getUser()) .gateway(purchase.getGateway()) diff --git a/src/test/java/com/yello/server/small/domain/purchase/PurchaseServiceTest.java b/src/test/java/com/yello/server/domain/purchase/small/PurchaseServiceTest.java similarity index 94% rename from src/test/java/com/yello/server/small/domain/purchase/PurchaseServiceTest.java rename to src/test/java/com/yello/server/domain/purchase/small/PurchaseServiceTest.java index 300f645c..bbb454f6 100644 --- a/src/test/java/com/yello/server/small/domain/purchase/PurchaseServiceTest.java +++ b/src/test/java/com/yello/server/domain/purchase/small/PurchaseServiceTest.java @@ -1,20 +1,21 @@ -package com.yello.server.small.domain.purchase; +package com.yello.server.domain.purchase.small; import static org.assertj.core.api.Assertions.assertThat; import com.yello.server.domain.group.entity.School; +import com.yello.server.domain.purchase.FakePurchaseRepository; import com.yello.server.domain.purchase.dto.response.UserSubscribeNeededResponse; import com.yello.server.domain.purchase.entity.Gateway; import com.yello.server.domain.purchase.entity.ProductType; import com.yello.server.domain.purchase.entity.Purchase; import com.yello.server.domain.purchase.repository.PurchaseRepository; import com.yello.server.domain.purchase.service.PurchaseService; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.Social; import com.yello.server.domain.user.entity.Subscribe; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserRepository; -import com.yello.server.small.domain.user.FakeUserRepository; import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/yello/server/small/domain/question/FakeQuestionRepository.java b/src/test/java/com/yello/server/domain/question/FakeQuestionRepository.java similarity index 95% rename from src/test/java/com/yello/server/small/domain/question/FakeQuestionRepository.java rename to src/test/java/com/yello/server/domain/question/FakeQuestionRepository.java index 8a3942c3..da1ab169 100644 --- a/src/test/java/com/yello/server/small/domain/question/FakeQuestionRepository.java +++ b/src/test/java/com/yello/server/domain/question/FakeQuestionRepository.java @@ -1,13 +1,13 @@ -package com.yello.server.small.domain.question; +package com.yello.server.domain.question; import static com.yello.server.global.common.ErrorCode.NOT_FOUND_QUESTION_EXCEPTION; +import com.yello.server.domain.keyword.FakeKeywordRepository; import com.yello.server.domain.keyword.entity.Keyword; import com.yello.server.domain.keyword.repository.KeywordRepository; import com.yello.server.domain.question.entity.Question; import com.yello.server.domain.question.exception.QuestionNotFoundException; import com.yello.server.domain.question.repository.QuestionRepository; -import com.yello.server.small.domain.keyword.FakeKeywordRepository; import java.util.ArrayList; import java.util.List; import java.util.Objects; diff --git a/src/test/java/com/yello/server/small/domain/user/FakeUserManager.java b/src/test/java/com/yello/server/domain/user/FakeUserManager.java similarity index 97% rename from src/test/java/com/yello/server/small/domain/user/FakeUserManager.java rename to src/test/java/com/yello/server/domain/user/FakeUserManager.java index 44d671a0..98786e09 100644 --- a/src/test/java/com/yello/server/small/domain/user/FakeUserManager.java +++ b/src/test/java/com/yello/server/domain/user/FakeUserManager.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.user; +package com.yello.server.domain.user; import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.Social; diff --git a/src/test/java/com/yello/server/small/domain/user/FakeUserRepository.java b/src/test/java/com/yello/server/domain/user/FakeUserRepository.java similarity index 99% rename from src/test/java/com/yello/server/small/domain/user/FakeUserRepository.java rename to src/test/java/com/yello/server/domain/user/FakeUserRepository.java index f9f88b1c..79f349a2 100644 --- a/src/test/java/com/yello/server/small/domain/user/FakeUserRepository.java +++ b/src/test/java/com/yello/server/domain/user/FakeUserRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.user; +package com.yello.server.domain.user; import static com.yello.server.global.common.ErrorCode.AUTH_UUID_NOT_FOUND_USER_EXCEPTION; import static com.yello.server.global.common.ErrorCode.USERID_NOT_FOUND_USER_EXCEPTION; diff --git a/src/test/java/com/yello/server/small/domain/user/UserManagerTest.java b/src/test/java/com/yello/server/domain/user/small/UserManagerTest.java similarity index 97% rename from src/test/java/com/yello/server/small/domain/user/UserManagerTest.java rename to src/test/java/com/yello/server/domain/user/small/UserManagerTest.java index 399be9f5..3d9d4477 100644 --- a/src/test/java/com/yello/server/small/domain/user/UserManagerTest.java +++ b/src/test/java/com/yello/server/domain/user/small/UserManagerTest.java @@ -1,8 +1,9 @@ -package com.yello.server.small.domain.user; +package com.yello.server.domain.user.small; import static org.assertj.core.api.Assertions.assertThat; import com.yello.server.domain.group.entity.School; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.Social; import com.yello.server.domain.user.entity.User; diff --git a/src/test/java/com/yello/server/small/domain/user/UserServiceTest.java b/src/test/java/com/yello/server/domain/user/small/UserServiceTest.java similarity index 86% rename from src/test/java/com/yello/server/small/domain/user/UserServiceTest.java rename to src/test/java/com/yello/server/domain/user/small/UserServiceTest.java index ba57057f..5ffd7f88 100644 --- a/src/test/java/com/yello/server/small/domain/user/UserServiceTest.java +++ b/src/test/java/com/yello/server/domain/user/small/UserServiceTest.java @@ -1,25 +1,26 @@ -package com.yello.server.small.domain.user; +package com.yello.server.domain.user.small; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.yello.server.domain.cooldown.FakeCooldownRepository; import com.yello.server.domain.cooldown.repository.CooldownRepository; +import com.yello.server.domain.friend.FakeFriendRepository; import com.yello.server.domain.friend.repository.FriendRepository; +import com.yello.server.domain.question.FakeQuestionRepository; import com.yello.server.domain.question.repository.QuestionRepository; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.dto.response.UserDetailResponse; import com.yello.server.domain.user.dto.response.UserResponse; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.exception.UserNotFoundException; import com.yello.server.domain.user.repository.UserRepository; import com.yello.server.domain.user.service.UserService; +import com.yello.server.domain.vote.FakeVoteRepository; import com.yello.server.domain.vote.repository.VoteRepository; +import com.yello.server.infrastructure.redis.FakeTokenRepository; import com.yello.server.infrastructure.redis.repository.TokenRepository; -import com.yello.server.small.domain.cooldown.FakeCooldownRepository; -import com.yello.server.small.domain.friend.FakeFriendRepository; -import com.yello.server.small.domain.question.FakeQuestionRepository; -import com.yello.server.small.domain.vote.FakeVoteRepository; -import com.yello.server.small.global.redis.FakeTokenRepository; -import com.yello.server.util.TestDataUtil; +import com.yello.server.util.TestDataRepositoryUtil; import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,7 +33,7 @@ class UserServiceTest { private final CooldownRepository cooldownRepository = new FakeCooldownRepository(); private final TokenRepository tokenRepository = new FakeTokenRepository(); private final QuestionRepository questionRepository = new FakeQuestionRepository(); - private final TestDataUtil testDataUtil = new TestDataUtil( + private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil( userRepository, voteRepository, questionRepository, diff --git a/src/test/java/com/yello/server/small/domain/vote/FakeVoteManager.java b/src/test/java/com/yello/server/domain/vote/FakeVoteManager.java similarity index 99% rename from src/test/java/com/yello/server/small/domain/vote/FakeVoteManager.java rename to src/test/java/com/yello/server/domain/vote/FakeVoteManager.java index f3729f3a..85c0d20b 100644 --- a/src/test/java/com/yello/server/small/domain/vote/FakeVoteManager.java +++ b/src/test/java/com/yello/server/domain/vote/FakeVoteManager.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.vote; +package com.yello.server.domain.vote; import static com.yello.server.domain.vote.common.WeightedRandomFactory.randomPoint; import static com.yello.server.global.common.ErrorCode.DUPLICATE_VOTE_EXCEPTION; diff --git a/src/test/java/com/yello/server/small/domain/vote/FakeVoteRepository.java b/src/test/java/com/yello/server/domain/vote/FakeVoteRepository.java similarity index 99% rename from src/test/java/com/yello/server/small/domain/vote/FakeVoteRepository.java rename to src/test/java/com/yello/server/domain/vote/FakeVoteRepository.java index ec33f7f4..15ea84ed 100644 --- a/src/test/java/com/yello/server/small/domain/vote/FakeVoteRepository.java +++ b/src/test/java/com/yello/server/domain/vote/FakeVoteRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.domain.vote; +package com.yello.server.domain.vote; import static com.yello.server.global.common.ErrorCode.NOT_FOUND_VOTE_EXCEPTION; diff --git a/src/test/java/com/yello/server/small/domain/vote/VoteManagerTest.java b/src/test/java/com/yello/server/domain/vote/small/VoteManagerTest.java similarity index 88% rename from src/test/java/com/yello/server/small/domain/vote/VoteManagerTest.java rename to src/test/java/com/yello/server/domain/vote/small/VoteManagerTest.java index f9cc2a07..8e8dd211 100644 --- a/src/test/java/com/yello/server/small/domain/vote/VoteManagerTest.java +++ b/src/test/java/com/yello/server/domain/vote/small/VoteManagerTest.java @@ -1,23 +1,24 @@ -package com.yello.server.small.domain.vote; +package com.yello.server.domain.vote.small; import static com.yello.server.global.common.factory.PaginationFactory.createPageable; import static org.assertj.core.api.Assertions.assertThat; +import com.yello.server.domain.friend.FakeFriendRepository; import com.yello.server.domain.friend.repository.FriendRepository; +import com.yello.server.domain.question.FakeQuestionRepository; import com.yello.server.domain.question.entity.Question; import com.yello.server.domain.question.repository.QuestionRepository; +import com.yello.server.domain.user.FakeUserManager; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserRepository; import com.yello.server.domain.user.service.UserManager; +import com.yello.server.domain.vote.FakeVoteRepository; import com.yello.server.domain.vote.entity.Vote; import com.yello.server.domain.vote.repository.VoteRepository; import com.yello.server.domain.vote.service.VoteManager; import com.yello.server.domain.vote.service.VoteManagerImpl; -import com.yello.server.small.domain.friend.FakeFriendRepository; -import com.yello.server.small.domain.question.FakeQuestionRepository; -import com.yello.server.small.domain.user.FakeUserManager; -import com.yello.server.small.domain.user.FakeUserRepository; -import com.yello.server.util.TestDataUtil; +import com.yello.server.util.TestDataRepositoryUtil; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeEach; @@ -30,7 +31,7 @@ public class VoteManagerTest { private final FriendRepository friendRepository = new FakeFriendRepository(); private final VoteRepository voteRepository = new FakeVoteRepository(); private final QuestionRepository questionRepository = new FakeQuestionRepository(); - private final TestDataUtil testDataUtil = new TestDataUtil( + private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil( userRepository, voteRepository, questionRepository, diff --git a/src/test/java/com/yello/server/small/domain/vote/VoteServiceTest.java b/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java similarity index 91% rename from src/test/java/com/yello/server/small/domain/vote/VoteServiceTest.java rename to src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java index d0848d95..99508d81 100644 --- a/src/test/java/com/yello/server/small/domain/vote/VoteServiceTest.java +++ b/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java @@ -1,18 +1,26 @@ -package com.yello.server.small.domain.vote; +package com.yello.server.domain.vote.small; import static com.yello.server.global.common.factory.PaginationFactory.createPageable; import static org.assertj.core.api.Assertions.assertThat; +import com.yello.server.domain.cooldown.FakeCooldownRepository; import com.yello.server.domain.cooldown.repository.CooldownRepository; +import com.yello.server.domain.friend.FakeFriendRepository; import com.yello.server.domain.friend.repository.FriendRepository; +import com.yello.server.domain.keyword.FakeKeywordRepository; import com.yello.server.domain.keyword.dto.response.KeywordCheckResponse; import com.yello.server.domain.keyword.repository.KeywordRepository; +import com.yello.server.domain.question.FakeQuestionRepository; import com.yello.server.domain.question.dto.response.QuestionForVoteResponse; import com.yello.server.domain.question.entity.Question; import com.yello.server.domain.question.repository.QuestionRepository; +import com.yello.server.domain.user.FakeUserManager; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserRepository; import com.yello.server.domain.user.service.UserManager; +import com.yello.server.domain.vote.FakeVoteManager; +import com.yello.server.domain.vote.FakeVoteRepository; import com.yello.server.domain.vote.dto.request.CreateVoteRequest; import com.yello.server.domain.vote.dto.request.VoteAnswer; import com.yello.server.domain.vote.dto.response.RevealNameResponse; @@ -26,16 +34,10 @@ import com.yello.server.domain.vote.repository.VoteRepository; import com.yello.server.domain.vote.service.VoteManager; import com.yello.server.domain.vote.service.VoteService; +import com.yello.server.infrastructure.rabbitmq.FakeMessageQueueRepository; +import com.yello.server.infrastructure.rabbitmq.FakeProducerService; import com.yello.server.infrastructure.rabbitmq.service.ProducerService; -import com.yello.server.small.domain.cooldown.FakeCooldownRepository; -import com.yello.server.small.domain.friend.FakeFriendRepository; -import com.yello.server.small.domain.keyword.FakeKeywordRepository; -import com.yello.server.small.domain.question.FakeQuestionRepository; -import com.yello.server.small.domain.user.FakeUserManager; -import com.yello.server.small.domain.user.FakeUserRepository; -import com.yello.server.small.global.rabbitmq.FakeMessageQueueRepository; -import com.yello.server.small.global.rabbitmq.FakeProducerService; -import com.yello.server.util.TestDataUtil; +import com.yello.server.util.TestDataRepositoryUtil; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.AfterEach; @@ -61,7 +63,7 @@ public class VoteServiceTest { userManager ); - private final TestDataUtil testDataUtil = new TestDataUtil( + private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil( userRepository, voteRepository, questionRepository, diff --git a/src/test/java/com/yello/server/small/global/firebase/FakeFcmManger.java b/src/test/java/com/yello/server/infrastructure/firebase/FakeFcmManger.java similarity index 94% rename from src/test/java/com/yello/server/small/global/firebase/FakeFcmManger.java rename to src/test/java/com/yello/server/infrastructure/firebase/FakeFcmManger.java index 3efcae87..aa42ffd6 100644 --- a/src/test/java/com/yello/server/small/global/firebase/FakeFcmManger.java +++ b/src/test/java/com/yello/server/infrastructure/firebase/FakeFcmManger.java @@ -1,12 +1,12 @@ -package com.yello.server.small.global.firebase; +package com.yello.server.infrastructure.firebase; import com.google.firebase.messaging.ApnsConfig; import com.google.firebase.messaging.Aps; import com.google.firebase.messaging.Message; +import com.yello.server.domain.vote.FakeVoteRepository; import com.yello.server.domain.vote.repository.VoteRepository; import com.yello.server.infrastructure.firebase.dto.request.NotificationMessage; import com.yello.server.infrastructure.firebase.manager.FCMManager; -import com.yello.server.small.domain.vote.FakeVoteRepository; public class FakeFcmManger implements FCMManager { diff --git a/src/test/java/com/yello/server/infrastructure/firebase/FcmManagerTest.java b/src/test/java/com/yello/server/infrastructure/firebase/FcmManagerTest.java new file mode 100644 index 00000000..d8bff141 --- /dev/null +++ b/src/test/java/com/yello/server/infrastructure/firebase/FcmManagerTest.java @@ -0,0 +1,71 @@ +package com.yello.server.infrastructure.firebase; + +import com.yello.server.domain.friend.FakeFriendRepository; +import com.yello.server.domain.friend.repository.FriendRepository; +import com.yello.server.domain.question.FakeQuestionRepository; +import com.yello.server.domain.question.entity.Question; +import com.yello.server.domain.question.repository.QuestionRepository; +import com.yello.server.domain.user.FakeUserRepository; +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.repository.UserRepository; +import com.yello.server.domain.vote.FakeVoteRepository; +import com.yello.server.domain.vote.repository.VoteRepository; +import com.yello.server.infrastructure.firebase.dto.request.NotificationMessage; +import com.yello.server.infrastructure.firebase.manager.FCMManager; +import com.yello.server.infrastructure.firebase.manager.FCMManagerImpl; +import com.yello.server.util.TestDataRepositoryUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class FcmManagerTest { + + private final UserRepository userRepository = new FakeUserRepository(); + private final VoteRepository voteRepository = new FakeVoteRepository(); + private final QuestionRepository questionRepository = new FakeQuestionRepository(); + private final FriendRepository friendRepository = new FakeFriendRepository(); + + private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil( + userRepository, + voteRepository, + questionRepository, + friendRepository + ); + + private FCMManager fcmManager; + + @BeforeEach + void init() { + this.fcmManager = FCMManagerImpl.builder() + .voteRepository(voteRepository) + .build(); + + User user = testDataUtil.generateUser(1L, 1L); + User target = testDataUtil.generateUser(2L, 1L); + Question question = testDataUtil.generateQuestion(1L); + testDataUtil.generateVote(1L, user, target, question); + } + + @Test + void path를_제외한_메세지_객체_생성에_성공합니다() { + // given + final String testDeviceToken = "testDeviceToken"; + final NotificationMessage notificationMessage = NotificationMessage.toVoteAvailableNotificationContent(); + + // when + // then + fcmManager.createMessage(testDeviceToken, notificationMessage); + } + + @Test + void path를_포함한_메세지_객체_생성에_성공합니다() { + // given + final String path = "/api/v1/vote/1"; + final String testDeviceToken = "deviceToken#2"; + final NotificationMessage notificationMessage = NotificationMessage.toVoteAvailableNotificationContent(); + + // when + // then + fcmManager.createMessage(testDeviceToken, notificationMessage, path); + } + +} diff --git a/src/test/java/com/yello/server/small/global/firebase/NotificationFcmServiceTest.java b/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java similarity index 96% rename from src/test/java/com/yello/server/small/global/firebase/NotificationFcmServiceTest.java rename to src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java index f14921bb..0bb02a20 100644 --- a/src/test/java/com/yello/server/small/global/firebase/NotificationFcmServiceTest.java +++ b/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java @@ -1,10 +1,11 @@ -package com.yello.server.small.global.firebase; +package com.yello.server.infrastructure.firebase; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.yello.server.domain.friend.entity.Friend; import com.yello.server.domain.group.entity.School; import com.yello.server.domain.question.entity.Question; +import com.yello.server.domain.user.FakeUserRepository; import com.yello.server.domain.user.entity.Gender; import com.yello.server.domain.user.entity.Social; import com.yello.server.domain.user.entity.User; @@ -14,9 +15,8 @@ import com.yello.server.infrastructure.firebase.manager.FCMManager; import com.yello.server.infrastructure.firebase.service.NotificationFcmService; import com.yello.server.infrastructure.firebase.service.NotificationService; +import com.yello.server.infrastructure.redis.FakeTokenRepository; import com.yello.server.infrastructure.redis.repository.TokenRepository; -import com.yello.server.small.domain.user.FakeUserRepository; -import com.yello.server.small.global.redis.FakeTokenRepository; import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/yello/server/small/global/rabbitmq/FakeMessageQueueRepository.java b/src/test/java/com/yello/server/infrastructure/rabbitmq/FakeMessageQueueRepository.java similarity index 88% rename from src/test/java/com/yello/server/small/global/rabbitmq/FakeMessageQueueRepository.java rename to src/test/java/com/yello/server/infrastructure/rabbitmq/FakeMessageQueueRepository.java index 66c85685..67521f3a 100644 --- a/src/test/java/com/yello/server/small/global/rabbitmq/FakeMessageQueueRepository.java +++ b/src/test/java/com/yello/server/infrastructure/rabbitmq/FakeMessageQueueRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.global.rabbitmq; +package com.yello.server.infrastructure.rabbitmq; import com.yello.server.infrastructure.rabbitmq.repository.MessageQueueRepository; import org.springframework.amqp.core.MessagePostProcessor; diff --git a/src/test/java/com/yello/server/small/global/rabbitmq/FakeProducerService.java b/src/test/java/com/yello/server/infrastructure/rabbitmq/FakeProducerService.java similarity index 92% rename from src/test/java/com/yello/server/small/global/rabbitmq/FakeProducerService.java rename to src/test/java/com/yello/server/infrastructure/rabbitmq/FakeProducerService.java index 0458d0d6..eea2c34d 100644 --- a/src/test/java/com/yello/server/small/global/rabbitmq/FakeProducerService.java +++ b/src/test/java/com/yello/server/infrastructure/rabbitmq/FakeProducerService.java @@ -1,4 +1,4 @@ -package com.yello.server.small.global.rabbitmq; +package com.yello.server.infrastructure.rabbitmq; import com.yello.server.domain.cooldown.entity.Cooldown; import com.yello.server.infrastructure.rabbitmq.repository.MessageQueueRepository; diff --git a/src/test/java/com/yello/server/small/global/redis/FakeTokenRepository.java b/src/test/java/com/yello/server/infrastructure/redis/FakeTokenRepository.java similarity index 91% rename from src/test/java/com/yello/server/small/global/redis/FakeTokenRepository.java rename to src/test/java/com/yello/server/infrastructure/redis/FakeTokenRepository.java index 483b1e7a..bc2133a0 100644 --- a/src/test/java/com/yello/server/small/global/redis/FakeTokenRepository.java +++ b/src/test/java/com/yello/server/infrastructure/redis/FakeTokenRepository.java @@ -1,4 +1,4 @@ -package com.yello.server.small.global.redis; +package com.yello.server.infrastructure.redis; import com.yello.server.domain.authorization.dto.ServiceTokenVO; import com.yello.server.infrastructure.redis.repository.TokenRepository; From eebd3fb4ef477a8f215ed033bcd8cbe8ac8dc1fa Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:38:24 +0900 Subject: [PATCH 05/41] =?UTF-8?q?YEL-139=20[test]=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=9C=A0=ED=8B=B8=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yello/server/util/TestDataEntityUtil.java | 109 +++++++++++++++ .../server/util/TestDataRepositoryUtil.java | 124 ++++++++++++++++++ .../com/yello/server/util/TestDataUtil.java | 111 ++-------------- .../server/util/WithAccessTokenUser.java | 11 ++ .../WithAccessTokenUserSecurityFactory.java | 56 ++++++++ 5 files changed, 308 insertions(+), 103 deletions(-) create mode 100644 src/test/java/com/yello/server/util/TestDataEntityUtil.java create mode 100644 src/test/java/com/yello/server/util/TestDataRepositoryUtil.java create mode 100644 src/test/java/com/yello/server/util/WithAccessTokenUser.java create mode 100644 src/test/java/com/yello/server/util/WithAccessTokenUserSecurityFactory.java diff --git a/src/test/java/com/yello/server/util/TestDataEntityUtil.java b/src/test/java/com/yello/server/util/TestDataEntityUtil.java new file mode 100644 index 00000000..d0275790 --- /dev/null +++ b/src/test/java/com/yello/server/util/TestDataEntityUtil.java @@ -0,0 +1,109 @@ +package com.yello.server.util; + +import com.yello.server.domain.friend.entity.Friend; +import com.yello.server.domain.group.entity.School; +import com.yello.server.domain.question.entity.Question; +import com.yello.server.domain.user.entity.Gender; +import com.yello.server.domain.user.entity.Social; +import com.yello.server.domain.user.entity.Subscribe; +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.vote.entity.Vote; +import java.time.LocalDateTime; + +public class TestDataEntityUtil implements TestDataUtil { + + @Override + public User generateUser(long index, long schoolIndex) { + School school = School.builder() + .id(schoolIndex) + .schoolName("테스트 대학교 %d".formatted(index)) + .departmentName("테스트 학과 %d".formatted(index)) + .build(); + + return User.builder() + .id((index)) + .recommendCount(0L) + .name("name%d".formatted(index)) + .yelloId("yelloId%d".formatted(index)) + .gender(Gender.MALE) + .point(200) + .social(Social.KAKAO) + .profileImage("test image") + .uuid("%d".formatted(index)) + .deletedAt(null) + .group(school) + .groupAdmissionYear(20) + .deviceToken("deviceToken#%d".formatted(index)) + .subscribe(Subscribe.NORMAL) + .ticketCount(0) + .email("test%d@test.com".formatted(index)) + .build(); + } + + @Override + public User generateDeletedUser(long index, long schoolIndex) { + School school = School.builder() + .id(schoolIndex) + .schoolName("테스트 대학교 %d".formatted(index)) + .departmentName("테스트 학과 %d".formatted(index)) + .build(); + + return User.builder() + .id(index) + .recommendCount(0L) + .name("name%d".formatted(index)) + .yelloId("yelloId%d".formatted(index)) + .gender(Gender.MALE) + .point(0) + .social(Social.KAKAO) + .profileImage("test image") + .uuid("%d".formatted(index)) + .deletedAt(LocalDateTime.now()) + .group(school) + .groupAdmissionYear(20) + .deviceToken(null) + .subscribe(Subscribe.NORMAL) + .ticketCount(0) + .email("test%d@test.com".formatted(index)) + .build(); + } + + @Override + public Friend generateFriend(User user, User target) { + return Friend.createFriend(user, target); + } + + @Override + public Vote generateVote(long index, User sender, User receiver, Question question) { + return Vote.builder() + .id(index) + .colorIndex(0) + .answer("test") + .isRead(false) + .nameHint(-1) + .isAnswerRevealed(false) + .sender(sender) + .receiver(receiver) + .question(question) + .createdAt(LocalDateTime.now()) + .build(); + } + + @Override + public Question generateQuestion(long index) { + return Question.builder() + .id(index) + .nameHead("나는").nameFoot("와") + .keywordHead("멋진").keywordFoot("에서 놀고싶어") + .build(); + } + + @Override + public School generateSchool(long index) { + return School.builder() + .id(index) + .schoolName("테스트 대학교 %d".formatted(index)) + .departmentName("테스트 학과 %d".formatted(index)) + .build(); + } +} diff --git a/src/test/java/com/yello/server/util/TestDataRepositoryUtil.java b/src/test/java/com/yello/server/util/TestDataRepositoryUtil.java new file mode 100644 index 00000000..a36c6873 --- /dev/null +++ b/src/test/java/com/yello/server/util/TestDataRepositoryUtil.java @@ -0,0 +1,124 @@ +package com.yello.server.util; + +import com.yello.server.domain.friend.entity.Friend; +import com.yello.server.domain.friend.repository.FriendRepository; +import com.yello.server.domain.group.entity.School; +import com.yello.server.domain.question.entity.Question; +import com.yello.server.domain.question.repository.QuestionRepository; +import com.yello.server.domain.user.entity.Gender; +import com.yello.server.domain.user.entity.Social; +import com.yello.server.domain.user.entity.Subscribe; +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.repository.UserRepository; +import com.yello.server.domain.vote.entity.Vote; +import com.yello.server.domain.vote.repository.VoteRepository; +import java.time.LocalDateTime; + +public class TestDataRepositoryUtil implements TestDataUtil { + + private final UserRepository userRepository; + private final VoteRepository voteRepository; + private final QuestionRepository questionRepository; + private final FriendRepository friendRepository; + + public TestDataRepositoryUtil(UserRepository userRepository, VoteRepository voteRepository, + QuestionRepository questionRepository, + FriendRepository friendRepository) { + this.userRepository = userRepository; + this.voteRepository = voteRepository; + this.questionRepository = questionRepository; + this.friendRepository = friendRepository; + } + + @Override + public User generateUser(long index, long schoolIndex) { + School school = generateSchool(schoolIndex); + + return userRepository.save(User.builder() + .id((index)) + .recommendCount(0L) + .name("name%d".formatted(index)) + .yelloId("yelloId%d".formatted(index)) + .gender(Gender.MALE) + .point(200) + .social(Social.KAKAO) + .profileImage("test image") + .uuid("%d".formatted(index)) + .deletedAt(null) + .group(school) + .groupAdmissionYear(20) + .deviceToken("deviceToken#%d".formatted(index)) + .subscribe(Subscribe.NORMAL) + .ticketCount(0) + .email("test%d@test.com".formatted(index)) + .build()); + } + + @Override + public User generateDeletedUser(long index, long schoolIndex) { + School school = generateSchool(schoolIndex); + + return userRepository.save(User.builder() + .id(index) + .recommendCount(0L) + .name("name%d".formatted(index)) + .yelloId("yelloId%d".formatted(index)) + .gender(Gender.MALE) + .point(0) + .social(Social.KAKAO) + .profileImage("test image") + .uuid("%d".formatted(index)) + .deletedAt(LocalDateTime.now()) + .group(school) + .groupAdmissionYear(20) + .deviceToken(null) + .subscribe(Subscribe.NORMAL) + .ticketCount(0) + .email("test%d@test.com".formatted(index)) + .build()); + } + + @Override + public Friend generateFriend(User user, User target) { + return friendRepository.save(Friend.createFriend(user, target)); + } + + @Override + public Vote generateVote(long index, User sender, User receiver, Question question) { + return voteRepository.save( + Vote.builder() + .id(index) + .colorIndex(0) + .answer("test") + .isRead(false) + .nameHint(-1) + .isAnswerRevealed(false) + .sender(sender) + .receiver(receiver) + .question(question) + .createdAt(LocalDateTime.now()) + .build() + ); + } + + @Override + public Question generateQuestion(long index) { + return questionRepository.save( + Question.builder() + .id(index) + .nameHead("나는").nameFoot("와") + .keywordHead("멋진").keywordFoot("에서 놀고싶어") + .build() + ); + } + + @Override + public School generateSchool(long index) { + return School.builder() + .id(index) + .schoolName("테스트 대학교 %d".formatted(index)) + .departmentName("테스트 학과 %d".formatted(index)) + .build(); + } + +} diff --git a/src/test/java/com/yello/server/util/TestDataUtil.java b/src/test/java/com/yello/server/util/TestDataUtil.java index 583edfff..0c7ca96c 100644 --- a/src/test/java/com/yello/server/util/TestDataUtil.java +++ b/src/test/java/com/yello/server/util/TestDataUtil.java @@ -1,118 +1,23 @@ package com.yello.server.util; import com.yello.server.domain.friend.entity.Friend; -import com.yello.server.domain.friend.repository.FriendRepository; import com.yello.server.domain.group.entity.School; import com.yello.server.domain.question.entity.Question; -import com.yello.server.domain.question.repository.QuestionRepository; -import com.yello.server.domain.user.entity.Gender; -import com.yello.server.domain.user.entity.Social; -import com.yello.server.domain.user.entity.Subscribe; import com.yello.server.domain.user.entity.User; -import com.yello.server.domain.user.repository.UserRepository; import com.yello.server.domain.vote.entity.Vote; -import com.yello.server.domain.vote.repository.VoteRepository; -import java.time.LocalDateTime; -public class TestDataUtil { +public interface TestDataUtil { - private final UserRepository userRepository; - private final VoteRepository voteRepository; - private final QuestionRepository questionRepository; - private final FriendRepository friendRepository; + User generateUser(long index, long schoolIndex); - public TestDataUtil(UserRepository userRepository, VoteRepository voteRepository, - QuestionRepository questionRepository, - FriendRepository friendRepository) { - this.userRepository = userRepository; - this.voteRepository = voteRepository; - this.questionRepository = questionRepository; - this.friendRepository = friendRepository; - } + User generateDeletedUser(long index, long schoolIndex); - public User generateUser(long index, long schoolIndex) { - School school = generateSchool(schoolIndex); + Friend generateFriend(User user, User target); - return userRepository.save(User.builder() - .id((index)) - .recommendCount(0L) - .name("name%d".formatted(index)) - .yelloId("yelloId%d".formatted(index)) - .gender(Gender.MALE) - .point(200) - .social(Social.KAKAO) - .profileImage("test image") - .uuid("%d".formatted(index)) - .deletedAt(null) - .group(school) - .groupAdmissionYear(20) - .deviceToken("deviceToken#%d".formatted(index)) - .subscribe(Subscribe.NORMAL) - .ticketCount(0) - .email("test%d@test.com".formatted(index)) - .build()); - } + Vote generateVote(long index, User sender, User receiver, Question question); - public User generateDeletedUser(long index, long schoolIndex) { - School school = generateSchool(schoolIndex); - - return userRepository.save(User.builder() - .id(index) - .recommendCount(0L) - .name("name%d".formatted(index)) - .yelloId("yelloId%d".formatted(index)) - .gender(Gender.MALE) - .point(0) - .social(Social.KAKAO) - .profileImage("test image") - .uuid("%d".formatted(index)) - .deletedAt(LocalDateTime.now()) - .group(school) - .groupAdmissionYear(20) - .deviceToken(null) - .subscribe(Subscribe.NORMAL) - .ticketCount(0) - .email("test%d@test.com".formatted(index)) - .build()); - } - - public void generateFriend(User user, User target) { - friendRepository.save(Friend.createFriend(user, target)); - } - - public Vote generateVote(long index, User sender, User receiver, Question question) { - return voteRepository.save( - Vote.builder() - .id(index) - .colorIndex(0) - .answer("test") - .isRead(false) - .nameHint(-1) - .isAnswerRevealed(false) - .sender(sender) - .receiver(receiver) - .question(question) - .createdAt(LocalDateTime.now()) - .build() - ); - } - - public Question generateQuestion(long index) { - return questionRepository.save( - Question.builder() - .id(index) - .nameHead("나는").nameFoot("와") - .keywordHead("멋진").keywordFoot("에서 놀고싶어") - .build() - ); - } - - public School generateSchool(long index) { - return School.builder() - .id(index) - .schoolName("테스트 대학교 %d".formatted(index)) - .departmentName("테스트 학과 %d".formatted(index)) - .build(); - } + Question generateQuestion(long index); + School generateSchool(long index); } + diff --git a/src/test/java/com/yello/server/util/WithAccessTokenUser.java b/src/test/java/com/yello/server/util/WithAccessTokenUser.java new file mode 100644 index 00000000..c430e8e7 --- /dev/null +++ b/src/test/java/com/yello/server/util/WithAccessTokenUser.java @@ -0,0 +1,11 @@ +package com.yello.server.util; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import org.springframework.security.test.context.support.WithSecurityContext; + +@Retention(RetentionPolicy.RUNTIME) +@WithSecurityContext(factory = WithAccessTokenUserSecurityFactory.class) +public @interface WithAccessTokenUser { + +} diff --git a/src/test/java/com/yello/server/util/WithAccessTokenUserSecurityFactory.java b/src/test/java/com/yello/server/util/WithAccessTokenUserSecurityFactory.java new file mode 100644 index 00000000..d242458e --- /dev/null +++ b/src/test/java/com/yello/server/util/WithAccessTokenUserSecurityFactory.java @@ -0,0 +1,56 @@ +package com.yello.server.util; + +import com.yello.server.domain.group.entity.School; +import com.yello.server.domain.user.entity.Gender; +import com.yello.server.domain.user.entity.Social; +import com.yello.server.domain.user.entity.Subscribe; +import com.yello.server.domain.user.entity.User; +import java.util.List; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.test.context.support.WithSecurityContextFactory; + +public class WithAccessTokenUserSecurityFactory implements WithSecurityContextFactory { + + @Override + public SecurityContext createSecurityContext(WithAccessTokenUser annotation) { + SecurityContext context = SecurityContextHolder.createEmptyContext(); + + School school = School.builder() + .schoolName("school") + .departmentName("department") + .build(); + + User user = User.builder() + .id(1L) + .recommendCount(0L) + .name("name") + .yelloId("yelloId") + .gender(Gender.MALE) + .point(200) + .social(Social.KAKAO) + .profileImage("profileImage") + .uuid("uuid") + .deletedAt(null) + .group(school) + .deviceToken("deviceToken") + .subscribe(Subscribe.NORMAL) + .ticketCount(0) + .groupAdmissionYear(20) + .email("test@test.com") + .build(); + + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + user.getYelloId(), + null, + List.of(new SimpleGrantedAuthority("USER")) + ); + + authentication.setDetails(user); + + context.setAuthentication(authentication); + return context; + } +} From bb1941043bbe5febbf9a81a81e7119bec672317c Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:38:45 +0900 Subject: [PATCH 06/41] =?UTF-8?q?YEL-139=20[test]=20JPA=20Configuration=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/yello/server/ServerApplication.java | 2 -- .../server/global/configuration/JpaConfiguration.java | 10 ++++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/yello/server/global/configuration/JpaConfiguration.java diff --git a/src/main/java/com/yello/server/ServerApplication.java b/src/main/java/com/yello/server/ServerApplication.java index 925d86c1..91b6def6 100644 --- a/src/main/java/com/yello/server/ServerApplication.java +++ b/src/main/java/com/yello/server/ServerApplication.java @@ -2,10 +2,8 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -@EnableJpaAuditing @SpringBootApplication public class ServerApplication { diff --git a/src/main/java/com/yello/server/global/configuration/JpaConfiguration.java b/src/main/java/com/yello/server/global/configuration/JpaConfiguration.java new file mode 100644 index 00000000..cb092039 --- /dev/null +++ b/src/main/java/com/yello/server/global/configuration/JpaConfiguration.java @@ -0,0 +1,10 @@ +package com.yello.server.global.configuration; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@EnableJpaAuditing +@Configuration +public class JpaConfiguration { + +} From e163af4e8de6b483312930951fce58f7298f5155 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:38:58 +0900 Subject: [PATCH 07/41] =?UTF-8?q?YEL-139=20[test]=20=EC=84=B1=EA=B3=B5=20?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=84=B8=EB=B6=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/yello/server/global/common/SuccessCode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/yello/server/global/common/SuccessCode.java b/src/main/java/com/yello/server/global/common/SuccessCode.java index 98d2210a..654d61a5 100644 --- a/src/main/java/com/yello/server/global/common/SuccessCode.java +++ b/src/main/java/com/yello/server/global/common/SuccessCode.java @@ -31,7 +31,8 @@ public enum SuccessCode { ONBOARDING_FRIENDS_SUCCESS(OK, "추천 친구 조회에 성공했습니다."), SCHOOL_NAME_SEARCH_SCHOOL_SUCCESS(OK, "학교 검색에 성공했습니다."), DEPARTMENT_NAME_SEARCH_BY_SCHOOL_NAME_SCHOOL_SUCCESS(OK, "학과 검색에 성공했습니다."), - REVEAL_NAME_HINT_SUCCESS(OK, "이름 초성 확인하는데 성공했습니다."), + REVEAL_NAME_HINT_SUCCESS(OK, "이름 초성 확인에 성공했습니다."), + REVEAL_NAME_SUCCESS(OK, "전체 이름 확인에 성공했습니다."), FRIEND_SEARCH_SUCCESS(OK, "친구 검색하기에 성공했습니다."), VERIFY_RECEIPT_SUCCESS(OK, "인앱결제 검증에 성공했습니다."), From 7bcf07835284a23a067d0ea3b20c1068f96c526d Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:39:16 +0900 Subject: [PATCH 08/41] =?UTF-8?q?YEL-139=20[test]=20=EC=96=B4=EC=83=89?= =?UTF-8?q?=ED=95=9C=20API=20Url=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AuthController.java | 10 +++--- .../controller/PurchaseController.java | 32 ++++++++----------- .../user/controller/UserController.java | 2 +- .../vote/controller/VoteController.java | 3 +- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java b/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java index 35ff9291..d21818d3 100644 --- a/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java +++ b/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java @@ -98,12 +98,12 @@ public BaseResponse postFriendList( responseCode = "200", content = @Content(mediaType = "application/json", schema = @Schema(implementation = GroupNameSearchResponse.class))), }) - @GetMapping("/school/school") + @GetMapping("/school") public BaseResponse getSchoolList( - @NotNull @RequestParam("search") String keyword, + @NotNull @RequestParam("keyword") String keyword, @NotNull @RequestParam("page") Integer page ) { - val data = authService.findSchoolsBySearch(keyword, createPageable(page)); + val data = authService.findSchoolsByKeyword(keyword, createPageable(page)); return BaseResponse.success(SCHOOL_NAME_SEARCH_SCHOOL_SUCCESS, data); } @@ -115,10 +115,10 @@ public BaseResponse getSchoolList( @GetMapping("/school/department") public BaseResponse getDepartmentList( @NotNull @RequestParam("school") String schoolName, - @NotNull @RequestParam("search") String keyword, + @NotNull @RequestParam("keyword") String keyword, @NotNull @RequestParam("page") Integer page ) { - val data = authService.findDepartmentsBySearch(schoolName, keyword, createPageable(page)); + val data = authService.findDepartmentsByKeyword(schoolName, keyword, createPageable(page)); return BaseResponse.success(DEPARTMENT_NAME_SEARCH_BY_SCHOOL_NAME_SCHOOL_SUCCESS, data); } diff --git a/src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java b/src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java index d6a023b4..c73c83cb 100644 --- a/src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java +++ b/src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java @@ -9,11 +9,10 @@ import com.yello.server.domain.purchase.dto.apple.AppleOrderResponse; import com.yello.server.domain.purchase.dto.apple.AppleTransaction; import com.yello.server.domain.purchase.dto.request.AppleInAppRefundRequest; -import com.yello.server.domain.purchase.dto.request.GoogleInAppGetRequest; -import com.yello.server.domain.purchase.dto.request.GoogleSubscriptionV2GetRequest; -import com.yello.server.domain.purchase.dto.response.GoogleInAppV1GetResponse; -import com.yello.server.domain.purchase.dto.request.GoogleSubscriptionV2GetRequest; -import com.yello.server.domain.purchase.dto.response.GoogleSubscriptionV2GetResponse; +import com.yello.server.domain.purchase.dto.request.GoogleSubscriptionGetRequest; +import com.yello.server.domain.purchase.dto.request.GoogleTicketGetRequest; +import com.yello.server.domain.purchase.dto.response.GoogleSubscriptionGetResponse; +import com.yello.server.domain.purchase.dto.response.GoogleTicketGetResponse; import com.yello.server.domain.purchase.dto.response.UserPurchaseInfoResponse; import com.yello.server.domain.purchase.dto.response.UserSubscribeNeededResponse; import com.yello.server.domain.purchase.service.PurchaseService; @@ -57,7 +56,6 @@ public BaseResponse verifyAppleSubscriptionTransaction( @AccessTokenUser User user ) { purchaseService.verifyAppleSubscriptionTransaction(user.getId(), appleTransaction); - return BaseResponse.success(VERIFY_RECEIPT_SUCCESS); } @@ -73,20 +71,19 @@ public BaseResponse verifyAppleTicketTransaction( @AccessTokenUser User user ) { purchaseService.verifyAppleTicketTransaction(user.getId(), appleTransaction); - return BaseResponse.success(VERIFY_RECEIPT_SUCCESS); } @Operation(summary = "구글 구독권 결제 정보 검증하기 API", responses = { @ApiResponse( responseCode = "201", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = GoogleSubscriptionV2GetResponse.class)) + content = @Content(mediaType = "application/json", schema = @Schema(implementation = GoogleSubscriptionGetResponse.class)) ) }) - @PostMapping("/google/subscriptionsv2/verify") - public BaseResponse verifyGoogleSubscriptionTransaction( + @PostMapping("/google/verify/subscribe") + public BaseResponse verifyGoogleSubscriptionTransaction( @AccessTokenUser User user, - @RequestBody GoogleSubscriptionV2GetRequest request + @RequestBody GoogleSubscriptionGetRequest request ) throws IOException { val data = purchaseService.verifyGoogleSubscriptionTransaction(user.getId(), request); return BaseResponse.success(GOOGLE_PURCHASE_SUBSCRIPTION_VERIFY_SUCCESS, data); @@ -98,12 +95,12 @@ public BaseResponse verifyGoogleSubscriptionTra content = @Content(mediaType = "application/json", schema = @Schema(implementation = GoogleInAppGetResponse.class)) ) }) - @PostMapping("/google/inapp/verify") - public BaseResponse verifyGoogleInAppTransaction( + @PostMapping("/google/verify/ticket") + public BaseResponse verifyGoogleTicketTransaction( @AccessTokenUser User user, - @RequestBody GoogleInAppGetRequest request + @RequestBody GoogleTicketGetRequest request ) throws IOException { - val data = purchaseService.verifyGoogleInAppTransaction(user.getId(), request); + val data = purchaseService.verifyGoogleTicketTransaction(user.getId(), request); return BaseResponse.success(GOOGLE_PURCHASE_INAPP_VERIFY_SUCCESS, data); } @@ -113,7 +110,7 @@ public BaseResponse verifyGoogleInAppTransaction( content = @Content(mediaType = "application/json", schema = @Schema(implementation = UserSubscribeNeededResponse.class)) ) }) - @GetMapping("/subscribeNeed") + @GetMapping("/subscribe") public BaseResponse getUserSubscribeNeeded( @AccessTokenUser User user) { val data = purchaseService.getUserSubscribe(user, LocalDateTime.now()); @@ -132,7 +129,6 @@ public BaseResponse refundInAppApple( AppleInAppRefundRequest request ) { purchaseService.refundInAppApple(user.getId(), request); - return BaseResponse.success(VERIFY_RECEIPT_SUCCESS); } @@ -142,7 +138,7 @@ public BaseResponse refundInAppApple( content = @Content(mediaType = "application/json", schema = @Schema(implementation = UserPurchaseInfoResponse.class)) ) }) - @GetMapping("/purchaseInfo") + @GetMapping() public BaseResponse getUserPurchaseInfo(@AccessTokenUser User user) { val data = UserPurchaseInfoResponse.of(user); return BaseResponse.success(USER_PURCHASE_INFO_READ_SUCCESS, data); diff --git a/src/main/java/com/yello/server/domain/user/controller/UserController.java b/src/main/java/com/yello/server/domain/user/controller/UserController.java index 8032d24a..ae831193 100644 --- a/src/main/java/com/yello/server/domain/user/controller/UserController.java +++ b/src/main/java/com/yello/server/domain/user/controller/UserController.java @@ -62,7 +62,7 @@ public BaseResponse findUserById(@PathVariable Long userId) { responseCode = "201", content = @Content(mediaType = "application/json", schema = @Schema(implementation = EmptyObject.class))), }) - @PutMapping("/deviceToken") + @PutMapping("/device") public BaseResponse putUserDeviceToken( @AccessTokenUser User user, @RequestBody UserDeviceTokenRequest request) { diff --git a/src/main/java/com/yello/server/domain/vote/controller/VoteController.java b/src/main/java/com/yello/server/domain/vote/controller/VoteController.java index 54347930..41886e77 100644 --- a/src/main/java/com/yello/server/domain/vote/controller/VoteController.java +++ b/src/main/java/com/yello/server/domain/vote/controller/VoteController.java @@ -177,7 +177,6 @@ public BaseResponse revealNameHint( @PathVariable Long voteId ) { val data = voteService.revealNameHint(user.getId(), voteId); - return BaseResponse.success(SuccessCode.REVEAL_NAME_HINT_SUCCESS, data); } @@ -192,7 +191,7 @@ public BaseResponse revealFullName( @PathVariable Long voteId ) { val data = voteService.revealFullName(user.getId(), voteId); - return BaseResponse.success(SuccessCode.REVEAL_NAME_HINT_SUCCESS, data); + return BaseResponse.success(SuccessCode.REVEAL_NAME_SUCCESS, data); } } From 2ce723b0319de3a50bcbf4f89159d4fff8d8a9ee Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:39:57 +0900 Subject: [PATCH 09/41] =?UTF-8?q?YEL-139=20[test]=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=B0=8F=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authorization/service/AuthService.java | 4 +-- .../purchase/dto/apple/AppleTransaction.java | 2 -- .../dto/response/GoogleTicketGetResponse.java | 6 ++-- .../purchase/service/PurchaseService.java | 29 +++++++++---------- .../vote/dto/response/VoteContentVO.java | 4 +-- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java index d5349c89..c3a689ff 100644 --- a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java +++ b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java @@ -147,14 +147,14 @@ public OnBoardingFriendResponse findOnBoardingFriends(OnBoardingFriendRequest fr return OnBoardingFriendResponse.of(kakaoFriends.size(), pageList); } - public GroupNameSearchResponse findSchoolsBySearch(String keyword, Pageable pageable) { + public GroupNameSearchResponse findSchoolsByKeyword(String keyword, Pageable pageable) { int totalCount = schoolRepository.countDistinctSchoolNameContaining(keyword); final List nameList = schoolRepository.findDistinctSchoolNameContaining(keyword, pageable); return GroupNameSearchResponse.of(totalCount, nameList); } - public DepartmentSearchResponse findDepartmentsBySearch(String schoolName, String keyword, + public DepartmentSearchResponse findDepartmentsByKeyword(String schoolName, String keyword, Pageable pageable) { int totalCount = schoolRepository.countAllBySchoolNameContaining(schoolName, keyword); final List schoolResult = schoolRepository.findAllBySchoolNameContaining(schoolName, diff --git a/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleTransaction.java b/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleTransaction.java index a17b58f4..b6d3524d 100644 --- a/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleTransaction.java +++ b/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleTransaction.java @@ -4,10 +4,8 @@ @Builder public record AppleTransaction( - String transactionId, String productId - ) { } diff --git a/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleTicketGetResponse.java b/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleTicketGetResponse.java index c9051493..374a5846 100644 --- a/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleTicketGetResponse.java +++ b/src/main/java/com/yello/server/domain/purchase/dto/response/GoogleTicketGetResponse.java @@ -4,13 +4,13 @@ import lombok.Builder; @Builder -public record GoogleTicketV1GetResponse( +public record GoogleTicketGetResponse( String productId, Integer ticketCount ) { - public static GoogleTicketV1GetResponse of(String productId, User user) { - return GoogleTicketV1GetResponse.builder() + public static GoogleTicketGetResponse of(String productId, User user) { + return GoogleTicketGetResponse.builder() .productId(productId) .ticketCount(user.getTicketCount()) .build(); diff --git a/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java b/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java index 28c80df4..a3b016b3 100644 --- a/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java +++ b/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java @@ -23,10 +23,10 @@ import com.yello.server.domain.purchase.dto.apple.AppleOrderResponse; import com.yello.server.domain.purchase.dto.apple.AppleTransaction; import com.yello.server.domain.purchase.dto.request.AppleInAppRefundRequest; -import com.yello.server.domain.purchase.dto.request.GoogleInAppGetRequest; -import com.yello.server.domain.purchase.dto.request.GoogleSubscriptionV2GetRequest; -import com.yello.server.domain.purchase.dto.response.GoogleInAppV1GetResponse; -import com.yello.server.domain.purchase.dto.response.GoogleSubscriptionV2GetResponse; +import com.yello.server.domain.purchase.dto.request.GoogleSubscriptionGetRequest; +import com.yello.server.domain.purchase.dto.request.GoogleTicketGetRequest; +import com.yello.server.domain.purchase.dto.response.GoogleSubscriptionGetResponse; +import com.yello.server.domain.purchase.dto.response.GoogleTicketGetResponse; import com.yello.server.domain.purchase.dto.response.UserSubscribeNeededResponse; import com.yello.server.domain.purchase.entity.Gateway; import com.yello.server.domain.purchase.entity.ProductType; @@ -77,7 +77,7 @@ public UserSubscribeNeededResponse getUserSubscribe(User user, LocalDateTime tim final Optional mostRecentPurchase = purchaseRepository.findTopByUserAndProductTypeOrderByCreatedAtDesc( user, ProductType.YELLO_PLUS); - final Boolean isSubscribeNeeded = user.getSubscribe() == Subscribe.CANCELED + final Boolean isSubscribeNeeded = user.getSubscribe()==Subscribe.CANCELED && mostRecentPurchase.isPresent() && Duration.between(mostRecentPurchase.get().getCreatedAt(), time).getSeconds() < 1 * 24 * 60 * 60; @@ -94,7 +94,7 @@ public void verifyAppleSubscriptionTransaction(Long userId, purchaseManager.handleAppleTransactionError(verifyReceiptResponse, request.transactionId()); - if (user.getSubscribe() == Subscribe.ACTIVE) { + if (user.getSubscribe()==Subscribe.ACTIVE) { throw new SubscriptionConflictException(SUBSCRIBE_ACTIVE_EXCEPTION); } @@ -134,12 +134,12 @@ public void verifyAppleTicketTransaction(Long userId, AppleTransaction request) } @Transactional - public GoogleSubscriptionV2GetResponse verifyGoogleSubscriptionTransaction(Long userId, - GoogleSubscriptionV2GetRequest request) throws IOException { + public GoogleSubscriptionGetResponse verifyGoogleSubscriptionTransaction(Long userId, + GoogleSubscriptionGetRequest request) throws IOException { User user = userRepository.getById(userId); // exception - if (user.getSubscribe() != Subscribe.NORMAL) { + if (user.getSubscribe()!=Subscribe.NORMAL) { throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_FORBIDDEN_EXCEPTION); } @@ -183,7 +183,7 @@ public GoogleSubscriptionV2GetResponse verifyGoogleSubscriptionTransaction(Long throw new GoogleBadRequestException(GOOGLE_SUBSCRIPTION_TRANSACTION_EXPIRED_EXCEPTION); } case ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_CANCELED -> { - if (user.getSubscribe() == Subscribe.CANCELED) { + if (user.getSubscribe()==Subscribe.CANCELED) { throw new GoogleBadRequestException(GOOGLE_SUBSCRIPTION_DUPLICATED_CANCEL_EXCEPTION); } else { // TODO messageQueue 를 이용한 결제 만료일 도달 시, 유저 구독 상태 변경하기 @@ -197,11 +197,11 @@ public GoogleSubscriptionV2GetResponse verifyGoogleSubscriptionTransaction(Long } } - return GoogleSubscriptionV2GetResponse.of(request.productId()); + return GoogleSubscriptionGetResponse.of(request.productId()); } @Transactional - public GoogleInAppV1GetResponse verifyGoogleInAppTransaction(Long userId, GoogleInAppGetRequest request) + public GoogleTicketGetResponse verifyGoogleTicketTransaction(Long userId, GoogleTicketGetRequest request) throws IOException { final User user = userRepository.getById(userId); @@ -233,7 +233,7 @@ public GoogleInAppV1GetResponse verifyGoogleInAppTransaction(Long userId, Google throw new GoogleTokenServerErrorException(GOOGLE_TOKEN_SERVER_EXCEPTION); } - if (inAppResponse.getBody().purchaseState() == 0) { + if (inAppResponse.getBody().purchaseState()==0) { purchaseRepository.findByTransactionId(inAppResponse.getBody().orderId()) .ifPresent(action -> { throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION); @@ -247,7 +247,7 @@ public GoogleInAppV1GetResponse verifyGoogleInAppTransaction(Long userId, Google throw new GoogleBadRequestException(GOOGLE_INAPP_BAD_REQUEST_EXCEPTION); } - return GoogleInAppV1GetResponse.of(request.productId(), user); + return GoogleTicketGetResponse.of(request.productId(), user); } public String reissueGoogleAccessToken(String refreshToken) throws IOException { @@ -271,7 +271,6 @@ public void refundInAppApple(Long userId, AppleInAppRefundRequest request) { purchaseRepository.delete(purchase); user.setSubscribe(Subscribe.NORMAL); - } public ProductType getProductType(String googleInAppId) { diff --git a/src/main/java/com/yello/server/domain/vote/dto/response/VoteContentVO.java b/src/main/java/com/yello/server/domain/vote/dto/response/VoteContentVO.java index aa11ff36..94eeb27e 100644 --- a/src/main/java/com/yello/server/domain/vote/dto/response/VoteContentVO.java +++ b/src/main/java/com/yello/server/domain/vote/dto/response/VoteContentVO.java @@ -23,7 +23,7 @@ public record VoteContentVO( String keywordFoot ) { - static VoteContentVO of(Vote vote) { + public static VoteContentVO of(Vote vote) { return VoteContentVO.builder() .nameHead(vote.getQuestion().getNameHead()) .nameFoot(deleteBracket(vote.getQuestion().getNameFoot())) @@ -35,6 +35,6 @@ static VoteContentVO of(Vote vote) { private static String deleteBracket(String target) { val slashIndex = target.indexOf('/'); - return slashIndex != -1 ? target.substring(slashIndex + 1) : target; + return slashIndex!=-1 ? target.substring(slashIndex + 1) : target; } } From 1a3f431775a17d129d5f4fa16f6c184febf72145 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:40:08 +0900 Subject: [PATCH 10/41] =?UTF-8?q?YEL-139=20[test]=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EC=9C=A0=EB=8B=9B=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../medium/AuthControllerTest.java | 295 ++++++++++++++ .../friend/medium/FriendControllerTest.java | 265 +++++++++++++ .../domain/pay/medium/PayControllerTest.java | 89 +++++ .../medium/PurchaseControllerTest.java | 241 +++++------- .../user/medium/UserControllerTest.java | 174 +++++++++ .../vote/medium/VoteControllerTest.java | 368 ++++++++++++++++++ 6 files changed, 1295 insertions(+), 137 deletions(-) create mode 100644 src/test/java/com/yello/server/domain/authorization/medium/AuthControllerTest.java create mode 100644 src/test/java/com/yello/server/domain/friend/medium/FriendControllerTest.java create mode 100644 src/test/java/com/yello/server/domain/pay/medium/PayControllerTest.java create mode 100644 src/test/java/com/yello/server/domain/user/medium/UserControllerTest.java create mode 100644 src/test/java/com/yello/server/domain/vote/medium/VoteControllerTest.java diff --git a/src/test/java/com/yello/server/domain/authorization/medium/AuthControllerTest.java b/src/test/java/com/yello/server/domain/authorization/medium/AuthControllerTest.java new file mode 100644 index 00000000..15536c6c --- /dev/null +++ b/src/test/java/com/yello/server/domain/authorization/medium/AuthControllerTest.java @@ -0,0 +1,295 @@ +package com.yello.server.domain.authorization.medium; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yello.server.domain.authorization.controller.AuthController; +import com.yello.server.domain.authorization.dto.ServiceTokenVO; +import com.yello.server.domain.authorization.dto.request.OAuthRequest; +import com.yello.server.domain.authorization.dto.request.OnBoardingFriendRequest; +import com.yello.server.domain.authorization.dto.request.SignUpRequest; +import com.yello.server.domain.authorization.dto.response.DepartmentSearchResponse; +import com.yello.server.domain.authorization.dto.response.GroupNameSearchResponse; +import com.yello.server.domain.authorization.dto.response.OAuthResponse; +import com.yello.server.domain.authorization.dto.response.OnBoardingFriendResponse; +import com.yello.server.domain.authorization.dto.response.SignUpResponse; +import com.yello.server.domain.authorization.filter.JwtExceptionFilter; +import com.yello.server.domain.authorization.filter.JwtFilter; +import com.yello.server.domain.authorization.service.AuthService; +import com.yello.server.domain.user.entity.Gender; +import com.yello.server.domain.user.entity.Social; +import com.yello.server.domain.user.entity.User; +import com.yello.server.global.exception.ControllerExceptionAdvice; +import com.yello.server.util.TestDataEntityUtil; +import com.yello.server.util.TestDataUtil; +import com.yello.server.util.WithAccessTokenUser; +import java.util.Arrays; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +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.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@AutoConfigureRestDocs +@WebMvcTest( + controllers = AuthController.class, + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ControllerExceptionAdvice.class) + }) +@WithAccessTokenUser +@DisplayNameGeneration(ReplaceUnderscores.class) +@DisplayName("Auth 컨트롤러에서") +class AuthControllerTest { + + final String[] excludeRequestHeaders = {"X-CSRF-TOKEN", "Host"}; + final String[] excludeResponseHeaders = {"X-Content-Type-Options", "X-XSS-Protection", "Cache-Control", "Pragma", + "Expires", "X-Frame-Options", "Content-Length"}; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private AuthService authService; + + private TestDataUtil testDataUtil = new TestDataEntityUtil(); + private User user; + private User target; + + @BeforeEach + void init() { + user = testDataUtil.generateUser(1L, 1L); + target = testDataUtil.generateUser(2L, 1L); + } + + @Test + void 소셜_로그인에_성공합니다() throws Exception { + // given + final OAuthRequest oAuthRequest = OAuthRequest.builder() + .accessToken("accessToken") + .deviceToken("deviceToken") + .social("social") + .build(); + + final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( + "serviceAccessToken", + "serviceRefreshToken" + ); + + final OAuthResponse oAuthResponse = OAuthResponse.of(false, serviceTokenVO); + + given(authService.oauthLogin(oAuthRequest)) + .willReturn(oAuthResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/oauth") + .with(csrf().asHeader()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(oAuthRequest))) + .andDo(print()) + .andDo(document("api/v1/auth/oauthLogin", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 옐로_아이디_중복_확인에_성공합니다() throws Exception { + // given + given(authService.isYelloIdDuplicated(anyString())) + .willReturn(false); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/valid") + .param("yelloId", "yelloId here")) + .andDo(print()) + .andDo(document("api/v1/auth/getYelloIdValidation", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("yelloId").description("중복 체크할 yelloId"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 회원_가입에_성공합니다() throws Exception { + // given + final SignUpRequest signUpRequest = SignUpRequest.builder() + .social(Social.KAKAO) + .uuid("uuid") + .deviceToken("deviceToken") + .email("email@emall.com") + .profileImage("profileImage") + .groupId(1L) + .groupAdmissionYear(20) + .name("name") + .yelloId("yelloId") + .gender(Gender.MALE) + .friends(Arrays.asList(1L)) + .recommendId("recommendId") + .build(); + + final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( + "serviceAccessToken", + "serviceRefreshToken" + ); + + final SignUpResponse signUpResponse = SignUpResponse.of("yelloId", serviceTokenVO); + + given(authService.signUp(signUpRequest)) + .willReturn(signUpResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/signup") + .with(csrf().asHeader()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(signUpRequest))) + .andDo(print()) + .andDo(document("api/v1/auth/postSignUp", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 가입한_친구_불러오기에_성공합니다() throws Exception { + // given + final OnBoardingFriendRequest onBoardingFriendRequest = OnBoardingFriendRequest.builder() + .friendKakaoId(Arrays.asList("friendKakaoId")) + .build(); + + final OnBoardingFriendResponse onBoardingFriendResponse = OnBoardingFriendResponse.of(0, Arrays.asList(user)); + + given(authService.findOnBoardingFriends(any(OnBoardingFriendRequest.class), any(Pageable.class))) + .willReturn(onBoardingFriendResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/friend") + .with(csrf().asHeader()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(onBoardingFriendRequest)) + .param("page", "0")) + .andDo(print()) + .andDo(document("api/v1/auth/findOnBoardingFriends", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("page").description("페이지네이션 페이지 번호"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 대학교_이름_검색에_성공합니다() throws Exception { + // given + final GroupNameSearchResponse groupNameSearchResponse = GroupNameSearchResponse.of( + 0, + Arrays.asList("groupName") + ); + + given(authService.findSchoolsByKeyword(anyString(), any(Pageable.class))) + .willReturn(groupNameSearchResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/school") + .param("page", "0") + .param("keyword", "keyword here") + ) + .andDo(print()) + .andDo(document("api/v1/auth/findSchoolsByKeyword", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters( + parameterWithName("page").description("페이지네이션 페이지 번호"), + parameterWithName("keyword").description("검색할 쿼리"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 학과_이름_검색에_성공합니다() throws Exception { + // given + final DepartmentSearchResponse departmentSearchResponse = DepartmentSearchResponse.of( + 0, + Arrays.asList(testDataUtil.generateSchool(1L)) + ); + + given(authService.findDepartmentsByKeyword(anyString(), anyString(), any(Pageable.class))) + .willReturn(departmentSearchResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/school/department") + .param("page", "0") + .param("school", "school name here") + .param("keyword", "keyword here") + ) + .andDo(print()) + .andDo(document("api/v1/auth/findDepartmentsByKeyword", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters( + parameterWithName("page").description("페이지네이션 페이지 번호"), + parameterWithName("school").description("학교 이름"), + parameterWithName("keyword").description("검색할 쿼리"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 토큰_재발급에_성공합니다() throws Exception { + // given + final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( + "new accessToken", + "new refreshToken" + ); + + given(authService.reIssueToken(any(ServiceTokenVO.class))) + .willReturn(serviceTokenVO); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/token/issue") + .with(csrf().asHeader()) + .header("X-ACCESS-AUTH", "Bearer your-access-token") + .header("X-REFRESH-AUTH", "Bearer your-refresh-token") + ) + .andDo(print()) + .andDo(document("api/v1/auth/reIssueToken", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } +} diff --git a/src/test/java/com/yello/server/domain/friend/medium/FriendControllerTest.java b/src/test/java/com/yello/server/domain/friend/medium/FriendControllerTest.java new file mode 100644 index 00000000..81aa392e --- /dev/null +++ b/src/test/java/com/yello/server/domain/friend/medium/FriendControllerTest.java @@ -0,0 +1,265 @@ +package com.yello.server.domain.friend.medium; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yello.server.domain.authorization.filter.JwtExceptionFilter; +import com.yello.server.domain.authorization.filter.JwtFilter; +import com.yello.server.domain.friend.controller.FriendController; +import com.yello.server.domain.friend.dto.request.KakaoRecommendRequest; +import com.yello.server.domain.friend.dto.response.FriendResponse; +import com.yello.server.domain.friend.dto.response.FriendShuffleResponse; +import com.yello.server.domain.friend.dto.response.FriendsResponse; +import com.yello.server.domain.friend.dto.response.RecommendFriendResponse; +import com.yello.server.domain.friend.dto.response.SearchFriendResponse; +import com.yello.server.domain.friend.dto.response.SearchFriendVO; +import com.yello.server.domain.friend.entity.Friend; +import com.yello.server.domain.friend.service.FriendService; +import com.yello.server.domain.user.dto.response.UserResponse; +import com.yello.server.domain.user.entity.User; +import com.yello.server.global.exception.ControllerExceptionAdvice; +import com.yello.server.infrastructure.firebase.service.NotificationService; +import com.yello.server.util.TestDataEntityUtil; +import com.yello.server.util.TestDataUtil; +import com.yello.server.util.WithAccessTokenUser; +import java.util.Arrays; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +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.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@WebMvcTest( + controllers = FriendController.class, + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ControllerExceptionAdvice.class) + }) +@AutoConfigureRestDocs +@WithAccessTokenUser +@DisplayNameGeneration(ReplaceUnderscores.class) +class FriendControllerTest { + + final String[] excludeRequestHeaders = {"X-CSRF-TOKEN", "Host"}; + final String[] excludeResponseHeaders = {"X-Content-Type-Options", "X-XSS-Protection", "Cache-Control", "Pragma", + "Expires", "X-Frame-Options", "Content-Length"}; + + @Autowired + protected ObjectMapper objectMapper; + + @Autowired + protected MockMvc mockMvc; + + @MockBean + private FriendService friendService; + + @MockBean + private NotificationService notificationService; + + private TestDataUtil testDataUtil = new TestDataEntityUtil(); + private User user; + private User target; + + @BeforeEach + void init() { + user = testDataUtil.generateUser(1L, 1L); + target = testDataUtil.generateUser(2L, 1L); + } + + @Test + void 친구_추가에_성공합니다() throws Exception { + // given + given(friendService.addFriend(anyLong(), anyLong())) + .willReturn(null); + + doNothing() + .when(notificationService) + .sendFriendNotification(any(Friend.class)); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/friend/{targetId}", 1) + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token")) + .andDo(print()) + .andDo(document("api/v1/friend/addFriend", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + pathParameters(parameterWithName("targetId").description("친구 신청할 상대 유저의 아이디 값"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 내_친구_전체_조회에_성공합니다() throws Exception { + // given + final UserResponse userResponse = UserResponse.of(user, 0, 0); + final FriendsResponse friendsResponse = FriendsResponse.of(0L, Arrays.asList(userResponse)); + + given(friendService.findAllFriends(any(Pageable.class), anyLong())) + .willReturn(friendsResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/friend") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .param("page", "0")) + .andDo(print()) + .andDo(document("api/v1/friend/findAllFriend", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("page").description("페이지네이션 페이지 번호"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 친구_투표_조회에_성공합니다() throws Exception { + // given + final Friend friend = testDataUtil.generateFriend(user, target); + final FriendShuffleResponse friendShuffleResponse = FriendShuffleResponse.of(friend); + + given(friendService.findShuffledFriend(anyLong())) + .willReturn(Arrays.asList(friendShuffleResponse)); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/friend/shuffle") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token")) + .andDo(print()) + .andDo(document("api/v1/friend/findShuffledFriend", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 그룹_추천_친구_조회에_성공합니다() throws Exception { + // given + final FriendResponse friendResponse = FriendResponse.of(user); + final RecommendFriendResponse recommendFriendResponse = RecommendFriendResponse.of(0, + Arrays.asList(friendResponse)); + + given(friendService.findAllRecommendSchoolFriends(any(Pageable.class), anyLong())) + .willReturn(recommendFriendResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/friend/recommend/school") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .param("page", "0")) + .andDo(print()) + .andDo(document("api/v1/friend/findAllRecommendSchoolFriends", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("page").description("페이지네이션 페이지 번호"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 카카오_추천_친구_조회에_성공합니다() throws Exception { + // given + final KakaoRecommendRequest kakaoRecommendRequest = KakaoRecommendRequest.builder() + .friendKakaoId(new String[]{"testKakaoId"}) + .build(); + final FriendResponse friendResponse = FriendResponse.of(user); + final RecommendFriendResponse recommendFriendResponse = RecommendFriendResponse.of(0, + Arrays.asList(friendResponse)); + + given(friendService.findAllRecommendKakaoFriends(any(Pageable.class), anyLong(), eq(kakaoRecommendRequest))) + .willReturn(recommendFriendResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/friend/recommend/kakao") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(kakaoRecommendRequest)) + .param("page", "0")) + .andDo(print()) + .andDo(document("api/v1/friend/findAllRecommendKakaoFriends", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("page").description("페이지네이션 페이지 번호"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 친구_삭제에_성공합니다() throws Exception { + // given + doNothing() + .when(friendService) + .deleteFriend(anyLong(), anyLong()); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.delete("/api/v1/friend/{targetId}", 1) + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/friend/deleteFriend", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + pathParameters(parameterWithName("targetId").description("삭제할 상대 유저의 아이디 값"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 친구_검색에_성공합니다() throws Exception { + // given + final SearchFriendVO searchFriendVO = SearchFriendVO.of(user, false); + final SearchFriendResponse searchFriendResponse = SearchFriendResponse.of(0, Arrays.asList(searchFriendVO)); + + given(friendService.searchFriend(anyLong(), any(Pageable.class), anyString())) + .willReturn(searchFriendResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/friend/search") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .param("page", "0") + .param("keyword", "keyword here") + ) + .andDo(print()) + .andDo(document("api/v1/friend/searchFriend", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters( + parameterWithName("page").description("페이지네이션 페이지 번호"), + parameterWithName("keyword").description("검색할 쿼리"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } +} diff --git a/src/test/java/com/yello/server/domain/pay/medium/PayControllerTest.java b/src/test/java/com/yello/server/domain/pay/medium/PayControllerTest.java new file mode 100644 index 00000000..bdbb1b15 --- /dev/null +++ b/src/test/java/com/yello/server/domain/pay/medium/PayControllerTest.java @@ -0,0 +1,89 @@ +package com.yello.server.domain.pay.medium; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yello.server.domain.authorization.filter.JwtExceptionFilter; +import com.yello.server.domain.authorization.filter.JwtFilter; +import com.yello.server.domain.pay.controller.PayController; +import com.yello.server.domain.pay.dto.request.PayCountRequest; +import com.yello.server.domain.pay.service.PayService; +import com.yello.server.global.exception.ControllerExceptionAdvice; +import com.yello.server.util.WithAccessTokenUser; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +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.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@AutoConfigureRestDocs +@WebMvcTest( + controllers = PayController.class, + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ControllerExceptionAdvice.class) + }) +@WithAccessTokenUser +@DisplayNameGeneration(ReplaceUnderscores.class) +@DisplayName("Pay 컨트롤러에서") +class PayControllerTest { + + final String[] excludeRequestHeaders = {"X-CSRF-TOKEN", "Host"}; + final String[] excludeResponseHeaders = {"X-Content-Type-Options", "X-XSS-Protection", "Cache-Control", "Pragma", + "Expires", "X-Frame-Options", "Content-Length"}; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private PayService payService; + + @Test + void 결제_전환율_체크에_성공합니다() throws Exception { + // given + final PayCountRequest request = PayCountRequest.builder() + .index(1) + .build(); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/pay") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andDo(print()) + .andDo(document("api/v1/pay/postPayCount", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + + verify(payService, times(1)) + .postPayCount(anyLong(), anyInt()); + } + +} diff --git a/src/test/java/com/yello/server/domain/purchase/medium/PurchaseControllerTest.java b/src/test/java/com/yello/server/domain/purchase/medium/PurchaseControllerTest.java index 7a2c9b4d..8e7ab3dc 100644 --- a/src/test/java/com/yello/server/domain/purchase/medium/PurchaseControllerTest.java +++ b/src/test/java/com/yello/server/domain/purchase/medium/PurchaseControllerTest.java @@ -1,38 +1,35 @@ -package com.yello.server.domain.authorization.medium; +package com.yello.server.domain.purchase.medium; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import com.fasterxml.jackson.databind.ObjectMapper; -import com.yello.server.domain.authorization.controller.AuthController; -import com.yello.server.domain.authorization.dto.ServiceTokenVO; -import com.yello.server.domain.authorization.dto.request.OAuthRequest; -import com.yello.server.domain.authorization.dto.request.OnBoardingFriendRequest; -import com.yello.server.domain.authorization.dto.request.SignUpRequest; -import com.yello.server.domain.authorization.dto.response.DepartmentSearchResponse; -import com.yello.server.domain.authorization.dto.response.GroupNameSearchResponse; -import com.yello.server.domain.authorization.dto.response.OAuthResponse; -import com.yello.server.domain.authorization.dto.response.OnBoardingFriendResponse; -import com.yello.server.domain.authorization.dto.response.SignUpResponse; import com.yello.server.domain.authorization.filter.JwtExceptionFilter; import com.yello.server.domain.authorization.filter.JwtFilter; -import com.yello.server.domain.authorization.service.AuthService; -import com.yello.server.domain.user.entity.Gender; -import com.yello.server.domain.user.entity.Social; +import com.yello.server.domain.purchase.controller.PurchaseController; +import com.yello.server.domain.purchase.dto.apple.AppleTransaction; +import com.yello.server.domain.purchase.dto.request.AppleInAppRefundRequest; +import com.yello.server.domain.purchase.dto.request.GoogleSubscriptionGetRequest; +import com.yello.server.domain.purchase.dto.request.GoogleTicketGetRequest; +import com.yello.server.domain.purchase.dto.response.GoogleSubscriptionGetResponse; +import com.yello.server.domain.purchase.dto.response.GoogleTicketGetResponse; +import com.yello.server.domain.purchase.dto.response.UserSubscribeNeededResponse; +import com.yello.server.domain.purchase.service.PurchaseService; import com.yello.server.domain.user.entity.User; import com.yello.server.global.exception.ControllerExceptionAdvice; import com.yello.server.util.TestDataEntityUtil; import com.yello.server.util.TestDataUtil; import com.yello.server.util.WithAccessTokenUser; -import java.util.Arrays; +import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; @@ -44,7 +41,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; -import org.springframework.data.domain.Pageable; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; @@ -54,7 +50,7 @@ @AutoConfigureRestDocs @WebMvcTest( - controllers = AuthController.class, + controllers = PurchaseController.class, excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), @@ -62,8 +58,8 @@ }) @WithAccessTokenUser @DisplayNameGeneration(ReplaceUnderscores.class) -@DisplayName("Auth 컨트롤러에서") -class AuthControllerTest { +@DisplayName("Purchase 컨트롤러에서") +class PurchaseControllerTest { final String[] excludeRequestHeaders = {"X-CSRF-TOKEN", "Host"}; final String[] excludeResponseHeaders = {"X-Content-Type-Options", "X-XSS-Protection", "Cache-Control", "Pragma", @@ -76,7 +72,7 @@ class AuthControllerTest { private ObjectMapper objectMapper; @MockBean - private AuthService authService; + private PurchaseService purchaseService; private TestDataUtil testDataUtil = new TestDataEntityUtil(); private User user; @@ -89,96 +85,87 @@ void init() { } @Test - void 소셜_로그인에_성공합니다() throws Exception { + void Apple_구독_구매_검증에_성공합니다() throws Exception { // given - final OAuthRequest oAuthRequest = OAuthRequest.builder() - .accessToken("accessToken") - .deviceToken("deviceToken") - .social("social") + final AppleTransaction appleTransaction = AppleTransaction.builder() + .transactionId("transactionId") + .productId("productId") .build(); - final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( - "serviceAccessToken", - "serviceRefreshToken" - ); - - final OAuthResponse oAuthResponse = OAuthResponse.of(false, serviceTokenVO); - - given(authService.oauthLogin(oAuthRequest)) - .willReturn(oAuthResponse); - // when // then - mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/oauth") + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/purchase/apple/verify/subscribe") .with(csrf().asHeader()) .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(oAuthRequest))) + .content(objectMapper.writeValueAsString(appleTransaction))) .andDo(print()) - .andDo(document("api/v1/auth/oauthLogin", + .andDo(document("api/v1/purchase/verifyAppleSubscriptionTransaction", Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) ) .andExpect(MockMvcResultMatchers.status().isOk()); + + verify(purchaseService, times(1)) + .verifyAppleSubscriptionTransaction(anyLong(), any(AppleTransaction.class)); } @Test - void 옐로_아이디_중복_확인에_성공합니다() throws Exception { + void Apple_열람권_구매_검증에_성공합니다() throws Exception { // given - given(authService.isYelloIdDuplicated(anyString())) - .willReturn(false); + final AppleTransaction appleTransaction = AppleTransaction.builder() + .transactionId("transactionId") + .productId("productId") + .build(); // when // then - mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/valid") + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/purchase/apple/verify/ticket") + .with(csrf().asHeader()) .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") - .param("yelloId", "yelloId here")) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(appleTransaction))) .andDo(print()) - .andDo(document("api/v1/auth/getYelloIdValidation", + .andDo(document("api/v1/purchase/verifyAppleTicketTransaction", Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), - Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), - requestParameters(parameterWithName("yelloId").description("중복 체크할 yelloId"))) + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) ) .andExpect(MockMvcResultMatchers.status().isOk()); + + verify(purchaseService, times(1)) + .verifyAppleTicketTransaction(anyLong(), any(AppleTransaction.class)); } @Test - void 회원_가입에_성공합니다() throws Exception { + void Google_구독_구매_검증에_성공합니다() throws Exception { // given - final SignUpRequest signUpRequest = SignUpRequest.builder() - .social(Social.KAKAO) - .uuid("uuid") - .deviceToken("deviceToken") - .email("email@emall.com") - .profileImage("profileImage") - .groupId(1L) - .groupAdmissionYear(20) - .name("name") - .yelloId("yelloId") - .gender(Gender.MALE) - .friends(Arrays.asList(1L)) - .recommendId("recommendId") + final GoogleSubscriptionGetRequest googleSubscriptionGetRequest = GoogleSubscriptionGetRequest.builder() + .orderId("orderId") + .packageName("packageName") + .productId("productId") + .purchaseTime(1L) + .purchaseState(1) + .purchaseToken("purchaseToken") + .quantity(1) + .autoRenewing(true) + .acknowledged(true) .build(); - final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( - "serviceAccessToken", - "serviceRefreshToken" - ); + final GoogleSubscriptionGetResponse response = GoogleSubscriptionGetResponse.of( + "productId"); - final SignUpResponse signUpResponse = SignUpResponse.of("yelloId", serviceTokenVO); - - given(authService.signUp(signUpRequest)) - .willReturn(signUpResponse); + given(purchaseService.verifyGoogleSubscriptionTransaction(anyLong(), any(GoogleSubscriptionGetRequest.class))) + .willReturn(response); // when // then - mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/signup") + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/purchase/google/verify/subscribe") .with(csrf().asHeader()) .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(signUpRequest))) + .content(objectMapper.writeValueAsString(googleSubscriptionGetRequest))) .andDo(print()) - .andDo(document("api/v1/auth/postSignUp", + .andDo(document("api/v1/purchase/verifyGoogleSubscriptionTransaction", Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) ) @@ -186,114 +173,94 @@ void init() { } @Test - void 가입한_친구_불러오기에_성공합니다() throws Exception { + void Google_열람권_구매_검증에_성공합니다() throws Exception { // given - final OnBoardingFriendRequest onBoardingFriendRequest = OnBoardingFriendRequest.builder() - .friendKakaoId(Arrays.asList("friendKakaoId")) + final GoogleTicketGetRequest googleTicketGetRequest = GoogleTicketGetRequest.builder() + .orderId("orderId") + .packageName("packageName") + .productId("productId") + .purchaseTime(1L) + .purchaseState(1) + .purchaseToken("purchaseToken") + .quantity(1) + .acknowledged(true) .build(); - final OnBoardingFriendResponse onBoardingFriendResponse = OnBoardingFriendResponse.of(0, Arrays.asList(user)); + final GoogleTicketGetResponse response = GoogleTicketGetResponse.of( + "productId", + user + ); - given(authService.findOnBoardingFriends(any(OnBoardingFriendRequest.class), any(Pageable.class))) - .willReturn(onBoardingFriendResponse); + given(purchaseService.verifyGoogleTicketTransaction(anyLong(), any(GoogleTicketGetRequest.class))) + .willReturn(response); // when // then - mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/friend") + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/purchase/google/verify/ticket") .with(csrf().asHeader()) .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(onBoardingFriendRequest)) - .param("page", "0")) + .content(objectMapper.writeValueAsString(googleTicketGetRequest))) .andDo(print()) - .andDo(document("api/v1/auth/findOnBoardingFriends", + .andDo(document("api/v1/purchase/verifyGoogleTicketTransaction", Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), - Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), - requestParameters(parameterWithName("page").description("페이지네이션 페이지 번호"))) + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) ) .andExpect(MockMvcResultMatchers.status().isOk()); } @Test - void 대학교_이름_검색에_성공합니다() throws Exception { + void 구독_연장_유도_필요_여부_조회에_성공합니다() throws Exception { // given - final GroupNameSearchResponse groupNameSearchResponse = GroupNameSearchResponse.of( - 0, - Arrays.asList("groupName") + final UserSubscribeNeededResponse response = UserSubscribeNeededResponse.of( + user, + false ); - given(authService.findSchoolsByKeyword(anyString(), any(Pageable.class))) - .willReturn(groupNameSearchResponse); + given(purchaseService.getUserSubscribe(any(User.class), any(LocalDateTime.class))) + .willReturn(response); // when // then - mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/school") - .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") - .param("page", "0") - .param("keyword", "keyword here") - ) + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/purchase/subscribe") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token")) .andDo(print()) - .andDo(document("api/v1/auth/findSchoolsByKeyword", + .andDo(document("api/v1/purchase/getUserSubscribeNeeded", Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), - Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), - requestParameters( - parameterWithName("page").description("페이지네이션 페이지 번호"), - parameterWithName("keyword").description("검색할 쿼리"))) + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) ) .andExpect(MockMvcResultMatchers.status().isOk()); } @Test - void 학과_이름_검색에_성공합니다() throws Exception { + void Apple_환불에_성공합니다() throws Exception { // given - final DepartmentSearchResponse departmentSearchResponse = DepartmentSearchResponse.of( - 0, - Arrays.asList(testDataUtil.generateSchool(1L)) - ); - - given(authService.findDepartmentsByKeyword(anyString(), anyString(), any(Pageable.class))) - .willReturn(departmentSearchResponse); + doNothing() + .when(purchaseService) + .refundInAppApple(anyLong(), any(AppleInAppRefundRequest.class)); // when // then - mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/auth/school/department") - .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") - .param("page", "0") - .param("school", "school name here") - .param("keyword", "keyword here") - ) + mockMvc.perform(RestDocumentationRequestBuilders.delete("/api/v1/purchase/apple/refund") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token")) .andDo(print()) - .andDo(document("api/v1/auth/findDepartmentsByKeyword", + .andDo(document("api/v1/purchase/refundInAppApple", Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), - Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), - requestParameters( - parameterWithName("page").description("페이지네이션 페이지 번호"), - parameterWithName("school").description("학교 이름"), - parameterWithName("keyword").description("검색할 쿼리"))) + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) ) .andExpect(MockMvcResultMatchers.status().isOk()); } @Test - void 토큰_재발급에_성공합니다() throws Exception { + void 구독_상태_및_구독권_개수_조회에_성공합니다() throws Exception { // given - final ServiceTokenVO serviceTokenVO = ServiceTokenVO.of( - "new accessToken", - "new refreshToken" - ); - - given(authService.reIssueToken(any(ServiceTokenVO.class))) - .willReturn(serviceTokenVO); - // when // then - mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/auth/token/issue") - .with(csrf().asHeader()) - .header("X-ACCESS-AUTH", "Bearer your-access-token") - .header("X-REFRESH-AUTH", "Bearer your-refresh-token") - ) + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/purchase") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token")) .andDo(print()) - .andDo(document("api/v1/auth/reIssueToken", + .andDo(document("api/v1/purchase/getUserPurchaseInfo", Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) ) diff --git a/src/test/java/com/yello/server/domain/user/medium/UserControllerTest.java b/src/test/java/com/yello/server/domain/user/medium/UserControllerTest.java new file mode 100644 index 00000000..6cda5faf --- /dev/null +++ b/src/test/java/com/yello/server/domain/user/medium/UserControllerTest.java @@ -0,0 +1,174 @@ +package com.yello.server.domain.user.medium; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yello.server.domain.authorization.filter.JwtExceptionFilter; +import com.yello.server.domain.authorization.filter.JwtFilter; +import com.yello.server.domain.user.controller.UserController; +import com.yello.server.domain.user.dto.request.UserDeviceTokenRequest; +import com.yello.server.domain.user.dto.response.UserDetailResponse; +import com.yello.server.domain.user.dto.response.UserResponse; +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.service.UserService; +import com.yello.server.global.common.dto.EmptyObject; +import com.yello.server.global.exception.ControllerExceptionAdvice; +import com.yello.server.util.WithAccessTokenUser; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +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.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@AutoConfigureRestDocs +@WebMvcTest( + controllers = UserController.class, + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ControllerExceptionAdvice.class) + }) +@WithAccessTokenUser +@DisplayNameGeneration(ReplaceUnderscores.class) +@DisplayName("User 컨트롤러에서") +class UserControllerTest { + + final String[] excludeRequestHeaders = {"X-CSRF-TOKEN", "Host"}; + final String[] excludeResponseHeaders = {"X-Content-Type-Options", "X-XSS-Protection", "Cache-Control", "Pragma", + "Expires", "X-Frame-Options", "Content-Length"}; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private UserService userService; + + @Test + void 내_정보_조회에_성공합니다() throws Exception { + // given + final UserDetailResponse userDetailResponse = UserDetailResponse.builder() + .userId(1L) + .name("test") + .group("group") + .profileImageUrl("profile") + .yelloId("yelloId") + .yelloCount(0) + .friendCount(0) + .point(200) + .build(); + + given(userService.findMyProfile(anyLong())) + .willReturn(userDetailResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/user") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/user/findUser", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 다른_유저_정보_조회에_성공합니다() throws Exception { + // given + final Long userId = 2L; + final UserResponse userResponse = UserResponse.builder() + .userId(userId) + .name("test") + .group("group") + .profileImageUrl("profile") + .yelloId("yelloId") + .yelloCount(0) + .friendCount(0) + .build(); + + given(userService.findUserById(anyLong())) + .willReturn(userResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/user/{userId}", userId) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/user/findUserById", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + pathParameters(parameterWithName("userId").description("유저 아이디 값"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 디바이스_토큰_수정에_성공합니다() throws Exception { + // given + final EmptyObject emptyObject = EmptyObject.builder().build(); + final UserDeviceTokenRequest userDeviceTokenRequest = UserDeviceTokenRequest.builder() + .deviceToken("testDeviceToken") + .build(); + + given(userService.updateUserDeviceToken(any(User.class), eq(userDeviceTokenRequest))) + .willReturn(emptyObject); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.put("/api/v1/user/device") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(userDeviceTokenRequest))) + .andDo(print()) + .andDo(document("api/v1/user/updateUserDeviceToken", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 유저_탈퇴에_성공합니다() throws Exception { + // given + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.delete("/api/v1/user") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/user/deleteUser", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + +} diff --git a/src/test/java/com/yello/server/domain/vote/medium/VoteControllerTest.java b/src/test/java/com/yello/server/domain/vote/medium/VoteControllerTest.java new file mode 100644 index 00000000..da193725 --- /dev/null +++ b/src/test/java/com/yello/server/domain/vote/medium/VoteControllerTest.java @@ -0,0 +1,368 @@ +package com.yello.server.domain.vote.medium; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yello.server.domain.authorization.filter.JwtExceptionFilter; +import com.yello.server.domain.authorization.filter.JwtFilter; +import com.yello.server.domain.cooldown.entity.Cooldown; +import com.yello.server.domain.friend.dto.response.FriendShuffleResponse; +import com.yello.server.domain.friend.entity.Friend; +import com.yello.server.domain.keyword.dto.response.KeywordCheckResponse; +import com.yello.server.domain.question.dto.response.QuestionForVoteResponse; +import com.yello.server.domain.question.dto.response.QuestionVO; +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.vote.controller.VoteController; +import com.yello.server.domain.vote.dto.request.CreateVoteRequest; +import com.yello.server.domain.vote.dto.request.VoteAnswer; +import com.yello.server.domain.vote.dto.response.RevealFullNameResponse; +import com.yello.server.domain.vote.dto.response.RevealNameResponse; +import com.yello.server.domain.vote.dto.response.VoteAvailableResponse; +import com.yello.server.domain.vote.dto.response.VoteCountVO; +import com.yello.server.domain.vote.dto.response.VoteCreateResponse; +import com.yello.server.domain.vote.dto.response.VoteCreateVO; +import com.yello.server.domain.vote.dto.response.VoteDetailResponse; +import com.yello.server.domain.vote.dto.response.VoteFriendResponse; +import com.yello.server.domain.vote.dto.response.VoteFriendVO; +import com.yello.server.domain.vote.dto.response.VoteListResponse; +import com.yello.server.domain.vote.dto.response.VoteResponse; +import com.yello.server.domain.vote.dto.response.VoteUnreadCountResponse; +import com.yello.server.domain.vote.entity.Vote; +import com.yello.server.domain.vote.service.VoteService; +import com.yello.server.global.exception.ControllerExceptionAdvice; +import com.yello.server.infrastructure.firebase.service.NotificationService; +import com.yello.server.util.TestDataEntityUtil; +import com.yello.server.util.TestDataUtil; +import com.yello.server.util.WithAccessTokenUser; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +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.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@AutoConfigureRestDocs +@WebMvcTest( + controllers = VoteController.class, + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtExceptionFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ControllerExceptionAdvice.class) + }) +@WithAccessTokenUser +@DisplayNameGeneration(ReplaceUnderscores.class) +@DisplayName("Vote 컨트롤러에서") +class VoteControllerTest { + + final String[] excludeRequestHeaders = {"X-CSRF-TOKEN", "Host"}; + final String[] excludeResponseHeaders = {"X-Content-Type-Options", "X-XSS-Protection", "Cache-Control", "Pragma", + "Expires", "X-Frame-Options", "Content-Length"}; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private VoteService voteService; + + @MockBean + private NotificationService notificationService; + + private TestDataUtil testDataUtil = new TestDataEntityUtil(); + private User user; + private User target; + + @BeforeEach + void init() { + user = testDataUtil.generateUser(1L, 1L); + target = testDataUtil.generateUser(2L, 1L); + } + + @Test + void 내_투표_전체_조회에_성공합니다() throws Exception { + // given + final Vote vote = testDataUtil.generateVote(1L, user, target, testDataUtil.generateQuestion(1L)); + final VoteResponse voteResponse = VoteResponse.of(vote); + final VoteCountVO voteCountVO = VoteCountVO.of(1, 0, 0, 0, 0); + final VoteListResponse voteListResponse = VoteListResponse.of(voteCountVO, Arrays.asList(voteResponse), user); + + given(voteService.findAllVotes(anyLong(), any(Pageable.class))) + .willReturn(voteListResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/vote") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .param("page", "0")) + .andDo(print()) + .andDo(document("api/v1/vote/findAllMyVotes", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("page").description("페이지네이션 페이지 번호"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 읽지_않은_쪽지_개수_조회에_성공합니다() throws Exception { + // given + final VoteUnreadCountResponse voteUnreadCountResponse = VoteUnreadCountResponse.of(1); + + given(voteService.getUnreadVoteCount(anyLong())) + .willReturn(voteUnreadCountResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/vote/count") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/vote/getUnreadVoteCount", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 친구_투표_조회에_성공합니다() throws Exception { + // given + final Vote vote = testDataUtil.generateVote(1L, user, target, testDataUtil.generateQuestion(1L)); + final VoteFriendVO voteFriendVO = VoteFriendVO.of(vote); + final VoteFriendResponse voteFriendResponse = VoteFriendResponse.of(1, Arrays.asList(voteFriendVO)); + + given(voteService.findAllFriendVotes(anyLong(), any(Pageable.class))) + .willReturn(voteFriendResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/vote/friend") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .param("page", "0")) + .andDo(print()) + .andDo(document("api/v1/vote/findAllFriendVotes", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + requestParameters(parameterWithName("page").description("페이지네이션 페이지 번호"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 투표_상세_조회에_성공합니다() throws Exception { + // given + final Vote vote = testDataUtil.generateVote(1L, user, target, testDataUtil.generateQuestion(1L)); + final VoteDetailResponse voteDetailResponse = VoteDetailResponse.of(vote, user); + + given(voteService.findVoteById(anyLong(), anyLong())) + .willReturn(voteDetailResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/vote/{voteId}", 1) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/vote/findVoteById", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + pathParameters(parameterWithName("voteId").description("투표 아이디 값"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 키워드_확인에_성공합니다() throws Exception { + // given + final Vote vote = testDataUtil.generateVote(1L, user, target, testDataUtil.generateQuestion(1L)); + final KeywordCheckResponse keywordCheckResponse = KeywordCheckResponse.of(vote); + + given(voteService.checkKeyword(anyLong(), anyLong())) + .willReturn(keywordCheckResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.patch("/api/v1/vote/{voteId}/keyword", 1) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .with(csrf().asHeader()) + ) + .andDo(print()) + .andDo(document("api/v1/vote/checkKeyword", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + pathParameters(parameterWithName("voteId").description("투표 아이디 값"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 투표_8개_조회에_성공합니다() throws Exception { + // given + final Friend friend = testDataUtil.generateFriend(user, target); + final List friendShuffleResponses = Arrays.asList(FriendShuffleResponse.of(friend)); + final List keywordList = Arrays.asList("A", "B", "C", "D"); + final QuestionVO questionVO = QuestionVO.of(testDataUtil.generateQuestion(1L)); + final QuestionForVoteResponse questionForVoteResponse = QuestionForVoteResponse.builder() + .question(questionVO) + .friendList(friendShuffleResponses) + .keywordList(keywordList) + .questionPoint(10) + .subscribe("normal | active") + .build(); + + given(voteService.findVoteQuestionList(anyLong())) + .willReturn(Arrays.asList(questionForVoteResponse)); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/vote/question") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/vote/findVoteQuestions", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 투표_가능_여부_조회에_성공합니다() throws Exception { + // given + final Cooldown cooldown = Cooldown.of(user, UUID.randomUUID().toString(), LocalDateTime.now()); + final VoteAvailableResponse voteAvailableResponse = VoteAvailableResponse.of(user, cooldown); + + given(voteService.checkVoteAvailable(anyLong())) + .willReturn(voteAvailableResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/v1/vote/available") + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + ) + .andDo(print()) + .andDo(document("api/v1/vote/checkVoteAvailable", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 투표_생성에_성공합니다() throws Exception { + // given + final Vote vote = testDataUtil.generateVote(1L, user, target, testDataUtil.generateQuestion(1L)); + final VoteCreateVO voteCreateVO = VoteCreateVO.of(10, Arrays.asList(vote)); + final VoteCreateResponse voteCreateResponse = VoteCreateResponse.of(10); + final VoteAnswer voteAnswer = VoteAnswer.builder() + .friendId(2L) + .questionId(1L) + .keywordName("키워드") + .colorIndex(0) + .build(); + + final CreateVoteRequest createVoteRequest = CreateVoteRequest.builder() + .voteAnswerList(Arrays.asList(voteAnswer)) + .totalPoint(10) + .build(); + + given(voteService.createVote(anyLong(), eq(createVoteRequest))) + .willReturn(voteCreateVO); + + doNothing() + .when(notificationService) + .sendYelloNotification(any()); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/v1/vote") + .with(csrf().asHeader()) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(createVoteRequest))) + .andDo(print()) + .andDo(document("api/v1/vote/createVote", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 투표_이름_부분_조회에_성공합니다() throws Exception { + // given + final Long voteId = 1L; + final RevealNameResponse revealNameResponse = RevealNameResponse.of(user, 0); + + given(voteService.revealNameHint(anyLong(), anyLong())) + .willReturn(revealNameResponse); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.patch("/api/v1/vote/{voteId}/name", voteId) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .with(csrf().asHeader()) + ) + .andDo(print()) + .andDo(document("api/v1/vote/revealNameHint", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + pathParameters(parameterWithName("voteId").description("투표 아이디 값"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + void 투표_이름_전체_조회에_성공합니다() throws Exception { + // given + final Long voteId = 1L; + final RevealFullNameResponse response = RevealFullNameResponse.of(user); + + given(voteService.revealFullName(anyLong(), anyLong())) + .willReturn(response); + + // when + // then + mockMvc.perform(RestDocumentationRequestBuilders.patch("/api/v1/vote/{voteId}/fullname", voteId) + .header(HttpHeaders.AUTHORIZATION, "Bearer your-access-token") + .with(csrf().asHeader()) + ) + .andDo(print()) + .andDo(document("api/v1/vote/revealFullName", + Preprocessors.preprocessRequest(prettyPrint(), removeHeaders(excludeRequestHeaders)), + Preprocessors.preprocessResponse(prettyPrint(), removeHeaders(excludeResponseHeaders)), + pathParameters(parameterWithName("voteId").description("투표 아이디 값"))) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + } +} From c5ff2fbc086fb0a90c1fdc16e5c407d36d6647c0 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:40:34 +0900 Subject: [PATCH 11/41] =?UTF-8?q?YEL-139=20[test]=20bootJar=EC=8B=9C=20res?= =?UTF-8?q?tdocs=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 87c76027..ff75c6b9 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ buildscript { } } + plugins { id 'java' id 'org.springframework.boot' version '2.7.4' @@ -109,6 +110,12 @@ tasks.named('test') { useJUnitPlatform() } +bootJar { + dependsOn asciidoctor + from("${asciidoctor.outputDir}") { + into 'static/docs' + } +} def querydslDir = "$buildDir/generated/querydsl" @@ -141,8 +148,3 @@ asciidoctor { asciidoctor.doFirst { delete file('src/docs/asciidocs') } -task copyDocument(type: Copy) { - dependsOn asciidoctor - from file("build/docs/asciidoc") - into file("src/main/resources/static/docs") -} \ No newline at end of file From 78e21902240f96ea3abca9dd47bc0e345d00e600 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 17:40:49 +0900 Subject: [PATCH 12/41] =?UTF-8?q?YEL-139=20[test]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=9C=20Builder=20=ED=8C=A8?= =?UTF-8?q?=ED=84=B4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/infrastructure/firebase/manager/FCMManagerImpl.java | 2 ++ .../rabbitmq/service/ConsumerRabbitmqService.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/main/java/com/yello/server/infrastructure/firebase/manager/FCMManagerImpl.java b/src/main/java/com/yello/server/infrastructure/firebase/manager/FCMManagerImpl.java index 256452c4..3e49021c 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/manager/FCMManagerImpl.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/manager/FCMManagerImpl.java @@ -7,9 +7,11 @@ import com.google.firebase.messaging.Notification; import com.yello.server.domain.vote.repository.VoteRepository; import com.yello.server.infrastructure.firebase.dto.request.NotificationMessage; +import lombok.Builder; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +@Builder @Service @RequiredArgsConstructor public class FCMManagerImpl implements FCMManager { diff --git a/src/main/java/com/yello/server/infrastructure/rabbitmq/service/ConsumerRabbitmqService.java b/src/main/java/com/yello/server/infrastructure/rabbitmq/service/ConsumerRabbitmqService.java index df9fa653..f73c26b9 100644 --- a/src/main/java/com/yello/server/infrastructure/rabbitmq/service/ConsumerRabbitmqService.java +++ b/src/main/java/com/yello/server/infrastructure/rabbitmq/service/ConsumerRabbitmqService.java @@ -5,12 +5,14 @@ import com.yello.server.infrastructure.firebase.service.NotificationService; import com.yello.server.infrastructure.rabbitmq.dto.response.VoteAvailableQueueResponse; import java.io.IOException; +import lombok.Builder; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Service; +@Builder @Service @RequiredArgsConstructor @Log4j2 From 8cd055501cf47c747b5416cd10a3a374edaf7425 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 23:29:45 +0900 Subject: [PATCH 13/41] =?UTF-8?q?YEL-139=20[test]=20Swagger=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 - .../controller/AuthController.java | 44 +------- .../friend/controller/FriendController.java | 80 +++----------- .../dto/response/RecommendFriendResponse.java | 5 - .../domain/pay/controller/PayController.java | 14 +-- .../controller/PurchaseController.java | 50 --------- .../question/dto/response/QuestionVO.java | 10 -- .../user/controller/UserController.java | 29 +---- .../vote/controller/VoteController.java | 102 ++---------------- .../dto/response/VoteAvailableResponse.java | 6 -- .../vote/dto/response/VoteContentVO.java | 10 -- .../vote/dto/response/VoteDetailResponse.java | 25 +---- .../vote/dto/response/VoteFriendVO.java | 12 --- .../vote/dto/response/VoteListResponse.java | 8 -- .../vote/dto/response/VoteResponse.java | 16 --- .../dto/response/VoteUnreadCountResponse.java | 2 - .../server/global/HealthCheckController.java | 2 - .../common/annotation/AccessTokenUser.java | 2 - .../configuration/SwaggerConfiguration.java | 33 ------ 19 files changed, 28 insertions(+), 426 deletions(-) delete mode 100644 src/main/java/com/yello/server/global/configuration/SwaggerConfiguration.java diff --git a/build.gradle b/build.gradle index ff75c6b9..1c7978f7 100644 --- a/build.gradle +++ b/build.gradle @@ -67,10 +67,6 @@ dependencies { implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2' implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.2' - - // Swagger - implementation 'org.springdoc:springdoc-openapi-ui:1.5.4' - // p6spy implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.7' diff --git a/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java b/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java index d21818d3..492aa2f9 100644 --- a/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java +++ b/src/main/java/com/yello/server/domain/authorization/controller/AuthController.java @@ -21,11 +21,6 @@ import com.yello.server.domain.authorization.service.AuthService; import com.yello.server.global.common.annotation.ServiceToken; import com.yello.server.global.common.dto.BaseResponse; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; import javax.validation.Valid; import javax.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; @@ -37,7 +32,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Tag(name = "03. Authentication") @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/auth") @@ -45,45 +39,24 @@ public class AuthController { private final AuthService authService; - @Operation(summary = "소셜 로그인 API", responses = { - @ApiResponse( - responseCode = "201", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = OAuthResponse.class))), - }) @PostMapping("/oauth") public BaseResponse oauthLogin(@RequestBody OAuthRequest oAuthRequest) { val data = authService.oauthLogin(oAuthRequest); return BaseResponse.success(LOGIN_SUCCESS, data); } - @Operation(summary = "옐로 아이디 중복 확인 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = Boolean.class))), - }) @GetMapping("/valid") public BaseResponse getYelloIdValidation(@RequestParam("yelloId") String yelloId) { val data = authService.isYelloIdDuplicated(yelloId); return BaseResponse.success(YELLOID_VALIDATION_SUCCESS, data); } - @Operation(summary = "회원가입 API", responses = { - @ApiResponse( - responseCode = "201", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = SignUpResponse.class))), - }) @PostMapping("/signup") - public BaseResponse postSignUp( - @Valid @RequestBody SignUpRequest signUpRequest) { + public BaseResponse postSignUp(@Valid @RequestBody SignUpRequest signUpRequest) { val data = authService.signUp(signUpRequest); return BaseResponse.success(SIGN_UP_SUCCESS, data); } - @Operation(summary = "가입한 친구 목록 불러오기 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = OnBoardingFriendResponse.class))), - }) @PostMapping("/friend") public BaseResponse postFriendList( @Valid @RequestBody OnBoardingFriendRequest friendRequest, @@ -93,11 +66,6 @@ public BaseResponse postFriendList( return BaseResponse.success(ONBOARDING_FRIENDS_SUCCESS, data); } - @Operation(summary = "대학교 이름 검색하기 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = GroupNameSearchResponse.class))), - }) @GetMapping("/school") public BaseResponse getSchoolList( @NotNull @RequestParam("keyword") String keyword, @@ -107,11 +75,6 @@ public BaseResponse getSchoolList( return BaseResponse.success(SCHOOL_NAME_SEARCH_SCHOOL_SUCCESS, data); } - @Operation(summary = "대학교 이름으로 학과 이름 검색하기 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = DepartmentSearchResponse.class))), - }) @GetMapping("/school/department") public BaseResponse getDepartmentList( @NotNull @RequestParam("school") String schoolName, @@ -122,11 +85,6 @@ public BaseResponse getDepartmentList( return BaseResponse.success(DEPARTMENT_NAME_SEARCH_BY_SCHOOL_NAME_SCHOOL_SUCCESS, data); } - @Operation(summary = "토큰 재발급 API", responses = { - @ApiResponse( - responseCode = "201", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = ServiceTokenVO.class))), - }) @PostMapping("/token/issue") public BaseResponse postReIssueToken(@ServiceToken ServiceTokenVO tokens) { val data = authService.reIssueToken(tokens); diff --git a/src/main/java/com/yello/server/domain/friend/controller/FriendController.java b/src/main/java/com/yello/server/domain/friend/controller/FriendController.java index a59d6370..85838714 100644 --- a/src/main/java/com/yello/server/domain/friend/controller/FriendController.java +++ b/src/main/java/com/yello/server/domain/friend/controller/FriendController.java @@ -18,13 +18,6 @@ import com.yello.server.global.common.annotation.AccessTokenUser; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.infrastructure.firebase.service.NotificationService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; import javax.validation.Valid; import lombok.RequiredArgsConstructor; @@ -39,7 +32,6 @@ import org.springframework.web.bind.annotation.RestController; -@Tag(name = "02. Friend") @RestController @RequestMapping("/api/v1/friend") @RequiredArgsConstructor @@ -48,57 +40,27 @@ public class FriendController { private final FriendService friendService; private final NotificationService notificationService; - @Operation(summary = "친구 추가하기 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json") - ) - }) @PostMapping("/{targetId}") - public BaseResponse addFriend( - @Parameter(name = "targetId", description = "친구 신청할 상대 유저의 아이디 값 입니다.") - @Valid @PathVariable Long targetId, - @AccessTokenUser User user) { + public BaseResponse addFriend(@Valid @PathVariable Long targetId, @AccessTokenUser User user) { val data = friendService.addFriend(user.getId(), targetId); notificationService.sendFriendNotification(data); return BaseResponse.success(ADD_FRIEND_SUCCESS); } - @Operation(summary = "내 친구 전체 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = FriendsResponse.class)) - ) - }) @GetMapping - public BaseResponse findAllFriend( - @Parameter(name = "page", description = "페이지네이션 페이지 번호입니다.", example = "1") - @Valid @RequestParam Integer page, - @AccessTokenUser User user) { + public BaseResponse findAllFriend(@Valid @RequestParam Integer page, @AccessTokenUser User user) { val data = friendService.findAllFriends(createPageableLimitTen(page), user.getId()); return BaseResponse.success(READ_FRIEND_SUCCESS, data); } - @Operation(summary = "친구 셔플 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = FriendShuffleResponse.class)))) - }) @GetMapping("/shuffle") - public BaseResponse> findShuffledFriend( - @AccessTokenUser User user) { + public BaseResponse> findShuffledFriend(@AccessTokenUser User user) { val friendShuffleResponse = friendService.findShuffledFriend(user.getId()); return BaseResponse.success(SHUFFLE_FRIEND_SUCCESS, friendShuffleResponse); } - @Operation(summary = "그룹 추천친구 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = RecommendFriendResponse.class))) - }) @GetMapping("/recommend/school") public BaseResponse recommendSchoolFriend( - @Parameter(name = "page", description = "페이지네이션 페이지 번호입니다.", example = "1") @Valid @RequestParam Integer page, @AccessTokenUser User user ) { @@ -107,51 +69,37 @@ public BaseResponse recommendSchoolFriend( return BaseResponse.success(READ_FRIEND_SUCCESS, data); } - @Operation(summary = "카카오 추천 친구 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = RecommendFriendResponse.class))) - }) @PostMapping("/recommend/kakao") public BaseResponse recommendKakaoFriend( @RequestBody KakaoRecommendRequest request, @Valid @RequestParam Integer page, @AccessTokenUser User user ) { - val data = - friendService.findAllRecommendKakaoFriends(createPageableByNameSort(page), user.getId(), - request); + val data = friendService.findAllRecommendKakaoFriends( + createPageableByNameSort(page), + user.getId(), + request + ); return BaseResponse.success(READ_FRIEND_SUCCESS, data); } - @Operation(summary = "친구 삭제하기 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json")) - }) @DeleteMapping("/{targetId}") - public BaseResponse deleteFriend( - @Parameter(name = "targetId", description = "삭제할 친구 유저의 아이디 값 입니다.") - @Valid @PathVariable Long targetId, - @AccessTokenUser User user) { + public BaseResponse deleteFriend(@Valid @PathVariable Long targetId, @AccessTokenUser User user) { friendService.deleteFriend(user.getId(), targetId); return BaseResponse.success(DELETE_FRIEND_SUCCESS); } - @Operation(summary = "친구 검색 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = RecommendFriendResponse.class))) - }) @GetMapping("/search") public BaseResponse searchFriend( @AccessTokenUser User user, @Valid @RequestParam("page") Integer page, @Valid @RequestParam("keyword") String keyword ) { - val data = - friendService.searchFriend(user.getId(), createPageableLimitTen(page), keyword); - // 이름이 한글인경우, 영어인경우 체크 + val data = friendService.searchFriend( + user.getId(), + createPageableLimitTen(page), + keyword + ); return BaseResponse.success(FRIEND_SEARCH_SUCCESS, data); } } diff --git a/src/main/java/com/yello/server/domain/friend/dto/response/RecommendFriendResponse.java b/src/main/java/com/yello/server/domain/friend/dto/response/RecommendFriendResponse.java index 3a7306de..296744ee 100644 --- a/src/main/java/com/yello/server/domain/friend/dto/response/RecommendFriendResponse.java +++ b/src/main/java/com/yello/server/domain/friend/dto/response/RecommendFriendResponse.java @@ -1,16 +1,12 @@ package com.yello.server.domain.friend.dto.response; -import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; import lombok.Builder; @Builder public record RecommendFriendResponse( - @Schema(description = "해당 유저의 친구들이 받은 총 투표 개수") Integer totalCount, - @Schema(description = "해당 유저의 친구들이 받은 총 투표") List friends - ) { public static RecommendFriendResponse of(Integer totalCount, List friends) { @@ -19,5 +15,4 @@ public static RecommendFriendResponse of(Integer totalCount, List verifyGoogleSubscriptionTransaction( @AccessTokenUser User user, @@ -89,12 +63,6 @@ public BaseResponse verifyGoogleSubscriptionTrans return BaseResponse.success(GOOGLE_PURCHASE_SUBSCRIPTION_VERIFY_SUCCESS, data); } - @Operation(summary = "구글 열람권 결제 정보 검증하기 API", responses = { - @ApiResponse( - responseCode = "201", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = GoogleInAppGetResponse.class)) - ) - }) @PostMapping("/google/verify/ticket") public BaseResponse verifyGoogleTicketTransaction( @AccessTokenUser User user, @@ -104,12 +72,6 @@ public BaseResponse verifyGoogleTicketTransaction( return BaseResponse.success(GOOGLE_PURCHASE_INAPP_VERIFY_SUCCESS, data); } - @Operation(summary = "구독 연장 유도 필요 여부 확인 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = UserSubscribeNeededResponse.class)) - ) - }) @GetMapping("/subscribe") public BaseResponse getUserSubscribeNeeded( @AccessTokenUser User user) { @@ -117,12 +79,6 @@ public BaseResponse getUserSubscribeNeeded( return BaseResponse.success(USER_SUBSCRIBE_NEEDED_READ_SUCCESS, data); } - @Operation(summary = "Apple 환불 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = AppleOrderResponse.class)) - ) - }) @DeleteMapping("/apple/refund") public BaseResponse refundInAppApple( @AccessTokenUser User user, @@ -132,12 +88,6 @@ public BaseResponse refundInAppApple( return BaseResponse.success(VERIFY_RECEIPT_SUCCESS); } - @Operation(summary = "구독 상태 및 구독권 갯수 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = UserPurchaseInfoResponse.class)) - ) - }) @GetMapping() public BaseResponse getUserPurchaseInfo(@AccessTokenUser User user) { val data = UserPurchaseInfoResponse.of(user); diff --git a/src/main/java/com/yello/server/domain/question/dto/response/QuestionVO.java b/src/main/java/com/yello/server/domain/question/dto/response/QuestionVO.java index 67e11a4c..c7c5010a 100644 --- a/src/main/java/com/yello/server/domain/question/dto/response/QuestionVO.java +++ b/src/main/java/com/yello/server/domain/question/dto/response/QuestionVO.java @@ -1,25 +1,15 @@ package com.yello.server.domain.question.dto.response; import com.yello.server.domain.question.entity.Question; -import io.swagger.v3.oas.annotations.media.Schema; import java.util.Objects; import lombok.Builder; @Builder public record QuestionVO( - @Schema(description = "투표 질문 id", example = "1") Long questionId, - - @Schema(description = "투표 내용 중 이름 앞 부분", example = "나는") String nameHead, - - @Schema(description = "투표 내용 중 이름 뒷 부분", example = "랑") String nameFoot, - - @Schema(description = "투표 내용 중 키워드 앞 부분", example = "한강에서") String keywordHead, - - @Schema(description = "투표 내용 중 키워드 뒷 부분", example = "하고 싶어") String keywordFoot ) { diff --git a/src/main/java/com/yello/server/domain/user/controller/UserController.java b/src/main/java/com/yello/server/domain/user/controller/UserController.java index ae831193..49ebff1d 100644 --- a/src/main/java/com/yello/server/domain/user/controller/UserController.java +++ b/src/main/java/com/yello/server/domain/user/controller/UserController.java @@ -12,11 +12,6 @@ import com.yello.server.global.common.annotation.AccessTokenUser; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.global.common.dto.EmptyObject; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.val; import org.springframework.web.bind.annotation.DeleteMapping; @@ -27,7 +22,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -@Tag(name = "04. User") @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/user") @@ -35,46 +29,27 @@ public class UserController { private final UserService userService; - @Operation(summary = "내 정보 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = UserDetailResponse.class))), - }) @GetMapping public BaseResponse findUser(@AccessTokenUser User user) { val data = userService.findMyProfile(user.getId()); return BaseResponse.success(READ_USER_SUCCESS, data); } - @Operation(summary = "유저 정보 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = UserResponse.class))), - }) @GetMapping("/{userId}") public BaseResponse findUserById(@PathVariable Long userId) { val data = userService.findUserById(userId); return BaseResponse.success(READ_USER_SUCCESS, data); } - @Operation(summary = "디바이스 토큰 수정 API", responses = { - @ApiResponse( - responseCode = "201", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = EmptyObject.class))), - }) @PutMapping("/device") public BaseResponse putUserDeviceToken( @AccessTokenUser User user, - @RequestBody UserDeviceTokenRequest request) { + @RequestBody UserDeviceTokenRequest request + ) { val data = userService.updateUserDeviceToken(user, request); return BaseResponse.success(UPDATE_DEVICE_TOKEN_USER_SUCCESS, data); } - @Operation(summary = "유저 탈퇴 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json")) - }) @DeleteMapping public BaseResponse deleteUser(@AccessTokenUser User user) { userService.delete(user); diff --git a/src/main/java/com/yello/server/domain/vote/controller/VoteController.java b/src/main/java/com/yello/server/domain/vote/controller/VoteController.java index 41886e77..7b8796a1 100644 --- a/src/main/java/com/yello/server/domain/vote/controller/VoteController.java +++ b/src/main/java/com/yello/server/domain/vote/controller/VoteController.java @@ -24,13 +24,6 @@ import com.yello.server.global.common.annotation.AccessTokenUser; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.infrastructure.firebase.service.NotificationService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.val; @@ -43,7 +36,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Tag(name = "01. Vote") @RestController @RequestMapping("api/v1/vote") @RequiredArgsConstructor @@ -52,108 +44,48 @@ public class VoteController { private final VoteService voteService; private final NotificationService notificationService; - @Operation(summary = "내 투표 전체 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = VoteListResponse.class))), - }) @GetMapping - public BaseResponse findAllMyVotes( - @Parameter(name = "page", description = "페이지네이션 페이지 번호입니다.", example = "1") - @RequestParam Integer page, - @AccessTokenUser User user - ) { + public BaseResponse findAllMyVotes(@RequestParam Integer page, @AccessTokenUser User user) { val data = voteService.findAllVotes(user.getId(), createPageableLimitTen(page)); return BaseResponse.success(READ_VOTE_SUCCESS, data); } - @Operation(summary = "읽지 않은 쪽지 개수 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = VoteUnreadCountResponse.class))), - }) @GetMapping("/count") - public BaseResponse getUnreadVoteCount( - @AccessTokenUser User user - ) { + public BaseResponse getUnreadVoteCount(@AccessTokenUser User user) { val data = voteService.getUnreadVoteCount(user.getId()); return BaseResponse.success(READ_VOTE_SUCCESS, data); } - @Operation(summary = "친구 투표 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = VoteFriendResponse.class))), - }) @GetMapping("/friend") - public BaseResponse findAllFriendVotes( - @Parameter(name = "page", description = "페이지네이션 페이지 번호입니다.", example = "1") - @RequestParam Integer page, - @AccessTokenUser User user - ) { + public BaseResponse findAllFriendVotes(@RequestParam Integer page, @AccessTokenUser User user) { val data = voteService.findAllFriendVotes(user.getId(), createPageableLimitTen(page)); return BaseResponse.success(READ_VOTE_SUCCESS, data); } - @Operation(summary = "투표 상세 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = VoteDetailResponse.class))), - }) @GetMapping("/{voteId}") - public BaseResponse findVote( - @PathVariable Long voteId, - @AccessTokenUser User user) { + public BaseResponse findVote(@PathVariable Long voteId, @AccessTokenUser User user) { val data = voteService.findVoteById(voteId, user.getId()); return BaseResponse.success(READ_VOTE_SUCCESS, data); } - @Operation(summary = "키워드 확인 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = KeywordCheckResponse.class))), - }) @PatchMapping("/{voteId}/keyword") - public BaseResponse checkKeyword( - @Parameter(name = "voteId", description = "해당 투표 아이디 값 입니다.") - @PathVariable Long voteId, - @AccessTokenUser User user - ) { + public BaseResponse checkKeyword(@PathVariable Long voteId, @AccessTokenUser User user) { val keywordCheckResponse = voteService.checkKeyword(user.getId(), voteId); return BaseResponse.success(CHECK_KEYWORD_SUCCESS, keywordCheckResponse); } - @Operation(summary = "투표 8개 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = QuestionForVoteResponse.class)))), - }) @GetMapping("/question") - public BaseResponse> findVoteQuestions( - @AccessTokenUser User user - ) { + public BaseResponse> findVoteQuestions(@AccessTokenUser User user) { val data = voteService.findVoteQuestionList(user.getId()); return BaseResponse.success(READ_YELLO_VOTE_SUCCESS, data); } - @Operation(summary = "투표 가능 여부 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = VoteAvailableResponse.class))), - }) @GetMapping("/available") - public BaseResponse checkVoteAvailable( - @AccessTokenUser User user - ) { + public BaseResponse checkVoteAvailable(@AccessTokenUser User user) { val data = voteService.checkVoteAvailable(user.getId()); return BaseResponse.success(READ_YELLO_START_SUCCESS, data); } - @Operation(summary = "투표 생성 API", responses = { - @ApiResponse( - responseCode = "201", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = VoteCreateResponse.class))), - }) @PostMapping public BaseResponse createVote( @AccessTokenUser User user, @@ -166,30 +98,14 @@ public BaseResponse createVote( return BaseResponse.success(CREATE_VOTE_SUCCESS, response); } - @Operation(summary = "투표 이름 부분 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = RevealNameResponse.class))), - }) @PatchMapping("/{voteId}/name") - public BaseResponse revealNameHint( - @AccessTokenUser User user, - @PathVariable Long voteId - ) { + public BaseResponse revealNameHint(@AccessTokenUser User user, @PathVariable Long voteId) { val data = voteService.revealNameHint(user.getId(), voteId); return BaseResponse.success(SuccessCode.REVEAL_NAME_HINT_SUCCESS, data); } - @Operation(summary = "투표 이름 전체 조회 API", responses = { - @ApiResponse( - responseCode = "200", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = RevealFullNameResponse.class))), - }) @PatchMapping("/{voteId}/fullname") - public BaseResponse revealFullName( - @AccessTokenUser User user, - @PathVariable Long voteId - ) { + public BaseResponse revealFullName(@AccessTokenUser User user, @PathVariable Long voteId) { val data = voteService.revealFullName(user.getId(), voteId); return BaseResponse.success(SuccessCode.REVEAL_NAME_SUCCESS, data); } diff --git a/src/main/java/com/yello/server/domain/vote/dto/response/VoteAvailableResponse.java b/src/main/java/com/yello/server/domain/vote/dto/response/VoteAvailableResponse.java index d0b5335a..9f7ecaef 100644 --- a/src/main/java/com/yello/server/domain/vote/dto/response/VoteAvailableResponse.java +++ b/src/main/java/com/yello/server/domain/vote/dto/response/VoteAvailableResponse.java @@ -6,19 +6,13 @@ import com.yello.server.domain.cooldown.entity.Cooldown; import com.yello.server.domain.user.entity.User; -import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; import lombok.Builder; @Builder public record VoteAvailableResponse( - @Schema(description = "투표 가능 여부 (true=가능, false=불가능)", example = "false") Boolean isPossible, - - @Schema(description = "현재 보유중인 포인트", example = "200") Integer point, - - @Schema(description = "마지막 투표 시점") String createdAt ) { diff --git a/src/main/java/com/yello/server/domain/vote/dto/response/VoteContentVO.java b/src/main/java/com/yello/server/domain/vote/dto/response/VoteContentVO.java index 94eeb27e..86f3e5c5 100644 --- a/src/main/java/com/yello/server/domain/vote/dto/response/VoteContentVO.java +++ b/src/main/java/com/yello/server/domain/vote/dto/response/VoteContentVO.java @@ -1,25 +1,15 @@ package com.yello.server.domain.vote.dto.response; import com.yello.server.domain.vote.entity.Vote; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.val; @Builder public record VoteContentVO( - @Schema(description = "투표 내용 중 이름 앞 부분", example = "나는") String nameHead, - - @Schema(description = "투표 내용 중 이름 뒷 부분", example = "랑") String nameFoot, - - @Schema(description = "투표 내용 중 키워드 앞 부분", example = "한강에서") String keywordHead, - - @Schema(description = "투표 내용 중 키워드 키워드 부분", example = "수영") String keyword, - - @Schema(description = "투표 내용 중 키워드 뒷 부분", example = "하고 싶어") String keywordFoot ) { diff --git a/src/main/java/com/yello/server/domain/vote/dto/response/VoteDetailResponse.java b/src/main/java/com/yello/server/domain/vote/dto/response/VoteDetailResponse.java index 201904bf..a1dfe2d0 100644 --- a/src/main/java/com/yello/server/domain/vote/dto/response/VoteDetailResponse.java +++ b/src/main/java/com/yello/server/domain/vote/dto/response/VoteDetailResponse.java @@ -3,41 +3,18 @@ import com.yello.server.domain.user.entity.Subscribe; import com.yello.server.domain.user.entity.User; import com.yello.server.domain.vote.entity.Vote; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; @Builder public record VoteDetailResponse( - @Schema(description = "투표 컬러 인덱스") Integer colorIndex, - - @Schema(description = "현재 보유중인 포인트") Integer currentPoint, - - @Schema(description = "이름 힌트 인덱스" - + "\n-3 → 첫 쪽지 (특별값)" - + "\n-2 → 구독권을 사용해서 이름 전체 확인" - + "\n-1 → 이름 힌트가 아직 밝혀지지 않음" - + "\n0 → 첫번째 위치에 이름 힌트가 밝혀짐" - + "\n1 → 두번째 위치에 이름 힌트가 밝혀짐") Integer nameHint, - - @Schema(description = "키워드 공개 여부") Boolean isAnswerRevealed, - - @Schema(description = "투표를 작성한 유저의 이름") String senderName, - - @Schema(description = "투표를 보낸 유저의 성별", example = "MALE | FEMALE") String senderGender, - - @Schema(description = "투표 내용") VoteContentVO vote, - - @Schema(description = "열람권 개수") Integer ticketCount, - - @Schema(description = "구독권 여부", example = "true | false") Boolean isSubscribe ) { @@ -51,7 +28,7 @@ public static VoteDetailResponse of(Vote vote, User user) { .senderGender(vote.getSender().getGender().name()) .vote(VoteContentVO.of(vote)) .ticketCount(user.getTicketCount()) - .isSubscribe(user.getSubscribe() != Subscribe.NORMAL) + .isSubscribe(user.getSubscribe()!=Subscribe.NORMAL) .build(); } } diff --git a/src/main/java/com/yello/server/domain/vote/dto/response/VoteFriendVO.java b/src/main/java/com/yello/server/domain/vote/dto/response/VoteFriendVO.java index 97367592..c83a5147 100644 --- a/src/main/java/com/yello/server/domain/vote/dto/response/VoteFriendVO.java +++ b/src/main/java/com/yello/server/domain/vote/dto/response/VoteFriendVO.java @@ -3,27 +3,15 @@ import static com.yello.server.global.common.factory.TimeFactory.toFormattedString; import com.yello.server.domain.vote.entity.Vote; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; @Builder public record VoteFriendVO( - @Schema(description = "투표 고유 Id 값") Long id, - - @Schema(description = "투표를 받은 유저의 이름", example = "권세훈") String receiverName, - - @Schema(description = "투표를 보낸 유저의 성별", example = "MALE") String senderGender, - - @Schema(description = "투표의 전체 문장") VoteContentVO vote, - - @Schema(description = "힌트 사용 여부") Boolean isHintUsed, - - @Schema(description = "투표 생성 일자", example = "1시간 전") String createdAt ) { diff --git a/src/main/java/com/yello/server/domain/vote/dto/response/VoteListResponse.java b/src/main/java/com/yello/server/domain/vote/dto/response/VoteListResponse.java index 668aeb45..ca97e794 100644 --- a/src/main/java/com/yello/server/domain/vote/dto/response/VoteListResponse.java +++ b/src/main/java/com/yello/server/domain/vote/dto/response/VoteListResponse.java @@ -1,25 +1,17 @@ package com.yello.server.domain.vote.dto.response; import com.yello.server.domain.user.entity.User; -import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; import lombok.Builder; @Builder public record VoteListResponse( - @Schema(description = "내 쪽지 전체 개수") Integer totalCount, - @Schema(description = "열람권 수") Integer ticketCount, - @Schema(description = "오픈한 쪽지 수") Integer openCount, - @Schema(description = "오픈한 키워드 쪽지 수") Integer openKeywordCount, - @Schema(description = "오픈한 초성 쪽지 수") Integer openNameCount, - @Schema(description = "오픈한 전체 이름 쪽지 수") Integer openFullNameCount, - @Schema(description = "내 쪽지 리스트") List votes ) { diff --git a/src/main/java/com/yello/server/domain/vote/dto/response/VoteResponse.java b/src/main/java/com/yello/server/domain/vote/dto/response/VoteResponse.java index 4ab04676..55412b4d 100644 --- a/src/main/java/com/yello/server/domain/vote/dto/response/VoteResponse.java +++ b/src/main/java/com/yello/server/domain/vote/dto/response/VoteResponse.java @@ -3,33 +3,17 @@ import static com.yello.server.global.common.factory.TimeFactory.toFormattedString; import com.yello.server.domain.vote.entity.Vote; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; @Builder public record VoteResponse( - @Schema(description = "투표 고유 Id 값") Long id, - - @Schema(description = "투표를 보낸 유저의 성별", example = "MALE") String senderGender, - - @Schema(description = "투표를 보낸 유저의 이름", example = "권세훈") String senderName, - - @Schema(description = "이름 힌트 인덱스", example = "-1") Integer nameHint, - - @Schema(description = "투표 내용") VoteContentVO vote, - - @Schema(description = "힌트 사용 여부") Boolean isHintUsed, - - @Schema(description = "투표 읽음 여부") Boolean isRead, - - @Schema(description = "투표 생성 일자", example = "1시간 전") String createdAt ) { diff --git a/src/main/java/com/yello/server/domain/vote/dto/response/VoteUnreadCountResponse.java b/src/main/java/com/yello/server/domain/vote/dto/response/VoteUnreadCountResponse.java index 11d56605..42c3f527 100644 --- a/src/main/java/com/yello/server/domain/vote/dto/response/VoteUnreadCountResponse.java +++ b/src/main/java/com/yello/server/domain/vote/dto/response/VoteUnreadCountResponse.java @@ -1,11 +1,9 @@ package com.yello.server.domain.vote.dto.response; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; @Builder public record VoteUnreadCountResponse( - @Schema(description = "읽지 않은 쪽지 개수", example = "1") Integer totalCount ) { diff --git a/src/main/java/com/yello/server/global/HealthCheckController.java b/src/main/java/com/yello/server/global/HealthCheckController.java index 01f00f37..a3cf6aa3 100644 --- a/src/main/java/com/yello/server/global/HealthCheckController.java +++ b/src/main/java/com/yello/server/global/HealthCheckController.java @@ -1,11 +1,9 @@ package com.yello.server.global; -import io.swagger.v3.oas.annotations.Hidden; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -@Hidden @RestController @RequiredArgsConstructor public class HealthCheckController { diff --git a/src/main/java/com/yello/server/global/common/annotation/AccessTokenUser.java b/src/main/java/com/yello/server/global/common/annotation/AccessTokenUser.java index 572520cb..fc204ea0 100644 --- a/src/main/java/com/yello/server/global/common/annotation/AccessTokenUser.java +++ b/src/main/java/com/yello/server/global/common/annotation/AccessTokenUser.java @@ -1,6 +1,5 @@ package com.yello.server.global.common.annotation; -import io.swagger.v3.oas.annotations.Parameter; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -8,7 +7,6 @@ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -@Parameter(hidden = true) public @interface AccessTokenUser { } diff --git a/src/main/java/com/yello/server/global/configuration/SwaggerConfiguration.java b/src/main/java/com/yello/server/global/configuration/SwaggerConfiguration.java deleted file mode 100644 index 50fcd700..00000000 --- a/src/main/java/com/yello/server/global/configuration/SwaggerConfiguration.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.yello.server.global.configuration; - -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.security.SecurityScheme; -import java.util.Arrays; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class SwaggerConfiguration { - - @Bean - public OpenAPI openAPI() { - Info info = new Info() - .title("YELL:O API Documentation") - .description("YELL:O API 공식 명세서 입니다.") - .version("v1"); - - SecurityScheme securityScheme = new SecurityScheme() - .type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT") - .in(SecurityScheme.In.HEADER).name("Authorization"); - - SecurityRequirement securityRequirement = new SecurityRequirement().addList("Bearer Token"); - - return new OpenAPI() - .components(new Components().addSecuritySchemes("Bearer Token", securityScheme)) - .security(Arrays.asList(securityRequirement)) - .info(info); - } -} From f2c2c70983f90bbc762758738e581e4558a3e1a7 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Wed, 23 Aug 2023 23:32:04 +0900 Subject: [PATCH 14/41] =?UTF-8?q?YEL-139=20[test]=20Github=20action=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 2 +- .github/workflows/deploy-test.yml | 2 +- .github/workflows/deploy.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a77ef705..22eccb54 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,7 +38,7 @@ jobs: shell: bash - name: 🐘 Gradle로 빌드 실행 - run: ./gradlew build -x test + run: ./gradlew build - name: 💡 배포 상태를 Slack을 통해 전송합니다. uses: rtCamp/action-slack-notify@v2 diff --git a/.github/workflows/deploy-test.yml b/.github/workflows/deploy-test.yml index c1c70f9a..f81407b9 100644 --- a/.github/workflows/deploy-test.yml +++ b/.github/workflows/deploy-test.yml @@ -46,7 +46,7 @@ jobs: shell: bash - name: 🐘 Gradle로 빌드 실행 - run: ./gradlew build -x test + run: ./gradlew build - name: 📦 배포를 진행하기 위한 .zip 파일을 생성합니다. run: | diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 350e4eb4..f9b1ed79 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -46,7 +46,7 @@ jobs: shell: bash - name: 🐘 Gradle로 빌드 실행 - run: ./gradlew build -x test + run: ./gradlew build - name: 📦 배포를 진행하기 위한 .zip 파일을 생성합니다. run: | From 72bf1e25faf045889201e05dfc83a61aaf286f73 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Thu, 24 Aug 2023 00:14:15 +0900 Subject: [PATCH 15/41] =?UTF-8?q?YEl-141=20[fix]=20=EC=98=90=EB=A1=9C=20?= =?UTF-8?q?=ED=94=8C=EB=9F=AC=EC=8A=A4=20=ED=95=9C=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=95=88=EA=B9=8C=EC=9D=B4?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/domain/vote/service/VoteManagerImpl.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java b/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java index c1950f05..1f3bd025 100644 --- a/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java +++ b/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java @@ -107,7 +107,7 @@ public List generateVoteQuestion(User user, List Date: Fri, 25 Aug 2023 12:11:13 +0900 Subject: [PATCH 16/41] =?UTF-8?q?YEL-139=20[test]=20Random=20=EC=84=B1?= =?UTF-8?q?=EB=8A=A5=EC=9D=84=20=EC=9C=84=ED=95=B4=20ThreadLocalRandom=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/vote/service/VoteManagerImpl.java | 9 ++++--- .../factory}/WeightedRandomFactory.java | 7 +++-- .../server/domain/vote/FakeVoteManager.java | 9 ++++--- .../common/factory/TimeFactoryTest.java | 27 +++++++++++++++++++ .../factory/WeightedRandomFactoryTest.java | 2 ++ 5 files changed, 44 insertions(+), 10 deletions(-) rename src/main/java/com/yello/server/{domain/vote/common => global/common/factory}/WeightedRandomFactory.java (90%) create mode 100644 src/test/java/com/yello/server/global/common/factory/TimeFactoryTest.java create mode 100644 src/test/java/com/yello/server/global/common/factory/WeightedRandomFactoryTest.java diff --git a/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java b/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java index c1950f05..92810609 100644 --- a/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java +++ b/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java @@ -1,9 +1,9 @@ package com.yello.server.domain.vote.service; -import static com.yello.server.domain.vote.common.WeightedRandomFactory.randomPoint; import static com.yello.server.global.common.ErrorCode.DUPLICATE_VOTE_EXCEPTION; import static com.yello.server.global.common.ErrorCode.INVALID_VOTE_EXCEPTION; import static com.yello.server.global.common.ErrorCode.LACK_POINT_EXCEPTION; +import static com.yello.server.global.common.factory.WeightedRandomFactory.randomPoint; import static com.yello.server.global.common.util.ConstantUtil.KEYWORD_HINT_POINT; import static com.yello.server.global.common.util.ConstantUtil.NAME_HINT_DEFAULT; import static com.yello.server.global.common.util.ConstantUtil.NAME_HINT_POINT; @@ -34,7 +34,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; import lombok.Builder; import lombok.RequiredArgsConstructor; @@ -115,7 +115,8 @@ public int useNameHint(User sender, Vote vote) { throw new VoteNotFoundException(INVALID_VOTE_EXCEPTION); } - int randomIndex = (int) (Math.random() * 2); + final ThreadLocalRandom random = ThreadLocalRandom.current(); + int randomIndex = random.nextInt(2); vote.checkNameIndexOf(randomIndex); sender.minusPoint(NAME_HINT_POINT); return randomIndex; @@ -187,7 +188,7 @@ private List getShuffledKeywords(Question question) { } private Vote createFirstVote(User sender, User receiver, Question question) { - Random random = new Random(); + final ThreadLocalRandom random = ThreadLocalRandom.current(); final String answer = "널 기다렸어"; return Vote.builder() diff --git a/src/main/java/com/yello/server/domain/vote/common/WeightedRandomFactory.java b/src/main/java/com/yello/server/global/common/factory/WeightedRandomFactory.java similarity index 90% rename from src/main/java/com/yello/server/domain/vote/common/WeightedRandomFactory.java rename to src/main/java/com/yello/server/global/common/factory/WeightedRandomFactory.java index d54200ab..327c201e 100644 --- a/src/main/java/com/yello/server/domain/vote/common/WeightedRandomFactory.java +++ b/src/main/java/com/yello/server/global/common/factory/WeightedRandomFactory.java @@ -13,6 +13,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; public class WeightedRandomFactory { @@ -32,9 +33,11 @@ public static Integer randomPoint() { weight.put(MIN_POINT + 16, SEVENTH_POINT_WEIGHT); weight.put(MIN_POINT + 20, EIGHT_POINT_WEIGHT); - final double pivot = Math.random() % REMINDER_NUMBER; + final ThreadLocalRandom random = ThreadLocalRandom.current(); + + final double pivot = random.nextDouble(1) % REMINDER_NUMBER; double currentWeight = 0; - + for (int key : weight.keySet()) { currentWeight += weight.getOrDefault(key, 0.0); if (currentWeight >= pivot) { diff --git a/src/test/java/com/yello/server/domain/vote/FakeVoteManager.java b/src/test/java/com/yello/server/domain/vote/FakeVoteManager.java index 85c0d20b..deadc264 100644 --- a/src/test/java/com/yello/server/domain/vote/FakeVoteManager.java +++ b/src/test/java/com/yello/server/domain/vote/FakeVoteManager.java @@ -1,9 +1,9 @@ package com.yello.server.domain.vote; -import static com.yello.server.domain.vote.common.WeightedRandomFactory.randomPoint; import static com.yello.server.global.common.ErrorCode.DUPLICATE_VOTE_EXCEPTION; import static com.yello.server.global.common.ErrorCode.INVALID_VOTE_EXCEPTION; import static com.yello.server.global.common.ErrorCode.LACK_POINT_EXCEPTION; +import static com.yello.server.global.common.factory.WeightedRandomFactory.randomPoint; import static com.yello.server.global.common.util.ConstantUtil.KEYWORD_HINT_POINT; import static com.yello.server.global.common.util.ConstantUtil.NAME_HINT_DEFAULT; import static com.yello.server.global.common.util.ConstantUtil.NAME_HINT_POINT; @@ -31,7 +31,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; public class FakeVoteManager implements VoteManager { @@ -115,7 +115,8 @@ public int useNameHint(User sender, Vote vote) { throw new VoteNotFoundException(INVALID_VOTE_EXCEPTION); } - int randomIndex = (int) (Math.random() * 2); + final ThreadLocalRandom random = ThreadLocalRandom.current(); + int randomIndex = random.nextInt(2); vote.checkNameIndexOf(randomIndex); sender.minusPoint(NAME_HINT_POINT); return randomIndex; @@ -185,7 +186,7 @@ private List getShuffledKeywords(Question question) { } private Vote createFirstVote(User sender, User receiver, Question question) { - Random random = new Random(); + final ThreadLocalRandom random = ThreadLocalRandom.current(); final String answer = "널 기다렸어"; return Vote.builder() diff --git a/src/test/java/com/yello/server/global/common/factory/TimeFactoryTest.java b/src/test/java/com/yello/server/global/common/factory/TimeFactoryTest.java new file mode 100644 index 00000000..0ec41b0e --- /dev/null +++ b/src/test/java/com/yello/server/global/common/factory/TimeFactoryTest.java @@ -0,0 +1,27 @@ +package com.yello.server.global.common.factory; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.concurrent.ThreadLocalRandom; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; + +@DisplayName("WeightedRandomFactory 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) +public class WeightedRandomFactoryTest { + + @Test + void 가중치_랜덤값_생성에_성공합니다() { + // given + final ThreadLocalRandom random = ThreadLocalRandom.current(); + + // when + Integer result = WeightedRandomFactory.randomPoint(); + + // then + assertThat(result).isBetween(5, 25); + assertThat(random.nextDouble()).isBetween(0.0, 1.0); + } +} \ No newline at end of file diff --git a/src/test/java/com/yello/server/global/common/factory/WeightedRandomFactoryTest.java b/src/test/java/com/yello/server/global/common/factory/WeightedRandomFactoryTest.java new file mode 100644 index 00000000..c6280ed6 --- /dev/null +++ b/src/test/java/com/yello/server/global/common/factory/WeightedRandomFactoryTest.java @@ -0,0 +1,2 @@ +package com.yello.server.global.common.factory;public class WeightedRandomFactoryTest { +} From e136c1637e902e25be09e6899380da8c690c791e Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 12:11:33 +0900 Subject: [PATCH 17/41] =?UTF-8?q?YEL-139=20[test]=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/factory/PaginationFactory.java | 1 - .../global/common/factory/TokenFactory.java | 44 +++++++++---------- .../common/factory/WeightedRandomFactory.java | 2 +- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/yello/server/global/common/factory/PaginationFactory.java b/src/main/java/com/yello/server/global/common/factory/PaginationFactory.java index 4f433360..b2b26bae 100644 --- a/src/main/java/com/yello/server/global/common/factory/PaginationFactory.java +++ b/src/main/java/com/yello/server/global/common/factory/PaginationFactory.java @@ -29,7 +29,6 @@ public static Pageable createPageableLimitTen(Integer page) { return PageRequest.of(page, PAGE_LIMIT_TEN); } - public static Page getPage(List list, Pageable pageable) { int start = (int) pageable.getOffset(); int end = Math.min((start + pageable.getPageSize()), list.size()); diff --git a/src/main/java/com/yello/server/global/common/factory/TokenFactory.java b/src/main/java/com/yello/server/global/common/factory/TokenFactory.java index a9a3dc84..9d84eda1 100644 --- a/src/main/java/com/yello/server/global/common/factory/TokenFactory.java +++ b/src/main/java/com/yello/server/global/common/factory/TokenFactory.java @@ -4,7 +4,6 @@ import io.jsonwebtoken.SignatureAlgorithm; import java.security.KeyFactory; import java.security.spec.PKCS8EncodedKeySpec; -import java.util.Calendar; import java.util.Date; import lombok.SneakyThrows; import org.apache.commons.codec.binary.Base64; @@ -15,35 +14,34 @@ public class TokenFactory { @Value("${kid}") - private String KID; + private String kid; + @Value("${iss}") - private String ISS; + private String iss; + @Value("${aud}") - private String AUD; + private String aud; + @Value("${bid}") - private String BID; + private String bid; + @Value("${sig}") - private String SIG; + private String sig; @SneakyThrows public String generateAppleToken() { - String jws = Jwts.builder() - // header - .setHeaderParam("kid", KID) - // payload - .setIssuer(ISS) - .setIssuedAt(new Date(Calendar.getInstance().getTimeInMillis())) // 발행 시간 - UNIX 시간 - .setExpiration( - new Date(Calendar.getInstance().getTimeInMillis() + (3 * 60 - * 1000))) // 만료 시간 (발행 시간 + 3분) - .setAudience(AUD) - .claim("bid", BID) - // sign - .signWith(SignatureAlgorithm.ES256, - KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec( - Base64.decodeBase64(SIG)))) + return Jwts.builder() + .setHeaderParam("kid", kid) + .setIssuer(iss) + .setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + (3 * 60 * 1000))) + .setAudience(aud) + .claim("bid", bid) + .signWith( + SignatureAlgorithm.ES256, + KeyFactory.getInstance("EC") + .generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(sig))) + ) .compact(); - - return jws; } } diff --git a/src/main/java/com/yello/server/global/common/factory/WeightedRandomFactory.java b/src/main/java/com/yello/server/global/common/factory/WeightedRandomFactory.java index 327c201e..8aba23c4 100644 --- a/src/main/java/com/yello/server/global/common/factory/WeightedRandomFactory.java +++ b/src/main/java/com/yello/server/global/common/factory/WeightedRandomFactory.java @@ -1,4 +1,4 @@ -package com.yello.server.domain.vote.common; +package com.yello.server.global.common.factory; import static com.yello.server.global.common.util.ConstantUtil.EIGHT_POINT_WEIGHT; import static com.yello.server.global.common.util.ConstantUtil.FIFTH_POINT_WEIGHT; From 4abcde5c95f6a82886bae7804f7412683ba1aa09 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 12:11:43 +0900 Subject: [PATCH 18/41] =?UTF-8?q?YEL-139=20[test]=20Factory=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/factory/TimeFactoryTest.java | 31 ++++++++++++++----- .../factory/WeightedRandomFactoryTest.java | 29 +++++++++++++++-- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/test/java/com/yello/server/global/common/factory/TimeFactoryTest.java b/src/test/java/com/yello/server/global/common/factory/TimeFactoryTest.java index 0ec41b0e..b19d2aa0 100644 --- a/src/test/java/com/yello/server/global/common/factory/TimeFactoryTest.java +++ b/src/test/java/com/yello/server/global/common/factory/TimeFactoryTest.java @@ -2,26 +2,41 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.util.concurrent.ThreadLocalRandom; +import java.time.Duration; +import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; -@DisplayName("WeightedRandomFactory 에서") +@DisplayName("TimeFactory 에서") @DisplayNameGeneration(ReplaceUnderscores.class) -public class WeightedRandomFactoryTest { +public class TimeFactoryTest { @Test - void 가중치_랜덤값_생성에_성공합니다() { + void 시간을_문자열_형식으로_포맷팅에_성공합니다() { // given - final ThreadLocalRandom random = ThreadLocalRandom.current(); + final LocalDateTime localDateTime = LocalDateTime.of(2023, 1, 1, 14, 0, 0); + + final LocalDateTime currentDateTime = LocalDateTime.now(); + Duration duration = Duration.between(localDateTime, currentDateTime); + long seconds = duration.getSeconds(); + String expect = ""; + + if (seconds < 60) { + expect = seconds + "초 전"; + } else if ((seconds /= 60) < 60) { + expect = seconds + "분 전"; + } else if ((seconds /= 60) < 24) { + expect = (seconds) + "시간 전"; + } + + expect = (seconds / 24) + "일 전"; // when - Integer result = WeightedRandomFactory.randomPoint(); + String result = TimeFactory.toFormattedString(localDateTime); // then - assertThat(result).isBetween(5, 25); - assertThat(random.nextDouble()).isBetween(0.0, 1.0); + assertThat(result).isEqualTo(expect); } } \ No newline at end of file diff --git a/src/test/java/com/yello/server/global/common/factory/WeightedRandomFactoryTest.java b/src/test/java/com/yello/server/global/common/factory/WeightedRandomFactoryTest.java index c6280ed6..0ec41b0e 100644 --- a/src/test/java/com/yello/server/global/common/factory/WeightedRandomFactoryTest.java +++ b/src/test/java/com/yello/server/global/common/factory/WeightedRandomFactoryTest.java @@ -1,2 +1,27 @@ -package com.yello.server.global.common.factory;public class WeightedRandomFactoryTest { -} +package com.yello.server.global.common.factory; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.concurrent.ThreadLocalRandom; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; + +@DisplayName("WeightedRandomFactory 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) +public class WeightedRandomFactoryTest { + + @Test + void 가중치_랜덤값_생성에_성공합니다() { + // given + final ThreadLocalRandom random = ThreadLocalRandom.current(); + + // when + Integer result = WeightedRandomFactory.randomPoint(); + + // then + assertThat(result).isBetween(5, 25); + assertThat(random.nextDouble()).isBetween(0.0, 1.0); + } +} \ No newline at end of file From d68c8fc6bc093b35f0e9baff7b5f1a97d71783fa Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 12:37:54 +0900 Subject: [PATCH 19/41] =?UTF-8?q?YEL-139=20[test]=20ListFactory=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/factory/ListFactoryTest.java | 38 +++++++++++++++++++ .../common/factory/PaginationFactoryTest.java | 2 + 2 files changed, 40 insertions(+) create mode 100644 src/test/java/com/yello/server/global/common/factory/ListFactoryTest.java create mode 100644 src/test/java/com/yello/server/global/common/factory/PaginationFactoryTest.java diff --git a/src/test/java/com/yello/server/global/common/factory/ListFactoryTest.java b/src/test/java/com/yello/server/global/common/factory/ListFactoryTest.java new file mode 100644 index 00000000..db5768f0 --- /dev/null +++ b/src/test/java/com/yello/server/global/common/factory/ListFactoryTest.java @@ -0,0 +1,38 @@ +package com.yello.server.global.common.factory; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; + +@DisplayName("ListFactory 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) +public class ListFactoryTest { + + @Test + void null이_없는_리스트_변환에_성공합니다() { + // given + List> optionalList = new ArrayList<>(); + optionalList.add(Optional.of(1)); + optionalList.add(Optional.empty()); + optionalList.add(Optional.of(3)); + optionalList.add(Optional.empty()); + optionalList.add(Optional.of(5)); + + // when + List result = ListFactory.toNonNullableList(optionalList); + + // then + assertThat(result).hasSize(3); + assertThat(result.get(0)).isEqualTo(1); + assertThat(result.get(1)).isEqualTo(3); + assertThat(result.get(2)).isEqualTo(5); + } + + +} diff --git a/src/test/java/com/yello/server/global/common/factory/PaginationFactoryTest.java b/src/test/java/com/yello/server/global/common/factory/PaginationFactoryTest.java new file mode 100644 index 00000000..1eea11a1 --- /dev/null +++ b/src/test/java/com/yello/server/global/common/factory/PaginationFactoryTest.java @@ -0,0 +1,2 @@ +package com.yello.server.global.common.factory;public class PaginationFactoryTest { +} From 2e939460d17fd178791fe7434de1d86d4b8bea9f Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 12:38:03 +0900 Subject: [PATCH 20/41] =?UTF-8?q?YEL-139=20[test]=20PaginationFactory=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/factory/PaginationFactoryTest.java | 89 ++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/yello/server/global/common/factory/PaginationFactoryTest.java b/src/test/java/com/yello/server/global/common/factory/PaginationFactoryTest.java index 1eea11a1..7fbaaabd 100644 --- a/src/test/java/com/yello/server/global/common/factory/PaginationFactoryTest.java +++ b/src/test/java/com/yello/server/global/common/factory/PaginationFactoryTest.java @@ -1,2 +1,89 @@ -package com.yello.server.global.common.factory;public class PaginationFactoryTest { +package com.yello.server.global.common.factory; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort.Direction; + +@DisplayName("PaginationFactory 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) +public class PaginationFactoryTest { + + private final int PAGE_LIMIT = 100; + private final int PAGE_LIMIT_TEN = 10; + + @Test + void Pageable_객체_생성에_성공합니다() { + // given + final Integer page = 1; + + // when + final Pageable pageable = PaginationFactory.createPageable(page); + + // then + assertThat(pageable.getPageNumber()).isEqualTo(page); + assertThat(pageable.getPageSize()).isEqualTo(PAGE_LIMIT); + } + + @Test + void 이름으로_정렬된_Pageable_객체_생성에_성공합니다() { + // given + final Integer page = 1; + + // when + final Pageable pageable = PaginationFactory.createPageableByNameSort(page); + + // then + assertThat(pageable.getPageNumber()).isEqualTo(page); + assertThat(pageable.getPageSize()).isEqualTo(PAGE_LIMIT); + assertThat(pageable.getSort().getOrderFor("name").getDirection()).isEqualTo(Direction.ASC); + } + + @Test + void Page_Size_10_고정_Pageable_객체_생성에_성공합니다() { + // given + final Integer page = 1; + + // when + final Pageable pageable = PaginationFactory.createPageable(page); + + // then + assertThat(pageable.getPageNumber()).isEqualTo(page); + assertThat(pageable.getPageSize()).isEqualTo(PAGE_LIMIT); + } + + @Test + void Page_객체_생성에_성공합니다() { + // given + final Integer page = 1; + final Pageable pageable = PageRequest.of(page, PAGE_LIMIT_TEN); + List dataList = new ArrayList<>(); + for (int i = 1; i <= 20; i++) { + dataList.add(i); + } + + // when + Page resultPage = PaginationFactory.getPage(dataList, pageable); + + // then + assertThat(pageable.getPageNumber()).isEqualTo(page); + assertThat(pageable.getPageSize()).isEqualTo(PAGE_LIMIT_TEN); + + assertThat(resultPage.getTotalElements()).isEqualTo(20); + assertThat(resultPage.getSize()).isEqualTo(PAGE_LIMIT_TEN); + assertThat(resultPage.getTotalPages()).isEqualTo(2); + + List content = resultPage.getContent(); + assertThat(content).hasSize(10); + assertThat(content.get(0)).isEqualTo(11); + assertThat(content.get(9)).isEqualTo(20); + } } From 70a4fbf2e5897b5ae0979d12b2573dffa87ece46 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 12:52:49 +0900 Subject: [PATCH 21/41] =?UTF-8?q?YEL-139=20[test]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yello/server/ServerApplicationTests.java | 13 ------------- .../domain/authorization/small/AuthManagerTest.java | 5 +++++ .../domain/authorization/small/AuthServiceTest.java | 5 +++++ .../domain/friend/medium/FriendControllerTest.java | 2 ++ .../domain/friend/small/FriendManagerTest.java | 5 +++++ .../domain/friend/small/FriendServiceTest.java | 6 +++++- .../domain/purchase/small/PurchaseServiceTest.java | 5 +++++ .../server/domain/user/small/UserManagerTest.java | 5 +++++ .../server/domain/user/small/UserServiceTest.java | 5 +++++ .../server/domain/vote/small/VoteManagerTest.java | 5 +++++ .../server/domain/vote/small/VoteServiceTest.java | 5 +++++ .../firebase/NotificationFcmServiceTest.java | 5 +++++ .../firebase/{ => small}/FcmManagerTest.java | 7 ++++++- 13 files changed, 58 insertions(+), 15 deletions(-) delete mode 100644 src/test/java/com/yello/server/ServerApplicationTests.java rename src/test/java/com/yello/server/infrastructure/firebase/{ => small}/FcmManagerTest.java (90%) diff --git a/src/test/java/com/yello/server/ServerApplicationTests.java b/src/test/java/com/yello/server/ServerApplicationTests.java deleted file mode 100644 index 0e120911..00000000 --- a/src/test/java/com/yello/server/ServerApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.yello.server; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class ServerApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/com/yello/server/domain/authorization/small/AuthManagerTest.java b/src/test/java/com/yello/server/domain/authorization/small/AuthManagerTest.java index 45372428..c8ac935c 100644 --- a/src/test/java/com/yello/server/domain/authorization/small/AuthManagerTest.java +++ b/src/test/java/com/yello/server/domain/authorization/small/AuthManagerTest.java @@ -26,8 +26,13 @@ import com.yello.server.util.TestDataRepositoryUtil; import java.util.Base64; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +@DisplayName("AuthManager 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) public class AuthManagerTest { private final String secretKey = Base64.getEncoder().encodeToString( diff --git a/src/test/java/com/yello/server/domain/authorization/small/AuthServiceTest.java b/src/test/java/com/yello/server/domain/authorization/small/AuthServiceTest.java index 8bcd38c5..e2425595 100644 --- a/src/test/java/com/yello/server/domain/authorization/small/AuthServiceTest.java +++ b/src/test/java/com/yello/server/domain/authorization/small/AuthServiceTest.java @@ -60,9 +60,14 @@ import java.util.Optional; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Pageable; +@DisplayName("AuthService 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) public class AuthServiceTest { private final String secretKey = Base64.getEncoder().encodeToString( diff --git a/src/test/java/com/yello/server/domain/friend/medium/FriendControllerTest.java b/src/test/java/com/yello/server/domain/friend/medium/FriendControllerTest.java index 81aa392e..998f0c75 100644 --- a/src/test/java/com/yello/server/domain/friend/medium/FriendControllerTest.java +++ b/src/test/java/com/yello/server/domain/friend/medium/FriendControllerTest.java @@ -37,6 +37,7 @@ import com.yello.server.util.WithAccessTokenUser; import java.util.Arrays; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; @@ -63,6 +64,7 @@ }) @AutoConfigureRestDocs @WithAccessTokenUser +@DisplayName("FriendController 에서") @DisplayNameGeneration(ReplaceUnderscores.class) class FriendControllerTest { diff --git a/src/test/java/com/yello/server/domain/friend/small/FriendManagerTest.java b/src/test/java/com/yello/server/domain/friend/small/FriendManagerTest.java index 6074bf04..c6ee375c 100644 --- a/src/test/java/com/yello/server/domain/friend/small/FriendManagerTest.java +++ b/src/test/java/com/yello/server/domain/friend/small/FriendManagerTest.java @@ -13,8 +13,13 @@ import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +@DisplayName("FriendManager 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) public class FriendManagerTest { private final UserRepository userRepository = new FakeUserRepository(); diff --git a/src/test/java/com/yello/server/domain/friend/small/FriendServiceTest.java b/src/test/java/com/yello/server/domain/friend/small/FriendServiceTest.java index d013e4ad..3378e964 100644 --- a/src/test/java/com/yello/server/domain/friend/small/FriendServiceTest.java +++ b/src/test/java/com/yello/server/domain/friend/small/FriendServiceTest.java @@ -28,12 +28,16 @@ import java.util.List; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Pageable; +@DisplayName("FriendService 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) class FriendServiceTest { - private final UserRepository userRepository = new FakeUserRepository(); private final FriendRepository friendRepository = new FakeFriendRepository(); private final VoteRepository voteRepository = new FakeVoteRepository(); diff --git a/src/test/java/com/yello/server/domain/purchase/small/PurchaseServiceTest.java b/src/test/java/com/yello/server/domain/purchase/small/PurchaseServiceTest.java index bbb454f6..bd4dd3e9 100644 --- a/src/test/java/com/yello/server/domain/purchase/small/PurchaseServiceTest.java +++ b/src/test/java/com/yello/server/domain/purchase/small/PurchaseServiceTest.java @@ -18,8 +18,13 @@ import com.yello.server.domain.user.repository.UserRepository; import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +@DisplayName("PurchaseService 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) public class PurchaseServiceTest { private final UserRepository userRepository = new FakeUserRepository(); diff --git a/src/test/java/com/yello/server/domain/user/small/UserManagerTest.java b/src/test/java/com/yello/server/domain/user/small/UserManagerTest.java index 3d9d4477..34dc4a15 100644 --- a/src/test/java/com/yello/server/domain/user/small/UserManagerTest.java +++ b/src/test/java/com/yello/server/domain/user/small/UserManagerTest.java @@ -11,8 +11,13 @@ import com.yello.server.domain.user.service.UserManager; import com.yello.server.domain.user.service.UserManagerImpl; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +@DisplayName("UserManager 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) public class UserManagerTest { private final static String OFFICIAL_NAME = "옐로팀"; diff --git a/src/test/java/com/yello/server/domain/user/small/UserServiceTest.java b/src/test/java/com/yello/server/domain/user/small/UserServiceTest.java index 5ffd7f88..b8f0a90a 100644 --- a/src/test/java/com/yello/server/domain/user/small/UserServiceTest.java +++ b/src/test/java/com/yello/server/domain/user/small/UserServiceTest.java @@ -23,8 +23,13 @@ import com.yello.server.util.TestDataRepositoryUtil; import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +@DisplayName("UserService 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) class UserServiceTest { private final UserRepository userRepository = new FakeUserRepository(); diff --git a/src/test/java/com/yello/server/domain/vote/small/VoteManagerTest.java b/src/test/java/com/yello/server/domain/vote/small/VoteManagerTest.java index 8e8dd211..9ce22a44 100644 --- a/src/test/java/com/yello/server/domain/vote/small/VoteManagerTest.java +++ b/src/test/java/com/yello/server/domain/vote/small/VoteManagerTest.java @@ -22,9 +22,14 @@ import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Pageable; +@DisplayName("VoteManager 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) public class VoteManagerTest { private final UserRepository userRepository = new FakeUserRepository(); diff --git a/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java b/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java index 99508d81..25b4c23b 100644 --- a/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java +++ b/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java @@ -42,9 +42,14 @@ import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Pageable; +@DisplayName("VoteService 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) public class VoteServiceTest { private final UserRepository userRepository = new FakeUserRepository(); diff --git a/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java b/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java index 0bb02a20..b11f2a90 100644 --- a/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java +++ b/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java @@ -19,8 +19,13 @@ import com.yello.server.infrastructure.redis.repository.TokenRepository; import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +@DisplayName("NotificationFcmService 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) class NotificationFcmServiceTest { private final UserRepository userRepository = new FakeUserRepository(); diff --git a/src/test/java/com/yello/server/infrastructure/firebase/FcmManagerTest.java b/src/test/java/com/yello/server/infrastructure/firebase/small/FcmManagerTest.java similarity index 90% rename from src/test/java/com/yello/server/infrastructure/firebase/FcmManagerTest.java rename to src/test/java/com/yello/server/infrastructure/firebase/small/FcmManagerTest.java index d8bff141..0ba548a7 100644 --- a/src/test/java/com/yello/server/infrastructure/firebase/FcmManagerTest.java +++ b/src/test/java/com/yello/server/infrastructure/firebase/small/FcmManagerTest.java @@ -1,4 +1,4 @@ -package com.yello.server.infrastructure.firebase; +package com.yello.server.infrastructure.firebase.small; import com.yello.server.domain.friend.FakeFriendRepository; import com.yello.server.domain.friend.repository.FriendRepository; @@ -15,8 +15,13 @@ import com.yello.server.infrastructure.firebase.manager.FCMManagerImpl; import com.yello.server.util.TestDataRepositoryUtil; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +@DisplayName("FcmManager 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) public class FcmManagerTest { private final UserRepository userRepository = new FakeUserRepository(); From 84fc647b9c67994d9f18d49283c516bb2f543393 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 12:53:01 +0900 Subject: [PATCH 22/41] =?UTF-8?q?YEL-139=20[test]=20=EC=BB=A4=EB=B2=84?= =?UTF-8?q?=EB=A6=AC=EC=A7=80=20=EA=B3=84=EC=82=B0=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20jacoco=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/build.gradle b/build.gradle index 1c7978f7..a2b895d1 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,7 @@ plugins { id 'io.spring.dependency-management' version '1.0.15.RELEASE' id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' id "org.asciidoctor.jvm.convert" version "3.3.2" + id 'jacoco' } ext { @@ -18,6 +19,7 @@ ext { } test { + finalizedBy 'jacocoTestReport' outputs.dir snippetsDir } @@ -136,6 +138,20 @@ jar { enabled = false } +jacoco { + toolVersion = "0.8.7" +} +jacocoTestReport { + reports { + xml.enabled true + csv.enabled true + html.enabled true + + xml.destination file("${buildDir}/jacoco/index.xml") + csv.destination file("${buildDir}/jacoco/index.csv") + html.destination file("${buildDir}/jacoco/index.html") + } +} asciidoctor { inputs.dir snippetsDir configurations 'asciidoctorExt' From cb776c8b1b897262d729fba59771a9ea3c95158c Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 13:01:25 +0900 Subject: [PATCH 23/41] =?UTF-8?q?YEL-139=20[test]=20Github=20Action=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b63454e1..83491d44 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,7 +47,13 @@ jobs: shell: bash - name: 📊 Gradle로 테스트 실행 - run: ./gradlew test + run: ./gradlew --info test + + - name: 💬 테스트 결과를 코멘트로 등록합니다. + uses: EnricoMi/publish-unit-test-result-action@v1 + if: ${{ always() }} + with: + files: build/test-results/**/*.xml - name: 💡 배포 상태를 Slack을 통해 전송합니다. uses: rtCamp/action-slack-notify@v2 From 6d81168b32728101951505286e5a14bf49c01bd6 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 13:06:14 +0900 Subject: [PATCH 24/41] =?UTF-8?q?YEL-139=20[test]=20Github=20Action=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 83491d44..d2a58e1a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,13 +47,20 @@ jobs: shell: bash - name: 📊 Gradle로 테스트 실행 - run: ./gradlew --info test + run: ./gradlew test - name: 💬 테스트 결과를 코멘트로 등록합니다. uses: EnricoMi/publish-unit-test-result-action@v1 - if: ${{ always() }} + if: always() + with: + files: '**/build/test-results/test/TEST-*.xml' + + - name: 테스트 실패 시, 실패한 코드 라인에 Check 코멘트를 등록합니다 + uses: mikepenz/action-junit-report@v3 + if: always() with: - files: build/test-results/**/*.xml + report_paths: '**/build/test-results/test/TEST-*.xml' + token: ${{ github.token }} - name: 💡 배포 상태를 Slack을 통해 전송합니다. uses: rtCamp/action-slack-notify@v2 From 26a891e0c9dcc94d12388c27fe7e744e928eb059 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 13:13:22 +0900 Subject: [PATCH 25/41] =?UTF-8?q?YEL-139=20[test]=20Github=20Action=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d2a58e1a..33981f60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ on: branches: [ "develop", "staging" ] permissions: - contents: read + contents: write jobs: build: From f27247781a7a8a764c6b3e8fdf86a40a3f752e81 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 13:19:07 +0900 Subject: [PATCH 26/41] =?UTF-8?q?YEL-139=20[test]=20Github=20Action=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b63454e1..33981f60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ on: branches: [ "develop", "staging" ] permissions: - contents: read + contents: write jobs: build: @@ -49,6 +49,19 @@ jobs: - name: 📊 Gradle로 테스트 실행 run: ./gradlew test + - name: 💬 테스트 결과를 코멘트로 등록합니다. + uses: EnricoMi/publish-unit-test-result-action@v1 + if: always() + with: + files: '**/build/test-results/test/TEST-*.xml' + + - name: 테스트 실패 시, 실패한 코드 라인에 Check 코멘트를 등록합니다 + uses: mikepenz/action-junit-report@v3 + if: always() + with: + report_paths: '**/build/test-results/test/TEST-*.xml' + token: ${{ github.token }} + - name: 💡 배포 상태를 Slack을 통해 전송합니다. uses: rtCamp/action-slack-notify@v2 env: From d7ccf7bfa2066c4120308978fe1777732012a615 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 13:22:05 +0900 Subject: [PATCH 27/41] =?UTF-8?q?YEL-139=20[test]=20Github=20Action=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b63454e1..33981f60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ on: branches: [ "develop", "staging" ] permissions: - contents: read + contents: write jobs: build: @@ -49,6 +49,19 @@ jobs: - name: 📊 Gradle로 테스트 실행 run: ./gradlew test + - name: 💬 테스트 결과를 코멘트로 등록합니다. + uses: EnricoMi/publish-unit-test-result-action@v1 + if: always() + with: + files: '**/build/test-results/test/TEST-*.xml' + + - name: 테스트 실패 시, 실패한 코드 라인에 Check 코멘트를 등록합니다 + uses: mikepenz/action-junit-report@v3 + if: always() + with: + report_paths: '**/build/test-results/test/TEST-*.xml' + token: ${{ github.token }} + - name: 💡 배포 상태를 Slack을 통해 전송합니다. uses: rtCamp/action-slack-notify@v2 env: From c234e19cf6afd5cb009bf070562be88bd8480df1 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 14:36:35 +0900 Subject: [PATCH 28/41] =?UTF-8?q?YEL-139=20[test]=20Github=20Action=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 33981f60..0f8a05ca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,9 @@ on: branches: [ "develop", "staging" ] permissions: - contents: write + contents: read + checks: write + id-token: write jobs: build: From 59334ba7b7e8a97dc0bf51f9246dd36622bb1b0e Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 16:05:21 +0900 Subject: [PATCH 29/41] =?UTF-8?q?YEL-139=20[test]=20Slack=20=EC=9B=B9?= =?UTF-8?q?=ED=9B=85=20=EC=97=AD=ED=95=A0=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/PurchaseController.java | 5 + .../exception/ControllerExceptionAdvice.java | 141 +++--------------- .../annotation/SlackPurchaseNotification.java | 12 ++ .../SlackPurchaseNotificationAspect.java | 47 ++++++ .../configuration/SlackConfiguration.java | 12 +- .../factory/SlackWebhookMessageFactory.java | 106 +++++++++++++ 6 files changed, 194 insertions(+), 129 deletions(-) create mode 100644 src/main/java/com/yello/server/infrastructure/slack/annotation/SlackPurchaseNotification.java create mode 100644 src/main/java/com/yello/server/infrastructure/slack/aspect/SlackPurchaseNotificationAspect.java create mode 100644 src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java diff --git a/src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java b/src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java index d0a92444..a05fc983 100644 --- a/src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java +++ b/src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java @@ -18,6 +18,7 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.global.common.annotation.AccessTokenUser; import com.yello.server.global.common.dto.BaseResponse; +import com.yello.server.infrastructure.slack.annotation.SlackPurchaseNotification; import java.io.IOException; import java.time.LocalDateTime; import lombok.RequiredArgsConstructor; @@ -37,6 +38,7 @@ public class PurchaseController { private final PurchaseService purchaseService; @PostMapping("/apple/verify/subscribe") + @SlackPurchaseNotification public BaseResponse verifyAppleSubscriptionTransaction( @RequestBody AppleTransaction appleTransaction, @AccessTokenUser User user @@ -46,6 +48,7 @@ public BaseResponse verifyAppleSubscriptionTransaction( } @PostMapping("/apple/verify/ticket") + @SlackPurchaseNotification public BaseResponse verifyAppleTicketTransaction( @RequestBody AppleTransaction appleTransaction, @AccessTokenUser User user @@ -55,6 +58,7 @@ public BaseResponse verifyAppleTicketTransaction( } @PostMapping("/google/verify/subscribe") + @SlackPurchaseNotification public BaseResponse verifyGoogleSubscriptionTransaction( @AccessTokenUser User user, @RequestBody GoogleSubscriptionGetRequest request @@ -64,6 +68,7 @@ public BaseResponse verifyGoogleSubscriptionTrans } @PostMapping("/google/verify/ticket") + @SlackPurchaseNotification public BaseResponse verifyGoogleTicketTransaction( @AccessTokenUser User user, @RequestBody GoogleTicketGetRequest request diff --git a/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java b/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java index 24b0c6d3..a91b9ee4 100644 --- a/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java +++ b/src/main/java/com/yello/server/global/exception/ControllerExceptionAdvice.java @@ -17,7 +17,6 @@ import com.yello.server.domain.authorization.exception.NotSignedInException; import com.yello.server.domain.authorization.exception.NotValidTokenForbiddenException; import com.yello.server.domain.authorization.exception.OAuthException; -import com.yello.server.domain.authorization.service.TokenProvider; import com.yello.server.domain.friend.exception.FriendException; import com.yello.server.domain.friend.exception.FriendNotFoundException; import com.yello.server.domain.group.exception.GroupNotFoundException; @@ -31,39 +30,24 @@ import com.yello.server.domain.purchase.exception.SubscriptionConflictException; import com.yello.server.domain.question.exception.QuestionException; import com.yello.server.domain.question.exception.QuestionNotFoundException; -import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.exception.UserBadRequestException; import com.yello.server.domain.user.exception.UserConflictException; import com.yello.server.domain.user.exception.UserException; import com.yello.server.domain.user.exception.UserNotFoundException; -import com.yello.server.domain.user.repository.UserRepository; import com.yello.server.domain.vote.exception.VoteForbiddenException; import com.yello.server.domain.vote.exception.VoteNotFoundException; import com.yello.server.global.common.dto.BaseResponse; import com.yello.server.infrastructure.redis.exception.RedisException; import com.yello.server.infrastructure.redis.exception.RedisNotFoundException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; +import com.yello.server.infrastructure.slack.factory.SlackWebhookMessageFactory; import javax.servlet.http.HttpServletRequest; -import lombok.RequiredArgsConstructor; import net.gpedro.integrations.slack.SlackApi; -import net.gpedro.integrations.slack.SlackAttachment; -import net.gpedro.integrations.slack.SlackField; import net.gpedro.integrations.slack.SlackMessage; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.task.TaskExecutor; -import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageConversionException; import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StreamUtils; import org.springframework.validation.BindException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; @@ -71,122 +55,33 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice -@RequiredArgsConstructor public class ControllerExceptionAdvice { - private final UserRepository userRepository; + private final SlackApi slackErrorApi; + private final SlackWebhookMessageFactory slackWebhookMessageFactory; private final TaskExecutor taskExecutor; - private final TokenProvider tokenProvider; - private final List slackSender; + public ControllerExceptionAdvice( + @Qualifier("slackErrorApi") SlackApi slackErrorApi, + SlackWebhookMessageFactory slackWebhookMessageFactory, + TaskExecutor taskExecutor + ) { + this.slackWebhookMessageFactory = slackWebhookMessageFactory; + this.taskExecutor = taskExecutor; + this.slackErrorApi = slackErrorApi; + } @ExceptionHandler(Exception.class) void handleException(HttpServletRequest request, Exception exception) throws Exception { - SlackAttachment slackAttachment = new SlackAttachment(); - slackAttachment.setFallback("Error"); - slackAttachment.setColor("danger"); - slackAttachment.setTitle("긴급 환자가 이송되었습니다"); - slackAttachment.setTitleLink(request.getContextPath()); - slackAttachment.setText(Arrays.toString(exception.getStackTrace())); - slackAttachment.setColor("danger"); - - List slackFieldList = new ArrayList<>(); - slackFieldList.add( - new SlackField().setTitle("Request URL").setValue(request.getRequestURL().toString())); - slackFieldList.add( - new SlackField().setTitle("Request Method").setValue(request.getMethod())); - slackFieldList.add(new SlackField().setTitle("Request Time").setValue( - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()))); - slackFieldList.add( - new SlackField().setTitle("Request IP").setValue(request.getRemoteAddr())); - slackFieldList.add( - new SlackField().setTitle("Request User-Agent") - .setValue(request.getHeader(HttpHeaders.USER_AGENT))); - slackFieldList.add( - new SlackField().setTitle("인증/인가 정보 - Authorization") - .setValue(request.getHeader(HttpHeaders.AUTHORIZATION))); - slackFieldList.add( - new SlackField().setTitle("Request Body") - .setValue( - StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8))); - - final String token = - request.getHeader(HttpHeaders.AUTHORIZATION).substring("Bearer ".length()); - final Long userId = tokenProvider.getUserId(token); - final Optional user = userRepository.findById(userId); - String userInfo = "userId : " + userId - + "\nyelloId : " + (user.isPresent() ? user.get().getYelloId() : "null") - + "\ndeviceToken : " + (user.isPresent() ? user.get().getDeviceToken() : "null"); - slackFieldList.add( - new SlackField().setTitle("인증/인가 정보 - 유저").setValue(userInfo)); - - slackAttachment.setFields(slackFieldList); - - SlackMessage slackMessage = new SlackMessage(); - slackMessage.setAttachments(Collections.singletonList(slackAttachment)); - slackMessage.setText("긴급 환자가 이송되었습니다"); - slackMessage.setUsername("옐로 소방서"); - - Runnable runnable = () -> slackSender.get(0).call(slackMessage); + SlackMessage slackMessage = slackWebhookMessageFactory.generateSlackErrorMessage( + request, + exception + ); + Runnable runnable = () -> slackErrorApi.call(slackMessage); taskExecutor.execute(runnable); throw exception; } - @ExceptionHandler(CustomException.class) - public void handlePurchase(HttpServletRequest request, CustomException exception) throws IOException { - if (request.getRequestURL().toString().contains("purchase")) { - SlackAttachment slackAttachment = new SlackAttachment(); - - slackAttachment.setColor("green"); - slackAttachment.setTitle("통장에 돈이 입금되었습니다"); - slackAttachment.setTitleLink(request.getContextPath()); - slackAttachment.setText(Arrays.toString(exception.getStackTrace())); - slackAttachment.setColor("green"); - - List slackFieldList = new ArrayList<>(); - slackFieldList.add( - new SlackField().setTitle("Request URL").setValue(request.getRequestURL().toString())); - slackFieldList.add( - new SlackField().setTitle("Request Method").setValue(request.getMethod())); - slackFieldList.add(new SlackField().setTitle("Request Time").setValue( - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()))); - slackFieldList.add( - new SlackField().setTitle("Request IP").setValue(request.getRemoteAddr())); - slackFieldList.add( - new SlackField().setTitle("Request User-Agent") - .setValue(request.getHeader(HttpHeaders.USER_AGENT))); - slackFieldList.add( - new SlackField().setTitle("인증/인가 정보 - Authorization") - .setValue(ObjectUtils.isEmpty(request.getHeader(HttpHeaders.AUTHORIZATION)) ? - "없음" : request.getHeader(HttpHeaders.AUTHORIZATION))); - slackFieldList.add( - new SlackField().setTitle("Request Body") - .setValue(StreamUtils.copyToString(request.getInputStream(), - StandardCharsets.UTF_8))); - - final String token = - request.getHeader(HttpHeaders.AUTHORIZATION).substring("Bearer ".length()); - final Long userId = tokenProvider.getUserId(token); - final Optional user = userRepository.findById(userId); - String userInfo = "userId : " + userId - + "\nyelloId : " + (user.isPresent() ? user.get().getYelloId() : "null") - + "\ndeviceToken : " + (user.isPresent() ? user.get().getDeviceToken() : "null"); - slackFieldList.add( - new SlackField().setTitle("인증/인가 정보 - 유저").setValue(userInfo)); - - slackAttachment.setFields(slackFieldList); - - SlackMessage slackMessage = new SlackMessage(); - slackMessage.setAttachments(Collections.singletonList(slackAttachment)); - slackMessage.setText("돈이 촤라락"); - slackMessage.setUsername("옐로 은행"); - - Runnable runnable = () -> slackSender.get(1).call(slackMessage); - taskExecutor.execute(runnable); - throw exception; - } - } - /** * 400 BAD REQUEST */ diff --git a/src/main/java/com/yello/server/infrastructure/slack/annotation/SlackPurchaseNotification.java b/src/main/java/com/yello/server/infrastructure/slack/annotation/SlackPurchaseNotification.java new file mode 100644 index 00000000..78ad5ac3 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/slack/annotation/SlackPurchaseNotification.java @@ -0,0 +1,12 @@ +package com.yello.server.infrastructure.slack.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SlackPurchaseNotification { + +} diff --git a/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackPurchaseNotificationAspect.java b/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackPurchaseNotificationAspect.java new file mode 100644 index 00000000..1a1d9853 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/slack/aspect/SlackPurchaseNotificationAspect.java @@ -0,0 +1,47 @@ +package com.yello.server.infrastructure.slack.aspect; + +import com.yello.server.infrastructure.slack.factory.SlackWebhookMessageFactory; +import javax.servlet.http.HttpServletRequest; +import net.gpedro.integrations.slack.SlackApi; +import net.gpedro.integrations.slack.SlackMessage; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.task.TaskExecutor; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +@Aspect +@Component +public class SlackPurchaseNotificationAspect { + + private final SlackApi slackPurchaseApi; + private final SlackWebhookMessageFactory slackWebhookMessageFactory; + private final TaskExecutor taskExecutor; + + public SlackPurchaseNotificationAspect( + @Qualifier("slackPurchaseApi") SlackApi slackPurchaseApi, + SlackWebhookMessageFactory slackWebhookMessageFactory, + TaskExecutor taskExecutor) { + this.slackPurchaseApi = slackPurchaseApi; + this.slackWebhookMessageFactory = slackWebhookMessageFactory; + this.taskExecutor = taskExecutor; + } + + @Around("@annotation(com.yello.server.infrastructure.slack.annotation.SlackPurchaseNotification)") + Object purchaseNotification(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()) + .getRequest(); + + SlackMessage slackMessage = slackWebhookMessageFactory.generateSlackPurchaseMessage( + request + ); + + Runnable runnable = () -> slackPurchaseApi.call(slackMessage); + taskExecutor.execute(runnable); + + return proceedingJoinPoint.proceed(); + } +} diff --git a/src/main/java/com/yello/server/infrastructure/slack/configuration/SlackConfiguration.java b/src/main/java/com/yello/server/infrastructure/slack/configuration/SlackConfiguration.java index d8fb64f1..495d7af2 100644 --- a/src/main/java/com/yello/server/infrastructure/slack/configuration/SlackConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/slack/configuration/SlackConfiguration.java @@ -9,18 +9,18 @@ public class SlackConfiguration { @Value("${slack.token.ambulence}") - String slackTokenAmbulence; + String slackTokenForError; @Value("${slack.token.bank}") - String slackTokenBank; + String slackTokenForPurchase; @Bean - SlackApi slackAmbulenceApi() { - return new SlackApi("https://hooks.slack.com/services/" + slackTokenAmbulence); + SlackApi slackErrorApi() { + return new SlackApi("https://hooks.slack.com/services/" + slackTokenForError); } @Bean - SlackApi slackBankApi() { - return new SlackApi("https://hooks.slack.com/services/" + slackTokenBank); + SlackApi slackPurchaseApi() { + return new SlackApi("https://hooks.slack.com/services/" + slackTokenForPurchase); } } diff --git a/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java b/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java new file mode 100644 index 00000000..9eb65dd5 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java @@ -0,0 +1,106 @@ +package com.yello.server.infrastructure.slack.factory; + +import com.yello.server.domain.authorization.service.TokenProvider; +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.repository.UserRepository; +import com.yello.server.global.common.factory.TimeFactory; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import javax.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import net.gpedro.integrations.slack.SlackAttachment; +import net.gpedro.integrations.slack.SlackField; +import net.gpedro.integrations.slack.SlackMessage; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; +import org.springframework.util.StreamUtils; + +@Component +@RequiredArgsConstructor +public class SlackWebhookMessageFactory { + + private static final String ERROR_TITLE = "긴급 환자가 이송되었습니다"; + private static final String ERROR_USERNAME = "옐로 소방서"; + private static final String PURCHASE_TITLE = "돈이 입금되었습니다."; + private static final String PURCHASE_USERNAME = "옐로 뱅크"; + + private final UserRepository userRepository; + private final TokenProvider tokenProvider; + + public SlackMessage generateSlackErrorMessage( + HttpServletRequest request, + Exception exception + ) throws IOException { + return new SlackMessage() + .setAttachments(generateSlackErrorAttachment(request, exception)) + .setText(ERROR_TITLE) + .setUsername(ERROR_USERNAME); + } + + public SlackMessage generateSlackPurchaseMessage( + HttpServletRequest request + ) throws IOException { + return new SlackMessage() + .setAttachments(generateSlackPurchaseAttachment(request)) + .setText(PURCHASE_TITLE) + .setUsername(PURCHASE_USERNAME); + } + + private List generateSlackErrorAttachment( + HttpServletRequest request, + Exception exception + ) throws IOException { + final SlackAttachment slackAttachment = new SlackAttachment() + .setFallback("Error") + .setColor("danger") + .setTitle(ERROR_TITLE) + .setTitleLink(request.getContextPath()) + .setText(Arrays.toString(exception.getStackTrace())) + .setColor("danger") + .setFields(generateSlackFieldList(request)); + return Collections.singletonList(slackAttachment); + } + + private List generateSlackPurchaseAttachment( + HttpServletRequest request + ) throws IOException { + final SlackAttachment slackAttachment = new SlackAttachment() + .setColor("green") + .setTitle(PURCHASE_TITLE) + .setTitleLink(request.getContextPath()) + .setText(PURCHASE_TITLE) + .setColor("green") + .setFields(generateSlackFieldList(request)); + return Collections.singletonList(slackAttachment); + } + + private List generateSlackFieldList( + HttpServletRequest request + ) throws IOException { + final String token = request.getHeader(HttpHeaders.AUTHORIZATION).substring("Bearer ".length()); + final Long userId = tokenProvider.getUserId(token); + final Optional user = userRepository.findById(userId); + final String yelloId = user.isPresent() ? user.get().getYelloId() : "null"; + final String deviceToken = user.isPresent() ? user.get().getDeviceToken() : "null"; + + String userInfo = String.format("userId : %d %nyelloId : %s %ndeviceToken : %s", userId, yelloId, deviceToken); + + return Arrays.asList( + new SlackField().setTitle("Request URL").setValue(request.getRequestURL().toString()), + new SlackField().setTitle("Request Time").setValue(TimeFactory.toDateFormattedString(LocalDateTime.now())), + new SlackField().setTitle("Request IP").setValue(request.getRemoteAddr()), + new SlackField().setTitle("Request User-Agent").setValue(request.getHeader(HttpHeaders.USER_AGENT)), + new SlackField().setTitle("인증/인가 정보 - Authorization") + .setValue(request.getHeader(HttpHeaders.AUTHORIZATION)), + new SlackField().setTitle("Request Body") + .setValue(StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8)), + new SlackField().setTitle("인증/인가 정보 - 유저").setValue(userInfo) + ); + } + +} From cfc6dccdd17ac683bbcfdbc80baa674c29ce430c Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 16:49:35 +0900 Subject: [PATCH 30/41] =?UTF-8?q?YEL-139=20[test]=20Github=20Action=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f8a05ca..9436ed8f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ on: branches: [ "develop", "staging" ] permissions: - contents: read + contents: write checks: write id-token: write From fc17e89d51a8fda9c29ca62787c72f46f855833f Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 16:53:15 +0900 Subject: [PATCH 31/41] =?UTF-8?q?YEL-139=20[test]=20Github=20Action=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f8a05ca..9436ed8f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ on: branches: [ "develop", "staging" ] permissions: - contents: read + contents: write checks: write id-token: write From a1fb256eae4b0fde6539887c4e59939978ca68d5 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 18:35:28 +0900 Subject: [PATCH 32/41] =?UTF-8?q?YEL-139=20[test]=20=EC=96=B4=EC=83=89?= =?UTF-8?q?=ED=95=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=EB=AA=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../purchase/service/PurchaseService.java | 10 ++++----- .../yello/server/domain/user/entity/User.java | 2 +- .../domain/vote/service/VoteService.java | 2 +- .../configuration/QueryDslConfiguration.java | 21 ------------------- .../domain/user/small/UserRepositoryTest.java | 2 ++ .../server/domain/user/small/UserTest.java | 2 ++ 6 files changed, 11 insertions(+), 28 deletions(-) delete mode 100644 src/main/java/com/yello/server/global/configuration/QueryDslConfiguration.java create mode 100644 src/test/java/com/yello/server/domain/user/small/UserRepositoryTest.java create mode 100644 src/test/java/com/yello/server/domain/user/small/UserTest.java diff --git a/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java b/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java index a3b016b3..9cb9ed0d 100644 --- a/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java +++ b/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java @@ -103,7 +103,7 @@ public void verifyAppleSubscriptionTransaction(Long userId, } purchaseManager.createSubscribe(user, Gateway.APPLE, request.transactionId()); - user.changeTicketCount(3); + user.addTicketCount(3); } @Transactional @@ -117,16 +117,16 @@ public void verifyAppleTicketTransaction(Long userId, AppleTransaction request) switch (request.productId()) { case ONE_TICKET_ID: purchaseManager.createTicket(user, ProductType.ONE_TICKET, Gateway.APPLE, request.transactionId()); - user.changeTicketCount(1); + user.addTicketCount(1); break; case TWO_TICKET_ID: purchaseManager.createTicket(user, ProductType.TWO_TICKET, Gateway.APPLE, request.transactionId()); - user.changeTicketCount(2); + user.addTicketCount(2); break; case FIVE_TICKET_ID: purchaseManager.createTicket(user, ProductType.FIVE_TICKET, Gateway.APPLE, request.transactionId()); - user.changeTicketCount(5); + user.addTicketCount(5); break; default: throw new PurchaseException(NOT_FOUND_TRANSACTION_EXCEPTION); @@ -241,7 +241,7 @@ public GoogleTicketGetResponse verifyGoogleTicketTransaction(Long userId, Google Purchase ticket = purchaseManager.createTicket(user, getProductType(request.productId()), Gateway.GOOGLE, request.orderId()); - user.changeTicketCount(getTicketAmount(request.productId()) * request.quantity()); + user.addTicketCount(getTicketAmount(request.productId()) * request.quantity()); ticket.setTransactionId(inAppResponse.getBody().orderId()); } else { throw new GoogleBadRequestException(GOOGLE_INAPP_BAD_REQUEST_EXCEPTION); diff --git a/src/main/java/com/yello/server/domain/user/entity/User.java b/src/main/java/com/yello/server/domain/user/entity/User.java index 333323c3..ba3bfb37 100644 --- a/src/main/java/com/yello/server/domain/user/entity/User.java +++ b/src/main/java/com/yello/server/domain/user/entity/User.java @@ -172,7 +172,7 @@ public void setSubscribe(Subscribe subscribe) { this.subscribe = subscribe; } - public void changeTicketCount(int ticketCount) { + public void addTicketCount(int ticketCount) { this.ticketCount += ticketCount; } diff --git a/src/main/java/com/yello/server/domain/vote/service/VoteService.java b/src/main/java/com/yello/server/domain/vote/service/VoteService.java index 1a1174b1..4e893782 100644 --- a/src/main/java/com/yello/server/domain/vote/service/VoteService.java +++ b/src/main/java/com/yello/server/domain/vote/service/VoteService.java @@ -195,7 +195,7 @@ public RevealFullNameResponse revealFullName(Long userId, Long voteId) { } vote.checkNameIndexOf(CHECK_FULL_NAME); - sender.changeTicketCount(MINUS_TICKET_COUNT); + sender.addTicketCount(MINUS_TICKET_COUNT); return RevealFullNameResponse.of(vote.getSender()); } diff --git a/src/main/java/com/yello/server/global/configuration/QueryDslConfiguration.java b/src/main/java/com/yello/server/global/configuration/QueryDslConfiguration.java deleted file mode 100644 index 79454eee..00000000 --- a/src/main/java/com/yello/server/global/configuration/QueryDslConfiguration.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.yello.server.global.configuration; - -import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.persistence.EntityManager; - -@Configuration -@RequiredArgsConstructor -public class QueryDslConfiguration { - - private final EntityManager entityManager; - - @Bean - public JPAQueryFactory queryFactory() { - return new JPAQueryFactory(entityManager); - } - -} diff --git a/src/test/java/com/yello/server/domain/user/small/UserRepositoryTest.java b/src/test/java/com/yello/server/domain/user/small/UserRepositoryTest.java new file mode 100644 index 00000000..8e95029d --- /dev/null +++ b/src/test/java/com/yello/server/domain/user/small/UserRepositoryTest.java @@ -0,0 +1,2 @@ +package com.yello.server.domain.user.small;public class UserRepositoryTest { +} diff --git a/src/test/java/com/yello/server/domain/user/small/UserTest.java b/src/test/java/com/yello/server/domain/user/small/UserTest.java new file mode 100644 index 00000000..36b4a143 --- /dev/null +++ b/src/test/java/com/yello/server/domain/user/small/UserTest.java @@ -0,0 +1,2 @@ +package com.yello.server.domain.user.small;public class UserTest { +} From ec9c3c47130e03d24518925bdabbf6a0e768f341 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 18:35:42 +0900 Subject: [PATCH 33/41] =?UTF-8?q?YEL-139=20[test]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- build.gradle | 128 +++++++-------- .../domain/user/small/UserRepositoryTest.java | 146 +++++++++++++++++- .../server/domain/user/small/UserTest.java | 146 +++++++++++++++++- 4 files changed, 348 insertions(+), 75 deletions(-) diff --git a/.gitignore b/.gitignore index f0bc2dc8..97200f80 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,5 @@ firebase*.json ### monitoring ### monitoring/prometheus/volume -monitoring/grafana \ No newline at end of file +monitoring/grafana +*.html \ No newline at end of file diff --git a/build.gradle b/build.gradle index a2b895d1..f1c6de79 100644 --- a/build.gradle +++ b/build.gradle @@ -1,35 +1,25 @@ -buildscript { - ext { - queryDslVersion = "5.0.0" - } -} - - plugins { id 'java' id 'org.springframework.boot' version '2.7.4' id 'io.spring.dependency-management' version '1.0.15.RELEASE' - id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' id "org.asciidoctor.jvm.convert" version "3.3.2" id 'jacoco' } +group = 'com.yello' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '17' + ext { snippetsDir = file('build/generated-snippets') } test { + useJUnitPlatform() finalizedBy 'jacocoTestReport' outputs.dir snippetsDir } -group = 'com.yello' -version = '0.0.1-SNAPSHOT' - -java { - sourceCompatibility = '17' -} - configurations { asciidoctorExt compileOnly { @@ -45,25 +35,18 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.junit.jupiter:junit-jupiter-params:5.4.2' - asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' - testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' - testImplementation 'org.springframework.security:spring-security-test' - // JPA & Database + // Repositories implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation 'org.springframework.amqp:spring-rabbit:2.3.12' + + runtimeOnly 'com.h2database:h2' + runtimeOnly 'com.mysql:mysql-connector-j:8.0.31' // Validations implementation 'org.springframework.boot:spring-boot-starter-validation' - // Health Check - implementation 'org.springframework.boot:spring-boot-starter-actuator' - runtimeOnly 'io.micrometer:micrometer-registry-prometheus' - - // JWT implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.2' implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2' @@ -79,20 +62,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'io.netty:netty-resolver-dns-native-macos:4.1.79.Final:osx-aarch_64' - - // QueryDSL - implementation "com.querydsl:querydsl-jpa:${queryDslVersion}" - implementation "com.querydsl:querydsl-apt:${queryDslVersion}" - - runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.mysql:mysql-connector-j:8.0.31' - // FCM implementation 'com.google.firebase:firebase-admin:9.2.0' - // rabbitmq - implementation 'org.springframework.amqp:spring-rabbit:2.3.12' - // slack-webhook implementation "net.gpedro.integrations.slack:slack-webhook:1.4.0" @@ -102,61 +74,73 @@ dependencies { // gson implementation 'com.google.code.gson:gson:2.10.1' + + // Testing + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.4.2' + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' + testImplementation 'org.springframework.security:spring-security-test' } -tasks.named('test') { - useJUnitPlatform() +asciidoctor { + inputs.dir snippetsDir + configurations 'asciidoctorExt' + dependsOn test +} + +asciidoctor.doFirst { + delete file('src/docs/asciidocs') } bootJar { dependsOn asciidoctor - from("${asciidoctor.outputDir}") { - into 'static/docs' + copy { + from asciidoctor.outputDir + into "src/main/resources/static/docs" } } -def querydslDir = "$buildDir/generated/querydsl" - -querydsl { - jpa = true - querydslSourcesDir = querydslDir -} -sourceSets { - main.java.srcDir querydslDir -} configurations { compileOnly { extendsFrom annotationProcessor } - querydsl.extendsFrom compileClasspath -} -compileQuerydsl { - options.annotationProcessorPath = configurations.querydsl } -jar { - enabled = false -} +jar.enabled = false +bootJar.enabled = false -jacoco { - toolVersion = "0.8.7" -} +jacoco.toolVersion = "0.8.7" jacocoTestReport { reports { - xml.enabled true + xml.enabled false csv.enabled true html.enabled true - xml.destination file("${buildDir}/jacoco/index.xml") csv.destination file("${buildDir}/jacoco/index.csv") html.destination file("${buildDir}/jacoco/index.html") } -} -asciidoctor { - inputs.dir snippetsDir - configurations 'asciidoctorExt' - dependsOn test -} -asciidoctor.doFirst { - delete file('src/docs/asciidocs') -} +// finalizedBy 'jacocoTestCoverageVerification' +} +//jacocoTestCoverageVerification { +// violationRules { +// rule { +// enabled = true +// element = 'CLASS' +// +// limit { +// counter = 'METHOD' +// value = 'COVEREDRATIO' +// minimum = 0.60 +// } +// +// limit { +// counter = 'INSTRUCTION' +// value = 'COVEREDRATIO' +// minimum = 0.60 +// } +// +// excludes = ["*.dto", "*.dto.*", "*.ServerApplication", "*.configuration.*", "*.security.*", "*.exception.*", "*.util.*"] +// } +// } +//} diff --git a/src/test/java/com/yello/server/domain/user/small/UserRepositoryTest.java b/src/test/java/com/yello/server/domain/user/small/UserRepositoryTest.java index 8e95029d..98f544d4 100644 --- a/src/test/java/com/yello/server/domain/user/small/UserRepositoryTest.java +++ b/src/test/java/com/yello/server/domain/user/small/UserRepositoryTest.java @@ -1,2 +1,146 @@ -package com.yello.server.domain.user.small;public class UserRepositoryTest { +package com.yello.server.domain.user.small; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; + +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.repository.UserJpaRepository; +import com.yello.server.domain.user.repository.UserRepositoryImpl; +import com.yello.server.util.TestDataEntityUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +@DisplayName("UserRepository 에서") +@DisplayNameGeneration(ReplaceUnderscores.class) +public class UserRepositoryTest { + + + private final TestDataEntityUtil testDataEntityUtil = new TestDataEntityUtil(); + + @Mock + private UserJpaRepository userJpaRepository; + + @InjectMocks + private UserRepositoryImpl userRepository; + + @BeforeEach + public void init() { + MockitoAnnotations.initMocks(this); + } + + @Test + void save에_성공합니다() { + // given + final User user = testDataEntityUtil.generateUser(1L, 1L); + + // when + given(userRepository.save(any(User.class))) + .willReturn(user); + + User newUser = userRepository.save(user); + + // then + assertThat(newUser.getId()).isEqualTo(user.getId()); + } + + @Test + void findById에_성공합니다() { + // given + // when + // then + } + + @Test + void getById에_성공합니다() { + // given + // when + // then + } + + @Test + void findByUuid에_성공합니다() { + // given + // when + // then + } + + @Test + void getByUuid에_성공합니다() { + // given + // when + // then + } + + @Test + void existsByUuid에_성공합니다() { + // given + // when + // then + } + + @Test + void findByYelloId에_성공합니다() { + // given + // when + // then + } + + @Test + void getByYelloId에_성공합니다() { + // given + // when + // then + } + + @Test + void findByDeviceToken에_성공합니다() { + // given + // when + // then + } + + @Test + void findAllByGroupId에_성공합니다() { + // given + // when + // then + } + + @Test + void findAllByGroupContainingName에_성공합니다() { + // given + // when + // then + } + + @Test + void findAllByOtherGroupContainingName에_성공합니다() { + // given + // when + // then + } + + @Test + void findAllByGroupContainingYelloId에_성공합니다() { + // given + // when + // then + } + + @Test + void findAllByOtherGroupContainingYelloId에_성공합니다() { + // given + // when + // then + } } diff --git a/src/test/java/com/yello/server/domain/user/small/UserTest.java b/src/test/java/com/yello/server/domain/user/small/UserTest.java index 36b4a143..e58eeff1 100644 --- a/src/test/java/com/yello/server/domain/user/small/UserTest.java +++ b/src/test/java/com/yello/server/domain/user/small/UserTest.java @@ -1,2 +1,146 @@ -package com.yello.server.domain.user.small;public class UserTest { +package com.yello.server.domain.user.small; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.yello.server.domain.user.entity.Subscribe; +import com.yello.server.domain.user.entity.User; +import com.yello.server.util.TestDataEntityUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Test; + +@DisplayName("User 엔티티에서") +@DisplayNameGeneration(ReplaceUnderscores.class) +public class UserTest { + + private final TestDataEntityUtil testDataEntityUtil = new TestDataEntityUtil(); + + private User user; + private User deletedUser; + + @BeforeEach + void init() { + user = testDataEntityUtil.generateUser(1L, 1L); + deletedUser = testDataEntityUtil.generateDeletedUser(2L, 1L); + } + + @Test + void 삭제에_성공합니다() { + // given + assertThat(user.getDeletedAt()).isNull(); + + // when + user.delete(); + + // then + assertThat(user.getDeletedAt()).isNotNull(); + assertThat(user.getPoint()).isZero(); + assertThat(user.getDeviceToken()).isNull(); + } + + @Test + void 재가입에_성공합니다() { + // given + assertThat(deletedUser.getDeletedAt()).isNotNull(); + assertThat(deletedUser.getPoint()).isZero(); + assertThat(deletedUser.getDeviceToken()).isNull(); + + // when + deletedUser.renew(); + + // then + assertThat(deletedUser.getDeletedAt()).isNull(); + assertThat(deletedUser.getPoint()).isZero(); + } + + @Test + void 그룹명_가져오기에_성공합니다() { + // given + // when + // then + assertThat(user.groupString()).isEqualTo("테스트 대학교 1 테스트 학과 1 20학번"); + } + + @Test + void 추천_카운트_증가에_성공합니다() { + // given + assertThat(user.getRecommendCount()).isZero(); + + // when + user.increaseRecommendCount(); + + // then + assertThat(user.getRecommendCount()).isEqualTo(1); + } + + @Test + void 포인트_증가에_성공합니다() { + // given + assertThat(user.getPoint()).isEqualTo(200); + + // when + user.increaseRecommendPoint(); + + // then + assertThat(user.getPoint()).isEqualTo(300); + } + + @Test + void 포인트_감소에_성공합니다() { + // given + assertThat(user.getPoint()).isEqualTo(200); + + // when + user.minusPoint(100); + + // then + assertThat(user.getPoint()).isEqualTo(100); + } + + @Test + void 디바이스_토큰_조회에_성공합니다() { + // given + // when + // then + assertThat(user.getDeviceToken()).isEqualTo("deviceToken#1"); + } + + @Test + void 디바이스_토큰_수정에_성공합니다() { + // given + assertThat(user.getDeviceToken()).isEqualTo("deviceToken#1"); + + // when + user.setDeviceToken("newDeviceToken"); + + // then + assertThat(user.getDeviceToken()).isEqualTo("newDeviceToken"); + } + + @Test + void 구독_여부_수정에_성공합니다() { + // given + assertThat(user.getSubscribe()).isEqualTo(Subscribe.NORMAL); + + // when + user.setSubscribe(Subscribe.ACTIVE); + + // then + assertThat(user.getSubscribe()).isEqualTo(Subscribe.ACTIVE); + } + + @Test + void 티켓_수량_수정에_성공합니다() { + // given + assertThat(user.getTicketCount()).isZero(); + + // when + user.addTicketCount(10); + + // then + assertThat(user.getTicketCount()).isEqualTo(10); + } + } From 943d649f378441010dbd4a4dcfc7dbccc54ed7a4 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 18:48:22 +0900 Subject: [PATCH 34/41] =?UTF-8?q?YEL-139=20[test]=20=EB=B9=8C=EB=93=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index f1c6de79..ed6683ef 100644 --- a/build.gradle +++ b/build.gradle @@ -108,7 +108,6 @@ configurations { } jar.enabled = false -bootJar.enabled = false jacoco.toolVersion = "0.8.7" jacocoTestReport { From 7fd37a180c1e43ecd3670f81040a4c7f03ce9955 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 19:27:27 +0900 Subject: [PATCH 35/41] =?UTF-8?q?YEL-139=20[test]=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=84=9C=20Filter=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/domain/authorization/filter/JwtExceptionFilter.java | 2 +- .../com/yello/server/domain/authorization/filter/JwtFilter.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java b/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java index 92c603e3..ecd3df30 100644 --- a/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java +++ b/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java @@ -41,7 +41,7 @@ protected void doFilterInternal( val requestPath = request.getServletPath(); if (requestPath.equals("/") - || requestPath.startsWith("/swagger-ui") || requestPath.startsWith("/v3/api-docs") + || requestPath.startsWith("/docs") || requestPath.startsWith("/actuator") || requestPath.startsWith("/prometheus") || requestPath.startsWith("/api/v1/auth")) { filterChain.doFilter(request, response); diff --git a/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java b/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java index 1dc63784..d96e535f 100644 --- a/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java +++ b/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java @@ -34,7 +34,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse final String requestPath = request.getServletPath(); if (requestPath.equals("/") - || requestPath.startsWith("/swagger-ui") || requestPath.startsWith("/v3/api-docs") + || requestPath.startsWith("/docs") || requestPath.startsWith("/actuator") || requestPath.startsWith("/prometheus") || requestPath.startsWith("/api/v1/auth")) { filterChain.doFilter(request, response); From 904a3342483137090880990ee4e569acd86261a6 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 20:52:35 +0900 Subject: [PATCH 36/41] =?UTF-8?q?YEL-139=20[test]=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 - src/docs/asciidoc/index.adoc | 2 - .../resources/static/docs/add-friend.html | 501 ++++++++++++++ src/main/resources/static/docs/apple.html | 549 ++++++++++++++++ .../resources/static/docs/check-keyword.html | 504 ++++++++++++++ .../static/docs/check-user-by-id.html | 488 ++++++++++++++ .../resources/static/docs/check-user.html | 489 ++++++++++++++ .../static/docs/check-vote-available.html | 484 ++++++++++++++ .../resources/static/docs/create-vote.html | 494 ++++++++++++++ .../resources/static/docs/delete-friend.html | 501 ++++++++++++++ .../resources/static/docs/delete-user.html | 479 ++++++++++++++ .../resources/static/docs/device-token.html | 486 ++++++++++++++ .../static/docs/find-friend-votes.html | 517 +++++++++++++++ .../resources/static/docs/find-friends.html | 512 +++++++++++++++ .../static/docs/find-group-friends.html | 509 +++++++++++++++ .../static/docs/find-kakao-friends.html | 506 +++++++++++++++ .../static/docs/find-onboarding-friends.html | 515 +++++++++++++++ .../resources/static/docs/find-question.html | 496 ++++++++++++++ src/main/resources/static/docs/find-vote.html | 518 +++++++++++++++ .../resources/static/docs/find-votes.html | 524 +++++++++++++++ .../static/docs/get-unread-vote.html | 482 ++++++++++++++ src/main/resources/static/docs/google.html | 525 +++++++++++++++ src/main/resources/static/docs/index.html | 614 ++++++++++++++++++ src/main/resources/static/docs/login.html | 491 ++++++++++++++ src/main/resources/static/docs/overview.html | 522 +++++++++++++++ src/main/resources/static/docs/pay.html | 485 ++++++++++++++ .../resources/static/docs/purchase-check.html | 484 ++++++++++++++ .../resources/static/docs/reissue-token.html | 512 +++++++++++++++ .../static/docs/reveal-full-name.html | 504 ++++++++++++++ .../resources/static/docs/reveal-name.html | 505 ++++++++++++++ .../static/docs/search-department.html | 514 +++++++++++++++ .../resources/static/docs/search-friend.html | 515 +++++++++++++++ .../resources/static/docs/search-school.html | 507 +++++++++++++++ .../static/docs/shuffle-friends.html | 484 ++++++++++++++ src/main/resources/static/docs/signup.html | 500 ++++++++++++++ src/main/resources/static/docs/sub-check.html | 483 ++++++++++++++ .../static/docs/validate-yelloid.html | 500 ++++++++++++++ 37 files changed, 17699 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/static/docs/add-friend.html create mode 100644 src/main/resources/static/docs/apple.html create mode 100644 src/main/resources/static/docs/check-keyword.html create mode 100644 src/main/resources/static/docs/check-user-by-id.html create mode 100644 src/main/resources/static/docs/check-user.html create mode 100644 src/main/resources/static/docs/check-vote-available.html create mode 100644 src/main/resources/static/docs/create-vote.html create mode 100644 src/main/resources/static/docs/delete-friend.html create mode 100644 src/main/resources/static/docs/delete-user.html create mode 100644 src/main/resources/static/docs/device-token.html create mode 100644 src/main/resources/static/docs/find-friend-votes.html create mode 100644 src/main/resources/static/docs/find-friends.html create mode 100644 src/main/resources/static/docs/find-group-friends.html create mode 100644 src/main/resources/static/docs/find-kakao-friends.html create mode 100644 src/main/resources/static/docs/find-onboarding-friends.html create mode 100644 src/main/resources/static/docs/find-question.html create mode 100644 src/main/resources/static/docs/find-vote.html create mode 100644 src/main/resources/static/docs/find-votes.html create mode 100644 src/main/resources/static/docs/get-unread-vote.html create mode 100644 src/main/resources/static/docs/google.html create mode 100644 src/main/resources/static/docs/index.html create mode 100644 src/main/resources/static/docs/login.html create mode 100644 src/main/resources/static/docs/overview.html create mode 100644 src/main/resources/static/docs/pay.html create mode 100644 src/main/resources/static/docs/purchase-check.html create mode 100644 src/main/resources/static/docs/reissue-token.html create mode 100644 src/main/resources/static/docs/reveal-full-name.html create mode 100644 src/main/resources/static/docs/reveal-name.html create mode 100644 src/main/resources/static/docs/search-department.html create mode 100644 src/main/resources/static/docs/search-friend.html create mode 100644 src/main/resources/static/docs/search-school.html create mode 100644 src/main/resources/static/docs/shuffle-friends.html create mode 100644 src/main/resources/static/docs/signup.html create mode 100644 src/main/resources/static/docs/sub-check.html create mode 100644 src/main/resources/static/docs/validate-yelloid.html diff --git a/.gitignore b/.gitignore index 97200f80..bf013630 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,3 @@ firebase*.json ### monitoring ### monitoring/prometheus/volume monitoring/grafana -*.html \ No newline at end of file diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 6e491286..d51d39c7 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -6,8 +6,6 @@ :toclevels: 3 :sectlinks: -테스트테스트 - [[API-List]] == APIs diff --git a/src/main/resources/static/docs/add-friend.html b/src/main/resources/static/docs/add-friend.html new file mode 100644 index 00000000..c11c538f --- /dev/null +++ b/src/main/resources/static/docs/add-friend.html @@ -0,0 +1,501 @@ + + + + + + + +친구 추가하기 + + + + + +
+
+

친구 추가하기

+
+
+

요청

+
+
+
POST /api/v1/friend/1 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/v1/friend/{targetId}
ParameterDescription

targetId

친구 신청할 상대 유저의 아이디 값

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "친구 추가에 성공했습니다."
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/apple.html b/src/main/resources/static/docs/apple.html new file mode 100644 index 00000000..3ff3b5c0 --- /dev/null +++ b/src/main/resources/static/docs/apple.html @@ -0,0 +1,549 @@ + + + + + + + +Apple 구독 구매 검증하기 + + + + + +
+
+

Apple 구독 구매 검증하기

+
+
+

요청

+
+
+
POST /api/v1/purchase/apple/verify/subscribe HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: Bearer your-access-token
+Content-Length: 68
+
+{
+  "transactionId" : "transactionId",
+  "productId" : "productId"
+}
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "인앱결제 검증에 성공했습니다."
+}
+
+
+
+
+
+
+

Apple 열람권 구매 검증하기

+
+
+

요청

+
+
+
POST /api/v1/purchase/apple/verify/ticket HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: Bearer your-access-token
+Content-Length: 68
+
+{
+  "transactionId" : "transactionId",
+  "productId" : "productId"
+}
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "인앱결제 검증에 성공했습니다."
+}
+
+
+
+
+
+
+

Apple 환불하기

+
+
+

요청

+
+
+
DELETE /api/v1/purchase/apple/refund HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "인앱결제 검증에 성공했습니다."
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/check-keyword.html b/src/main/resources/static/docs/check-keyword.html new file mode 100644 index 00000000..97598443 --- /dev/null +++ b/src/main/resources/static/docs/check-keyword.html @@ -0,0 +1,504 @@ + + + + + + + +투표 키워드 확인하기 + + + + + +
+
+

투표 키워드 확인하기

+
+
+

요청

+
+
+
PATCH /api/v1/vote/1/keyword HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/v1/vote/{voteId}/keyword
ParameterDescription

voteId

투표 아이디 값

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "키워드 확인에 성공했습니다.",
+  "data" : {
+    "answer" : "test"
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/check-user-by-id.html b/src/main/resources/static/docs/check-user-by-id.html new file mode 100644 index 00000000..a29df723 --- /dev/null +++ b/src/main/resources/static/docs/check-user-by-id.html @@ -0,0 +1,488 @@ + + + + + + + +유저 정보 조회하기 + + + + + +
+
+

유저 정보 조회하기

+
+
+

요청

+
+
+
GET /api/v1/user/2 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "유저 조회에 성공했습니다.",
+  "data" : {
+    "userId" : 2,
+    "name" : "test",
+    "profileImageUrl" : "profile",
+    "group" : "group",
+    "yelloId" : "yelloId",
+    "yelloCount" : 0,
+    "friendCount" : 0
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/check-user.html b/src/main/resources/static/docs/check-user.html new file mode 100644 index 00000000..4b0acfd6 --- /dev/null +++ b/src/main/resources/static/docs/check-user.html @@ -0,0 +1,489 @@ + + + + + + + +내 정보 조회하기 + + + + + +
+
+

내 정보 조회하기

+
+
+

요청

+
+
+
GET /api/v1/user HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "유저 조회에 성공했습니다.",
+  "data" : {
+    "userId" : 1,
+    "name" : "test",
+    "profileImageUrl" : "profile",
+    "group" : "group",
+    "yelloId" : "yelloId",
+    "yelloCount" : 0,
+    "friendCount" : 0,
+    "point" : 200
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/check-vote-available.html b/src/main/resources/static/docs/check-vote-available.html new file mode 100644 index 00000000..6f192f97 --- /dev/null +++ b/src/main/resources/static/docs/check-vote-available.html @@ -0,0 +1,484 @@ + + + + + + + +투표 가능 여부 조회 + + + + + +
+
+

투표 가능 여부 조회

+
+
+

요청

+
+
+
GET /api/v1/vote/available HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "투표 시작하기에 성공했습니다.",
+  "data" : {
+    "isPossible" : false,
+    "point" : 200,
+    "createdAt" : "2023-08-25 20:51:31"
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/create-vote.html b/src/main/resources/static/docs/create-vote.html new file mode 100644 index 00000000..cb8ac7e9 --- /dev/null +++ b/src/main/resources/static/docs/create-vote.html @@ -0,0 +1,494 @@ + + + + + + + +투표 생성하기 + + + + + +
+
+

투표 생성하기

+
+
+

요청

+
+
+
POST /api/v1/vote HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: Bearer your-access-token
+Content-Length: 151
+
+{
+  "voteAnswerList" : [ {
+    "friendId" : 2,
+    "questionId" : 1,
+    "keywordName" : "키워드",
+    "colorIndex" : 0
+  } ],
+  "totalPoint" : 10
+}
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 201,
+  "message" : "투표를 성공했습니다.",
+  "data" : {
+    "point" : 10
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/delete-friend.html b/src/main/resources/static/docs/delete-friend.html new file mode 100644 index 00000000..4707d7f8 --- /dev/null +++ b/src/main/resources/static/docs/delete-friend.html @@ -0,0 +1,501 @@ + + + + + + + +친구 삭제하기 + + + + + +
+
+

친구 삭제하기

+
+
+

요청

+
+
+
DELETE /api/v1/friend/1 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/v1/friend/{targetId}
ParameterDescription

targetId

삭제할 상대 유저의 아이디 값

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "친구 삭제에 성공했습니다."
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/delete-user.html b/src/main/resources/static/docs/delete-user.html new file mode 100644 index 00000000..63e884e2 --- /dev/null +++ b/src/main/resources/static/docs/delete-user.html @@ -0,0 +1,479 @@ + + + + + + + +유저 탈퇴하기 + + + + + +
+
+

유저 탈퇴하기

+
+
+

요청

+
+
+
DELETE /api/v1/user HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "유저 탈퇴에 성공했습니다."
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/device-token.html b/src/main/resources/static/docs/device-token.html new file mode 100644 index 00000000..424399f4 --- /dev/null +++ b/src/main/resources/static/docs/device-token.html @@ -0,0 +1,486 @@ + + + + + + + +디바이스 토큰 수정하기 + + + + + +
+
+

디바이스 토큰 수정하기

+
+
+

요청

+
+
+
PUT /api/v1/user/device HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: Bearer your-access-token
+Content-Length: 39
+
+{
+  "deviceToken" : "testDeviceToken"
+}
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "deviceToken 업데이트에 성공하였습니다",
+  "data" : { }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/find-friend-votes.html b/src/main/resources/static/docs/find-friend-votes.html new file mode 100644 index 00000000..21065f52 --- /dev/null +++ b/src/main/resources/static/docs/find-friend-votes.html @@ -0,0 +1,517 @@ + + + + + + + +친구 투표 전체 조회 + + + + + +
+
+

친구 투표 전체 조회

+
+
+

요청

+
+
+
GET /api/v1/vote/friend?page=0 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "투표 조회에 성공했습니다.",
+  "data" : {
+    "totalCount" : 1,
+    "friendVotes" : [ {
+      "id" : 1,
+      "receiverName" : "name2",
+      "senderGender" : "MALE",
+      "vote" : {
+        "nameHead" : "나는",
+        "nameFoot" : "와",
+        "keywordHead" : "멋진",
+        "keyword" : "test",
+        "keywordFoot" : "에서 놀고싶어"
+      },
+      "isHintUsed" : false,
+      "createdAt" : "0초 전"
+    } ]
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/find-friends.html b/src/main/resources/static/docs/find-friends.html new file mode 100644 index 00000000..9948df48 --- /dev/null +++ b/src/main/resources/static/docs/find-friends.html @@ -0,0 +1,512 @@ + + + + + + + +내 친구 전체 조회하기 + + + + + +
+
+

내 친구 전체 조회하기

+
+
+

요청

+
+
+
GET /api/v1/friend?page=0 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "친구 조회에 성공했습니다.",
+  "data" : {
+    "totalCount" : 0,
+    "friends" : [ {
+      "userId" : 1,
+      "name" : "name1",
+      "profileImageUrl" : "test image",
+      "group" : "테스트 대학교 1 테스트 학과 1 20학번",
+      "yelloId" : "yelloId1",
+      "yelloCount" : 0,
+      "friendCount" : 0
+    } ]
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/find-group-friends.html b/src/main/resources/static/docs/find-group-friends.html new file mode 100644 index 00000000..dd2e1b4e --- /dev/null +++ b/src/main/resources/static/docs/find-group-friends.html @@ -0,0 +1,509 @@ + + + + + + + +그룹 추천 친구 조회하기 + + + + + +
+
+

그룹 추천 친구 조회하기

+
+
+

요청

+
+
+
GET /api/v1/friend/recommend/school?page=0 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "친구 조회에 성공했습니다.",
+  "data" : {
+    "totalCount" : 0,
+    "friends" : [ {
+      "id" : 1,
+      "name" : "name1",
+      "group" : "테스트 대학교 1 테스트 학과 1 20학번",
+      "profileImage" : "test image"
+    } ]
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/find-kakao-friends.html b/src/main/resources/static/docs/find-kakao-friends.html new file mode 100644 index 00000000..fe65ed1e --- /dev/null +++ b/src/main/resources/static/docs/find-kakao-friends.html @@ -0,0 +1,506 @@ + + + + + + + +카카오 추천 친구 조회하기 + + + + + +
+
+

카카오 추천 친구 조회하기

+
+
+

요청

+
+
+
POST /api/v1/friend/recommend/kakao?page=0 HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: Bearer your-access-token
+Content-Length: 41
+
+{
+  "friendKakaoId" : [ "testKakaoId" ]
+}
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "친구 조회에 성공했습니다."
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/find-onboarding-friends.html b/src/main/resources/static/docs/find-onboarding-friends.html new file mode 100644 index 00000000..3e3723d7 --- /dev/null +++ b/src/main/resources/static/docs/find-onboarding-friends.html @@ -0,0 +1,515 @@ + + + + + + + +가입한 친구 목록 불러오기 + + + + + +
+
+

가입한 친구 목록 불러오기

+
+
+

요청

+
+
+
POST /api/v1/auth/friend?page=0 HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 43
+
+{
+  "friendKakaoId" : [ "friendKakaoId" ]
+}
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "추천 친구 조회에 성공했습니다.",
+  "data" : {
+    "totalCount" : 0,
+    "friendList" : [ {
+      "group" : "KAKAO",
+      "id" : 1,
+      "name" : "name1",
+      "profileImage" : "test image",
+      "groupName" : "테스트 대학교 1 테스트 학과 1"
+    } ]
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/find-question.html b/src/main/resources/static/docs/find-question.html new file mode 100644 index 00000000..e41d8086 --- /dev/null +++ b/src/main/resources/static/docs/find-question.html @@ -0,0 +1,496 @@ + + + + + + + +투표 질문 조회하기 + + + + + +
+
+

투표 질문 조회하기

+
+
+

요청

+
+
+
GET /api/v1/vote/question HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "투표 질문 리스트 조회에 성공했습니다.",
+  "data" : [ {
+    "question" : {
+      "questionId" : 1,
+      "nameHead" : "나는",
+      "nameFoot" : "와",
+      "keywordHead" : "멋진",
+      "keywordFoot" : "에서 놀고싶어"
+    },
+    "friendList" : [ {
+      "friendId" : 2,
+      "friendName" : "name2",
+      "friendYelloId" : "yelloId2"
+    } ],
+    "keywordList" : [ "A", "B", "C", "D" ],
+    "questionPoint" : 10,
+    "subscribe" : "normal | active"
+  } ]
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/find-vote.html b/src/main/resources/static/docs/find-vote.html new file mode 100644 index 00000000..8e583c19 --- /dev/null +++ b/src/main/resources/static/docs/find-vote.html @@ -0,0 +1,518 @@ + + + + + + + +투표 상세 조회 + + + + + +
+
+

투표 상세 조회

+
+
+

요청

+
+
+
GET /api/v1/vote/1 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/v1/vote/{voteId}
ParameterDescription

voteId

투표 아이디 값

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "투표 조회에 성공했습니다.",
+  "data" : {
+    "colorIndex" : 0,
+    "currentPoint" : 200,
+    "nameHint" : -1,
+    "isAnswerRevealed" : false,
+    "senderName" : "name1",
+    "senderGender" : "MALE",
+    "vote" : {
+      "nameHead" : "나는",
+      "nameFoot" : "와",
+      "keywordHead" : "멋진",
+      "keyword" : "test",
+      "keywordFoot" : "에서 놀고싶어"
+    },
+    "ticketCount" : 0,
+    "isSubscribe" : false
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/find-votes.html b/src/main/resources/static/docs/find-votes.html new file mode 100644 index 00000000..72e36426 --- /dev/null +++ b/src/main/resources/static/docs/find-votes.html @@ -0,0 +1,524 @@ + + + + + + + +내 투표 전체 조회 + + + + + +
+
+

내 투표 전체 조회

+
+
+

요청

+
+
+
GET /api/v1/vote?page=0 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "투표 조회에 성공했습니다.",
+  "data" : {
+    "totalCount" : 1,
+    "ticketCount" : 0,
+    "openCount" : 0,
+    "openKeywordCount" : 0,
+    "openNameCount" : 0,
+    "openFullNameCount" : 0,
+    "votes" : [ {
+      "id" : 1,
+      "senderGender" : "MALE",
+      "senderName" : "name1",
+      "nameHint" : -1,
+      "vote" : {
+        "nameHead" : "나는",
+        "nameFoot" : "와",
+        "keywordHead" : "멋진",
+        "keyword" : "test",
+        "keywordFoot" : "에서 놀고싶어"
+      },
+      "isHintUsed" : false,
+      "isRead" : false,
+      "createdAt" : "0초 전"
+    } ]
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/get-unread-vote.html b/src/main/resources/static/docs/get-unread-vote.html new file mode 100644 index 00000000..332c20f5 --- /dev/null +++ b/src/main/resources/static/docs/get-unread-vote.html @@ -0,0 +1,482 @@ + + + + + + + +읽지 않은 쪽지 개수 조회 + + + + + +
+
+

읽지 않은 쪽지 개수 조회

+
+
+

요청

+
+
+
GET /api/v1/vote/count HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "투표 조회에 성공했습니다.",
+  "data" : {
+    "totalCount" : 1
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/google.html b/src/main/resources/static/docs/google.html new file mode 100644 index 00000000..af531fa5 --- /dev/null +++ b/src/main/resources/static/docs/google.html @@ -0,0 +1,525 @@ + + + + + + + +Google 구독 구매 검증하기 + + + + + +
+
+

Google 구독 구매 검증하기

+
+
+

요청

+
+
+
POST /api/v1/purchase/google/verify/subscribe HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: Bearer your-access-token
+Content-Length: 239
+
+{
+  "orderId" : "orderId",
+  "packageName" : "packageName",
+  "productId" : "productId",
+  "purchaseTime" : 1,
+  "purchaseState" : 1,
+  "purchaseToken" : "purchaseToken",
+  "quantity" : 1,
+  "autoRenewing" : true,
+  "acknowledged" : true
+}
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 201,
+  "message" : "구글 구독 결제 검증 및 반영에 성공하였습니다.",
+  "data" : {
+    "productId" : "productId",
+    "expiredAt" : "2023-08-25T20:51:30.274390"
+  }
+}
+
+
+
+
+
+
+

Google 열람권 구매 검증하기

+
+
+

요청

+
+
+
GET /api/v1/friend/recommend/school?page=0 HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "인앱결제 검증에 성공했습니다."
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/index.html b/src/main/resources/static/docs/index.html new file mode 100644 index 00000000..dad0d7ec --- /dev/null +++ b/src/main/resources/static/docs/index.html @@ -0,0 +1,614 @@ + + + + + + + +YELL:O API 문서 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/docs/login.html b/src/main/resources/static/docs/login.html new file mode 100644 index 00000000..c5f4577b --- /dev/null +++ b/src/main/resources/static/docs/login.html @@ -0,0 +1,491 @@ + + + + + + + +소셜 로그인 + + + + + +
+
+

소셜 로그인

+
+
+

요청

+
+
+
POST /api/v1/auth/oauth HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 91
+
+{
+  "accessToken" : "accessToken",
+  "social" : "social",
+  "deviceToken" : "deviceToken"
+}
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 201,
+  "message" : "로그인이 성공했습니다.",
+  "data" : {
+    "isResigned" : false,
+    "accessToken" : "serviceAccessToken",
+    "refreshToken" : "serviceRefreshToken"
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/overview.html b/src/main/resources/static/docs/overview.html new file mode 100644 index 00000000..8b891673 --- /dev/null +++ b/src/main/resources/static/docs/overview.html @@ -0,0 +1,522 @@ + + + + + + + +Overview + + + + + +
+
+

Overview

+
+
+

Host

+ ++++ + + + + + + + + + + + + + + + + +
환경Host

Development

BE팀에게 문의

Production

BE팀에게 문의

+
+
+

HTTP status codes

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
상태 코드설명

200 OK

성공

400 Bad Request

잘못된 요청

401 Unauthorized

비인증 상태

403 Forbidden

권한 거부

404 Not Found

존재하지 않는 요청 리소스

500 Internal Server Error

서버 에러

+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/pay.html b/src/main/resources/static/docs/pay.html new file mode 100644 index 00000000..87595924 --- /dev/null +++ b/src/main/resources/static/docs/pay.html @@ -0,0 +1,485 @@ + + + + + + + +친구 추가하기 + + + + + +
+
+

친구 추가하기

+
+
+

요청

+
+
+
POST /api/v1/pay HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: Bearer your-access-token
+Content-Length: 17
+
+{
+  "index" : 1
+}
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 201,
+  "message" : "이용권 버튼 클릭 횟수가 저장에 성공했습니다."
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/purchase-check.html b/src/main/resources/static/docs/purchase-check.html new file mode 100644 index 00000000..400081bb --- /dev/null +++ b/src/main/resources/static/docs/purchase-check.html @@ -0,0 +1,484 @@ + + + + + + + +구독 상태 및 열람권 개수 조회하기 + + + + + +
+
+

구독 상태 및 열람권 개수 조회하기

+
+
+

요청

+
+
+
GET /api/v1/purchase HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "유저 결제 정보 조회에 성공하였습니다",
+  "data" : {
+    "subscribeState" : "NORMAL",
+    "isSubscribe" : false,
+    "ticketCount" : 0
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/reissue-token.html b/src/main/resources/static/docs/reissue-token.html new file mode 100644 index 00000000..20957548 --- /dev/null +++ b/src/main/resources/static/docs/reissue-token.html @@ -0,0 +1,512 @@ + + + + + + + +토큰 재발급 + + + + + +
+
+

토큰 재발급

+
+
+

HTTP request

+
+
+
POST /api/v1/auth/token/issue HTTP/1.1
+X-ACCESS-AUTH: Bearer your-access-token
+X-REFRESH-AUTH: Bearer your-refresh-token
+
+
+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 201,
+  "message" : "토큰 재발급에 성공했습니다.",
+  "data" : {
+    "accessToken" : "new accessToken",
+    "refreshToken" : "new refreshToken"
+  }
+}
+
+
+
+
+

요청

+
+
+
POST /api/v1/auth/token/issue HTTP/1.1
+X-ACCESS-AUTH: Bearer your-access-token
+X-REFRESH-AUTH: Bearer your-refresh-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 201,
+  "message" : "토큰 재발급에 성공했습니다.",
+  "data" : {
+    "accessToken" : "new accessToken",
+    "refreshToken" : "new refreshToken"
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/reveal-full-name.html b/src/main/resources/static/docs/reveal-full-name.html new file mode 100644 index 00000000..0972a3b8 --- /dev/null +++ b/src/main/resources/static/docs/reveal-full-name.html @@ -0,0 +1,504 @@ + + + + + + + +투표 이름 전체 조회 + + + + + +
+
+

투표 이름 전체 조회

+
+
+

요청

+
+
+
PATCH /api/v1/vote/1/fullname HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/v1/vote/{voteId}/fullname
ParameterDescription

voteId

투표 아이디 값

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "전체 이름 확인에 성공했습니다.",
+  "data" : {
+    "name" : "name1"
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/reveal-name.html b/src/main/resources/static/docs/reveal-name.html new file mode 100644 index 00000000..d07b83d4 --- /dev/null +++ b/src/main/resources/static/docs/reveal-name.html @@ -0,0 +1,505 @@ + + + + + + + +투표 이름 부분 조회 + + + + + +
+
+

투표 이름 부분 조회

+
+
+

요청

+
+
+
PATCH /api/v1/vote/1/name HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ + ++++ + + + + + + + + + + + + +
Table 1. /api/v1/vote/{voteId}/name
ParameterDescription

voteId

투표 아이디 값

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "이름 초성 확인에 성공했습니다.",
+  "data" : {
+    "name" : "n",
+    "nameIndex" : 0
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/search-department.html b/src/main/resources/static/docs/search-department.html new file mode 100644 index 00000000..5ae8c19f --- /dev/null +++ b/src/main/resources/static/docs/search-department.html @@ -0,0 +1,514 @@ + + + + + + + +대학교 학과 검색하기 + + + + + +
+
+

대학교 학과 검색하기

+
+
+

요청

+
+
+
GET /api/v1/auth/school/department?page=0&school=school+name+here&keyword=keyword+here HTTP/1.1
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

school

학교 이름

keyword

검색할 쿼리

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "학과 검색에 성공했습니다.",
+  "data" : {
+    "totalCount" : 0,
+    "groupList" : [ {
+      "groupId" : 1,
+      "departmentName" : "테스트 학과 1"
+    } ]
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/search-friend.html b/src/main/resources/static/docs/search-friend.html new file mode 100644 index 00000000..faa74135 --- /dev/null +++ b/src/main/resources/static/docs/search-friend.html @@ -0,0 +1,515 @@ + + + + + + + +친구 검색하기 + + + + + +
+
+

친구 검색하기

+
+
+

요청

+
+
+
GET /api/v1/friend/search?page=0&keyword=keyword+here HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

keyword

검색할 쿼리

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "친구 검색하기에 성공했습니다.",
+  "data" : {
+    "totalCount" : 0,
+    "friendList" : [ {
+      "id" : 1,
+      "name" : "name1",
+      "group" : "테스트 대학교 1 테스트 학과 1 20학번",
+      "profileImage" : "test image",
+      "yelloId" : "yelloId1",
+      "isFriend" : false
+    } ]
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/search-school.html b/src/main/resources/static/docs/search-school.html new file mode 100644 index 00000000..637a5812 --- /dev/null +++ b/src/main/resources/static/docs/search-school.html @@ -0,0 +1,507 @@ + + + + + + + +대학교 검색하기 + + + + + +
+
+

대학교 검색하기

+
+
+

요청

+
+
+
GET /api/v1/auth/school?page=0&keyword=keyword+here HTTP/1.1
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription

page

페이지네이션 페이지 번호

keyword

검색할 쿼리

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "학교 검색에 성공했습니다.",
+  "data" : {
+    "totalCount" : 0,
+    "groupNameList" : [ "groupName" ]
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/shuffle-friends.html b/src/main/resources/static/docs/shuffle-friends.html new file mode 100644 index 00000000..6dd6752a --- /dev/null +++ b/src/main/resources/static/docs/shuffle-friends.html @@ -0,0 +1,484 @@ + + + + + + + +셔플한 친구 조회하기 + + + + + +
+
+

셔플한 친구 조회하기

+
+
+

요청

+
+
+
GET /api/v1/friend/shuffle HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "친구 셔플에 성공했습니다.",
+  "data" : [ {
+    "friendId" : 2,
+    "friendName" : "name2",
+    "friendYelloId" : "yelloId2"
+  } ]
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/signup.html b/src/main/resources/static/docs/signup.html new file mode 100644 index 00000000..81c5ec72 --- /dev/null +++ b/src/main/resources/static/docs/signup.html @@ -0,0 +1,500 @@ + + + + + + + +회원가입 + + + + + +
+
+

회원가입

+
+
+

요청

+
+
+
POST /api/v1/auth/signup HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 307
+
+{
+  "social" : "KAKAO",
+  "uuid" : "uuid",
+  "deviceToken" : "deviceToken",
+  "email" : "email@emall.com",
+  "profileImage" : "profileImage",
+  "groupId" : 1,
+  "groupAdmissionYear" : 20,
+  "name" : "name",
+  "yelloId" : "yelloId",
+  "gender" : "MALE",
+  "friends" : [ 1 ],
+  "recommendId" : "recommendId"
+}
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 201,
+  "message" : "회원 가입에 성공했습니다.",
+  "data" : {
+    "yelloId" : "yelloId",
+    "accessToken" : "serviceAccessToken",
+    "refreshToken" : "serviceRefreshToken"
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/sub-check.html b/src/main/resources/static/docs/sub-check.html new file mode 100644 index 00000000..6b02b3be --- /dev/null +++ b/src/main/resources/static/docs/sub-check.html @@ -0,0 +1,483 @@ + + + + + + + +구독 연장 유도 필요 여부 확인하기 + + + + + +
+
+

구독 연장 유도 필요 여부 확인하기

+
+
+

요청

+
+
+
GET /api/v1/purchase/subscribe HTTP/1.1
+Authorization: Bearer your-access-token
+
+
+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "유저 구독 연장 유도 필요 여부 확인 조회에 성공하였습니다.",
+  "data" : {
+    "subscribe" : "NORMAL",
+    "isSubscribeNeeded" : false
+  }
+}
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/validate-yelloid.html b/src/main/resources/static/docs/validate-yelloid.html new file mode 100644 index 00000000..89a3508a --- /dev/null +++ b/src/main/resources/static/docs/validate-yelloid.html @@ -0,0 +1,500 @@ + + + + + + + +옐로 아이디 중복 확인 + + + + + +
+
+

옐로 아이디 중복 확인

+
+
+

요청

+
+
+
GET /api/v1/auth/valid?yelloId=yelloId+here HTTP/1.1
+
+
+
+
+

요청 파라미터

+ ++++ + + + + + + + + + + + + +
ParameterDescription

yelloId

중복 체크할 yelloId

+
+
+

응답

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "status" : 200,
+  "message" : "옐로 아이디 중복 여부 조회에 성공했습니다.",
+  "data" : false
+}
+
+
+
+
+
+
+ + + \ No newline at end of file From f2e53c9fb57933687c5a8419a290247ed488d603 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Fri, 25 Aug 2023 20:55:44 +0900 Subject: [PATCH 37/41] =?UTF-8?q?YEL-139=20[test]=20Test=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9436ed8f..ae81427d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,9 +14,8 @@ on: branches: [ "develop", "staging" ] permissions: - contents: write checks: write - id-token: write + pull-requests: write jobs: build: @@ -52,7 +51,7 @@ jobs: run: ./gradlew test - name: 💬 테스트 결과를 코멘트로 등록합니다. - uses: EnricoMi/publish-unit-test-result-action@v1 + uses: EnricoMi/publish-unit-test-result-action@v2 if: always() with: files: '**/build/test-results/test/TEST-*.xml' From 5f376ff5839784ca726c782929348f4540f05355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=98=EC=A0=9C?= Date: Sun, 27 Aug 2023 00:20:17 +0900 Subject: [PATCH 38/41] =?UTF-8?q?YEL-145=20[fix]=20soft=20deleted=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=EC=9D=98=20yelloId=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authorization/service/AuthManagerImpl.java | 4 ++-- .../domain/authorization/service/AuthService.java | 4 ++-- .../domain/user/repository/UserJpaRepository.java | 4 ++++ .../domain/user/repository/UserRepository.java | 2 ++ .../domain/user/repository/UserRepositoryImpl.java | 5 +++++ .../yello/server/global/HealthCheckController.java | 5 +++++ .../server/domain/authorization/FakeAuthManager.java | 4 ++-- .../yello/server/domain/user/FakeUserRepository.java | 12 ++++++++++-- 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/yello/server/domain/authorization/service/AuthManagerImpl.java b/src/main/java/com/yello/server/domain/authorization/service/AuthManagerImpl.java index d46e7bae..b161037d 100644 --- a/src/main/java/com/yello/server/domain/authorization/service/AuthManagerImpl.java +++ b/src/main/java/com/yello/server/domain/authorization/service/AuthManagerImpl.java @@ -71,7 +71,7 @@ public void validateSignupRequest(SignUpRequest signUpRequest) { throw new UserConflictException(UUID_CONFLICT_USER_EXCEPTION); }); - userRepository.findByYelloId(signUpRequest.yelloId()) + userRepository.findByYelloIdNotFiltered(signUpRequest.yelloId()) .ifPresent(action -> { throw new UserConflictException(YELLOID_CONFLICT_USER_EXCEPTION); }); @@ -81,7 +81,7 @@ public void validateSignupRequest(SignUpRequest signUpRequest) { public Boolean renewUserData(User user) { final Long userId = user.getId(); - if (user.getDeletedAt()!=null) { + if (user.getDeletedAt() != null) { user.renew(); friendRepository.findAllByUserIdNotFiltered(userId) diff --git a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java index c3a689ff..972e0b28 100644 --- a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java +++ b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java @@ -80,7 +80,7 @@ public Boolean isYelloIdDuplicated(String yelloId) { throw new AuthBadRequestException(YELLOID_REQUIRED_EXCEPTION); } - return userRepository.findByYelloId(yelloId).isPresent(); + return userRepository.findByYelloIdNotFiltered(yelloId).isPresent(); } @Transactional @@ -103,7 +103,7 @@ public SignUpResponse signUp(SignUpRequest signUpRequest) { @Transactional public void recommendUser(String recommendYelloId, String userYelloId) { - if (recommendYelloId!=null && !recommendYelloId.isEmpty()) { + if (recommendYelloId != null && !recommendYelloId.isEmpty()) { User recommendedUser = userRepository.getByYelloId(recommendYelloId); User user = userRepository.getByYelloId(userYelloId); diff --git a/src/main/java/com/yello/server/domain/user/repository/UserJpaRepository.java b/src/main/java/com/yello/server/domain/user/repository/UserJpaRepository.java index f0cceea9..dcfd13a9 100644 --- a/src/main/java/com/yello/server/domain/user/repository/UserJpaRepository.java +++ b/src/main/java/com/yello/server/domain/user/repository/UserJpaRepository.java @@ -28,6 +28,10 @@ public interface UserJpaRepository extends JpaRepository { "and u.deletedAt is null") Optional findByYelloId(@Param("yelloId") String yelloId); + @Query("select u from User u " + + "where u.yelloId = :yelloId") + Optional findByYelloIdNotFiltered(@Param("yelloId") String yelloId); + @Query("select u from User u " + "where u.group.id = :groupId " + "and u.deletedAt is null") diff --git a/src/main/java/com/yello/server/domain/user/repository/UserRepository.java b/src/main/java/com/yello/server/domain/user/repository/UserRepository.java index 8196c4fe..1ba44451 100644 --- a/src/main/java/com/yello/server/domain/user/repository/UserRepository.java +++ b/src/main/java/com/yello/server/domain/user/repository/UserRepository.java @@ -20,6 +20,8 @@ public interface UserRepository { Optional findByYelloId(String yelloId); + Optional findByYelloIdNotFiltered(String yelloId); + User getByYelloId(String yelloId); Optional findByDeviceToken(String deviceToken); diff --git a/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java b/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java index f1cf794c..8303653c 100644 --- a/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java +++ b/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java @@ -57,6 +57,11 @@ public Optional findByYelloId(String yelloId) { return userJpaRepository.findByYelloId(yelloId); } + @Override + public Optional findByYelloIdNotFiltered(String yelloId) { + return userJpaRepository.findByYelloIdNotFiltered(yelloId); + } + @Override public User getByYelloId(String yelloId) { return userJpaRepository.findByYelloId(yelloId) diff --git a/src/main/java/com/yello/server/global/HealthCheckController.java b/src/main/java/com/yello/server/global/HealthCheckController.java index a3cf6aa3..34431b25 100644 --- a/src/main/java/com/yello/server/global/HealthCheckController.java +++ b/src/main/java/com/yello/server/global/HealthCheckController.java @@ -12,4 +12,9 @@ public class HealthCheckController { public String healthCheck() { return "Yell:o world!"; } + + @GetMapping("/abc") + public void text() throws Exception { + throw new Exception("Abc"); + } } diff --git a/src/test/java/com/yello/server/domain/authorization/FakeAuthManager.java b/src/test/java/com/yello/server/domain/authorization/FakeAuthManager.java index 1c99dee5..c23cb568 100644 --- a/src/test/java/com/yello/server/domain/authorization/FakeAuthManager.java +++ b/src/test/java/com/yello/server/domain/authorization/FakeAuthManager.java @@ -76,7 +76,7 @@ public void validateSignupRequest(SignUpRequest signUpRequest) { throw new UserConflictException(UUID_CONFLICT_USER_EXCEPTION); }); - userRepository.findByYelloId(signUpRequest.yelloId()) + userRepository.findByYelloIdNotFiltered(signUpRequest.yelloId()) .ifPresent(action -> { throw new UserConflictException(YELLOID_CONFLICT_USER_EXCEPTION); }); @@ -86,7 +86,7 @@ public void validateSignupRequest(SignUpRequest signUpRequest) { public Boolean renewUserData(User user) { final Long userId = user.getId(); - if (user.getDeletedAt()!=null) { + if (user.getDeletedAt() != null) { user.renew(); friendRepository.findAllByUserIdNotFiltered(userId) diff --git a/src/test/java/com/yello/server/domain/user/FakeUserRepository.java b/src/test/java/com/yello/server/domain/user/FakeUserRepository.java index 79f349a2..7c130a7c 100644 --- a/src/test/java/com/yello/server/domain/user/FakeUserRepository.java +++ b/src/test/java/com/yello/server/domain/user/FakeUserRepository.java @@ -18,12 +18,12 @@ public class FakeUserRepository implements UserRepository { @Override public User save(User user) { - if (user.getId()!=null && user.getId() > id) { + if (user.getId() != null && user.getId() > id) { id = user.getId(); } User newUser = User.builder() - .id(user.getId()==null ? ++id : user.getId()) + .id(user.getId() == null ? ++id : user.getId()) .recommendCount(0L) .name(user.getName()) .yelloId(user.getYelloId()) @@ -82,6 +82,14 @@ public boolean existsByUuid(String uuid) { @Override public Optional findByYelloId(String yelloId) { + return data.stream() + .filter(user -> user.getDeletedAt() == null) + .filter(user -> user.getYelloId().equals(yelloId)) + .findFirst(); + } + + @Override + public Optional findByYelloIdNotFiltered(String yelloId) { return data.stream() .filter(user -> user.getYelloId().equals(yelloId)) .findFirst(); From 41df0a6ef07fb75176dbe7d1b58bdfed6d141b60 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Sun, 27 Aug 2023 01:54:39 +0900 Subject: [PATCH 39/41] =?UTF-8?q?YEL-144=20[fix]=20apple=20=EA=B2=B0?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/apple/AppleOrderResponse.java | 3 +-- .../factory/SlackWebhookMessageFactory.java | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleOrderResponse.java b/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleOrderResponse.java index 15502202..d1d884de 100644 --- a/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleOrderResponse.java +++ b/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleOrderResponse.java @@ -5,8 +5,7 @@ @Builder public record AppleOrderResponse( int appAppleId, - String environment, - String JWSTransaction + String environment ) { } diff --git a/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java b/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java index 9eb65dd5..6738b667 100644 --- a/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java +++ b/src/main/java/com/yello/server/infrastructure/slack/factory/SlackWebhookMessageFactory.java @@ -70,11 +70,10 @@ private List generateSlackPurchaseAttachment( HttpServletRequest request ) throws IOException { final SlackAttachment slackAttachment = new SlackAttachment() - .setColor("green") + .setColor("good") .setTitle(PURCHASE_TITLE) .setTitleLink(request.getContextPath()) .setText(PURCHASE_TITLE) - .setColor("green") .setFields(generateSlackFieldList(request)); return Collections.singletonList(slackAttachment); } @@ -82,23 +81,29 @@ private List generateSlackPurchaseAttachment( private List generateSlackFieldList( HttpServletRequest request ) throws IOException { - final String token = request.getHeader(HttpHeaders.AUTHORIZATION).substring("Bearer ".length()); + final String token = + request.getHeader(HttpHeaders.AUTHORIZATION).substring("Bearer ".length()); final Long userId = tokenProvider.getUserId(token); final Optional user = userRepository.findById(userId); final String yelloId = user.isPresent() ? user.get().getYelloId() : "null"; final String deviceToken = user.isPresent() ? user.get().getDeviceToken() : "null"; - String userInfo = String.format("userId : %d %nyelloId : %s %ndeviceToken : %s", userId, yelloId, deviceToken); + String userInfo = + String.format("userId : %d %nyelloId : %s %ndeviceToken : %s", userId, yelloId, + deviceToken); return Arrays.asList( new SlackField().setTitle("Request URL").setValue(request.getRequestURL().toString()), - new SlackField().setTitle("Request Time").setValue(TimeFactory.toDateFormattedString(LocalDateTime.now())), + new SlackField().setTitle("Request Time") + .setValue(TimeFactory.toDateFormattedString(LocalDateTime.now())), new SlackField().setTitle("Request IP").setValue(request.getRemoteAddr()), - new SlackField().setTitle("Request User-Agent").setValue(request.getHeader(HttpHeaders.USER_AGENT)), + new SlackField().setTitle("Request User-Agent") + .setValue(request.getHeader(HttpHeaders.USER_AGENT)), new SlackField().setTitle("인증/인가 정보 - Authorization") .setValue(request.getHeader(HttpHeaders.AUTHORIZATION)), new SlackField().setTitle("Request Body") - .setValue(StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8)), + .setValue( + StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8)), new SlackField().setTitle("인증/인가 정보 - 유저").setValue(userInfo) ); } From a777056b96c1bc36158decc311633d26f64d2fc7 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Sun, 27 Aug 2023 22:56:46 +0900 Subject: [PATCH 40/41] =?UTF-8?q?YEL-139=20[test]=20=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EA=B2=B0=EC=A0=9C=20=EA=B4=80=EB=A0=A8=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=84=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/google.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/docs/asciidoc/google.adoc b/src/docs/asciidoc/google.adoc index 1d208f6c..8b2450e5 100644 --- a/src/docs/asciidoc/google.adoc +++ b/src/docs/asciidoc/google.adoc @@ -12,8 +12,8 @@ include::{snippets}/api/v1/purchase/verifyGoogleSubscriptionTransaction/http-res === 요청 -include::{snippets}/api/v1/friend/findAllRecommendSchoolFriends/http-request.adoc[] +include::{snippets}/api/v1/purchase/verifyGoogleTicketTransaction/http-request.adoc[] === 응답 -include::{snippets}/api/v1/purchase/verifyAppleTicketTransaction/http-response.adoc[] \ No newline at end of file +include::{snippets}/api/v1/purchase/verifyGoogleTicketTransaction/http-response.adoc[] \ No newline at end of file From f6b3988aaf67ee6e2bcccb10fabe13e970960305 Mon Sep 17 00:00:00 2001 From: Kwon Sehoon Date: Sun, 27 Aug 2023 23:12:26 +0900 Subject: [PATCH 41/41] =?UTF-8?q?YEL-139=20[docs]=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=84=9C=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../static/docs/check-vote-available.html | 2 +- src/main/resources/static/docs/google.html | 29 +++++++++++++++---- src/main/resources/static/docs/index.html | 2 +- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/main/resources/static/docs/check-vote-available.html b/src/main/resources/static/docs/check-vote-available.html index 6f192f97..8633b56f 100644 --- a/src/main/resources/static/docs/check-vote-available.html +++ b/src/main/resources/static/docs/check-vote-available.html @@ -465,7 +465,7 @@

응답

"data" : { "isPossible" : false, "point" : 200, - "createdAt" : "2023-08-25 20:51:31" + "createdAt" : "2023-08-27 23:08:50" } } diff --git a/src/main/resources/static/docs/google.html b/src/main/resources/static/docs/google.html index af531fa5..7fd1a3ed 100644 --- a/src/main/resources/static/docs/google.html +++ b/src/main/resources/static/docs/google.html @@ -478,7 +478,7 @@

응답

"message" : "구글 구독 결제 검증 및 반영에 성공하였습니다.", "data" : { "productId" : "productId", - "expiredAt" : "2023-08-25T20:51:30.274390" + "expiredAt" : "2023-08-27T23:08:49.542865" } } @@ -493,8 +493,21 @@

Google 열람권 구매 검증하

요청

-
GET /api/v1/friend/recommend/school?page=0 HTTP/1.1
-Authorization: Bearer your-access-token
+
POST /api/v1/purchase/google/verify/ticket HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: Bearer your-access-token
+Content-Length: 214
+
+{
+  "orderId" : "orderId",
+  "packageName" : "packageName",
+  "productId" : "productId",
+  "purchaseTime" : 1,
+  "purchaseState" : 1,
+  "purchaseToken" : "purchaseToken",
+  "quantity" : 1,
+  "acknowledged" : true
+}
@@ -506,8 +519,12 @@

응답

Content-Type: application/json { - "status" : 200, - "message" : "인앱결제 검증에 성공했습니다." + "status" : 201, + "message" : "구글 인앱 결제 검증 및 반영에 성공하였습니다.", + "data" : { + "productId" : "productId", + "ticketCount" : 0 + } } @@ -518,7 +535,7 @@

응답

diff --git a/src/main/resources/static/docs/index.html b/src/main/resources/static/docs/index.html index dad0d7ec..9601d2ea 100644 --- a/src/main/resources/static/docs/index.html +++ b/src/main/resources/static/docs/index.html @@ -604,7 +604,7 @@

Pay API