From a391b047e5d85638ea79d93147ad937af34e27d2 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen <127725498+ntqdinh-axonivy@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:37:38 +0700 Subject: [PATCH] MARP-1099 Market website show nonexist version then fail in step installation market item --- .../market/controller/ProductController.java | 6 +- .../repository/CustomProductRepository.java | 2 - .../impl/CustomProductRepositoryImpl.java | 19 +- .../market/service/ProductService.java | 2 + .../service/impl/ProductServiceImpl.java | 177 +++++++------ .../service/impl/VersionServiceImpl.java | 16 +- .../com/axonivy/market/util/MavenUtils.java | 5 + .../com/axonivy/market/util/VersionUtils.java | 16 +- .../java/com/axonivy/market/BaseSetup.java | 25 +- .../controller/ProductControllerTest.java | 6 +- .../impl/CustomProductRepositoryImplTest.java | 63 ++--- .../service/impl/ProductServiceImplTest.java | 246 ++++++++---------- .../service/impl/VersionServiceImplTest.java | 14 +- .../src/test/resources/installationCount.json | 3 +- 14 files changed, 306 insertions(+), 294 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 a52d09613..25e360c0e 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 @@ -122,10 +122,14 @@ public ResponseEntity syncProducts(@RequestHeader(value = AUTHORIZATION @PutMapping(SYNC_PRODUCT_VERSION) @Operation(hidden = true) - public ResponseEntity syncProductVersions(@RequestHeader(value = AUTHORIZATION) String authorizationHeader) { + public ResponseEntity syncProductVersions(@RequestHeader(value = AUTHORIZATION) String authorizationHeader + ,@RequestParam(value = RESET_SYNC, required = false) Boolean resetSync) { String token = AuthorizationUtils.getBearerToken(authorizationHeader); gitHubService.validateUserInOrganizationAndTeam(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME, GitHubConstants.AXONIVY_MARKET_TEAM_NAME); + if (Boolean.TRUE.equals(resetSync)) { + productService.clearAllProductVersion(); + } int nonSyncResult = metadataService.syncAllProductsMetadata(); var message = new Message(); HttpStatus statusCode = HttpStatus.OK; diff --git a/marketplace-service/src/main/java/com/axonivy/market/repository/CustomProductRepository.java b/marketplace-service/src/main/java/com/axonivy/market/repository/CustomProductRepository.java index 93d39e5dd..fbedca61c 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/repository/CustomProductRepository.java +++ b/marketplace-service/src/main/java/com/axonivy/market/repository/CustomProductRepository.java @@ -13,8 +13,6 @@ public interface CustomProductRepository { Product getProductById(String id); - Product getProductByIdWithNewestReleaseVersion(String id, Boolean isShowDevVersion); - List getReleasedVersionsById(String id); int updateInitialCount(String productId, int initialCount); diff --git a/marketplace-service/src/main/java/com/axonivy/market/repository/impl/CustomProductRepositoryImpl.java b/marketplace-service/src/main/java/com/axonivy/market/repository/impl/CustomProductRepositoryImpl.java index 7328de2ab..672ba7323 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/repository/impl/CustomProductRepositoryImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/repository/impl/CustomProductRepositoryImpl.java @@ -12,10 +12,8 @@ import com.axonivy.market.repository.CustomProductRepository; import com.axonivy.market.repository.CustomRepository; import com.axonivy.market.repository.ProductModuleContentRepository; -import com.axonivy.market.util.VersionUtils; import lombok.AllArgsConstructor; import lombok.Builder; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.bson.BsonRegularExpression; import org.springframework.data.domain.Page; @@ -42,7 +40,7 @@ public class CustomProductRepositoryImpl extends CustomRepository implements Cus public static final String LOCALIZE_SEARCH_PATTERN = "%s.%s"; final MongoTemplate mongoTemplate; - final ProductModuleContentRepository contentRepository; + final ProductModuleContentRepository contentRepo; public Product queryProductByAggregation(Aggregation aggregation) { return Optional.of(mongoTemplate.aggregate(aggregation, EntityConstants.PRODUCT, Product.class)) @@ -64,19 +62,6 @@ public Product getProductByIdWithTagOrVersion(String id, String tag) { return result; } - @Override - public Product getProductByIdWithNewestReleaseVersion(String id, Boolean isShowDevVersion) { - Product result = findProductById(id); - if (ObjectUtils.isEmpty(result)) { - return null; - } - List devVersions = VersionUtils.getVersionsToDisplay(result.getReleasedVersions(), isShowDevVersion, null); - String currentTag = VersionUtils.convertVersionToTag(result.getId(), devVersions.get(0)); - ProductModuleContent content = contentRepository.findByTagAndProductId(currentTag, id); - result.setProductModuleContent(content); - return result; - } - @Override public ProductModuleContent findByProductIdAndTagOrMavenVersion(String productId, String tag) { Criteria productIdCriteria = Criteria.where(MongoDBConstants.PRODUCT_ID).is(productId); @@ -97,7 +82,7 @@ private Product findProductById(String id) { public Product getProductById(String id) { Product result = findProductById(id); if (!Objects.isNull(result)) { - ProductModuleContent content = contentRepository.findByTagAndProductId( + ProductModuleContent content = contentRepo.findByTagAndProductId( result.getNewestReleaseVersion(), id); result.setProductModuleContent(content); } 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 eaafb2b7d..a1e6368bb 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 @@ -28,4 +28,6 @@ public interface ProductService { Product fetchProductDetailByIdAndVersion(String id, String version); boolean syncOneProduct(String productId, String marketItemPath, Boolean overrideMarketItemPath); + + void clearAllProductVersion(); } 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 117b3a546..7577fb4bb 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 @@ -8,7 +8,6 @@ import com.axonivy.market.criteria.ProductSearchCriteria; import com.axonivy.market.entity.GitHubRepoMeta; import com.axonivy.market.entity.Image; -import com.axonivy.market.entity.MavenArtifactVersion; import com.axonivy.market.entity.Product; import com.axonivy.market.entity.ProductCustomSort; import com.axonivy.market.entity.ProductModuleContent; @@ -91,18 +90,18 @@ @Service public class ProductServiceImpl implements ProductService { private static final String INITIAL_VERSION = "1.0"; - private final ProductRepository productRepository; - private final ProductModuleContentRepository productModuleContentRepository; + private final ProductRepository productRepo; + private final ProductModuleContentRepository productModuleContentRepo; private final GHAxonIvyMarketRepoService axonIvyMarketRepoService; private final GHAxonIvyProductRepoService axonIvyProductRepoService; - private final GitHubRepoMetaRepository gitHubRepoMetaRepository; + private final GitHubRepoMetaRepository gitHubRepoMetaRepo; private final GitHubService gitHubService; - private final ProductCustomSortRepository productCustomSortRepository; + private final ProductCustomSortRepository productCustomSortRepo; private final MavenArtifactVersionRepository mavenArtifactVersionRepo; - private final MetadataSyncRepository metadataSyncRepository; - private final MetadataRepository metadataRepository; - private final ProductJsonContentRepository productJsonContentRepository; - private final ImageRepository imageRepository; + private final MetadataSyncRepository metadataSyncRepo; + private final MetadataRepository metadataRepo; + private final ProductJsonContentRepository productJsonContentRepo; + private final ImageRepository imageRepo; private final ImageService imageService; private final MongoTemplate mongoTemplate; private final MetadataService metadataService; @@ -115,29 +114,29 @@ public class ProductServiceImpl implements ProductService { @Value("${market.github.market.branch}") private String marketRepoBranch; - public ProductServiceImpl(ProductRepository productRepository, - ProductModuleContentRepository productModuleContentRepository, + public ProductServiceImpl(ProductRepository productRepo, + ProductModuleContentRepository productModuleContentRepo, GHAxonIvyMarketRepoService axonIvyMarketRepoService, GHAxonIvyProductRepoService axonIvyProductRepoService, - GitHubRepoMetaRepository gitHubRepoMetaRepository, GitHubService gitHubService, - ProductCustomSortRepository productCustomSortRepository, MavenArtifactVersionRepository mavenArtifactVersionRepo, - ImageRepository imageRepository, MetadataService metadataService, MetadataSyncRepository metadataSyncRepository, - MetadataRepository metadataRepository, ImageService imageService, MongoTemplate mongoTemplate, - ProductJsonContentRepository productJsonContentRepository) { - this.productRepository = productRepository; - this.productModuleContentRepository = productModuleContentRepository; + GitHubRepoMetaRepository gitHubRepoMetaRepo, GitHubService gitHubService, + ProductCustomSortRepository productCustomSortRepo, MavenArtifactVersionRepository mavenArtifactVersionRepo, + ImageRepository imageRepo, MetadataService metadataService, MetadataSyncRepository metadataSyncRepo, + MetadataRepository metadataRepo, ImageService imageService, MongoTemplate mongoTemplate, + ProductJsonContentRepository productJsonContentRepo) { + this.productRepo = productRepo; + this.productModuleContentRepo = productModuleContentRepo; this.axonIvyMarketRepoService = axonIvyMarketRepoService; this.axonIvyProductRepoService = axonIvyProductRepoService; - this.gitHubRepoMetaRepository = gitHubRepoMetaRepository; + this.gitHubRepoMetaRepo = gitHubRepoMetaRepo; this.gitHubService = gitHubService; - this.productCustomSortRepository = productCustomSortRepository; + this.productCustomSortRepo = productCustomSortRepo; this.mavenArtifactVersionRepo = mavenArtifactVersionRepo; - this.metadataSyncRepository = metadataSyncRepository; - this.metadataRepository = metadataRepository; + this.metadataSyncRepo = metadataSyncRepo; + this.metadataRepo = metadataRepo; this.metadataService = metadataService; - this.imageRepository = imageRepository; + this.imageRepo = imageRepo; this.imageService = imageService; this.mongoTemplate = mongoTemplate; - this.productJsonContentRepository = productJsonContentRepository; + this.productJsonContentRepo = productJsonContentRepo; } private static Predicate filterNonPersistGhTagName(List currentTags) { @@ -157,7 +156,7 @@ public Page findProducts(String type, String keyword, String language, if (BooleanUtils.isTrue(isRESTClient)) { searchCriteria.setExcludeFields(List.of(SHORT_DESCRIPTIONS)); } - return productRepository.searchByCriteria(searchCriteria, searchPageable); + return productRepo.searchByCriteria(searchCriteria, searchPageable); } @Override @@ -179,22 +178,22 @@ public List syncLatestDataFromMarketRepo() { @Override public int updateInstallationCountForProduct(String key, String designerVersion) { - Product product = productRepository.getProductById(key); + Product product = productRepo.getProductById(key); if (Objects.isNull(product)) { return 0; } log.info("Increase installation count for product {} By Designer Version {}", key, designerVersion); if (StringUtils.isNotBlank(designerVersion)) { - productRepository.increaseInstallationCountForProductByDesignerVersion(key, designerVersion); + productRepo.increaseInstallationCountForProductByDesignerVersion(key, designerVersion); } log.info("updating installation count for product {}", key); if (BooleanUtils.isTrue(product.getSynchronizedInstallationCount())) { - return productRepository.increaseInstallationCount(key); + return productRepo.increaseInstallationCount(key); } syncInstallationCountWithProduct(product); - return productRepository.updateInitialCount(key, product.getInstallationCount() + 1); + return productRepo.updateInitialCount(key, product.getInstallationCount() + 1); } public void syncInstallationCountWithProduct(Product product) { @@ -225,7 +224,7 @@ private void syncRepoMetaDataStatus() { marketRepoMeta.setRepoName(GitHubConstants.AXONIVY_MARKETPLACE_REPO_NAME); marketRepoMeta.setLastSHA1(lastGHCommit.getSHA1()); marketRepoMeta.setLastChange(GitHubUtils.getGHCommitDate(lastGHCommit)); - gitHubRepoMetaRepository.save(marketRepoMeta); + gitHubRepoMetaRepo.save(marketRepoMeta); marketRepoMeta = null; } @@ -265,19 +264,19 @@ private String removeProductAndImage(GitHubFile file) { String[] splitMetaJsonPath = file.getFileName().split(SLASH); String extractMarketDirectory = file.getFileName().replace(splitMetaJsonPath[splitMetaJsonPath.length - 1], EMPTY); - List productList = productRepository.findByMarketDirectory(extractMarketDirectory); + List productList = productRepo.findByMarketDirectory(extractMarketDirectory); if (ObjectUtils.isNotEmpty(productList)) { productId = productList.get(0).getId(); - productRepository.deleteById(productId); - imageRepository.deleteAllByProductId(productId); + productRepo.deleteById(productId); + imageRepo.deleteAllByProductId(productId); } } else { - List images = imageRepository.findByImageUrlEndsWithIgnoreCase(file.getFileName()); + List images = imageRepo.findByImageUrlEndsWithIgnoreCase(file.getFileName()); if (ObjectUtils.isNotEmpty(images)) { Image currentImage = images.get(0); productId = currentImage.getProductId(); - productRepository.deleteById(productId); - imageRepository.deleteAllByProductId(productId); + productRepo.deleteById(productId); + imageRepo.deleteAllByProductId(productId); } } return productId; @@ -301,7 +300,7 @@ private String updateProductByMetaJsonAndLogo(GHContent fileContent, GitHubFile ProductFactory.mappingByGHContent(product, fileContent); mappingVendorImageFromGHContent(product, fileContent); transferComputedDataFromDB(product); - productId = productRepository.save(product).getId(); + productId = productRepo.save(product).getId(); } else { productId = modifyProductLogo(parentPath, fileContent); } @@ -312,14 +311,14 @@ private String modifyProductLogo(String parentPath, GHContent fileContent) { var searchCriteria = new ProductSearchCriteria(); searchCriteria.setKeyword(parentPath); searchCriteria.setFields(List.of(MARKET_DIRECTORY)); - Product result = productRepository.findByCriteria(searchCriteria); + Product result = productRepo.findByCriteria(searchCriteria); if (result != null) { Optional.ofNullable(imageService.mappingImageFromGHContent(result.getId(), fileContent, true)).ifPresent(image -> { if (StringUtils.isNotBlank(result.getLogoId())) { - imageRepository.deleteById(result.getLogoId()); + imageRepo.deleteById(result.getLogoId()); } result.setLogoId(image.getId()); - productRepository.save(result); + productRepo.save(result); }); return result.getId(); } @@ -351,7 +350,7 @@ public Order createOrder(SortOption sortOption, String language) { } private Order getExtensionOrder(String language) { - List customSorts = productCustomSortRepository.findAll(); + List customSorts = productCustomSortRepo.findAll(); if (!customSorts.isEmpty()) { SortOption sortOptionExtension = SortOption.of(customSorts.get(0).getRuleForRemainder()); @@ -363,7 +362,7 @@ private Order getExtensionOrder(String language) { private boolean isLastGithubCommitCovered() { boolean isLastCommitCovered = false; long lastCommitTime = 0L; - marketRepoMeta = gitHubRepoMetaRepository.findByRepoName(GitHubConstants.AXONIVY_MARKETPLACE_REPO_NAME); + marketRepoMeta = gitHubRepoMetaRepo.findByRepoName(GitHubConstants.AXONIVY_MARKETPLACE_REPO_NAME); if (marketRepoMeta != null) { lastCommitTime = marketRepoMeta.getLastChange(); } @@ -376,7 +375,7 @@ private boolean isLastGithubCommitCovered() { } private void updateLatestReleaseTagContentsFromProductRepo() { - List products = productRepository.findAll(); + List products = productRepo.findAll(); if (ObjectUtils.isEmpty(products)) { return; } @@ -384,15 +383,15 @@ private void updateLatestReleaseTagContentsFromProductRepo() { for (Product product : products) { if (StringUtils.isNotBlank(product.getRepositoryName())) { getProductContents(product); - productRepository.save(product); + productRepo.save(product); } } } private void getProductContents(Product product) { try { - GHRepository productRepo = gitHubService.getRepository(product.getRepositoryName()); - updateProductFromReleaseTags(product, productRepo); + GHRepository productRepository = gitHubService.getRepository(product.getRepositoryName()); + updateProductFromReleaseTags(product, productRepository); } catch (IOException e) { log.error("Cannot find product repository {} {}", product.getRepositoryName(), e); } @@ -412,12 +411,12 @@ private List syncProductsFromGitHubRepo() { mappingVendorImageFromGHContent(product, content); mappingLogoFromGHContent(product, content); } - if (productRepository.findById(product.getId()).isPresent()) { + if (productRepo.findById(product.getId()).isPresent()) { continue; } updateRelatedThingsOfProductFromGHContent(ghContentEntity.getValue(), product); transferComputedDataFromDB(product); - syncedProductIds.add(productRepository.save(product).getId()); + syncedProductIds.add(productRepo.save(product).getId()); } return syncedProductIds; } @@ -465,7 +464,7 @@ private void updateProductFromReleaseTags(Product product, GHRepository productR product.setNewestReleaseVersion(lastTag.getName()); List currentTags = VersionUtils.getReleaseTagsFromProduct(product); if (CollectionUtils.isEmpty(currentTags)) { - currentTags = productModuleContentRepository.findTagsByProductId(product.getId()); + currentTags = productModuleContentRepo.findTagsByProductId(product.getId()); } ghTags = ghTags.stream().filter(filterNonPersistGhTagName(currentTags)).toList(); @@ -482,7 +481,7 @@ private void updateProductFromReleaseTags(Product product, GHRepository productR product.getReleasedVersions().add(versionFromTag); } if (!CollectionUtils.isEmpty(productModuleContents)) { - productModuleContentRepository.saveAll(productModuleContents); + productModuleContentRepo.saveAll(productModuleContents); } } @@ -534,7 +533,7 @@ public String getCompatibilityFromOldestTag(String oldestTag) { @Override public Product fetchProductDetail(String id, Boolean isShowDevVersion) { - Product product = productRepository.getProductByIdWithNewestReleaseVersion(id, isShowDevVersion); + Product product = getProductByIdWithNewestReleaseVersion(id, isShowDevVersion); return Optional.ofNullable(product).map(productItem -> { updateProductInstallationCount(id, productItem); return productItem; @@ -543,14 +542,13 @@ public Product fetchProductDetail(String id, Boolean isShowDevVersion) { @Override public Product fetchBestMatchProductDetail(String id, String version) { - MavenArtifactVersion existingMavenArtifactVersion = mavenArtifactVersionRepo.findById(id).orElse( - MavenArtifactVersion.builder().productId(id).build()); - List versions = MavenUtils.getAllExistingVersions(existingMavenArtifactVersion, true, - null); - String bestMatchVersion = VersionUtils.getBestMatchVersion(versions, version); + List installableVersions = VersionUtils.getInstallableVersionsFromMetadataList( + metadataRepo.findByProductId(id)); + String bestMatchVersion = VersionUtils.getBestMatchVersion(installableVersions, version); String bestMatchTag = VersionUtils.convertVersionToTag(id, bestMatchVersion); - Product product = StringUtils.isBlank(bestMatchTag) ? productRepository.getProductByIdWithNewestReleaseVersion( - id, false) : productRepository.getProductByIdWithTagOrVersion(id, bestMatchTag); + // Cover exception case of employee onboarding without any product.json file + Product product = StringUtils.isBlank(bestMatchTag) ? getProductByIdWithNewestReleaseVersion(id, + false) : productRepo.getProductByIdWithTagOrVersion(id, bestMatchTag); return Optional.ofNullable(product).map(productItem -> { updateProductInstallationCount(id, productItem); productItem.setBestMatchVersion(bestMatchVersion); @@ -558,23 +556,41 @@ public Product fetchBestMatchProductDetail(String id, String version) { }).orElse(null); } + public Product getProductByIdWithNewestReleaseVersion(String id, Boolean isShowDevVersion) { + List versions; + String version = StringUtils.EMPTY; + var mavenArtifactVersion = mavenArtifactVersionRepo.findById(id); + if(mavenArtifactVersion.isPresent()) { + versions = MavenUtils.getAllExistingVersions(mavenArtifactVersion.get(), BooleanUtils.isTrue(isShowDevVersion), + StringUtils.EMPTY); + version = VersionUtils.convertVersionToTag(id, CollectionUtils.firstElement(versions)); + } + // Cover exception case of employee onboarding without any product.json file + if (StringUtils.isBlank(version)) { + versions = VersionUtils.getVersionsToDisplay(productRepo.getReleasedVersionsById(id), isShowDevVersion, + StringUtils.EMPTY); + version = CollectionUtils.firstElement(versions); + } + return productRepo.getProductByIdWithTagOrVersion(id, version); + } + public void updateProductInstallationCount(String id, Product productItem) { if (!BooleanUtils.isTrue(productItem.getSynchronizedInstallationCount())) { syncInstallationCountWithProduct(productItem); - int persistedInitialCount = productRepository.updateInitialCount(id, productItem.getInstallationCount()); + int persistedInitialCount = productRepo.updateInitialCount(id, productItem.getInstallationCount()); productItem.setInstallationCount(persistedInitialCount); } } @Override public Product fetchProductDetailByIdAndVersion(String id, String version) { - return productRepository.getProductByIdWithTagOrVersion(id, version); + return productRepo.getProductByIdWithTagOrVersion(id, version); } @Override public void clearAllProducts() { - gitHubRepoMetaRepository.deleteAll(); - productRepository.deleteAll(); + gitHubRepoMetaRepo.deleteAll(); + productRepo.deleteAll(); } @Override @@ -582,10 +598,10 @@ public void addCustomSortProduct(ProductCustomSortRequest customSort) throws Inv SortOption.of(customSort.getRuleForRemainder()); ProductCustomSort productCustomSort = new ProductCustomSort(customSort.getRuleForRemainder()); - productCustomSortRepository.deleteAll(); + productCustomSortRepo.deleteAll(); removeFieldFromAllProductDocuments(ProductJsonConstants.CUSTOM_ORDER); - productCustomSortRepository.save(productCustomSort); - productRepository.saveAll(refineOrderedListOfProductsInCustomSort(customSort.getOrderedListOfProducts())); + productCustomSortRepo.save(productCustomSort); + productRepo.saveAll(refineOrderedListOfProductsInCustomSort(customSort.getOrderedListOfProducts())); } public List refineOrderedListOfProductsInCustomSort(List orderedListOfProducts) @@ -594,14 +610,14 @@ public List refineOrderedListOfProductsInCustomSort(List ordere int descendingOrder = orderedListOfProducts.size(); for (String productId : orderedListOfProducts) { - Optional productOptional = productRepository.findById(productId); + Optional productOptional = productRepo.findById(productId); if (productOptional.isEmpty()) { throw new InvalidParamException(ErrorCode.PRODUCT_NOT_FOUND, "Not found product with id: " + productId); } Product product = productOptional.get(); product.setCustomOrder(descendingOrder--); - productRepository.save(product); + productRepo.save(product); productEntries.add(product); } @@ -614,7 +630,7 @@ public void removeFieldFromAllProductDocuments(String fieldName) { } public void transferComputedDataFromDB(Product product) { - productRepository.findById(product.getId()).ifPresent(persistedData -> + productRepo.findById(product.getId()).ifPresent(persistedData -> ProductFactory.transferComputedPersistedDataToProduct(persistedData, product) ); } @@ -631,7 +647,7 @@ public boolean syncOneProduct(String productId, String marketItemPath, Boolean o log.info("Update data of product {} from meta.json and logo files", productId); mappingMetaDataAndLogoFromGHContent(gitHubContents, product); updateRelatedThingsOfProductFromGHContent(gitHubContents, product); - productRepository.save(product); + productRepo.save(product); metadataService.syncProductMetadata(product); log.info("Sync product {} is finished!", productId); return true; @@ -642,17 +658,24 @@ public boolean syncOneProduct(String productId, String marketItemPath, Boolean o return false; } + @Override + public void clearAllProductVersion() { + metadataRepo.deleteAll(); + metadataSyncRepo.deleteAll(); + mavenArtifactVersionRepo.deleteAll(); + } + private Product renewProductById(String productId, String marketItemPath, Boolean overrideMarketItemPath) { Product product = new Product(); - productRepository.findById(productId).ifPresent(foundProduct -> { + productRepo.findById(productId).ifPresent(foundProduct -> { ProductFactory.transferComputedPersistedDataToProduct(foundProduct, product); - imageRepository.deleteAllByProductId(foundProduct.getId()); - metadataRepository.deleteAllByProductId(foundProduct.getId()); - metadataSyncRepository.deleteAllByProductId(foundProduct.getId()); + imageRepo.deleteAllByProductId(foundProduct.getId()); + metadataRepo.deleteAllByProductId(foundProduct.getId()); + metadataSyncRepo.deleteAllByProductId(foundProduct.getId()); mavenArtifactVersionRepo.deleteAllById(List.of(foundProduct.getId())); - productModuleContentRepository.deleteAllByProductId(foundProduct.getId()); - productJsonContentRepository.deleteAllByProductId(foundProduct.getId()); - productRepository.delete(foundProduct); + productModuleContentRepo.deleteAllByProductId(foundProduct.getId()); + productJsonContentRepo.deleteAllByProductId(foundProduct.getId()); + productRepo.delete(foundProduct); } ); @@ -692,6 +715,6 @@ private void updateProductContentForNonStandardProduct(List ghContent product.setReleasedVersions(List.of(INITIAL_VERSION)); product.setNewestReleaseVersion(INITIAL_VERSION); axonIvyProductRepoService.extractReadMeFileFromContents(product, ghContentEntity, initialContent); - productModuleContentRepository.save(initialContent); + productModuleContentRepo.save(initialContent); } } diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/impl/VersionServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/service/impl/VersionServiceImpl.java index 7107fa2e5..b6328cc15 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/impl/VersionServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/impl/VersionServiceImpl.java @@ -1,6 +1,7 @@ package com.axonivy.market.service.impl; import com.axonivy.market.bo.Artifact; +import com.axonivy.market.comparator.LatestVersionComparator; import com.axonivy.market.constants.MavenConstants; import com.axonivy.market.controller.ProductDetailsController; import com.axonivy.market.entity.MavenArtifactVersion; @@ -29,9 +30,12 @@ import org.springframework.util.CollectionUtils; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import static com.axonivy.market.constants.ProductJsonConstants.NAME; @@ -93,10 +97,14 @@ public Map getProductJsonContentByIdAndTag(String productId, Str @Override public List getVersionsForDesigner(String productId) { List versionAndUrlList = new ArrayList<>(); - MavenArtifactVersion existingMavenArtifactVersion = mavenArtifactVersionRepo.findById(productId).orElse( - MavenArtifactVersion.builder().productId(productId).build()); - List versions = MavenUtils.getAllExistingVersions(existingMavenArtifactVersion, true, - null); + List releasedVersions = + VersionUtils.getInstallableVersionsFromMetadataList(metadataRepo.findByProductId(productId)); + if (CollectionUtils.isEmpty(releasedVersions)) { + return Collections.emptyList(); + } + List versions = releasedVersions.stream().filter( + version -> VersionUtils.isOfficialVersionOrUnReleasedDevVersion(releasedVersions, version)).sorted( + new LatestVersionComparator()).toList(); for (String version : versions) { Link link = linkTo( methodOn(ProductDetailsController.class).findProductJsonContent(productId, version)).withSelfRel(); diff --git a/marketplace-service/src/main/java/com/axonivy/market/util/MavenUtils.java b/marketplace-service/src/main/java/com/axonivy/market/util/MavenUtils.java index 42ecbb337..95037618f 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/util/MavenUtils.java +++ b/marketplace-service/src/main/java/com/axonivy/market/util/MavenUtils.java @@ -319,4 +319,9 @@ public static List getAllExistingVersions(MavenArtifactVersion existingM return VersionUtils.getVersionsToDisplay(new ArrayList<>(existingProductsArtifactByVersion), isShowDevVersion, designerVersion); } + + public static boolean isProductMetadata(Metadata metadata) { + return StringUtils.endsWith(Objects.requireNonNullElse(metadata, new Metadata()).getArtifactId(), + MavenConstants.PRODUCT_ARTIFACT_POSTFIX); + } } diff --git a/marketplace-service/src/main/java/com/axonivy/market/util/VersionUtils.java b/marketplace-service/src/main/java/com/axonivy/market/util/VersionUtils.java index 7003b9514..ab36f2185 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/util/VersionUtils.java +++ b/marketplace-service/src/main/java/com/axonivy/market/util/VersionUtils.java @@ -4,6 +4,7 @@ import com.axonivy.market.comparator.MavenVersionComparator; import com.axonivy.market.constants.CommonConstants; import com.axonivy.market.constants.GitHubConstants; +import com.axonivy.market.entity.Metadata; import com.axonivy.market.entity.Product; import com.axonivy.market.enums.NonStandardProduct; import lombok.extern.log4j.Log4j2; @@ -17,10 +18,12 @@ import org.springframework.util.CollectionUtils; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; import static com.axonivy.market.constants.MavenConstants.*; @Log4j2 @@ -71,7 +74,7 @@ public static String getBestMatchVersion(List versions, String designerV return bestMatchVersion; } - public static boolean isOfficialVersionOrUnReleasedDevVersion(List versions, String version) { + public static boolean isOfficialVersionOrUnReleasedDevVersion(Collection versions, String version) { if (isReleasedVersion(version)) { return true; } @@ -150,7 +153,7 @@ public static String getOldestVersion(List tags) { if (!CollectionUtils.isEmpty(tags)) { List releasedTags = tags.stream().map(tag -> tag.getName().replaceAll(NON_NUMERIC_CHAR, Strings.EMPTY)) .distinct().sorted(new LatestVersionComparator()).toList(); - return CollectionUtils.lastElement(releasedTags); + result = CollectionUtils.lastElement(releasedTags); } return result; } @@ -182,4 +185,13 @@ public static boolean isMajorVersion(String version) { public static boolean isMinorVersion(String version) { return getNumbersOnly(version).split(MAIN_VERSION_REGEX).length == 2 && isReleasedVersion(version); } + + public static List getInstallableVersionsFromMetadataList(List metadataList) { + if (CollectionUtils.isEmpty(metadataList)) { + return new ArrayList<>(); + } + return metadataList.stream().filter(MavenUtils::isProductMetadata).findAny().map( + metadata -> metadata.getVersions().stream().sorted(new LatestVersionComparator()).collect( + Collectors.toList())).orElse(new ArrayList<>()); + } } diff --git a/marketplace-service/src/test/java/com/axonivy/market/BaseSetup.java b/marketplace-service/src/test/java/com/axonivy/market/BaseSetup.java index 8745dabb7..55df55847 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/BaseSetup.java +++ b/marketplace-service/src/test/java/com/axonivy/market/BaseSetup.java @@ -11,13 +11,16 @@ import com.axonivy.market.enums.Language; import com.axonivy.market.enums.SortOption; import com.axonivy.market.model.MavenArtifactModel; +import com.axonivy.market.util.MavenUtils; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Assertions; 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.util.CollectionUtils; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -40,6 +43,7 @@ public class BaseSetup { protected static final Pageable PAGEABLE = PageRequest.of(0, 20, Sort.by(SortOption.ALPHABETICALLY.getOption()).descending()); protected static final String MOCK_PRODUCT_ID = "bpmn-statistic"; + protected static final String MOCK_PRODUCT_ID_WITH_TAG = "bpmn-statistic-v10.0.10"; protected static final String MOCK_ARTIFACT_ID = "bpmn-statistic"; protected static final String MOCK_PRODUCT_ARTIFACT_ID = "bpmn-statistic-product"; protected static final String MOCK_RELEASED_VERSION = "10.0.10"; @@ -68,6 +72,7 @@ public class BaseSetup { ".com/com/axonivy/util/bpmn-statistic/10.0.10-SNAPSHOT/bpmn-statistic-10.0.10-SNAPSHOT.zip"; protected static final String MOCK_ARTIFACT_NAME = "bpmn statistic (zip)"; protected static final String MOCK_ARTIFACT_DOWNLOAD_FILE = "bpmn-statistic.zip"; + protected static final String LEGACY_INSTALLATION_COUNT_PATH_FIELD_NAME = "legacyInstallationCountPath"; protected Page createPageProductsMock() { var mockProducts = new ArrayList(); @@ -165,11 +170,23 @@ protected MavenArtifactVersion getMockMavenArtifactVersion() { new HashMap<>()); } + protected MavenArtifactVersion getMockMavenArtifactVersionWithData() { + MavenArtifactVersion mockMavenArtifactVersion = getMockMavenArtifactVersion(); + Map> mockArtifactModelsByVersion = new HashMap<>(); + mockArtifactModelsByVersion.put(MOCK_SNAPSHOT_VERSION, new ArrayList<>()); + mockMavenArtifactVersion.setProductArtifactsByVersion(mockArtifactModelsByVersion); + return mockMavenArtifactVersion; + } + + protected Product getMockProduct() { + Product mockProduct = Product.builder().id(MOCK_PRODUCT_ID).releasedVersions(new ArrayList<>()).artifacts( + List.of(getMockArtifact())).build(); + mockProduct.getReleasedVersions().add(MOCK_RELEASED_VERSION); + return mockProduct; + } + protected List getMockProducts() { - Product mockProduct = - Product.builder().id(MOCK_PRODUCT_ID).releasedVersions(List.of(MOCK_RELEASED_VERSION)).artifacts( - List.of(getMockArtifact())).build(); - return List.of(mockProduct); + return List.of(getMockProduct()); } protected Metadata getMockMetadata() { 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 15fd40305..b536e1552 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 @@ -150,12 +150,12 @@ void testSyncProductsInvalidToken() { @Test void testSyncMavenVersionSuccess() { - var response = productController.syncProductVersions(AUTHORIZATION_HEADER); + var response = productController.syncProductVersions(AUTHORIZATION_HEADER, false); assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); assertTrue(response.hasBody()); assertEquals(ErrorCode.MAVEN_VERSION_SYNC_FAILED.getCode(), Objects.requireNonNull(response.getBody()).getHelpCode()); when(metadataService.syncAllProductsMetadata()).thenReturn(1); - response = productController.syncProductVersions(AUTHORIZATION_HEADER); + response = productController.syncProductVersions(AUTHORIZATION_HEADER, false); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue(response.hasBody()); assertEquals(ErrorCode.SUCCESSFUL.getCode(), Objects.requireNonNull(response.getBody()).getHelpCode()); @@ -169,7 +169,7 @@ void testSyncMavenVersionWithInvalidToken() { .validateUserInOrganizationAndTeam(any(String.class), any(String.class), any(String.class)); UnauthorizedException exception = assertThrows(UnauthorizedException.class, - () -> productController.syncProductVersions(INVALID_AUTHORIZATION_HEADER)); + () -> productController.syncProductVersions(INVALID_AUTHORIZATION_HEADER, false)); assertEquals(ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText(), exception.getMessage()); } diff --git a/marketplace-service/src/test/java/com/axonivy/market/repository/impl/CustomProductRepositoryImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/repository/impl/CustomProductRepositoryImplTest.java index 573220118..4ed738baf 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/repository/impl/CustomProductRepositoryImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/repository/impl/CustomProductRepositoryImplTest.java @@ -4,7 +4,8 @@ import com.axonivy.market.constants.MongoDBConstants; import com.axonivy.market.entity.Product; import com.axonivy.market.entity.ProductDesignerInstallation; -import com.axonivy.market.entity.ProductModuleContent; +import com.axonivy.market.repository.MavenArtifactVersionRepository; +import com.axonivy.market.repository.MetadataRepository; import com.axonivy.market.repository.ProductModuleContentRepository; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -25,15 +26,16 @@ @ExtendWith(MockitoExtension.class) class CustomProductRepositoryImplTest extends BaseSetup { - private static final String ID = "bmpn-statistic"; - private static final String TAG = "v10.0.21"; @Mock ProductModuleContentRepository contentRepo; private Product mockProduct; private Aggregation mockAggregation; @Mock private MongoTemplate mongoTemplate; - + @Mock + private MetadataRepository metadataRepo; + @Mock + private MavenArtifactVersionRepository mavenArtifactVersionRepo; @InjectMocks private CustomProductRepositoryImpl repo; @@ -52,7 +54,7 @@ private void setUpMockAggregateResult() { when(mongoTemplate.aggregate(any(Aggregation.class), eq(MongoDBConstants.PRODUCT_COLLECTION), eq(Product.class))).thenReturn(aggregationResults); mockProduct = new Product(); - mockProduct.setId(ID); + mockProduct.setId(MOCK_PRODUCT_ID); when(aggregationResults.getUniqueMappedResult()).thenReturn(mockProduct); } @@ -77,70 +79,39 @@ void testReleasedVersionsById_WhenResultIsNull() { eq(Product.class))).thenReturn(aggregationResults); when(aggregationResults.getUniqueMappedResult()).thenReturn(null); - List results = repo.getReleasedVersionsById(ID); + List results = repo.getReleasedVersionsById(MOCK_PRODUCT_ID); assertEquals(0, results.size()); } @Test void testGetProductById() { setUpMockAggregateResult(); - Product actualProduct = repo.getProductById(ID); - assertEquals(mockProduct, actualProduct); - } - - @Test - void testGetProductById_andFindProductModuleContentByNewestVersion() { - mockAggregation = mock(Aggregation.class); - AggregationResults aggregationResults = mock(AggregationResults.class); - - when(mongoTemplate.aggregate(any(Aggregation.class), eq(MongoDBConstants.PRODUCT_COLLECTION), - eq(Product.class))).thenReturn(aggregationResults); - - ProductModuleContent productModuleContent = ProductModuleContent.builder() - .productId("bmpn-statistic") - .tag("v11.3.0") - .build(); - - when(contentRepo.findByTagAndProductId("v11.3.0", ID)).thenReturn(productModuleContent); - - mockProduct = Product.builder() - .id(ID) - .newestReleaseVersion("12.0.0-m264") - .releasedVersions(List.of("11.1.1", "11.1.0", "11.3.0")) - .productModuleContent(productModuleContent) - .build(); - - when(aggregationResults.getUniqueMappedResult()).thenReturn(mockProduct); - - Product actualProduct = repo.getProductByIdWithNewestReleaseVersion(ID, false); - - verify(contentRepo, times(1)).findByTagAndProductId("v11.3.0", ID); + Product actualProduct = repo.getProductById(MOCK_PRODUCT_ID); assertEquals(mockProduct, actualProduct); } @Test void testGetProductByIdAndTag() { setUpMockAggregateResult(); - Product actualProduct = repo.getProductByIdWithTagOrVersion(ID, TAG); + Product actualProduct = repo.getProductByIdWithTagOrVersion(MOCK_PRODUCT_ID, MOCK_TAG_FROM_RELEASED_VERSION); assertEquals(mockProduct, actualProduct); } @Test void testGetReleasedVersionsById() { setUpMockAggregateResult(); - List actualReleasedVersions = repo.getReleasedVersionsById(ID); + List actualReleasedVersions = repo.getReleasedVersionsById(MOCK_PRODUCT_ID); assertEquals(mockProduct.getReleasedVersions(), actualReleasedVersions); } @Test void testIncreaseInstallationCount() { - String productId = "testProductId"; Product product = new Product(); - product.setId(productId); + product.setId(MOCK_PRODUCT_ID); product.setInstallationCount(5); when(mongoTemplate.findAndModify(any(Query.class), any(Update.class), any(FindAndModifyOptions.class), eq(Product.class))).thenReturn(product); - int updatedCount = repo.increaseInstallationCount(productId); + int updatedCount = repo.increaseInstallationCount(MOCK_PRODUCT_ID); assertEquals(5, updatedCount); verify(mongoTemplate).findAndModify(any(Query.class), any(Update.class), any(FindAndModifyOptions.class), eq(Product.class)); @@ -150,7 +121,7 @@ void testIncreaseInstallationCount() { void testIncreaseInstallationCount_NullProduct() { when(mongoTemplate.findAndModify(any(Query.class), any(Update.class), any(FindAndModifyOptions.class), eq(Product.class))).thenReturn(null); - int updatedCount = repo.increaseInstallationCount(ID); + int updatedCount = repo.increaseInstallationCount(MOCK_PRODUCT_ID); assertEquals(0, updatedCount); } @@ -158,15 +129,15 @@ void testIncreaseInstallationCount_NullProduct() { void testUpdateInitialCount() { setUpMockAggregateResult(); int initialCount = 10; - repo.updateInitialCount(ID, initialCount); + repo.updateInitialCount(MOCK_PRODUCT_ID, initialCount); verify(mongoTemplate).updateFirst(any(Query.class), - eq(new Update().inc("InstallationCount", initialCount).set("SynchronizedInstallationCount", true)), + eq(new Update().inc(MongoDBConstants.INSTALLATION_COUNT, initialCount).set(MongoDBConstants.SYNCHRONIZED_INSTALLATION_COUNT, true)), eq(Product.class)); } @Test void testIncreaseInstallationCountForProductByDesignerVersion() { - repo.increaseInstallationCountForProductByDesignerVersion("portal", "10.0.20"); + repo.increaseInstallationCountForProductByDesignerVersion(MOCK_PRODUCT_ID, MOCK_RELEASED_VERSION); verify(mongoTemplate).upsert(any(Query.class), any(Update.class), eq(ProductDesignerInstallation.class)); } } diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/impl/ProductServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/impl/ProductServiceImplTest.java index 104e39a74..897b97ddc 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/impl/ProductServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/impl/ProductServiceImplTest.java @@ -5,6 +5,7 @@ import com.axonivy.market.criteria.ProductSearchCriteria; import com.axonivy.market.entity.GitHubRepoMeta; import com.axonivy.market.entity.MavenArtifactVersion; +import com.axonivy.market.entity.Metadata; import com.axonivy.market.entity.Product; import com.axonivy.market.entity.ProductCustomSort; import com.axonivy.market.entity.ProductModuleContent; @@ -31,8 +32,7 @@ import com.axonivy.market.repository.ProductRepository; import com.axonivy.market.service.ImageService; import com.axonivy.market.service.MetadataService; -import com.axonivy.market.util.MavenUtils; -import com.axonivy.market.util.VersionUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -44,8 +44,6 @@ import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -61,7 +59,6 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -79,8 +76,6 @@ @ExtendWith(MockitoExtension.class) class ProductServiceImplTest extends BaseSetup { - - public static final String RELEASE_TAG = "v10.0.2"; private static final long LAST_CHANGE_TIME = 1718096290000L; private static final Pageable PAGEABLE = PageRequest.of(0, 20, Sort.by(SortOption.ALPHABETICALLY.getOption()).descending()); @@ -106,27 +101,27 @@ class ProductServiceImplTest extends BaseSetup { @Mock private GHRepository ghRepository; @Mock - private ProductRepository productRepository; + private ProductRepository productRepo; @Mock - private ProductModuleContentRepository productModuleContentRepository; + private ProductModuleContentRepository productModuleContentRepo; @Mock - private ProductJsonContentRepository productJsonContentRepository; + private ProductJsonContentRepository productJsonContentRepo; @Mock private GHAxonIvyMarketRepoService marketRepoService; @Mock - private GitHubRepoMetaRepository repoMetaRepository; + private GitHubRepoMetaRepository repoMetaRepo; @Mock private GitHubService gitHubService; @Mock private MetadataService metadataService; @Mock - private ImageRepository imageRepository; + private ImageRepository imageRepo; @Mock - private MetadataRepository metadataRepository; + private MetadataRepository metadataRepo; @Mock - private MetadataSyncRepository metadataSyncRepository; + private MetadataSyncRepository metadataSyncRepo; @Mock - private ProductCustomSortRepository productCustomSortRepository; + private ProductCustomSortRepository productCustomSortRepo; @Mock private GHAxonIvyProductRepoService ghAxonIvyProductRepoService; @Mock @@ -143,17 +138,18 @@ public void setup() { @Test void testUpdateInstallationCountForProduct() { - String designerVersion = "10.0.20"; - int result = productService.updateInstallationCountForProduct(null, designerVersion); + int result = productService.updateInstallationCountForProduct(null, MOCK_RELEASED_VERSION); assertEquals(0, result); - Product product = mockProduct(); - when(productRepository.getProductById(product.getId())).thenReturn(product); - when(productRepository.increaseInstallationCount(product.getId())).thenReturn(31); - result = productService.updateInstallationCountForProduct(product.getId(), designerVersion); + Product product = getMockProduct(); + product.setSynchronizedInstallationCount(true); + when(productRepo.getProductById(MOCK_PRODUCT_ID)).thenReturn(product); + when(productRepo.increaseInstallationCount(MOCK_PRODUCT_ID)).thenReturn(31); + + result = productService.updateInstallationCountForProduct(MOCK_PRODUCT_ID, MOCK_RELEASED_VERSION); assertEquals(31, result); - result = productService.updateInstallationCountForProduct(product.getId(), ""); + result = productService.updateInstallationCountForProduct(MOCK_PRODUCT_ID, StringUtils.EMPTY); assertEquals(31, result); } @@ -161,8 +157,8 @@ void testUpdateInstallationCountForProduct() { void testSyncInstallationCountWithNewProduct() { Product product = new Product(); product.setSynchronizedInstallationCount(null); - product.setId("portal"); - ReflectionTestUtils.setField(productService, "legacyInstallationCountPath", INSTALLATION_FILE_PATH); + product.setId(MOCK_PRODUCT_ID); + ReflectionTestUtils.setField(productService, LEGACY_INSTALLATION_COUNT_PATH_FIELD_NAME, INSTALLATION_FILE_PATH); productService.syncInstallationCountWithProduct(product); @@ -172,8 +168,8 @@ void testSyncInstallationCountWithNewProduct() { @Test void testSyncInstallationCountWithProduct() { - ReflectionTestUtils.setField(productService, "legacyInstallationCountPath", INSTALLATION_FILE_PATH); - Product product = mockProduct(); + ReflectionTestUtils.setField(productService, LEGACY_INSTALLATION_COUNT_PATH_FIELD_NAME, INSTALLATION_FILE_PATH); + Product product = getMockProduct(); product.setSynchronizedInstallationCount(false); productService.syncInstallationCountWithProduct(product); @@ -182,16 +178,11 @@ void testSyncInstallationCountWithProduct() { assertTrue(product.getSynchronizedInstallationCount()); } - private Product mockProduct() { - return Product.builder().id("google-maps-connector").language("English").synchronizedInstallationCount(true) - .build(); - } - @Test void testFindProducts() { language = "en"; // Start testing by All - when(productRepository.searchByCriteria(any(), any(Pageable.class))).thenReturn(mockResultReturn); + when(productRepo.searchByCriteria(any(), any(Pageable.class))).thenReturn(mockResultReturn); // Executes var result = productService.findProducts(TypeOption.ALL.getOption(), keyword, language, false, PAGEABLE); assertEquals(mockResultReturn, result); @@ -210,7 +201,7 @@ void testFindProducts() { @Test void testFindProductsInRESTClientOfDesigner() { productService.findProducts(TypeOption.CONNECTORS.getOption(), keyword, Language.EN.getValue(), true, PAGEABLE); - verify(productRepository).searchByCriteria(productSearchCriteriaArgumentCaptor.capture(), any(Pageable.class)); + verify(productRepo).searchByCriteria(productSearchCriteriaArgumentCaptor.capture(), any(Pageable.class)); assertEquals(List.of(SHORT_DESCRIPTIONS), productSearchCriteriaArgumentCaptor.getValue().getExcludeFields()); } @@ -230,7 +221,7 @@ void testSyncProductsAsUpdateMetaJSONFromGitHub() throws IOException { var mockGHContent = mockGHContentAsMetaJSON(); when(gitHubService.getGHContent(any(), anyString(), any())).thenReturn(mockGHContent); when(mockGHContent.read()).thenReturn(this.getClass().getResourceAsStream(EMPTY_SOURCE_URL_META_JSON_FILE)); - when(productRepository.save(any(Product.class))).thenReturn(new Product()); + when(productRepo.save(any(Product.class))).thenReturn(new Product()); // Executes var result = productService.syncLatestDataFromMarketRepo(); @@ -281,14 +272,14 @@ void testSyncProductsAsUpdateLogoFromGitHub() throws IOException { @Test void testFindAllProductsWithKeyword() { language = "en"; - when(productRepository.searchByCriteria(any(), any(Pageable.class))).thenReturn(mockResultReturn); + when(productRepo.searchByCriteria(any(), any(Pageable.class))).thenReturn(mockResultReturn); // Executes var result = productService.findProducts(TypeOption.ALL.getOption(), keyword, language, false, PAGEABLE); assertEquals(mockResultReturn, result); - verify(productRepository).searchByCriteria(any(), any(Pageable.class)); + verify(productRepo).searchByCriteria(any(), any(Pageable.class)); // Test has keyword - when(productRepository.searchByCriteria(any(), any(Pageable.class))) + when(productRepo.searchByCriteria(any(), any(Pageable.class))) .thenReturn(new PageImpl<>(mockResultReturn.stream() .filter(product -> product.getNames().get(Language.EN.getValue()).equals(SAMPLE_PRODUCT_NAME)) .toList())); @@ -298,7 +289,7 @@ void testFindAllProductsWithKeyword() { assertEquals(SAMPLE_PRODUCT_NAME, result.getContent().get(0).getNames().get(Language.EN.getValue())); // Test has keyword and type is connector - when(productRepository.searchByCriteria(any(), any(Pageable.class))) + when(productRepo.searchByCriteria(any(), any(Pageable.class))) .thenReturn(new PageImpl<>(mockResultReturn.stream() .filter(product -> product.getNames().get(Language.EN.getValue()).equals(SAMPLE_PRODUCT_NAME) && product.getType().equals(TypeOption.CONNECTORS.getCode())) @@ -314,7 +305,7 @@ void testFindAllProductsWithKeyword() { void testSyncProductsFirstTime() throws IOException { var mockCommit = mockGHCommitHasSHA1(SHA1_SAMPLE); when(marketRepoService.getLastCommit(anyLong())).thenReturn(mockCommit); - when(repoMetaRepository.findByRepoName(anyString())).thenReturn(null); + when(repoMetaRepo.findByRepoName(anyString())).thenReturn(null); when(ghAxonIvyProductRepoService.getReadmeAndProductContentsFromTag(any(), any(), anyString())).thenReturn( mockReadmeProductContent()); when(gitHubService.getRepository(any())).thenReturn(ghRepository); @@ -322,7 +313,7 @@ void testSyncProductsFirstTime() throws IOException { GHTag mockTag = mock(GHTag.class); GHCommit mockGHCommit = mock(GHCommit.class); - when(mockTag.getName()).thenReturn(RELEASE_TAG); + when(mockTag.getName()).thenReturn(MOCK_TAG_FROM_RELEASED_VERSION); when(mockTag.getCommit()).thenReturn(mockGHCommit); when(mockGHCommit.getCommitDate()).thenReturn(new Date()); @@ -330,15 +321,15 @@ void testSyncProductsFirstTime() throws IOException { Map> mockGHContentMap = new HashMap<>(); mockGHContentMap.put(SAMPLE_PRODUCT_ID, mockMetaJsonAndLogoList()); when(marketRepoService.fetchAllMarketItems()).thenReturn(mockGHContentMap); - when(productModuleContentRepository.saveAll(anyList())).thenReturn(List.of(mockReadmeProductContent())); + when(productModuleContentRepo.saveAll(anyList())).thenReturn(List.of(mockReadmeProductContent())); when(imageService.mappingImageFromGHContent(any(), any(), anyBoolean())) .thenReturn(GHAxonIvyProductRepoServiceImplTest.mockImage()); - when(productRepository.save(any(Product.class))).thenReturn(new Product()); + when(productRepo.save(any(Product.class))).thenReturn(new Product()); // Executes productService.syncLatestDataFromMarketRepo(); - verify(productModuleContentRepository).saveAll(argumentCaptorProductModuleContents.capture()); - verify(productRepository).save(argumentCaptor.capture()); + verify(productModuleContentRepo).saveAll(argumentCaptorProductModuleContents.capture()); + verify(productRepo).save(argumentCaptor.capture()); assertEquals(1, argumentCaptorProductModuleContents.getValue().size()); assertThat(argumentCaptorProductModuleContents.getValue().get(0).getId()) @@ -349,7 +340,7 @@ void testSyncProductsFirstTime() throws IOException { void testSyncProductsFirstTimeWithOutSourceUrl() throws IOException { var mockCommit = mockGHCommitHasSHA1(SHA1_SAMPLE); when(marketRepoService.getLastCommit(anyLong())).thenReturn(mockCommit); - when(repoMetaRepository.findByRepoName(anyString())).thenReturn(null); + when(repoMetaRepo.findByRepoName(anyString())).thenReturn(null); var mockContent = mockGHContentAsMetaJSON(); InputStream inputStream = this.getClass().getResourceAsStream(EMPTY_SOURCE_URL_META_JSON_FILE); @@ -363,33 +354,30 @@ void testSyncProductsFirstTimeWithOutSourceUrl() throws IOException { when(marketRepoService.fetchAllMarketItems()).thenReturn(mockGHContentMap); when(imageService.mappingImageFromGHContent(any(), any(), anyBoolean())).thenReturn( GHAxonIvyProductRepoServiceImplTest.mockImage()); - when(productRepository.save(any(Product.class))).thenReturn(new Product()); + when(productRepo.save(any(Product.class))).thenReturn(new Product()); // Executes productService.syncLatestDataFromMarketRepo(); - verify(productModuleContentRepository).save(argumentCaptorProductModuleContent.capture()); + verify(productModuleContentRepo).save(argumentCaptorProductModuleContent.capture()); assertEquals("1.0", argumentCaptorProductModuleContent.getValue().getTag()); } @Test void testSyncProductsSecondTime() throws IOException { + Product mockProduct = getMockProduct(); + mockProduct.setProductModuleContent(mockReadmeProductContent()); + mockProduct.setRepositoryName("axonivy-market/bpmn-statistic"); var gitHubRepoMeta = mock(GitHubRepoMeta.class); when(gitHubRepoMeta.getLastSHA1()).thenReturn(SHA1_SAMPLE); var mockCommit = mockGHCommitHasSHA1(SHA1_SAMPLE); when(marketRepoService.getLastCommit(anyLong())).thenReturn(mockCommit); - when(repoMetaRepository.findByRepoName(anyString())).thenReturn(gitHubRepoMeta); - - when(productRepository.findAll()).thenReturn(mockProducts()); - - GHCommit mockGHCommit = mock(GHCommit.class); + when(repoMetaRepo.findByRepoName(anyString())).thenReturn(gitHubRepoMeta); + when(productRepo.findAll()).thenReturn(List.of(mockProduct)); GHTag mockTag = mock(GHTag.class); - when(mockTag.getName()).thenReturn("v10.0.2"); + when(mockTag.getName()).thenReturn(MOCK_TAG_FROM_RELEASED_VERSION); GHTag mockTag2 = mock(GHTag.class); when(mockTag2.getName()).thenReturn("v10.0.3"); - when(mockTag2.getCommit()).thenReturn(mockGHCommit); - - when(mockGHCommit.getCommitDate()).thenReturn(new Date()); when(gitHubService.getRepositoryTags(anyString())).thenReturn(Arrays.asList(mockTag, mockTag2)); ProductModuleContent mockReturnProductContent = mockReadmeProductContent(); @@ -397,14 +385,14 @@ void testSyncProductsSecondTime() throws IOException { when(ghAxonIvyProductRepoService.getReadmeAndProductContentsFromTag(any(), any(), anyString())) .thenReturn(mockReturnProductContent); - when(productModuleContentRepository.saveAll(anyList())) + when(productModuleContentRepo.saveAll(anyList())) .thenReturn(List.of(mockReadmeProductContent(), mockReturnProductContent)); // Executes productService.syncLatestDataFromMarketRepo(); - verify(productModuleContentRepository).saveAll(argumentCaptorProductModuleContents.capture()); - verify(productRepository).save(argumentCaptor.capture()); + verify(productModuleContentRepo).saveAll(argumentCaptorProductModuleContents.capture()); + verify(productRepo).save(argumentCaptor.capture()); assertThat(argumentCaptor.getValue().getProductModuleContent().getId()) .isEqualTo(mockReadmeProductContent().getId()); } @@ -415,7 +403,7 @@ void testNothingToSync() { when(gitHubRepoMeta.getLastSHA1()).thenReturn(SHA1_SAMPLE); var mockCommit = mockGHCommitHasSHA1(SHA1_SAMPLE); when(marketRepoService.getLastCommit(anyLong())).thenReturn(mockCommit); - when(repoMetaRepository.findByRepoName(anyString())).thenReturn(gitHubRepoMeta); + when(repoMetaRepo.findByRepoName(anyString())).thenReturn(gitHubRepoMeta); // Executes var result = productService.syncLatestDataFromMarketRepo(); @@ -427,16 +415,16 @@ void testNothingToSync() { void testSyncNullProductModuleContent() { var mockCommit = mockGHCommitHasSHA1(SHA1_SAMPLE); when(marketRepoService.getLastCommit(anyLong())).thenReturn(mockCommit); - when(repoMetaRepository.findByRepoName(anyString())).thenReturn(null); + when(repoMetaRepo.findByRepoName(anyString())).thenReturn(null); Map> mockGHContentMap = new HashMap<>(); mockGHContentMap.put(SAMPLE_PRODUCT_ID, new ArrayList<>()); when(marketRepoService.fetchAllMarketItems()).thenReturn(mockGHContentMap); - when(productRepository.save(any(Product.class))).thenReturn(new Product()); + when(productRepo.save(any(Product.class))).thenReturn(new Product()); // Executes productService.syncLatestDataFromMarketRepo(); - verify(productRepository).save(argumentCaptor.capture()); + verify(productRepo).save(argumentCaptor.capture()); assertThat(argumentCaptor.getValue().getProductModuleContent()).isNull(); } @@ -447,66 +435,64 @@ void testSearchProducts() { String type = TypeOption.ALL.getOption(); keyword = "on"; language = "en"; - when(productRepository.searchByCriteria(any(), any(Pageable.class))).thenReturn( + when(productRepo.searchByCriteria(any(), any(Pageable.class))).thenReturn( mockResultReturn); var result = productService.findProducts(type, keyword, language, false, simplePageable); assertEquals(result, mockResultReturn); - verify(productRepository).searchByCriteria(any(), any(Pageable.class)); + verify(productRepo).searchByCriteria(any(), any(Pageable.class)); } @Test void testFetchProductDetail() { - String id = "amazon-comprehend"; - Product mockProduct = mockResultReturn.getContent().get(0); + MavenArtifactVersion mockMavenArtifactVersion = getMockMavenArtifactVersionWithData(); + Product mockProduct = getMockProduct(); + when(mavenArtifactVersionRepo.findById(MOCK_PRODUCT_ID)).thenReturn( + Optional.ofNullable(mockMavenArtifactVersion)); + when(productRepo.getProductByIdWithTagOrVersion(MOCK_PRODUCT_ID, MOCK_TAG_FROM_SNAPSHOT_VERSION)).thenReturn(null); mockProduct.setSynchronizedInstallationCount(true); - when(productRepository.getProductByIdWithNewestReleaseVersion(id, false)).thenReturn(mockProduct); - Product result = productService.fetchProductDetail(id, false); + Product result = productService.fetchProductDetail(MOCK_PRODUCT_ID, true); + assertNull(result); + } + + @Test + void testGetProductByIdWithNewestReleaseVersion() { + MavenArtifactVersion mockMavenArtifactVersion = getMockMavenArtifactVersionWithData(); + Product mockProduct = getMockProduct(); + when(mavenArtifactVersionRepo.findById(MOCK_PRODUCT_ID)).thenReturn( + Optional.ofNullable(mockMavenArtifactVersion)); + when(productRepo.getProductByIdWithTagOrVersion(MOCK_PRODUCT_ID, MOCK_TAG_FROM_SNAPSHOT_VERSION)).thenReturn(mockProduct); + Product result = productService.getProductByIdWithNewestReleaseVersion(MOCK_PRODUCT_ID, true); + assertEquals(mockProduct, result); + when(mavenArtifactVersionRepo.findById(MOCK_PRODUCT_ID)).thenReturn(Optional.ofNullable(null)); + when(productRepo.getReleasedVersionsById(MOCK_PRODUCT_ID)).thenReturn(List.of(MOCK_SNAPSHOT_VERSION)); + when(productRepo.getProductByIdWithTagOrVersion(MOCK_PRODUCT_ID, MOCK_SNAPSHOT_VERSION)).thenReturn(mockProduct); + result = productService.getProductByIdWithNewestReleaseVersion(MOCK_PRODUCT_ID, true); assertEquals(mockProduct, result); - verify(productRepository, times(1)).getProductByIdWithNewestReleaseVersion(id, false); } @Test void testFetchProductDetailByIdAndVersion() { - String id = "amazon-comprehend"; - String version = "10.0.2"; Product mockProduct = mockResultReturn.getContent().get(0); - when(productRepository.getProductByIdWithTagOrVersion(id, version)).thenReturn(mockProduct); + when(productRepo.getProductByIdWithTagOrVersion(MOCK_PRODUCT_ID, MOCK_RELEASED_VERSION)).thenReturn(mockProduct); - Product result = productService.fetchProductDetailByIdAndVersion(id, version); + Product result = productService.fetchProductDetailByIdAndVersion(MOCK_PRODUCT_ID, MOCK_RELEASED_VERSION); assertEquals(mockProduct, result); - verify(productRepository).getProductByIdWithTagOrVersion(id, version); + verify(productRepo).getProductByIdWithTagOrVersion(MOCK_PRODUCT_ID, MOCK_RELEASED_VERSION); } @Test void testFetchBestMatchProductDetailByIdAndVersion() { - String id = "amazon-comprehend"; - String version = "v10.0.2"; - String bestMatchVersion = "10.0.2"; - - MavenArtifactVersion mockMavenArtifactVersion = new MavenArtifactVersion(); - mockMavenArtifactVersion.getProductArtifactsByVersion().put(bestMatchVersion, Collections.emptyList()); - - List mockVersions = Arrays.asList("10.0.1", "10.0.2"); - when(mavenArtifactVersionRepo.findById(id)).thenReturn(Optional.of(mockMavenArtifactVersion)); - try (MockedStatic mockVersionUtils = Mockito.mockStatic(VersionUtils.class)) { - when(MavenUtils.getAllExistingVersions(mockMavenArtifactVersion, true, null)).thenReturn(mockVersions); - mockVersionUtils.when(() -> VersionUtils.getBestMatchVersion(mockVersions, version)).thenReturn(bestMatchVersion); - mockVersionUtils.when(() -> VersionUtils.convertVersionToTag(id, bestMatchVersion)).thenReturn(version); - - Product mockProduct = new Product(); - mockProduct.setSynchronizedInstallationCount(true); - when(productRepository.getProductByIdWithTagOrVersion(id, version)).thenReturn(mockProduct); - - Product result = productService.fetchBestMatchProductDetail(id, version); - - assertEquals(mockProduct, result); - assertEquals(bestMatchVersion, result.getBestMatchVersion()); - verify(mavenArtifactVersionRepo).findById(id); - verify(productRepository).getProductByIdWithTagOrVersion(id, version); - } + ReflectionTestUtils.setField(productService, LEGACY_INSTALLATION_COUNT_PATH_FIELD_NAME, INSTALLATION_FILE_PATH); + Product mockProduct = getMockProduct(); + Metadata mockMetadata = getMockMetadataWithVersions(); + mockMetadata.setArtifactId(MOCK_PRODUCT_ARTIFACT_ID); + when(metadataRepo.findByProductId(MOCK_PRODUCT_ID)).thenReturn(List.of(mockMetadata)); + when(productRepo.getProductByIdWithTagOrVersion(MOCK_PRODUCT_ID,MOCK_TAG_FROM_RELEASED_VERSION)).thenReturn(mockProduct); + Product result = productService.fetchBestMatchProductDetail(MOCK_PRODUCT_ID, MOCK_RELEASED_VERSION); + assertEquals(mockProduct, result); } @Test @@ -526,7 +512,7 @@ void testGetCompatibilityFromNumericTag() { void testRemoveFieldFromAllProductDocuments() { productService.removeFieldFromAllProductDocuments("customOrder"); - verify(mongoTemplate, times(1)).updateMulti(any(Query.class), any(Update.class), eq(Product.class)); + verify(mongoTemplate).updateMulti(any(Query.class), any(Update.class), eq(Product.class)); } @Test @@ -535,19 +521,19 @@ void testRefineOrderedListOfProductsInCustomSort() throws InvalidParamException List orderedListOfProducts = List.of(SAMPLE_PRODUCT_ID); Product mockProduct = new Product(); mockProduct.setId(SAMPLE_PRODUCT_ID); - when(productRepository.findById(SAMPLE_PRODUCT_ID)).thenReturn(Optional.of(mockProduct)); + when(productRepo.findById(SAMPLE_PRODUCT_ID)).thenReturn(Optional.of(mockProduct)); List refinedProducts = productService.refineOrderedListOfProductsInCustomSort(orderedListOfProducts); assertEquals(1, refinedProducts.size()); assertEquals(1, refinedProducts.get(0).getCustomOrder()); - verify(productRepository, times(1)).findById(SAMPLE_PRODUCT_ID); + verify(productRepo).findById(SAMPLE_PRODUCT_ID); } @Test void testRefineOrderedListOfProductsInCustomSort_ProductNotFound() { List orderedListOfProducts = List.of(SAMPLE_PRODUCT_ID); - when(productRepository.findById(SAMPLE_PRODUCT_ID)).thenReturn(Optional.empty()); + when(productRepo.findById(SAMPLE_PRODUCT_ID)).thenReturn(Optional.empty()); InvalidParamException exception = assertThrows(InvalidParamException.class, () -> productService.refineOrderedListOfProductsInCustomSort(orderedListOfProducts)); @@ -563,14 +549,14 @@ void testAddCustomSortProduct() throws InvalidParamException { Product mockProduct = new Product(); mockProduct.setId(SAMPLE_PRODUCT_ID); - when(productRepository.findById(SAMPLE_PRODUCT_ID)).thenReturn(Optional.of(mockProduct)); + when(productRepo.findById(SAMPLE_PRODUCT_ID)).thenReturn(Optional.of(mockProduct)); productService.addCustomSortProduct(customSortRequest); - verify(productCustomSortRepository).deleteAll(); + verify(productCustomSortRepo).deleteAll(); verify(mongoTemplate).updateMulti(any(Query.class), any(Update.class), eq(Product.class)); - verify(productCustomSortRepository).save(any(ProductCustomSort.class)); - verify(productRepository).saveAll(productListArgumentCaptor.capture()); + verify(productCustomSortRepo).save(any(ProductCustomSort.class)); + verify(productRepo).saveAll(productListArgumentCaptor.capture()); List capturedProducts = productListArgumentCaptor.getValue(); assertEquals(1, capturedProducts.size()); @@ -579,12 +565,12 @@ void testAddCustomSortProduct() throws InvalidParamException { @Test void testUpdateProductInstallationCountWhenNotSynchronized() { - Product product = mockProduct(); + Product product = getMockProduct(); product.setSynchronizedInstallationCount(false); String id = product.getId(); - ReflectionTestUtils.setField(productService, "legacyInstallationCountPath", INSTALLATION_FILE_PATH); + ReflectionTestUtils.setField(productService, LEGACY_INSTALLATION_COUNT_PATH_FIELD_NAME, INSTALLATION_FILE_PATH); - when(productRepository.updateInitialCount(eq(id), anyInt())).thenReturn(10); + when(productRepo.updateInitialCount(eq(id), anyInt())).thenReturn(10); productService.updateProductInstallationCount(id, product); @@ -603,8 +589,8 @@ void testCreateOrder() { void testClearAllProducts() { productService.clearAllProducts(); - verify(repoMetaRepository).deleteAll(); - verify(productRepository).deleteAll(); + verify(repoMetaRepo).deleteAll(); + verify(productRepo).deleteAll(); } private void mockMarketRepoMetaStatus() { @@ -613,7 +599,7 @@ private void mockMarketRepoMetaStatus() { mockMarketRepoMeta.setRepoName(GitHubConstants.AXONIVY_MARKETPLACE_REPO_NAME); mockMarketRepoMeta.setLastChange(LAST_CHANGE_TIME); mockMarketRepoMeta.setLastSHA1(SHA1_SAMPLE); - when(repoMetaRepository.findByRepoName(any())).thenReturn(mockMarketRepoMeta); + when(repoMetaRepo.findByRepoName(any())).thenReturn(mockMarketRepoMeta); } private GHCommit mockGHCommitHasSHA1(String sha1) { @@ -636,21 +622,15 @@ private GHContent mockGHContentAsLogo() { private ProductModuleContent mockReadmeProductContent() { ProductModuleContent productModuleContent = new ProductModuleContent(); - productModuleContent.setId("amazon-comprehendv-10.0.2"); - productModuleContent.setTag("v10.0.2"); - productModuleContent.setName("Amazon Comprehend"); + productModuleContent.setId(MOCK_PRODUCT_ID_WITH_TAG); + productModuleContent.setTag(MOCK_TAG_FROM_RELEASED_VERSION); + productModuleContent.setName(MOCK_PRODUCT_NAME); Map description = new HashMap<>(); description.put(Language.EN.getValue(), "testDescription"); productModuleContent.setDescription(description); return productModuleContent; } - private List mockProducts() { - Product product1 = Product.builder().id("amazon-comprehend-connector").repositoryName("axonivy-market/amazon-comprehend-connector") - .productModuleContent(mockReadmeProductContent()).build(); - return List.of(product1); - } - @Test void testUpdateNewLogoFromGitHub_removeOldLogo() throws IOException { // Start testing by adding new logo @@ -674,14 +654,14 @@ void testUpdateNewLogoFromGitHub_removeOldLogo() throws IOException { when(mockCommit.getSHA1()).thenReturn(UUID.randomUUID().toString()); mockGitHubFile.setStatus(FileStatus.REMOVED); when(marketRepoService.fetchMarketItemsBySHA1Range(any(), any())).thenReturn(List.of(mockGitHubFile)); - when(imageRepository.findByImageUrlEndsWithIgnoreCase(anyString())) + when(imageRepo.findByImageUrlEndsWithIgnoreCase(anyString())) .thenReturn(List.of(GHAxonIvyProductRepoServiceImplTest.mockImage())); // Executes result = productService.syncLatestDataFromMarketRepo(); - verify(productRepository, times(1)).deleteById(anyString()); - verify(imageRepository, times(1)).deleteAllByProductId(anyString()); - verify(imageRepository, times(1)).findByImageUrlEndsWithIgnoreCase(anyString()); + verify(productRepo).deleteById(anyString()); + verify(imageRepo).deleteAllByProductId(anyString()); + verify(imageRepo).findByImageUrlEndsWithIgnoreCase(anyString()); assertNotNull(result); assertFalse(result.isEmpty()); } @@ -699,15 +679,15 @@ void testUpdateNewLogoFromGitHub_ModifyLogo() throws IOException { mockGitHubFile.setType(FileType.META); mockGitHubFile.setStatus(FileStatus.REMOVED); when(marketRepoService.fetchMarketItemsBySHA1Range(any(), any())).thenReturn(List.of(mockGitHubFile)); - when(productRepository.findByMarketDirectory(anyString())).thenReturn(mockProducts()); + when(productRepo.findByMarketDirectory(anyString())).thenReturn(getMockProducts()); // Executes var result = productService.syncLatestDataFromMarketRepo(); assertNotNull(result); assertFalse(result.isEmpty()); - verify(productRepository, times(1)).deleteById(anyString()); - verify(imageRepository, times(1)).deleteAllByProductId(anyString()); + verify(productRepo).deleteById(anyString()); + verify(imageRepo).deleteAllByProductId(anyString()); } @Test @@ -715,11 +695,11 @@ void testSyncOneProduct() throws IOException { Product mockProduct = new Product(); mockProduct.setId(SAMPLE_PRODUCT_ID); mockProduct.setMarketDirectory(SAMPLE_PRODUCT_PATH); - when(productRepository.findById(anyString())).thenReturn(Optional.of(mockProduct)); + when(productRepo.findById(anyString())).thenReturn(Optional.of(mockProduct)); var mockContents = mockMetaJsonAndLogoList(); when(marketRepoService.getMarketItemByPath(anyString())).thenReturn(mockContents); when(metadataService.syncProductMetadata(any(Product.class))).thenReturn(true); - when(productRepository.save(any(Product.class))).thenReturn(mockProduct); + when(productRepo.save(any(Product.class))).thenReturn(mockProduct); // Executes var result = productService.syncOneProduct(SAMPLE_PRODUCT_PATH, SAMPLE_PRODUCT_ID, false); assertTrue(result); @@ -750,7 +730,7 @@ void testSyncProductsAsUpdateMetaJSONFromGitHub_AddVendorLogo() throws IOExcepti var mockGHContent = mockGHContentAsMetaJSON(); when(gitHubService.getGHContent(any(), anyString(), any())).thenReturn(mockGHContent); when(mockGHContent.read()).thenReturn(this.getClass().getResourceAsStream(META_JSON_FILE_WITH_VENDOR_INFORMATION)); - when(productRepository.save(any(Product.class))).thenReturn(new Product()); + when(productRepo.save(any(Product.class))).thenReturn(new Product()); // Executes var result = productService.syncLatestDataFromMarketRepo(); diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/impl/VersionServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/impl/VersionServiceImplTest.java index c096c3672..8bc7f8f5e 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/impl/VersionServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/impl/VersionServiceImplTest.java @@ -5,6 +5,7 @@ import com.axonivy.market.bo.Artifact; import com.axonivy.market.constants.MavenConstants; import com.axonivy.market.entity.MavenArtifactVersion; +import com.axonivy.market.entity.Metadata; import com.axonivy.market.entity.Product; import com.axonivy.market.entity.ProductJsonContent; import com.axonivy.market.enums.DevelopmentVersion; @@ -32,6 +33,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -130,11 +132,17 @@ void testFindArchivedArtifactInfoBestMatchWithVersion() { void testGetVersionsForDesigner() { MavenArtifactVersion mockMavenArtifactVersion = new MavenArtifactVersion(); List mockVersions = List.of("11.3.0-SNAPSHOT", "11.1.1", "11.1.0", "10.0.2"); + Metadata mockMetadata = getMockMetadata(); + mockMetadata.setArtifactId(MOCK_PRODUCT_ARTIFACT_ID); + mockMetadata.setVersions(new HashSet<>()); + mockMetadata.getVersions().addAll(mockVersions); for (String version : mockVersions) { mockMavenArtifactVersion.getProductArtifactsByVersion().put(version, new ArrayList<>()); } - when(mavenArtifactVersionRepo.findById(MOCK_PRODUCT_ID)).thenReturn(Optional.of(mockMavenArtifactVersion)); List result = versionService.getVersionsForDesigner(MOCK_PRODUCT_ID); + Assertions.assertTrue(CollectionUtils.isEmpty(result)); + when(metadataRepo.findByProductId(MOCK_PRODUCT_ID)).thenReturn(List.of(mockMetadata)); + result = versionService.getVersionsForDesigner(MOCK_PRODUCT_ID); Assertions.assertEquals(result.stream().map(VersionAndUrlModel::getVersion).toList(), mockVersions); Assertions.assertTrue(result.get(0).getUrl().endsWith("/api/product-details/bpmn-statistic/11.3.0-SNAPSHOT/json")); Assertions.assertTrue(result.get(1).getUrl().endsWith("/api/product-details/bpmn-statistic/11.1.1/json")); @@ -176,9 +184,7 @@ void testGetAllExistingVersions() { MavenArtifactVersion mockMavenArtifactVersion = new MavenArtifactVersion(); Assertions.assertTrue(CollectionUtils.isEmpty(MavenUtils.getAllExistingVersions(mockMavenArtifactVersion, false, StringUtils.EMPTY))); - Map> mockArtifactModelsByVersion = new HashMap<>(); - mockArtifactModelsByVersion.put(MOCK_SNAPSHOT_VERSION, new ArrayList<>()); - mockMavenArtifactVersion.setProductArtifactsByVersion(mockArtifactModelsByVersion); + mockMavenArtifactVersion = getMockMavenArtifactVersionWithData(); Assertions.assertTrue(ObjectUtils.isNotEmpty(MavenUtils.getAllExistingVersions(mockMavenArtifactVersion, true, StringUtils.EMPTY))); Assertions.assertTrue(CollectionUtils.isEmpty(MavenUtils.getAllExistingVersions(mockMavenArtifactVersion, false, diff --git a/marketplace-service/src/test/resources/installationCount.json b/marketplace-service/src/test/resources/installationCount.json index a0c8a3fbb..19b687a4a 100644 --- a/marketplace-service/src/test/resources/installationCount.json +++ b/marketplace-service/src/test/resources/installationCount.json @@ -1,3 +1,4 @@ { - "google-maps-connector": 40 + "google-maps-connector": 40, + "bpmn-statistic": 40 } \ No newline at end of file