From f271d95346130029bedf918afc5523f59934e09c Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 19 Jul 2024 18:12:31 +0700 Subject: [PATCH 01/15] Implement authorization for SYNC product --- .../market/constants/GitHubConstants.java | 10 ++++-- .../constants/RequestMappingConstants.java | 1 - .../market/controller/FeedbackController.java | 2 +- .../market/controller/OAuth2Controller.java | 2 +- .../market/controller/ProductController.java | 17 +++++++-- .../com/axonivy/market/enums/ErrorCode.java | 4 +-- .../market/exceptions/ExceptionHandlers.java | 10 ++++++ .../model/UnauthorizedException.java | 20 +++++++++++ .../model/GitHubAccessTokenResponse.java | 2 +- .../market/github/service/GitHubService.java | 5 ++- .../service/impl/GitHubServiceImpl.java | 36 +++++++++++++++++-- .../market/github/util/GitHubUtils.java | 24 +++++++++++++ .../controller/OAuth2ControllerTest.java | 2 +- 13 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 marketplace-service/src/main/java/com/axonivy/market/exceptions/model/UnauthorizedException.java rename marketplace-service/src/main/java/com/axonivy/market/{ => github}/model/GitHubAccessTokenResponse.java (91%) diff --git a/marketplace-service/src/main/java/com/axonivy/market/constants/GitHubConstants.java b/marketplace-service/src/main/java/com/axonivy/market/constants/GitHubConstants.java index 6e81a25f9..2cf5753df 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/constants/GitHubConstants.java +++ b/marketplace-service/src/main/java/com/axonivy/market/constants/GitHubConstants.java @@ -16,16 +16,20 @@ public class GitHubConstants { @NoArgsConstructor(access = AccessLevel.PRIVATE) public static class Json { - public static final String ACCESS_TOKEN = "access_token"; public static final String TOKEN = "token"; public static final String CLIENT_ID = "client_id"; public static final String CLIENT_SECRET = "client_secret"; public static final String CODE = "code"; - public static final String ERROR = "error"; - public static final String ERROR_DESCRIPTION = "error"; public static final String USER_ID = "id"; public static final String USER_NAME = "name"; public static final String USER_AVATAR_URL = "avatar_url"; public static final String USER_LOGIN_NAME = "login"; } + + @NoArgsConstructor(access = AccessLevel.PRIVATE) + public static class Url { + private static final String BASE_URL = "https://api.github.com"; + public static final String USER = BASE_URL + "/user"; + public static final String USER_ORGS = USER + "/orgs"; + } } diff --git a/marketplace-service/src/main/java/com/axonivy/market/constants/RequestMappingConstants.java b/marketplace-service/src/main/java/com/axonivy/market/constants/RequestMappingConstants.java index 5efdc47e6..1ea85be50 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/constants/RequestMappingConstants.java +++ b/marketplace-service/src/main/java/com/axonivy/market/constants/RequestMappingConstants.java @@ -8,7 +8,6 @@ public class RequestMappingConstants { public static final String ROOT = "/"; public static final String API = ROOT + "api"; public static final String SYNC = ROOT + "sync"; - public static final String USER_MAPPING = "/user"; public static final String PRODUCT = API + "/product"; public static final String PRODUCT_DETAILS = API + "/product-details"; public static final String FEEDBACK = API + "/feedback"; diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index 4d04faa3c..94696f335 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -78,7 +78,7 @@ public ResponseEntity findFeedbackByUserIdAndProductId(@RequestPa @PostMapping public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModel feedback, - @RequestHeader(value = "Authorization", required = false) String authorizationHeader) { + @RequestHeader(value = "Authorization") String authorizationHeader) { String token = null; if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { token = authorizationHeader.substring(7); // Remove "Bearer " prefix diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java index 611b6a860..813ccaafe 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java @@ -3,7 +3,7 @@ import com.axonivy.market.constants.GitHubConstants; import com.axonivy.market.entity.User; import com.axonivy.market.github.service.GitHubService; -import com.axonivy.market.model.GitHubAccessTokenResponse; +import com.axonivy.market.github.model.GitHubAccessTokenResponse; import com.axonivy.market.model.Oauth2AuthorizationCode; import com.axonivy.market.service.JwtService; import org.springframework.beans.factory.annotation.Value; diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 498424e11..3bae8910a 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -1,8 +1,11 @@ package com.axonivy.market.controller; import com.axonivy.market.assembler.ProductModelAssembler; +import com.axonivy.market.constants.GitHubConstants; import com.axonivy.market.entity.Product; import com.axonivy.market.enums.ErrorCode; +import com.axonivy.market.github.service.GitHubService; +import com.axonivy.market.github.util.GitHubUtils; import com.axonivy.market.model.Message; import com.axonivy.market.model.ProductModel; import com.axonivy.market.service.ProductService; @@ -17,9 +20,11 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpClientErrorException; import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; import static com.axonivy.market.constants.RequestMappingConstants.SYNC; @@ -29,12 +34,14 @@ public class ProductController { private final ProductService productService; + private final GitHubService gitHubService; private final ProductModelAssembler assembler; private final PagedResourcesAssembler pagedResourcesAssembler; - public ProductController(ProductService productService, ProductModelAssembler assembler, + public ProductController(ProductService productService, GitHubService gitHubService, ProductModelAssembler assembler, PagedResourcesAssembler pagedResourcesAssembler) { this.productService = productService; + this.gitHubService = gitHubService; this.assembler = assembler; this.pagedResourcesAssembler = pagedResourcesAssembler; } @@ -54,7 +61,13 @@ public ResponseEntity> findProducts(@RequestParam(name } @PutMapping(SYNC) - public ResponseEntity syncProducts() { + public ResponseEntity syncProducts(@RequestHeader(value = "Authorization") String authorizationHeader) { + String token = null; + if (authorizationHeader.startsWith("Bearer ")) { + token = authorizationHeader.substring(7); // Remove "Bearer " prefix + } + gitHubService.validateUserOrganization(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME); + var stopWatch = new StopWatch(); stopWatch.start(); var isAlreadyUpToDate = productService.syncLatestDataFromMarketRepo(); diff --git a/marketplace-service/src/main/java/com/axonivy/market/enums/ErrorCode.java b/marketplace-service/src/main/java/com/axonivy/market/enums/ErrorCode.java index 650463ef5..c12d7ed44 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/enums/ErrorCode.java +++ b/marketplace-service/src/main/java/com/axonivy/market/enums/ErrorCode.java @@ -17,8 +17,8 @@ public enum ErrorCode { PRODUCT_SORT_INVALID("1102", "PRODUCT_SORT_INVALID"), PRODUCT_NOT_FOUND("1103", "PRODUCT_NOT_FOUND"), GH_FILE_STATUS_INVALID("0201", "GIT_HUB_FILE_STATUS_INVALID"), GH_FILE_TYPE_INVALID("0202", "GIT_HUB_FILE_TYPE_INVALID"), USER_NOT_FOUND("2103", "USER_NOT_FOUND"), - GITHUB_USER_NOT_FOUND("2204", "GITHUB_USER_NOT_FOUND"), FEEDBACK_NOT_FOUND("3103", "FEEDBACK_NOT_FOUND"), - ARGUMENT_BAD_REQUEST("4000", "ARGUMENT_BAD_REQUEST"); + GITHUB_USER_NOT_FOUND("2204", "GITHUB_USER_NOT_FOUND"), GITHUB_USER_UNAUTHORIZED("2205", "GITHUB_USER_UNAUTHORIZED"), + FEEDBACK_NOT_FOUND("3103", "FEEDBACK_NOT_FOUND"), ARGUMENT_BAD_REQUEST("4000", "ARGUMENT_BAD_REQUEST"); String code; String helpText; diff --git a/marketplace-service/src/main/java/com/axonivy/market/exceptions/ExceptionHandlers.java b/marketplace-service/src/main/java/com/axonivy/market/exceptions/ExceptionHandlers.java index 948d28fc3..3ec95b44d 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/exceptions/ExceptionHandlers.java +++ b/marketplace-service/src/main/java/com/axonivy/market/exceptions/ExceptionHandlers.java @@ -5,6 +5,7 @@ import com.axonivy.market.exceptions.model.MissingHeaderException; import com.axonivy.market.exceptions.model.NotFoundException; import com.axonivy.market.exceptions.model.Oauth2ExchangeCodeException; +import com.axonivy.market.exceptions.model.UnauthorizedException; import com.axonivy.market.model.Message; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -74,4 +75,13 @@ public ResponseEntity handleOauth2ExchangeCodeException( errorMessage.setMessageDetails(oauth2ExchangeCodeException.getErrorDescription()); return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST); } + @ExceptionHandler(UnauthorizedException.class) + public ResponseEntity handleUnauthorizedException( + UnauthorizedException unauthorizedException) { + var errorMessage = new Message(); + errorMessage.setHelpCode(unauthorizedException.getError()); + errorMessage.setMessageDetails(unauthorizedException.getMessage()); + return new ResponseEntity<>(errorMessage, HttpStatus.UNAUTHORIZED); + } + } diff --git a/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/UnauthorizedException.java b/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/UnauthorizedException.java new file mode 100644 index 000000000..6a557a88f --- /dev/null +++ b/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/UnauthorizedException.java @@ -0,0 +1,20 @@ +package com.axonivy.market.exceptions.model; + +import com.axonivy.market.enums.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serial; + +@Getter +@Setter +@AllArgsConstructor +public class UnauthorizedException extends RuntimeException { + + @Serial + private static final long serialVersionUID = 6778659812221728814L; + + private final String error; + private final String message; +} diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/GitHubAccessTokenResponse.java b/marketplace-service/src/main/java/com/axonivy/market/github/model/GitHubAccessTokenResponse.java similarity index 91% rename from marketplace-service/src/main/java/com/axonivy/market/model/GitHubAccessTokenResponse.java rename to marketplace-service/src/main/java/com/axonivy/market/github/model/GitHubAccessTokenResponse.java index be3e89bd7..f48202ea3 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/GitHubAccessTokenResponse.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/model/GitHubAccessTokenResponse.java @@ -1,4 +1,4 @@ -package com.axonivy.market.model; +package com.axonivy.market.github.model; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/service/GitHubService.java b/marketplace-service/src/main/java/com/axonivy/market/github/service/GitHubService.java index 6e4a19ff5..ae4753315 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/service/GitHubService.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/service/GitHubService.java @@ -1,7 +1,8 @@ package com.axonivy.market.github.service; import com.axonivy.market.entity.User; -import com.axonivy.market.model.GitHubAccessTokenResponse; +import com.axonivy.market.exceptions.model.UnauthorizedException; +import com.axonivy.market.github.model.GitHubAccessTokenResponse; import org.kohsuke.github.GHContent; import org.kohsuke.github.GHOrganization; import org.kohsuke.github.GHRepository; @@ -25,4 +26,6 @@ public interface GitHubService { GitHubAccessTokenResponse getAccessToken(String code, String clientId, String clientSecret); User getAndUpdateUser(String accessToken); + + void validateUserOrganization(String accessToken, String organization) throws UnauthorizedException; } diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java index ba63635ad..822780af8 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java @@ -5,8 +5,10 @@ import com.axonivy.market.enums.ErrorCode; import com.axonivy.market.exceptions.model.NotFoundException; import com.axonivy.market.exceptions.model.Oauth2ExchangeCodeException; +import com.axonivy.market.exceptions.model.UnauthorizedException; +import com.axonivy.market.github.model.GitHubAccessTokenResponse; import com.axonivy.market.github.service.GitHubService; -import com.axonivy.market.model.GitHubAccessTokenResponse; +import com.axonivy.market.github.util.GitHubUtils; import com.axonivy.market.repository.UserRepository; import org.kohsuke.github.GHContent; import org.kohsuke.github.GHOrganization; @@ -25,6 +27,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ResourceUtils; +import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import java.io.File; @@ -105,7 +108,7 @@ public User getAndUpdateUser(String accessToken) { headers.setBearerAuth(accessToken); HttpEntity entity = new HttpEntity<>(headers); - ResponseEntity> response = restTemplate.exchange("https://api.github.com/user", HttpMethod.GET, + ResponseEntity> response = restTemplate.exchange(GitHubConstants.Url.USER, HttpMethod.GET, entity, new ParameterizedTypeReference<>() { }); @@ -134,4 +137,33 @@ public User getAndUpdateUser(String accessToken) { return user; } + + @Override + public void validateUserOrganization(String accessToken, String organization) throws UnauthorizedException { + List> userOrganizations = getUserOrganizations(accessToken); + for (var org : userOrganizations) { + if (org.get("login").equals(organization)) { + return; + } + } + throw new UnauthorizedException(ErrorCode.GITHUB_USER_UNAUTHORIZED.getCode(), + ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText() + + "-User must be a member of the Axon Ivy Market Organization"); + } + + private List> getUserOrganizations(String accessToken) throws UnauthorizedException { + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(accessToken); + HttpEntity entity = new HttpEntity<>(headers); + try { + ResponseEntity>> response = restTemplate.exchange(GitHubConstants.Url.USER_ORGS, + HttpMethod.GET, entity, new ParameterizedTypeReference<>() { + }); + return response.getBody(); + } + catch (HttpClientErrorException exception) { + throw new UnauthorizedException(ErrorCode.GITHUB_USER_UNAUTHORIZED.getCode(), + ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText() + "-" + GitHubUtils.extractMessageFromExceptionMessage(exception.getMessage())); + } + } } \ No newline at end of file diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java b/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java index c3b172014..5a1f31237 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java @@ -6,6 +6,7 @@ import lombok.NoArgsConstructor; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; +import org.bson.json.JsonObject; import org.kohsuke.github.GHCommit; import org.kohsuke.github.GHContent; import org.kohsuke.github.PagedIterable; @@ -130,4 +131,27 @@ public static String getNonStandardImageFolder(String productId) { } return pathToImageFolder; } + + public static String extractMessageFromExceptionMessage(String exceptionMessage) { + String json = extractJson(exceptionMessage); + String key = "\"message\":\""; + int startIndex = json.indexOf(key); + if (startIndex != -1) { + startIndex += key.length(); + int endIndex = json.indexOf("\"", startIndex); + if (endIndex != -1) { + return json.substring(startIndex, endIndex); + } + } + return ""; + } + + private static String extractJson(String text) { + int start = text.indexOf("{"); + int end = text.lastIndexOf("}") + 1; + if (start != -1 && end != -1) { + return text.substring(start, end); + } + return ""; + } } diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/OAuth2ControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/OAuth2ControllerTest.java index efcc39756..f4a67a939 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/OAuth2ControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/OAuth2ControllerTest.java @@ -2,7 +2,7 @@ import com.axonivy.market.entity.User; import com.axonivy.market.github.service.GitHubService; -import com.axonivy.market.model.GitHubAccessTokenResponse; +import com.axonivy.market.github.model.GitHubAccessTokenResponse; import com.axonivy.market.model.Oauth2AuthorizationCode; import com.axonivy.market.service.JwtService; import org.junit.jupiter.api.BeforeEach; From 2f85dbf0ac26bac8bfb289b5be5b671a5da03429 Mon Sep 17 00:00:00 2001 From: ndkhanh-axonivy Date: Mon, 22 Jul 2024 02:52:14 +0700 Subject: [PATCH 02/15] add param resetSync --- .../com/axonivy/market/controller/ProductController.java | 5 ++++- .../java/com/axonivy/market/service/ProductService.java | 2 ++ .../com/axonivy/market/service/impl/ProductServiceImpl.java | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 3bae8910a..cc92df834 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -61,12 +61,15 @@ public ResponseEntity> findProducts(@RequestParam(name } @PutMapping(SYNC) - public ResponseEntity syncProducts(@RequestHeader(value = "Authorization") String authorizationHeader) { + public ResponseEntity syncProducts(@RequestHeader(value = "Authorization") String authorizationHeader, @RequestParam("resetSync") boolean resetSync) { String token = null; if (authorizationHeader.startsWith("Bearer ")) { token = authorizationHeader.substring(7); // Remove "Bearer " prefix } gitHubService.validateUserOrganization(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME); + if (resetSync) { + productService.clearAllProducts(); + } var stopWatch = new StopWatch(); stopWatch.start(); diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/ProductService.java b/marketplace-service/src/main/java/com/axonivy/market/service/ProductService.java index 89bef2d95..87a57f2d3 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/ProductService.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/ProductService.java @@ -13,4 +13,6 @@ public interface ProductService { Product fetchProductDetail(String id); String getCompatibilityFromOldestTag(String oldestTag); + + void clearAllProducts(); } diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java index e87bf73ef..00f7a129d 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java @@ -344,4 +344,10 @@ public Product fetchProductDetail(String id) { return productItem; }).orElse(null); } + + @Override + public void clearAllProducts() { + gitHubRepoMetaRepository.deleteAll(); + productRepository.deleteAll(); + } } From aa915838e5f2fb4bf2fabbaff7bc4d7f9c3b2c3e Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Mon, 22 Jul 2024 09:26:59 +0700 Subject: [PATCH 03/15] Add require false for resetSync and reformat code --- .../market/controller/OAuth2Controller.java | 2 +- .../market/controller/ProductController.java | 5 +- .../com/axonivy/market/entity/Product.java | 24 ++++--- .../model/UnauthorizedException.java | 1 - .../market/factory/ProductFactory.java | 34 +++++----- .../impl/GHAxonIvyProductRepoServiceImpl.java | 38 ++++++----- .../market/github/util/GitHubUtils.java | 1 - .../axonivy/market/model/ProductModel.java | 16 ++--- .../service/impl/ProductServiceImpl.java | 64 +++++++++---------- 9 files changed, 86 insertions(+), 99 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java index 813ccaafe..f5e6c93ce 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java @@ -2,8 +2,8 @@ import com.axonivy.market.constants.GitHubConstants; import com.axonivy.market.entity.User; -import com.axonivy.market.github.service.GitHubService; import com.axonivy.market.github.model.GitHubAccessTokenResponse; +import com.axonivy.market.github.service.GitHubService; import com.axonivy.market.model.Oauth2AuthorizationCode; import com.axonivy.market.service.JwtService; import org.springframework.beans.factory.annotation.Value; diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index cc92df834..1e20a3b61 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -5,7 +5,6 @@ import com.axonivy.market.entity.Product; import com.axonivy.market.enums.ErrorCode; import com.axonivy.market.github.service.GitHubService; -import com.axonivy.market.github.util.GitHubUtils; import com.axonivy.market.model.Message; import com.axonivy.market.model.ProductModel; import com.axonivy.market.service.ProductService; @@ -24,7 +23,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.HttpClientErrorException; import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; import static com.axonivy.market.constants.RequestMappingConstants.SYNC; @@ -61,7 +59,8 @@ public ResponseEntity> findProducts(@RequestParam(name } @PutMapping(SYNC) - public ResponseEntity syncProducts(@RequestHeader(value = "Authorization") String authorizationHeader, @RequestParam("resetSync") boolean resetSync) { + public ResponseEntity syncProducts(@RequestHeader(value = "Authorization") String authorizationHeader, + @RequestParam(value = "resetSync", required = false) boolean resetSync) { String token = null; if (authorizationHeader.startsWith("Bearer ")) { token = authorizationHeader.substring(7); // Remove "Bearer " prefix diff --git a/marketplace-service/src/main/java/com/axonivy/market/entity/Product.java b/marketplace-service/src/main/java/com/axonivy/market/entity/Product.java index ea1964863..a760e0e85 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/entity/Product.java +++ b/marketplace-service/src/main/java/com/axonivy/market/entity/Product.java @@ -1,25 +1,23 @@ package com.axonivy.market.entity; -import static com.axonivy.market.constants.EntityConstants.PRODUCT; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; - import com.axonivy.market.github.model.MavenArtifact; import com.fasterxml.jackson.annotation.JsonProperty; - import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static com.axonivy.market.constants.EntityConstants.PRODUCT; @Getter @Setter diff --git a/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/UnauthorizedException.java b/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/UnauthorizedException.java index 6a557a88f..e84dd49e8 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/UnauthorizedException.java +++ b/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/UnauthorizedException.java @@ -1,6 +1,5 @@ package com.axonivy.market.exceptions.model; -import com.axonivy.market.enums.ErrorCode; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; diff --git a/marketplace-service/src/main/java/com/axonivy/market/factory/ProductFactory.java b/marketplace-service/src/main/java/com/axonivy/market/factory/ProductFactory.java index 034f26594..d687c1577 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/factory/ProductFactory.java +++ b/marketplace-service/src/main/java/com/axonivy/market/factory/ProductFactory.java @@ -1,31 +1,29 @@ package com.axonivy.market.factory; -import static com.axonivy.market.constants.CommonConstants.LOGO_FILE; -import static com.axonivy.market.constants.CommonConstants.SLASH; -import static com.axonivy.market.constants.MetaConstants.DEFAULT_VENDOR_NAME; -import static com.axonivy.market.constants.MetaConstants.DEFAULT_VENDOR_URL; -import static com.axonivy.market.constants.MetaConstants.META_FILE; -import static org.apache.commons.lang3.StringUtils.EMPTY; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.kohsuke.github.GHContent; -import org.springframework.util.CollectionUtils; - import com.axonivy.market.entity.Product; import com.axonivy.market.github.model.Meta; import com.axonivy.market.github.util.GitHubUtils; import com.axonivy.market.model.DisplayValue; import com.fasterxml.jackson.databind.ObjectMapper; - import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.kohsuke.github.GHContent; +import org.springframework.util.CollectionUtils; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.axonivy.market.constants.CommonConstants.LOGO_FILE; +import static com.axonivy.market.constants.CommonConstants.SLASH; +import static com.axonivy.market.constants.MetaConstants.DEFAULT_VENDOR_NAME; +import static com.axonivy.market.constants.MetaConstants.DEFAULT_VENDOR_URL; +import static com.axonivy.market.constants.MetaConstants.META_FILE; +import static org.apache.commons.lang3.StringUtils.EMPTY; @Log4j2 @NoArgsConstructor(access = AccessLevel.PRIVATE) diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GHAxonIvyProductRepoServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GHAxonIvyProductRepoServiceImpl.java index 033503792..7a2916da3 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GHAxonIvyProductRepoServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GHAxonIvyProductRepoServiceImpl.java @@ -1,24 +1,5 @@ package com.axonivy.market.github.service.impl; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.util.Strings; -import org.kohsuke.github.GHContent; -import org.kohsuke.github.GHOrganization; -import org.kohsuke.github.GHRepository; -import org.kohsuke.github.GHTag; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - import com.axonivy.market.constants.CommonConstants; import com.axonivy.market.constants.GitHubConstants; import com.axonivy.market.constants.MavenConstants; @@ -34,8 +15,25 @@ import com.axonivy.market.github.util.GitHubUtils; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; - import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.util.Strings; +import org.kohsuke.github.GHContent; +import org.kohsuke.github.GHOrganization; +import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GHTag; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Log4j2 @Service diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java b/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java index 5a1f31237..26ffb7260 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java @@ -6,7 +6,6 @@ import lombok.NoArgsConstructor; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; -import org.bson.json.JsonObject; import org.kohsuke.github.GHCommit; import org.kohsuke.github.GHContent; import org.kohsuke.github.PagedIterable; diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/ProductModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/ProductModel.java index fba99e845..1eeb4f3bc 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/ProductModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/ProductModel.java @@ -1,19 +1,17 @@ package com.axonivy.market.model; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.springframework.hateoas.RepresentationModel; -import org.springframework.hateoas.server.core.Relation; - import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; - import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.server.core.Relation; + +import java.util.List; +import java.util.Map; @Getter @Setter diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java index 00f7a129d..cf1c86090 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java @@ -1,37 +1,5 @@ package com.axonivy.market.service.impl; -import static java.util.Optional.ofNullable; -import static org.apache.commons.lang3.StringUtils.EMPTY; - -import java.io.IOException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.util.Strings; -import org.kohsuke.github.GHCommit; -import org.kohsuke.github.GHContent; -import org.kohsuke.github.GHRepository; -import org.kohsuke.github.GHTag; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Order; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - import com.axonivy.market.constants.CommonConstants; import com.axonivy.market.constants.GitHubConstants; import com.axonivy.market.entity.GitHubRepoMeta; @@ -51,8 +19,38 @@ import com.axonivy.market.service.ProductService; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; - import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.util.Strings; +import org.kohsuke.github.GHCommit; +import org.kohsuke.github.GHContent; +import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GHTag; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Order; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static java.util.Optional.ofNullable; +import static org.apache.commons.lang3.StringUtils.EMPTY; @Log4j2 @Service From 2b8a409604841f6ac9ff9c7b82a7301fb0cc9204 Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Mon, 22 Jul 2024 12:37:40 +0700 Subject: [PATCH 04/15] Add unit tests --- .../service/impl/GitHubServiceImpl.java | 8 +- .../controller/ProductControllerTest.java | 75 ++++++++++++++----- .../market/service/GitHubServiceImplTest.java | 9 +-- 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java index 822780af8..d0711c41e 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java @@ -151,7 +151,7 @@ public void validateUserOrganization(String accessToken, String organization) th + "-User must be a member of the Axon Ivy Market Organization"); } - private List> getUserOrganizations(String accessToken) throws UnauthorizedException { + public List> getUserOrganizations(String accessToken) throws UnauthorizedException { HttpHeaders headers = new HttpHeaders(); headers.setBearerAuth(accessToken); HttpEntity entity = new HttpEntity<>(headers); @@ -160,10 +160,10 @@ private List> getUserOrganizations(String accessToken) throw HttpMethod.GET, entity, new ParameterizedTypeReference<>() { }); return response.getBody(); - } - catch (HttpClientErrorException exception) { + } catch (HttpClientErrorException exception) { throw new UnauthorizedException(ErrorCode.GITHUB_USER_UNAUTHORIZED.getCode(), - ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText() + "-" + GitHubUtils.extractMessageFromExceptionMessage(exception.getMessage())); + ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText() + "-" + GitHubUtils.extractMessageFromExceptionMessage( + exception.getMessage())); } } } \ No newline at end of file diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductControllerTest.java index fa5c2ff4e..9152a506f 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductControllerTest.java @@ -1,14 +1,14 @@ package com.axonivy.market.controller; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import com.axonivy.market.assembler.ProductModelAssembler; +import com.axonivy.market.entity.Product; +import com.axonivy.market.enums.ErrorCode; +import com.axonivy.market.enums.Language; +import com.axonivy.market.enums.SortOption; +import com.axonivy.market.enums.TypeOption; +import com.axonivy.market.exceptions.model.UnauthorizedException; +import com.axonivy.market.github.service.GitHubService; +import com.axonivy.market.service.ProductService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -25,14 +25,16 @@ import org.springframework.hateoas.PagedModel.PageMetadata; import org.springframework.http.HttpStatus; -import com.axonivy.market.assembler.ProductModelAssembler; -import com.axonivy.market.entity.Product; -import com.axonivy.market.enums.ErrorCode; -import com.axonivy.market.enums.Language; -import com.axonivy.market.enums.SortOption; -import com.axonivy.market.enums.TypeOption; -import com.axonivy.market.model.ProductRating; -import com.axonivy.market.service.ProductService; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class ProductControllerTest { @@ -40,6 +42,8 @@ class ProductControllerTest { private static final String PRODUCT_NAME_DE_SAMPLE = "Amazon Comprehend DE"; private static final String PRODUCT_DESC_SAMPLE = "Amazon Comprehend is a AI service that uses machine learning to uncover information in unstructured data."; private static final String PRODUCT_DESC_DE_SAMPLE = "Amazon Comprehend is a AI service that uses machine learning to uncover information in unstructured data. DE"; + private static final String AUTHORIZATION_HEADER = "Bearer valid_token"; + private static final String INVALID_AUTHORIZATION_HEADER = "Bearer invalid_token"; @Mock private ProductService service; @@ -53,6 +57,9 @@ class ProductControllerTest { @Mock private PagedModel pagedProductModel; + @Mock + private GitHubService gitHubService; + @InjectMocks private ProductController productController; @@ -95,11 +102,41 @@ void testFindProducts() { } @Test - void testSyncProducts() { - var response = productController.syncProducts(); + void testSyncProductsSuccess() { + when(service.syncLatestDataFromMarketRepo()).thenReturn(true); + + var response = productController.syncProducts(AUTHORIZATION_HEADER, false); + + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertTrue(response.hasBody()); + assertEquals(ErrorCode.SUCCESSFUL.getCode(), response.getBody().getHelpCode()); + assertEquals("Data is already up to date, nothing to sync", response.getBody().getMessageDetails()); + } + + @Test + void testSyncProductsWithResetSuccess() { + // Mocking the dependencies for success case with resetSync = true + when(service.syncLatestDataFromMarketRepo()).thenReturn(false); + + var response = productController.syncProducts(AUTHORIZATION_HEADER, false); + assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue(response.hasBody()); assertEquals(ErrorCode.SUCCESSFUL.getCode(), response.getBody().getHelpCode()); + assertTrue(response.getBody().getMessageDetails().contains("Finished sync data")); + } + + @Test + void testSyncProductsInvalidToken() { + doThrow(new UnauthorizedException(ErrorCode.GITHUB_USER_UNAUTHORIZED.getCode(), + ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText())).when(gitHubService) + .validateUserOrganization(any(String.class), any(String.class)); + + UnauthorizedException exception = assertThrows(UnauthorizedException.class, () -> { + productController.syncProducts(INVALID_AUTHORIZATION_HEADER, false); + }); + + assertEquals(ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText(), exception.getMessage()); } private Product createProductMock() { diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java index c4e0c07ea..6270e4e4b 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java @@ -1,7 +1,6 @@ package com.axonivy.market.service; import com.axonivy.market.github.service.impl.GitHubServiceImpl; -import com.axonivy.market.repository.UserRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -23,13 +22,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; + @ExtendWith(MockitoExtension.class) class GitHubServiceImplTest { private static final String DUMMY_API_URL = "https://api.github.com"; - @Mock - GitHub gitHub; - @Mock GHRepository ghRepository; @@ -39,16 +36,12 @@ class GitHubServiceImplTest { @Mock private RestTemplate restTemplate; - @Mock - private UserRepository userRepository; - @InjectMocks private GitHubServiceImpl gitHubService; @BeforeEach public void setUp() { MockitoAnnotations.openMocks(this); - // Use lenient stubbing lenient().when(restTemplateBuilder.build()).thenReturn(restTemplate); } From 22daa94735c125201cad8298bf2db6d079a666a2 Mon Sep 17 00:00:00 2001 From: ndkhanh-axonivy Date: Mon, 22 Jul 2024 20:18:13 +0700 Subject: [PATCH 05/15] Handle conflict --- .../market/controller/ProductController.java | 21 ++-------- .../service/impl/GitHubServiceImpl.java | 38 +++++-------------- 2 files changed, 13 insertions(+), 46 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 385c7667e..c69417aa1 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -9,9 +9,6 @@ import com.axonivy.market.model.ProductModel; import com.axonivy.market.service.ProductService; import io.swagger.v3.oas.annotations.Operation; -import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; -import static com.axonivy.market.constants.RequestMappingConstants.SYNC; - import org.apache.commons.lang3.time.StopWatch; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -20,22 +17,10 @@ import org.springframework.hateoas.PagedModel; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import com.axonivy.market.assembler.ProductModelAssembler; -import com.axonivy.market.entity.Product; -import com.axonivy.market.enums.ErrorCode; -import com.axonivy.market.model.Message; -import com.axonivy.market.model.ProductModel; -import com.axonivy.market.service.ProductService; - -import io.swagger.v3.oas.annotations.Operation; +import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; +import static com.axonivy.market.constants.RequestMappingConstants.SYNC; @RestController @RequestMapping(PRODUCT) diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java index 19b105dc4..46c5e8c03 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GitHubServiceImpl.java @@ -1,13 +1,5 @@ package com.axonivy.market.github.service.impl; -import static org.apache.commons.lang3.StringUtils.EMPTY; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; - import com.axonivy.market.constants.GitHubConstants; import com.axonivy.market.entity.User; import com.axonivy.market.enums.ErrorCode; @@ -15,38 +7,28 @@ import com.axonivy.market.exceptions.model.Oauth2ExchangeCodeException; import com.axonivy.market.exceptions.model.UnauthorizedException; import com.axonivy.market.github.model.GitHubAccessTokenResponse; +import com.axonivy.market.github.model.GitHubProperty; import com.axonivy.market.github.service.GitHubService; import com.axonivy.market.github.util.GitHubUtils; import com.axonivy.market.repository.UserRepository; -import org.kohsuke.github.GHContent; -import org.kohsuke.github.GHOrganization; -import org.kohsuke.github.GHRepository; -import org.kohsuke.github.GitHub; -import org.kohsuke.github.GitHubBuilder; +import org.kohsuke.github.*; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.util.ResourceUtils; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; -import com.axonivy.market.constants.GitHubConstants; -import com.axonivy.market.entity.User; -import com.axonivy.market.enums.ErrorCode; -import com.axonivy.market.exceptions.model.NotFoundException; -import com.axonivy.market.exceptions.model.Oauth2ExchangeCodeException; -import com.axonivy.market.github.model.GitHubProperty; -import com.axonivy.market.github.service.GitHubService; -import com.axonivy.market.model.GitHubAccessTokenResponse; -import com.axonivy.market.repository.UserRepository; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.apache.commons.lang3.StringUtils.EMPTY; @Service public class GitHubServiceImpl implements GitHubService { From 86859afe2095358c3dcaa5fa8682305321b0717d Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Wed, 24 Jul 2024 17:10:01 +0700 Subject: [PATCH 06/15] Add unit tests --- .../service/impl/FeedbackServiceImpl.java | 4 +- .../service/FeedbackServiceImplTest.java | 315 +++++++++++------- .../market/service/GitHubServiceImplTest.java | 35 +- .../market/service/UserServiceImplTest.java | 92 +++-- 4 files changed, 287 insertions(+), 159 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/impl/FeedbackServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/service/impl/FeedbackServiceImpl.java index 4305fe0e8..77e007e1b 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/impl/FeedbackServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/impl/FeedbackServiceImpl.java @@ -96,13 +96,13 @@ public List getProductRatingById(String productId) { }).toList(); } - private void validateProductExists(String productId) throws NotFoundException { + public void validateProductExists(String productId) throws NotFoundException { if (productRepository.findById(productId).isEmpty()) { throw new NotFoundException(ErrorCode.PRODUCT_NOT_FOUND, "Not found product with id: " + productId); } } - private void validateUserExists(String userId) { + public void validateUserExists(String userId) { if (userRepository.findById(userId).isEmpty()) { throw new NotFoundException(ErrorCode.USER_NOT_FOUND, "Not found user with id: " + userId); } diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java index 5237742c3..1f70286ae 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java @@ -1,7 +1,9 @@ package com.axonivy.market.service; import com.axonivy.market.entity.Feedback; +import com.axonivy.market.entity.Product; import com.axonivy.market.entity.User; +import com.axonivy.market.enums.ErrorCode; import com.axonivy.market.exceptions.model.NotFoundException; import com.axonivy.market.model.FeedbackModel; import com.axonivy.market.model.ProductRating; @@ -15,19 +17,17 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class FeedbackServiceImplTest { @@ -44,167 +44,230 @@ class FeedbackServiceImplTest { @InjectMocks private FeedbackServiceImpl feedbackService; + private Feedback feedback; + private FeedbackModel feedbackModel; + @BeforeEach void setUp() { - // Mock initialization or setup if needed + feedback = new Feedback(); + feedback.setId("1"); + feedback.setUserId("user1"); + feedback.setProductId("product1"); + feedback.setRating(5); + feedback.setContent("Great product!"); + + feedbackModel = new FeedbackModel(); + feedbackModel.setUserId("user1"); + feedbackModel.setProductId("product1"); + feedbackModel.setRating(5); + feedbackModel.setContent("Great product!"); } @Test - void testFindFeedbacks_ProductNotFound() { - String productId = "nonExistingProduct"; + void testFindFeedbacks() throws NotFoundException { + String productId = "product1"; + Pageable pageable = PageRequest.of(0, 10); + Page page = new PageImpl<>(Collections.singletonList(feedback)); - when(productRepository.findById(productId)).thenReturn(Optional.empty()); + when(productRepository.findById(productId)).thenReturn(Optional.of(new Product())); + when(feedbackRepository.searchByProductId(productId, pageable)).thenReturn(page); - Pageable unpaged = Pageable.unpaged(); + Page result = feedbackService.findFeedbacks(productId, pageable); + assertNotNull(result); + assertEquals(1, result.getTotalElements()); + verify(productRepository, times(1)).findById(productId); + verify(feedbackRepository, times(1)).searchByProductId(productId, pageable); + } - assertThrows(NotFoundException.class, () -> feedbackService.findFeedbacks(productId, unpaged)); + @Test + void testFindFeedbacks_ProductNotFound() { + String productId = "product1"; + Pageable pageable = PageRequest.of(0, 10); + when(productRepository.findById(productId)).thenReturn(Optional.empty()); + + NotFoundException exception = assertThrows(NotFoundException.class, () -> { + feedbackService.findFeedbacks(productId, pageable); + }); + assertEquals(ErrorCode.PRODUCT_NOT_FOUND.getCode(), exception.getCode()); verify(productRepository, times(1)).findById(productId); - verify(feedbackRepository, never()).searchByProductId(any(), any()); + verify(feedbackRepository, times(0)).searchByProductId(productId, pageable); } @Test - void testFindFeedback_Success() throws NotFoundException { - // Mock data - String feedbackId = "feedback123"; - Feedback mockFeedback = new Feedback(); - mockFeedback.setId(feedbackId); + void testFindFeedback() throws NotFoundException { + String feedbackId = "1"; - // Mock behavior - when(feedbackRepository.findById(feedbackId)).thenReturn(Optional.of(mockFeedback)); + when(feedbackRepository.findById(feedbackId)).thenReturn(Optional.of(feedback)); - // Test method Feedback result = feedbackService.findFeedback(feedbackId); - - // Verify - assertEquals(mockFeedback, result); + assertNotNull(result); + assertEquals(feedbackId, result.getId()); verify(feedbackRepository, times(1)).findById(feedbackId); } @Test void testFindFeedback_NotFound() { - // Mock data - String nonExistingId = "nonExistingFeedbackId"; - - // Mock behavior - when(feedbackRepository.findById(nonExistingId)).thenReturn(Optional.empty()); + String feedbackId = "1"; - // Test and verify exception - assertThrows(NotFoundException.class, () -> feedbackService.findFeedback(nonExistingId)); + when(feedbackRepository.findById(feedbackId)).thenReturn(Optional.empty()); - // Verify interactions - verify(feedbackRepository, times(1)).findById(nonExistingId); + NotFoundException exception = assertThrows(NotFoundException.class, () -> { + feedbackService.findFeedback(feedbackId); + }); + assertEquals(ErrorCode.FEEDBACK_NOT_FOUND.getCode(), exception.getCode()); + verify(feedbackRepository, times(1)).findById(feedbackId); } @Test - void testFindFeedbackByUserIdAndProductId_UserNotFound() { - // Mock data - String nonExistingUserId = "nonExistingUser"; - String productId = "product123"; + void testFindFeedbackByUserIdAndProductId() throws NotFoundException { + String userId = "user1"; + String productId = "product1"; + + when(userRepository.findById(userId)).thenReturn(Optional.of(new User())); + when(productRepository.findById(productId)).thenReturn(Optional.of(new Product())); + when(feedbackRepository.findByUserIdAndProductId(userId, productId)).thenReturn(feedback); + + Feedback result = feedbackService.findFeedbackByUserIdAndProductId(userId, productId); + assertNotNull(result); + assertEquals(userId, result.getUserId()); + assertEquals(productId, result.getProductId()); + verify(userRepository, times(1)).findById(userId); + verify(productRepository, times(1)).findById(productId); + verify(feedbackRepository, times(1)).findByUserIdAndProductId(userId, productId); + } - // Mock behavior - when(userRepository.findById(nonExistingUserId)).thenReturn(Optional.empty()); + @Test + void testFindFeedbackByUserIdAndProductId_NotFound() { + String userId = "user1"; + String productId = "product1"; - // Test and verify exception - assertThrows(NotFoundException.class, - () -> feedbackService.findFeedbackByUserIdAndProductId(nonExistingUserId, productId)); + when(userRepository.findById(userId)).thenReturn(Optional.of(new User())); + when(productRepository.findById(productId)).thenReturn(Optional.of(new Product())); + when(feedbackRepository.findByUserIdAndProductId(userId, productId)).thenReturn(null); - // Verify interactions - verify(userRepository, times(1)).findById(nonExistingUserId); - verify(feedbackRepository, never()).findByUserIdAndProductId(any(), any()); + NotFoundException exception = assertThrows(NotFoundException.class, () -> { + feedbackService.findFeedbackByUserIdAndProductId(userId, productId); + }); + assertEquals(ErrorCode.FEEDBACK_NOT_FOUND.getCode(), exception.getCode()); + verify(userRepository, times(1)).findById(userId); + verify(productRepository, times(1)).findById(productId); + verify(feedbackRepository, times(1)).findByUserIdAndProductId(userId, productId); } @Test - void testUpsertFeedback_NewFeedback() throws NotFoundException { - // Mock data - FeedbackModel newFeedbackModel = new FeedbackModel(); - newFeedbackModel.setUserId("user123"); - newFeedbackModel.setProductId("product123"); - newFeedbackModel.setContent("Great product!"); - newFeedbackModel.setRating(5); - - Feedback newFeedback = new Feedback(); - newFeedback.setUserId(newFeedbackModel.getUserId()); - newFeedback.setProductId(newFeedbackModel.getProductId()); - newFeedback.setContent(newFeedbackModel.getContent()); - newFeedback.setRating(newFeedbackModel.getRating()); - - User u = new User(); - u.setId(newFeedbackModel.getUserId()); - when(userRepository.findById(newFeedbackModel.getUserId())).thenReturn(Optional.of(u)); - when(feedbackRepository.findByUserIdAndProductId(newFeedbackModel.getUserId(), - newFeedbackModel.getProductId())).thenReturn(null); - when(feedbackRepository.save(any(Feedback.class))).thenReturn(newFeedback); - - // Test method - Feedback result = feedbackService.upsertFeedback(newFeedbackModel); - - // Verify - assertEquals(newFeedback, result); + void testUpsertFeedback_Insert() throws NotFoundException { + String userId = "user1"; + String productId = "product1"; + + when(userRepository.findById(userId)).thenReturn(Optional.of(new User())); + when(feedbackRepository.findByUserIdAndProductId(userId, productId)).thenReturn(null); + when(feedbackRepository.save(any(Feedback.class))).thenReturn(feedback); + + Feedback result = feedbackService.upsertFeedback(feedbackModel); + assertNotNull(result); + assertEquals(feedbackModel.getUserId(), result.getUserId()); + assertEquals(feedbackModel.getProductId(), result.getProductId()); + assertEquals(feedbackModel.getRating(), result.getRating()); + assertEquals(feedbackModel.getContent(), result.getContent()); + verify(userRepository, times(1)).findById(userId); + verify(feedbackRepository, times(1)).findByUserIdAndProductId(userId, productId); + verify(feedbackRepository, times(1)).save(any(Feedback.class)); } @Test - void testUpsertFeedback_UpdateFeedback() throws NotFoundException { - // Mock data - FeedbackModel existingFeedbackModel = new FeedbackModel(); - existingFeedbackModel.setId("existingFeedback123"); - existingFeedbackModel.setUserId("user123"); - existingFeedbackModel.setProductId("product123"); - existingFeedbackModel.setContent("Good product! Very well!"); - existingFeedbackModel.setRating(5); - - Feedback existingFeedback = new Feedback(); - existingFeedback.setId("existingFeedback123"); - existingFeedback.setUserId("user123"); - existingFeedback.setProductId("product123"); - existingFeedback.setContent("Bad product!"); - existingFeedback.setRating(1); - - User u = new User(); - u.setId(existingFeedback.getUserId()); - when(userRepository.findById(existingFeedback.getUserId())).thenReturn(Optional.of(u)); - when(feedbackRepository.findByUserIdAndProductId(existingFeedback.getUserId(), - existingFeedback.getProductId())).thenReturn(existingFeedback); - when(feedbackRepository.save(existingFeedback)).thenReturn(existingFeedback); - - // Test method - Feedback updatedFeedback = new Feedback(); - updatedFeedback.setId(existingFeedback.getId()); - updatedFeedback.setUserId(existingFeedback.getUserId()); - updatedFeedback.setProductId(existingFeedback.getProductId()); - updatedFeedback.setContent("Good product! Very well!"); - updatedFeedback.setRating(5); - - Feedback result = feedbackService.upsertFeedback(existingFeedbackModel); - - // Verify - assertEquals(updatedFeedback.getId(), result.getId()); - assertEquals(updatedFeedback.getContent(), result.getContent()); - assertEquals(updatedFeedback.getRating(), result.getRating()); - verify(userRepository, times(1)).findById(existingFeedback.getUserId()); - verify(feedbackRepository, times(1)).findByUserIdAndProductId(existingFeedback.getUserId(), - existingFeedback.getProductId()); - verify(feedbackRepository, times(1)).save(existingFeedback); + void testUpsertFeedback_Update() throws NotFoundException { + String userId = "user1"; + String productId = "product1"; + + when(userRepository.findById(userId)).thenReturn(Optional.of(new User())); + when(feedbackRepository.findByUserIdAndProductId(userId, productId)).thenReturn(feedback); + when(feedbackRepository.save(any(Feedback.class))).thenReturn(feedback); + + Feedback result = feedbackService.upsertFeedback(feedbackModel); + assertNotNull(result); + assertEquals(feedbackModel.getUserId(), result.getUserId()); + assertEquals(feedbackModel.getProductId(), result.getProductId()); + assertEquals(feedbackModel.getRating(), result.getRating()); + assertEquals(feedbackModel.getContent(), result.getContent()); + verify(userRepository, times(1)).findById(userId); + verify(feedbackRepository, times(1)).findByUserIdAndProductId(userId, productId); + verify(feedbackRepository, times(1)).save(any(Feedback.class)); } @Test - void testGetProductRatingById_NoFeedbacks() { - // Mock data - String productId = "product123"; + void testGetProductRatingById() { + String productId = "product1"; + List feedbacks = Collections.singletonList(feedback); + + when(feedbackRepository.findByProductId(productId)).thenReturn(feedbacks); + + List ratings = feedbackService.getProductRatingById(productId); + assertNotNull(ratings); + assertEquals(5, ratings.size()); + assertEquals(1, ratings.get(4).getCommentNumber()); + assertEquals(100, ratings.get(4).getPercent()); + verify(feedbackRepository, times(1)).findByProductId(productId); + } - // Mock behavior - when(feedbackRepository.findByProductId(productId)).thenReturn(new ArrayList<>()); + void testGetProductRatingById_NoFeedbacks() { + String productId = "product1"; - // Test method - List result = feedbackService.getProductRatingById(productId); + when(feedbackRepository.findByProductId(productId)).thenReturn(Collections.emptyList()); - // Verify - assertEquals(5, result.size()); // Expect ratings for stars 1 to 5 - result.forEach(rating -> { + List ratings = feedbackService.getProductRatingById(productId); + assertNotNull(ratings); + assertEquals(5, ratings.size()); + for (ProductRating rating : ratings) { assertEquals(0, rating.getCommentNumber()); assertEquals(0, rating.getPercent()); - }); + } verify(feedbackRepository, times(1)).findByProductId(productId); } -} + @Test + void testValidateProductExists() { + String productId = "product1"; + + when(productRepository.findById(productId)).thenReturn(Optional.of(new Product())); + + assertDoesNotThrow(() -> feedbackService.validateProductExists(productId)); + verify(productRepository, times(1)).findById(productId); + } + + @Test + void testValidateProductExists_NotFound() { + String productId = "product1"; + + when(productRepository.findById(productId)).thenReturn(Optional.empty()); + + NotFoundException exception = assertThrows(NotFoundException.class, () -> { + feedbackService.validateProductExists(productId); + }); + assertEquals(ErrorCode.PRODUCT_NOT_FOUND.getCode(), exception.getCode()); + verify(productRepository, times(1)).findById(productId); + } + + @Test + void testValidateUserExists() { + String userId = "user1"; + + when(userRepository.findById(userId)).thenReturn(Optional.of(new User())); + + assertDoesNotThrow(() -> feedbackService.validateUserExists(userId)); + verify(userRepository, times(1)).findById(userId); + } + + @Test + void testValidateUserExists_NotFound() { + String userId = "user1"; + + when(userRepository.findById(userId)).thenReturn(Optional.empty()); + + NotFoundException exception = assertThrows(NotFoundException.class, () -> { + feedbackService.validateUserExists(userId); + }); + assertEquals(ErrorCode.USER_NOT_FOUND.getCode(), exception.getCode()); + verify(userRepository, times(1)).findById(userId); + } +} \ No newline at end of file diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java index 6270e4e4b..3252094f4 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java @@ -1,5 +1,7 @@ package com.axonivy.market.service; +import com.axonivy.market.constants.GitHubConstants; +import com.axonivy.market.github.model.GitHubAccessTokenResponse; import com.axonivy.market.github.service.impl.GitHubServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -12,11 +14,20 @@ import org.mockito.MockitoAnnotations; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.io.IOException; +import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; @@ -42,7 +53,7 @@ class GitHubServiceImplTest { @BeforeEach public void setUp() { MockitoAnnotations.openMocks(this); - lenient().when(restTemplateBuilder.build()).thenReturn(restTemplate); + when(restTemplateBuilder.build()).thenReturn(restTemplate); } @Test @@ -66,4 +77,26 @@ void testGetDirectoryContent() throws IOException { var result = gitHubService.getDirectoryContent(ghRepository, "", ""); assertEquals(0, result.size()); } + + @Test + void testGetAccessToken() { + String code = "code"; + String clientId = "clientId"; + String clientSecret = "clientSecret"; + + GitHubAccessTokenResponse tokenResponse = new GitHubAccessTokenResponse(); + tokenResponse.setAccessToken("accessToken"); + + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + HttpEntity> request = new HttpEntity<>(new LinkedMultiValueMap<>(), headers); + + when(restTemplate.postForEntity(GitHubConstants.GITHUB_GET_ACCESS_TOKEN_URL, request, GitHubAccessTokenResponse.class)) + .thenReturn(new ResponseEntity<>(tokenResponse, HttpStatus.OK)); + + GitHubAccessTokenResponse result = gitHubService.getAccessToken(code, clientId, clientSecret); + assertNotNull(result); + assertEquals(tokenResponse.getAccessToken(), result.getAccessToken()); + } + } diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java index dd786a093..457378568 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java @@ -1,55 +1,87 @@ -package com.axonivy.market.service; +package com.axonivy.market.service.impl; import com.axonivy.market.entity.User; +import com.axonivy.market.enums.ErrorCode; +import com.axonivy.market.exceptions.model.NotFoundException; import com.axonivy.market.repository.UserRepository; -import com.axonivy.market.service.impl.UserServiceImpl; -import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.Collections; import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class UserServiceImplTest { - @InjectMocks - private UserServiceImpl employeeService; - @Mock private UserRepository userRepository; + @InjectMocks + private UserServiceImpl userService; + + private User user; + + @BeforeEach + void setUp() { + user = new User(); + user.setId("1"); + user.setName("John Doe"); + user.setUsername("john.doe@example.com"); + } + @Test - void testFindAllUser() { - // Mock data and service - User mockUser = new User(); - mockUser.setId("123"); - mockUser.setName("tvtTest"); - List mockResultReturn = List.of(mockUser); - Mockito.when(userRepository.findAll()).thenReturn(mockResultReturn); - - // exercise - List result = employeeService.getAllUsers(); - - // Verify - Assertions.assertEquals(result, mockResultReturn); + void testGetAllUsers() { + when(userRepository.findAll()).thenReturn(Collections.singletonList(user)); + + List result = userService.getAllUsers(); + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(user.getId(), result.get(0).getId()); + verify(userRepository, times(1)).findAll(); } @Test - void testCreateUser() { - // Mock data - User mockUser = new User(); - mockUser.setId("123"); - mockUser.setName("tvtTest"); - Mockito.when(userRepository.save(mockUser)).thenReturn(mockUser); + void testFindUser() throws NotFoundException { + String userId = "1"; - // Exercise - User result = employeeService.createUser(mockUser); + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + + User result = userService.findUser(userId); + assertNotNull(result); + assertEquals(userId, result.getId()); + verify(userRepository, times(1)).findById(userId); + } + + @Test + void testFindUser_NotFound() { + String userId = "1"; + + when(userRepository.findById(userId)).thenReturn(Optional.empty()); + + NotFoundException exception = assertThrows(NotFoundException.class, () -> { + userService.findUser(userId); + }); + assertEquals(ErrorCode.USER_NOT_FOUND.getCode(), exception.getCode()); + verify(userRepository, times(1)).findById(userId); + } + + @Test + void testCreateUser() { + when(userRepository.save(any(User.class))).thenReturn(user); - // Verify - Assertions.assertEquals(result, mockUser); + User result = userService.createUser(user); + assertNotNull(result); + assertEquals(user.getId(), result.getId()); + assertEquals(user.getName(), result.getName()); + assertEquals(user.getUsername(), result.getUsername()); + verify(userRepository, times(1)).save(user); } } From a28cf7f294289cfd8995496cc3e30fec4924353e Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Thu, 25 Jul 2024 16:05:20 +0700 Subject: [PATCH 07/15] Update GitHubServiceImplTest.java --- .../market/service/GitHubServiceImplTest.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java index 3252094f4..f0185c972 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java @@ -77,26 +77,4 @@ void testGetDirectoryContent() throws IOException { var result = gitHubService.getDirectoryContent(ghRepository, "", ""); assertEquals(0, result.size()); } - - @Test - void testGetAccessToken() { - String code = "code"; - String clientId = "clientId"; - String clientSecret = "clientSecret"; - - GitHubAccessTokenResponse tokenResponse = new GitHubAccessTokenResponse(); - tokenResponse.setAccessToken("accessToken"); - - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - HttpEntity> request = new HttpEntity<>(new LinkedMultiValueMap<>(), headers); - - when(restTemplate.postForEntity(GitHubConstants.GITHUB_GET_ACCESS_TOKEN_URL, request, GitHubAccessTokenResponse.class)) - .thenReturn(new ResponseEntity<>(tokenResponse, HttpStatus.OK)); - - GitHubAccessTokenResponse result = gitHubService.getAccessToken(code, clientId, clientSecret); - assertNotNull(result); - assertEquals(tokenResponse.getAccessToken(), result.getAccessToken()); - } - } From bacb5ff1e1866140e0137d618020adafda269647 Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Thu, 25 Jul 2024 16:11:45 +0700 Subject: [PATCH 08/15] Update GitHubServiceImplTest.java --- .../java/com/axonivy/market/service/GitHubServiceImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java index f0185c972..afe25e7ce 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java @@ -53,7 +53,7 @@ class GitHubServiceImplTest { @BeforeEach public void setUp() { MockitoAnnotations.openMocks(this); - when(restTemplateBuilder.build()).thenReturn(restTemplate); + lenient().when(restTemplateBuilder.build()).thenReturn(restTemplate); } @Test From 74fed8bcb5721334dd132b25663242b96278b94f Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Thu, 25 Jul 2024 16:28:07 +0700 Subject: [PATCH 09/15] Update ProductController.java --- .../java/com/axonivy/market/controller/ProductController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index c69417aa1..747313764 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -55,7 +55,7 @@ public ResponseEntity> findProducts(@RequestParam(name @PutMapping(SYNC) public ResponseEntity syncProducts(@RequestHeader(value = "Authorization") String authorizationHeader, - @RequestParam(value = "resetSync", required = false) boolean resetSync) { + @RequestParam(value = "resetSync", required = false) Boolean resetSync) { String token = null; if (authorizationHeader.startsWith("Bearer ")) { token = authorizationHeader.substring(7); // Remove "Bearer " prefix From addd91a4e28df4c961276431d4284af48f9e7322 Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Thu, 25 Jul 2024 16:41:54 +0700 Subject: [PATCH 10/15] Update ProductController.java --- .../java/com/axonivy/market/controller/ProductController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 747313764..7f8b7d5cd 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -61,7 +61,7 @@ public ResponseEntity syncProducts(@RequestHeader(value = "Authorizatio token = authorizationHeader.substring(7); // Remove "Bearer " prefix } gitHubService.validateUserOrganization(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME); - if (resetSync) { + if (Boolean.TRUE.equals(resetSync)) { productService.clearAllProducts(); } From 5a84943530532a2c1a7336c561895d4fea1df411 Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 26 Jul 2024 15:30:44 +0700 Subject: [PATCH 11/15] Remove unused imports --- .../market/service/GitHubServiceImplTest.java | 12 ------------ .../axonivy/market/service/UserServiceImplTest.java | 12 +++++++++--- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java index afe25e7ce..b6703cdc7 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java @@ -1,33 +1,21 @@ package com.axonivy.market.service; -import com.axonivy.market.constants.GitHubConstants; -import com.axonivy.market.github.model.GitHubAccessTokenResponse; import com.axonivy.market.github.service.impl.GitHubServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kohsuke.github.GHContent; import org.kohsuke.github.GHRepository; -import org.kohsuke.github.GitHub; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.io.IOException; -import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java index 457378568..87729f91d 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java @@ -1,9 +1,10 @@ -package com.axonivy.market.service.impl; +package com.axonivy.market.service; import com.axonivy.market.entity.User; import com.axonivy.market.enums.ErrorCode; import com.axonivy.market.exceptions.model.NotFoundException; import com.axonivy.market.repository.UserRepository; +import com.axonivy.market.service.impl.UserServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -15,8 +16,13 @@ import java.util.List; import java.util.Optional; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class UserServiceImplTest { From 3ab6b76d1fb1316f284532b17ea817466c7b766e Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 26 Jul 2024 15:33:01 +0700 Subject: [PATCH 12/15] Revert "Remove unused imports" This reverts commit 5a84943530532a2c1a7336c561895d4fea1df411. --- .../market/service/GitHubServiceImplTest.java | 12 ++++++++++++ .../axonivy/market/service/UserServiceImplTest.java | 12 +++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java index b6703cdc7..afe25e7ce 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java @@ -1,21 +1,33 @@ package com.axonivy.market.service; +import com.axonivy.market.constants.GitHubConstants; +import com.axonivy.market.github.model.GitHubAccessTokenResponse; import com.axonivy.market.github.service.impl.GitHubServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kohsuke.github.GHContent; import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GitHub; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.io.IOException; +import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java index 87729f91d..457378568 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java @@ -1,10 +1,9 @@ -package com.axonivy.market.service; +package com.axonivy.market.service.impl; import com.axonivy.market.entity.User; import com.axonivy.market.enums.ErrorCode; import com.axonivy.market.exceptions.model.NotFoundException; import com.axonivy.market.repository.UserRepository; -import com.axonivy.market.service.impl.UserServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -16,13 +15,8 @@ import java.util.List; import java.util.Optional; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class UserServiceImplTest { From d333dc4b3862087d100818e10a55b80ef280448e Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 26 Jul 2024 16:03:07 +0700 Subject: [PATCH 13/15] Refactor code --- .../market/constants/CommonConstants.java | 1 + .../market/controller/FeedbackController.java | 5 +-- .../market/controller/ProductController.java | 5 +-- .../market/entity/MavenArtifactModel.java | 2 ++ .../market/entity/MavenArtifactVersion.java | 2 ++ .../com/axonivy/market/entity/Product.java | 2 ++ .../market/entity/ProductModuleContent.java | 2 ++ .../model/InvalidParamException.java | 3 ++ .../market/github/model/ArchivedArtifact.java | 2 ++ .../market/github/model/MavenArtifact.java | 2 ++ .../market/controller/AppControllerTest.java | 6 ++-- .../controller/FeedbackControllerTest.java | 11 +++--- .../controller/OAuth2ControllerTest.java | 2 +- .../controller/ProductControllerTest.java | 21 +++++------ .../ProductDetailsControllerTest.java | 2 -- .../market/factory/ProductFactoryTest.java | 12 ------- .../service/FeedbackServiceImplTest.java | 35 ++++++++++--------- .../GHAxonIvyMarketRepoServiceImplTest.java | 2 +- .../market/service/GitHubServiceImplTest.java | 12 ------- .../service/ProductServiceImplTest.java | 2 +- .../market/service/SchedulingTasksTest.java | 12 +++---- .../market/service/UserServiceImplTest.java | 7 ++-- 22 files changed, 70 insertions(+), 80 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/constants/CommonConstants.java b/marketplace-service/src/main/java/com/axonivy/market/constants/CommonConstants.java index 5f6eea10d..9785cc676 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/constants/CommonConstants.java +++ b/marketplace-service/src/main/java/com/axonivy/market/constants/CommonConstants.java @@ -14,4 +14,5 @@ public class CommonConstants { public static final String PLUS = "+"; public static final String DASH_SEPARATOR = "-"; public static final String SPACE_SEPARATOR = " "; + public static final String BEARER = "Bearer"; } diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index 22b61b65d..ce7a8e10a 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -1,6 +1,7 @@ package com.axonivy.market.controller; import com.axonivy.market.assembler.FeedbackModelAssembler; +import com.axonivy.market.constants.CommonConstants; import com.axonivy.market.entity.Feedback; import com.axonivy.market.model.FeedbackModel; import com.axonivy.market.model.ProductRating; @@ -82,8 +83,8 @@ public ResponseEntity findFeedbackByUserIdAndProductId(@RequestPa public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModel feedback, @RequestHeader(value = "Authorization") String authorizationHeader) { String token = null; - if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { - token = authorizationHeader.substring(7); // Remove "Bearer " prefix + if (authorizationHeader != null && authorizationHeader.startsWith(CommonConstants.BEARER)) { + token = authorizationHeader.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix } // Validate the token diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 7f8b7d5cd..2d4980d08 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -1,6 +1,7 @@ package com.axonivy.market.controller; import com.axonivy.market.assembler.ProductModelAssembler; +import com.axonivy.market.constants.CommonConstants; import com.axonivy.market.constants.GitHubConstants; import com.axonivy.market.entity.Product; import com.axonivy.market.enums.ErrorCode; @@ -57,8 +58,8 @@ public ResponseEntity> findProducts(@RequestParam(name public ResponseEntity syncProducts(@RequestHeader(value = "Authorization") String authorizationHeader, @RequestParam(value = "resetSync", required = false) Boolean resetSync) { String token = null; - if (authorizationHeader.startsWith("Bearer ")) { - token = authorizationHeader.substring(7); // Remove "Bearer " prefix + if (authorizationHeader.startsWith(CommonConstants.BEARER)) { + token = authorizationHeader.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix } gitHubService.validateUserOrganization(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME); if (Boolean.TRUE.equals(resetSync)) { diff --git a/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactModel.java b/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactModel.java index 1c9ad87ec..81a27e864 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactModel.java @@ -6,6 +6,7 @@ import lombok.Setter; import org.springframework.data.annotation.Transient; +import java.io.Serial; import java.io.Serializable; import java.util.Objects; @@ -14,6 +15,7 @@ @Setter @Getter public class MavenArtifactModel implements Serializable { + @Serial private static final long serialVersionUID = 1L; private String name; private String downloadUrl; diff --git a/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactVersion.java b/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactVersion.java index 8f2e87291..e7a6a2e92 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactVersion.java +++ b/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactVersion.java @@ -7,6 +7,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; @@ -21,6 +22,7 @@ @NoArgsConstructor @Document(MAVEN_ARTIFACT_VERSION) public class MavenArtifactVersion implements Serializable { + @Serial private static final long serialVersionUID = -6492612804634492078L; @Id diff --git a/marketplace-service/src/main/java/com/axonivy/market/entity/Product.java b/marketplace-service/src/main/java/com/axonivy/market/entity/Product.java index a760e0e85..c1ec15ded 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/entity/Product.java +++ b/marketplace-service/src/main/java/com/axonivy/market/entity/Product.java @@ -12,6 +12,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import java.io.Serial; import java.io.Serializable; import java.util.Date; import java.util.List; @@ -26,6 +27,7 @@ @Builder @Document(PRODUCT) public class Product implements Serializable { + @Serial private static final long serialVersionUID = -8770801877877277258L; @Id private String id; diff --git a/marketplace-service/src/main/java/com/axonivy/market/entity/ProductModuleContent.java b/marketplace-service/src/main/java/com/axonivy/market/entity/ProductModuleContent.java index f8df6160c..bc48a39ad 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/entity/ProductModuleContent.java +++ b/marketplace-service/src/main/java/com/axonivy/market/entity/ProductModuleContent.java @@ -5,6 +5,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; +import java.io.Serial; import java.io.Serializable; import java.util.Map; @@ -13,6 +14,7 @@ @NoArgsConstructor @AllArgsConstructor public class ProductModuleContent implements Serializable { + @Serial private static final long serialVersionUID = 1L; private String tag; private Map description; diff --git a/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/InvalidParamException.java b/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/InvalidParamException.java index 3cecdf03e..42f066651 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/InvalidParamException.java +++ b/marketplace-service/src/main/java/com/axonivy/market/exceptions/model/InvalidParamException.java @@ -4,9 +4,12 @@ import lombok.Getter; import lombok.Setter; +import java.io.Serial; + @Getter @Setter public class InvalidParamException extends NotFoundException { + @Serial private static final long serialVersionUID = 1L; public InvalidParamException(String code, String message) { diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/model/ArchivedArtifact.java b/marketplace-service/src/main/java/com/axonivy/market/github/model/ArchivedArtifact.java index 0bd450349..557a9e4ee 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/model/ArchivedArtifact.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/model/ArchivedArtifact.java @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; +import java.io.Serial; import java.io.Serializable; @Getter @@ -16,6 +17,7 @@ @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown = true) public class ArchivedArtifact implements Serializable { + @Serial private static final long serialVersionUID = 1L; private String lastVersion; private String groupId; diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/model/MavenArtifact.java b/marketplace-service/src/main/java/com/axonivy/market/github/model/MavenArtifact.java index 5c7cf3a37..61e1891e1 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/model/MavenArtifact.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/model/MavenArtifact.java @@ -8,6 +8,7 @@ import lombok.Setter; import org.springframework.data.annotation.Transient; +import java.io.Serial; import java.io.Serializable; import java.util.List; @@ -18,6 +19,7 @@ @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown = true) public class MavenArtifact implements Serializable { + @Serial private static final long serialVersionUID = 1L; private String repoUrl; private String name; diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/AppControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/AppControllerTest.java index 055b81d2c..27a62c6b8 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/AppControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/AppControllerTest.java @@ -6,6 +6,8 @@ import org.springframework.http.HttpStatus; import org.springframework.test.context.junit.jupiter.SpringExtension; +import java.util.Objects; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -16,10 +18,10 @@ class AppControllerTest { private AppController appController; @Test - void testRoot() throws Exception { + void testRoot() { var response = appController.root(); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue(response.hasBody()); - assertTrue(response.getBody().getMessageDetails().contains("/swagger-ui/index.html")); + assertTrue(Objects.requireNonNull(response.getBody()).getMessageDetails().contains("/swagger-ui/index.html")); } } \ No newline at end of file diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/FeedbackControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/FeedbackControllerTest.java index ea02160f9..1af06b839 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/FeedbackControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/FeedbackControllerTest.java @@ -25,6 +25,7 @@ import org.springframework.web.context.request.ServletRequestAttributes; import java.util.List; +import java.util.Objects; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -73,7 +74,7 @@ void testFindFeedbacksAsEmpty() { var result = feedbackController.findFeedbacks(PRODUCT_ID_SAMPLE, pageable); assertEquals(HttpStatus.OK, result.getStatusCode()); assertTrue(result.hasBody()); - assertEquals(0, result.getBody().getContent().size()); + assertEquals(0, Objects.requireNonNull(result.getBody()).getContent().size()); } @Test @@ -91,7 +92,7 @@ void testFindFeedbacks() { var result = feedbackController.findFeedbacks(PRODUCT_ID_SAMPLE, pageable); assertEquals(HttpStatus.OK, result.getStatusCode()); assertTrue(result.hasBody()); - assertEquals(1, result.getBody().getContent().size()); + assertEquals(1, Objects.requireNonNull(result.getBody()).getContent().size()); assertEquals(USER_NAME_SAMPLE, result.getBody().getContent().iterator().next().getUsername()); } @@ -104,7 +105,7 @@ void testFindFeedback() { var result = feedbackController.findFeedback(FEEDBACK_ID_SAMPLE); assertEquals(HttpStatus.OK, result.getStatusCode()); assertTrue(result.hasBody()); - assertEquals(USER_NAME_SAMPLE, result.getBody().getUsername()); + assertEquals(USER_NAME_SAMPLE, Objects.requireNonNull(result.getBody()).getUsername()); } @Test @@ -116,7 +117,7 @@ void testFindFeedbackByUserIdAndProductId() { var result = feedbackController.findFeedbackByUserIdAndProductId(USER_ID_SAMPLE, PRODUCT_ID_SAMPLE); assertEquals(HttpStatus.OK, result.getStatusCode()); assertTrue(result.hasBody()); - assertEquals(USER_NAME_SAMPLE, result.getBody().getUsername()); + assertEquals(USER_NAME_SAMPLE, Objects.requireNonNull(result.getBody()).getUsername()); } @Test @@ -132,7 +133,7 @@ void testCreateFeedback() { var result = feedbackController.createFeedback(mockFeedbackModel, "Bearer " + TOKEN_SAMPLE); assertEquals(HttpStatus.CREATED, result.getStatusCode()); - assertTrue(result.getHeaders().getLocation().toString().contains(mockFeedback.getId())); + assertTrue(Objects.requireNonNull(result.getHeaders().getLocation()).toString().contains(mockFeedback.getId())); } private Feedback createFeedbackMock() { diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/OAuth2ControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/OAuth2ControllerTest.java index f4a67a939..e53c4fd6d 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/OAuth2ControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/OAuth2ControllerTest.java @@ -51,7 +51,7 @@ void testGitHubLogin() { ResponseEntity response = oAuth2Controller.gitHubLogin(oauth2AuthorizationCode); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); assertEquals(Map.of("token", jwtToken), response.getBody()); } diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductControllerTest.java index 9152a506f..c28c96b6a 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductControllerTest.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -54,9 +55,6 @@ class ProductControllerTest { @Mock private PagedResourcesAssembler pagedResourcesAssembler; - @Mock - private PagedModel pagedProductModel; - @Mock private GitHubService gitHubService; @@ -71,13 +69,13 @@ void setup() { @Test void testFindProductsAsEmpty() { PageRequest pageable = PageRequest.of(0, 20); - Page mockProducts = new PageImpl(List.of(), pageable, 0); + Page mockProducts = new PageImpl<>(List.of(), pageable, 0); when(service.findProducts(any(), any(), any(), any())).thenReturn(mockProducts); when(pagedResourcesAssembler.toEmptyModel(any(), any())).thenReturn(PagedModel.empty()); var result = productController.findProducts(TypeOption.ALL.getOption(), null, "en", pageable); assertEquals(HttpStatus.OK, result.getStatusCode()); assertTrue(result.hasBody()); - assertEquals(0, result.getBody().getContent().size()); + assertEquals(0, Objects.requireNonNull(result.getBody()).getContent().size()); } @Test @@ -85,7 +83,7 @@ void testFindProducts() { PageRequest pageable = PageRequest.of(0, 20, Sort.by(Order.by(SortOption.ALPHABETICALLY.getOption()))); Product mockProduct = createProductMock(); - Page mockProducts = new PageImpl(List.of(mockProduct), pageable, 1); + Page mockProducts = new PageImpl<>(List.of(mockProduct), pageable, 1); when(service.findProducts(any(), any(), any(), any())).thenReturn(mockProducts); assembler = new ProductModelAssembler(); var mockProductModel = assembler.toModel(mockProduct); @@ -94,7 +92,7 @@ void testFindProducts() { var result = productController.findProducts(TypeOption.ALL.getOption(), "", "en", pageable); assertEquals(HttpStatus.OK, result.getStatusCode()); assertTrue(result.hasBody()); - assertEquals(1, result.getBody().getContent().size()); + assertEquals(1, Objects.requireNonNull(result.getBody()).getContent().size()); assertEquals(PRODUCT_NAME_SAMPLE, result.getBody().getContent().iterator().next().getNames().get(Language.EN.getValue())); assertEquals(PRODUCT_NAME_DE_SAMPLE, @@ -109,7 +107,7 @@ void testSyncProductsSuccess() { assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue(response.hasBody()); - assertEquals(ErrorCode.SUCCESSFUL.getCode(), response.getBody().getHelpCode()); + assertEquals(ErrorCode.SUCCESSFUL.getCode(), Objects.requireNonNull(response.getBody()).getHelpCode()); assertEquals("Data is already up to date, nothing to sync", response.getBody().getMessageDetails()); } @@ -122,7 +120,7 @@ void testSyncProductsWithResetSuccess() { assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue(response.hasBody()); - assertEquals(ErrorCode.SUCCESSFUL.getCode(), response.getBody().getHelpCode()); + assertEquals(ErrorCode.SUCCESSFUL.getCode(), Objects.requireNonNull(response.getBody()).getHelpCode()); assertTrue(response.getBody().getMessageDetails().contains("Finished sync data")); } @@ -132,9 +130,8 @@ void testSyncProductsInvalidToken() { ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText())).when(gitHubService) .validateUserOrganization(any(String.class), any(String.class)); - UnauthorizedException exception = assertThrows(UnauthorizedException.class, () -> { - productController.syncProducts(INVALID_AUTHORIZATION_HEADER, false); - }); + UnauthorizedException exception = assertThrows(UnauthorizedException.class, + () -> productController.syncProducts(INVALID_AUTHORIZATION_HEADER, false)); assertEquals(ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText(), exception.getMessage()); } diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java index e1163587e..1f3810b61 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java @@ -9,9 +9,7 @@ import java.util.Objects; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Objects; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/marketplace-service/src/test/java/com/axonivy/market/factory/ProductFactoryTest.java b/marketplace-service/src/test/java/com/axonivy/market/factory/ProductFactoryTest.java index 5b9f3727e..fe7ff227e 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/factory/ProductFactoryTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/factory/ProductFactoryTest.java @@ -19,18 +19,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.io.IOException; -import java.io.InputStream; - -import com.axonivy.market.github.model.Meta; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.kohsuke.github.GHContent; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.axonivy.market.constants.CommonConstants; -import com.axonivy.market.entity.Product; import com.axonivy.market.enums.Language; @ExtendWith(MockitoExtension.class) diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java index 1f70286ae..75f97b562 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java @@ -26,8 +26,14 @@ import java.util.List; import java.util.Optional; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class FeedbackServiceImplTest { @@ -86,9 +92,8 @@ void testFindFeedbacks_ProductNotFound() { when(productRepository.findById(productId)).thenReturn(Optional.empty()); - NotFoundException exception = assertThrows(NotFoundException.class, () -> { - feedbackService.findFeedbacks(productId, pageable); - }); + NotFoundException exception = assertThrows(NotFoundException.class, + () -> feedbackService.findFeedbacks(productId, pageable)); assertEquals(ErrorCode.PRODUCT_NOT_FOUND.getCode(), exception.getCode()); verify(productRepository, times(1)).findById(productId); verify(feedbackRepository, times(0)).searchByProductId(productId, pageable); @@ -112,9 +117,7 @@ void testFindFeedback_NotFound() { when(feedbackRepository.findById(feedbackId)).thenReturn(Optional.empty()); - NotFoundException exception = assertThrows(NotFoundException.class, () -> { - feedbackService.findFeedback(feedbackId); - }); + NotFoundException exception = assertThrows(NotFoundException.class, () -> feedbackService.findFeedback(feedbackId)); assertEquals(ErrorCode.FEEDBACK_NOT_FOUND.getCode(), exception.getCode()); verify(feedbackRepository, times(1)).findById(feedbackId); } @@ -146,9 +149,8 @@ void testFindFeedbackByUserIdAndProductId_NotFound() { when(productRepository.findById(productId)).thenReturn(Optional.of(new Product())); when(feedbackRepository.findByUserIdAndProductId(userId, productId)).thenReturn(null); - NotFoundException exception = assertThrows(NotFoundException.class, () -> { - feedbackService.findFeedbackByUserIdAndProductId(userId, productId); - }); + NotFoundException exception = assertThrows(NotFoundException.class, + () -> feedbackService.findFeedbackByUserIdAndProductId(userId, productId)); assertEquals(ErrorCode.FEEDBACK_NOT_FOUND.getCode(), exception.getCode()); verify(userRepository, times(1)).findById(userId); verify(productRepository, times(1)).findById(productId); @@ -210,6 +212,7 @@ void testGetProductRatingById() { verify(feedbackRepository, times(1)).findByProductId(productId); } + @Test void testGetProductRatingById_NoFeedbacks() { String productId = "product1"; @@ -241,9 +244,8 @@ void testValidateProductExists_NotFound() { when(productRepository.findById(productId)).thenReturn(Optional.empty()); - NotFoundException exception = assertThrows(NotFoundException.class, () -> { - feedbackService.validateProductExists(productId); - }); + NotFoundException exception = assertThrows(NotFoundException.class, + () -> feedbackService.validateProductExists(productId)); assertEquals(ErrorCode.PRODUCT_NOT_FOUND.getCode(), exception.getCode()); verify(productRepository, times(1)).findById(productId); } @@ -264,9 +266,8 @@ void testValidateUserExists_NotFound() { when(userRepository.findById(userId)).thenReturn(Optional.empty()); - NotFoundException exception = assertThrows(NotFoundException.class, () -> { - feedbackService.validateUserExists(userId); - }); + NotFoundException exception = assertThrows(NotFoundException.class, + () -> feedbackService.validateUserExists(userId)); assertEquals(ErrorCode.USER_NOT_FOUND.getCode(), exception.getCode()); verify(userRepository, times(1)).findById(userId); } diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyMarketRepoServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyMarketRepoServiceImplTest.java index 5eda06723..c26a567a2 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyMarketRepoServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyMarketRepoServiceImplTest.java @@ -108,7 +108,7 @@ void testFetchMarketItemsBySHA1Range() throws IOException { @Test void testGetLastCommit() throws IOException { - var lastCommit = axonIvyMarketRepoServiceImpl.getLastCommit(0l); + var lastCommit = axonIvyMarketRepoServiceImpl.getLastCommit(0L); assertEquals(null, lastCommit); } } diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java index afe25e7ce..b6703cdc7 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GitHubServiceImplTest.java @@ -1,33 +1,21 @@ package com.axonivy.market.service; -import com.axonivy.market.constants.GitHubConstants; -import com.axonivy.market.github.model.GitHubAccessTokenResponse; import com.axonivy.market.github.service.impl.GitHubServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kohsuke.github.GHContent; import org.kohsuke.github.GHRepository; -import org.kohsuke.github.GitHub; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.io.IOException; -import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/ProductServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/ProductServiceImplTest.java index 1242e442f..a0231e7cb 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/ProductServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/ProductServiceImplTest.java @@ -72,7 +72,7 @@ class ProductServiceImplTest { private static final String SAMPLE_PRODUCT_ID = "amazon-comprehend"; private static final String SAMPLE_PRODUCT_NAME = "Amazon Comprehend"; - private static final long LAST_CHANGE_TIME = 1718096290000l; + private static final long LAST_CHANGE_TIME = 1718096290000L; private static final Pageable PAGEABLE = PageRequest.of(0, 20, Sort.by(SortOption.ALPHABETICALLY.getOption()).descending()); private static final String SHA1_SAMPLE = "35baa89091b2452b77705da227f1a964ecabc6c8"; diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/SchedulingTasksTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/SchedulingTasksTest.java index aa7b8af7c..5d7571a98 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/SchedulingTasksTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/SchedulingTasksTest.java @@ -10,10 +10,9 @@ import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.verify; -@SpringBootTest(properties = { "MONGODB_USERNAME=user", - "MONGODB_PASSWORD=password", "MONGODB_HOST=mongoHost", "MONGODB_DATABASE=product", - "MARKET_GITHUB_OAUTH_APP_CLIENT_ID=clientId", "MARKET_GITHUB_OAUTH_APP_CLIENT_SECRET=clientSecret", - "MARKET_JWT_SECRET_KEY=jwtSecret" }) +@SpringBootTest(properties = { "MONGODB_USERNAME=user", "MONGODB_PASSWORD=password", "MONGODB_HOST=mongoHost", + "MONGODB_DATABASE=product", "MARKET_GITHUB_OAUTH_APP_CLIENT_ID=clientId", + "MARKET_GITHUB_OAUTH_APP_CLIENT_SECRET=clientSecret", "MARKET_JWT_SECRET_KEY=jwtSecret" }) class SchedulingTasksTest { @SpyBean @@ -21,8 +20,7 @@ class SchedulingTasksTest { @Test void testShouldNotTriggerAfterApplicationStarted() { - Awaitility.await().atMost(Durations.TEN_SECONDS).untilAsserted(() -> { - verify(tasks, atLeast(0)).syncDataForProductFromGitHubRepo(); - }); + Awaitility.await().atMost(Durations.TEN_SECONDS) + .untilAsserted(() -> verify(tasks, atLeast(0)).syncDataForProductFromGitHubRepo()); } } diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java index 457378568..f340bb336 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/UserServiceImplTest.java @@ -1,9 +1,10 @@ -package com.axonivy.market.service.impl; +package com.axonivy.market.service; import com.axonivy.market.entity.User; import com.axonivy.market.enums.ErrorCode; import com.axonivy.market.exceptions.model.NotFoundException; import com.axonivy.market.repository.UserRepository; +import com.axonivy.market.service.impl.UserServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -66,9 +67,7 @@ void testFindUser_NotFound() { when(userRepository.findById(userId)).thenReturn(Optional.empty()); - NotFoundException exception = assertThrows(NotFoundException.class, () -> { - userService.findUser(userId); - }); + NotFoundException exception = assertThrows(NotFoundException.class, () -> userService.findUser(userId)); assertEquals(ErrorCode.USER_NOT_FOUND.getCode(), exception.getCode()); verify(userRepository, times(1)).findById(userId); } From f82ccd251dfcd2d31b12678e54762289e929ee10 Mon Sep 17 00:00:00 2001 From: nntthuy-axonivy Date: Fri, 26 Jul 2024 16:37:45 +0700 Subject: [PATCH 14/15] MARP-572: Fix warning codes --- .../com/axonivy/market/constants/ProductJsonConstants.java | 1 - .../service/impl/GHAxonIvyProductRepoServiceImpl.java | 2 +- .../java/com/axonivy/market/github/util/GitHubUtils.java | 2 +- .../com/axonivy/market/repository/ProductRepository.java | 2 -- .../market/controller/ProductDetailsControllerTest.java | 2 +- .../market/service/GHAxonIvyProductRepoServiceImplTest.java | 6 +++--- .../com/axonivy/market/service/ProductServiceImplTest.java | 4 ++-- 7 files changed, 8 insertions(+), 11 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/constants/ProductJsonConstants.java b/marketplace-service/src/main/java/com/axonivy/market/constants/ProductJsonConstants.java index 8d3aa03a2..4a9bef8ed 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/constants/ProductJsonConstants.java +++ b/marketplace-service/src/main/java/com/axonivy/market/constants/ProductJsonConstants.java @@ -12,7 +12,6 @@ public class ProductJsonConstants { public static final String TYPE = "type"; public static final String DEPENDENCIES = "dependencies"; public static final String INSTALLERS = "installers"; - public static final String DEPENDENCY_SUFFIX = "-dependency"; public static final String MAVEN_IMPORT_INSTALLER_ID = "maven-import"; public static final String MAVEN_DROPIN_INSTALLER_ID = "maven-dropins"; public static final String MAVEN_DEPENDENCY_INSTALLER_ID = "maven-dependency"; diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GHAxonIvyProductRepoServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GHAxonIvyProductRepoServiceImpl.java index 7a2916da3..308d97c80 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GHAxonIvyProductRepoServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/service/impl/GHAxonIvyProductRepoServiceImpl.java @@ -164,7 +164,7 @@ public ProductModuleContent getReadmeAndProductContentsFromTag(Product product, } } } catch (Exception e) { - log.error("Cannot get product.json and README file's content {}", e); + log.error("Cannot get product.json and README file's content {}", e.getMessage()); return null; } return productModuleContent; diff --git a/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java b/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java index 26ffb7260..2e7af413c 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java +++ b/marketplace-service/src/main/java/com/axonivy/market/github/util/GitHubUtils.java @@ -20,7 +20,6 @@ public class GitHubUtils { private static String pathToProductFolderFromTagContent; - private static String pathToImageFolder; public static long getGHCommitDate(GHCommit commit) { long commitTime = 0L; @@ -111,6 +110,7 @@ public static String getNonStandardProductFilePath(String productId) { } public static String getNonStandardImageFolder(String productId) { + String pathToImageFolder; switch (productId) { case NonStandardProductPackageConstants.EXCEL_IMPORTER: pathToImageFolder = "doc"; diff --git a/marketplace-service/src/main/java/com/axonivy/market/repository/ProductRepository.java b/marketplace-service/src/main/java/com/axonivy/market/repository/ProductRepository.java index b638e30ea..7d72b8257 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/repository/ProductRepository.java +++ b/marketplace-service/src/main/java/com/axonivy/market/repository/ProductRepository.java @@ -16,8 +16,6 @@ public interface ProductRepository extends MongoRepository { Product findByLogoUrl(String logoUrl); - Product findByIdAndType(String id, String type); - Optional findById(String productId); @Query("{'marketDirectory': {$regex : ?0, $options: 'i'}}") diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java index 1f3810b61..3d3a2af8a 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/ProductDetailsControllerTest.java @@ -85,7 +85,7 @@ void testFindProductVersionsById() { Mockito.when( versionService.getArtifactsAndVersionToDisplay(Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyString())) .thenReturn(models); - ResponseEntity> result = productDetailsController.findProductVersionsById("protal", + ResponseEntity> result = productDetailsController.findProductVersionsById("portal", true, "10.0.1"); Assertions.assertEquals(HttpStatus.OK, result.getStatusCode()); Assertions.assertEquals(1, Objects.requireNonNull(result.getBody()).size()); diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyProductRepoServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyProductRepoServiceImplTest.java index 52c01e218..5db1f148c 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyProductRepoServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyProductRepoServiceImplTest.java @@ -80,7 +80,7 @@ void setup() throws IOException { } @AfterEach - void after() throws IOException { + void after() { reset(mockGHOrganization); reset(gitHubService); } @@ -230,7 +230,7 @@ void testGetReadmeAndProductContentFromTag_ImageFromFolder() throws IOException when(mockImageFile.isDirectory()).thenReturn(true); when(mockImageFile.getDownloadUrl()).thenReturn(IMAGE_DOWNLOAD_URL); - PagedIterable pagedIterable = mock(PagedIterable.class); + PagedIterable pagedIterable = Mockito.mock(String.valueOf(GHContent.class)); when(mockImageFile.listDirectoryContent()).thenReturn(pagedIterable); when(pagedIterable.toList()).thenReturn(List.of(mockImageFile)); @@ -340,7 +340,7 @@ private static InputStream getMockInputStreamWithOutProjectAndDependency() { return new ByteArrayInputStream(jsonContent.getBytes(StandardCharsets.UTF_8)); } - private Product createMockProduct() throws IOException { + private Product createMockProduct() { Product product = new Product(); product.setId("docuware-connector"); product.setLanguage("en"); diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/ProductServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/ProductServiceImplTest.java index a0231e7cb..4b244e2c2 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/ProductServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/ProductServiceImplTest.java @@ -280,7 +280,7 @@ void testSyncProductsFirstTime() throws IOException { when(ghAxonIvyProductRepoService.getReadmeAndProductContentsFromTag(any(), any(), anyString())).thenReturn( mockReadmeProductContent()); when(gitHubService.getRepository(any())).thenReturn(ghRepository); - PagedIterable pagedIterable = mock(PagedIterable.class); + PagedIterable pagedIterable = Mockito.mock(String.valueOf(GHTag.class)); when(ghRepository.listTags()).thenReturn(pagedIterable); GHTag mockTag = mock(GHTag.class); @@ -341,7 +341,7 @@ void testFetchProductDetail() { String id = "amazon-comprehend"; Product mockProduct = mockResultReturn.getContent().get(0); mockProduct.setSynchronizedInstallationCount(true); - when(productRepository.findById(id)).thenReturn(Optional.ofNullable(mockProduct)); + when(productRepository.findById(id)).thenReturn(Optional.of(mockProduct)); Product result = productService.fetchProductDetail(id); assertEquals(mockProduct, result); verify(productRepository, times(1)).findById(id); From f897855e0c5c19b3aef889cf556129cf06f677dc Mon Sep 17 00:00:00 2001 From: Hoan Nguyen Date: Fri, 26 Jul 2024 16:58:58 +0700 Subject: [PATCH 15/15] Fix warning in mock test --- .../market/service/GHAxonIvyProductRepoServiceImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyProductRepoServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyProductRepoServiceImplTest.java index 5db1f148c..762172f55 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyProductRepoServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/GHAxonIvyProductRepoServiceImplTest.java @@ -138,7 +138,7 @@ void testExtractMavenArtifactFromJsonNode() { private void createListNodeForDataNoteByName(String nodeName) { JsonNode sectionNode = Mockito.mock(JsonNode.class); - Iterator iterator = Mockito.mock(Iterator.class); + Iterator iterator = Mockito.mock(String.valueOf(Iterator.class)); Mockito.when(dataNode.path(nodeName)).thenReturn(sectionNode); Mockito.when(sectionNode.iterator()).thenReturn(iterator); Mockito.when(iterator.hasNext()).thenReturn(true, false);