diff --git a/marketplace-service/src/main/java/com/axonivy/market/util/ProductContentUtils.java b/marketplace-service/src/main/java/com/axonivy/market/util/ProductContentUtils.java index 43821814c..9e3bbb078 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/util/ProductContentUtils.java +++ b/marketplace-service/src/main/java/com/axonivy/market/util/ProductContentUtils.java @@ -27,7 +27,7 @@ public class ProductContentUtils { public static final String DESCRIPTION = "description"; public static final String DEMO = "demo"; public static final String SETUP = "setup"; - public static final String README_IMAGE_FORMAT = "\\(([^)]*?%s[^)]*?)\\)"; + public static final String README_IMAGE_FORMAT = "\\(([^)]*?/)?%s\\)"; public static final String IMAGE_DOWNLOAD_URL_FORMAT = "(%s)"; private ProductContentUtils() { 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 2b470f035..53ad34759 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/BaseSetup.java +++ b/marketplace-service/src/test/java/com/axonivy/market/BaseSetup.java @@ -51,6 +51,8 @@ public class BaseSetup { protected static final String MOCK_GROUP_ID = "com.axonivy.util"; protected static final String MOCK_PRODUCT_NAME = "bpmn statistic"; protected static final String MOCK_PRODUCT_REPOSITORY_NAME = "axonivy-market/bpmn-statistic"; + protected static final String MOCK_IMAGE_ID_FORMAT_1 = "imageId-66e2b14868f2f95b2f95549a"; + protected static final String MOCK_IMAGE_ID_FORMAT_2 = "imageId-66e2b14868f2f95b2f95550a"; protected static final String MOCK_PRODUCT_JSON_FILE_PATH = "src/test/resources/product.json"; protected static final String MOCK_PRODUCT_JSON_FILE_PATH_NO_URL = "src/test/resources/productMissingURL.json"; protected static final String MOCK_PRODUCT_JSON_WITH_DROPINS_FILE_PATH = "src/test/resources/product-dropins.json"; diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/impl/ProductContentServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/impl/ProductContentServiceImplTest.java index d008f9adf..addba7e0f 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/impl/ProductContentServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/impl/ProductContentServiceImplTest.java @@ -64,8 +64,8 @@ void testUpdateImagesWithDownloadUrl() throws IOException { String productId = MOCK_PRODUCT_ID; try (MockedStatic mockedFiles = Mockito.mockStatic(Files.class)) { Path downloadLocation = Paths.get(EXTRACT_DIR_LOCATION); - Path imagePath1 = Paths.get("screen1.png"); - Path imagePath2 = Paths.get("screen2.png"); + Path imagePath1 = Paths.get("images/slash-command.png"); + Path imagePath2 = Paths.get("images/create-slash-command.png"); when(Files.walk(downloadLocation)).thenReturn(Stream.of(downloadLocation, imagePath1, imagePath2)); mockedFiles.when(() -> Files.isRegularFile(imagePath1)).thenReturn(true); @@ -76,9 +76,9 @@ void testUpdateImagesWithDownloadUrl() throws IOException { String result = productContentService.updateImagesWithDownloadUrl(productId, EXTRACT_DIR_LOCATION, readmeContent); - String expectedResult = readmeContent.replace("screen1.png \"Screen 1\"", - "imageId-66e2b14868f2f95b2f95549a").replace("screen2.png " + "\"Screen 2\"", - "imageId-66e2b14868f2f95b2f95550a"); + String expectedResult = readmeContent.replace("images/slash-command.png", + MOCK_IMAGE_ID_FORMAT_1).replace("images/create-slash-command.png", + MOCK_IMAGE_ID_FORMAT_2); assertEquals(expectedResult, result); } } diff --git a/marketplace-service/src/test/java/com/axonivy/market/util/ProductContentUtilsTest.java b/marketplace-service/src/test/java/com/axonivy/market/util/ProductContentUtilsTest.java index 9aec6fa4f..949da49da 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/util/ProductContentUtilsTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/util/ProductContentUtilsTest.java @@ -4,12 +4,15 @@ import com.axonivy.market.bo.Artifact; import com.axonivy.market.entity.ProductModuleContent; import org.apache.commons.lang3.StringUtils; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(MockitoExtension.class) class ProductContentUtilsTest extends BaseSetup { @@ -18,23 +21,38 @@ void testUpdateProductModule() { ProductModuleContent mockProductModuleContent = new ProductModuleContent(); Artifact mockArtifact = getMockArtifact(); ProductContentUtils.updateProductModule(mockProductModuleContent, List.of(mockArtifact)); - Assertions.assertEquals(mockArtifact.getGroupId(), mockProductModuleContent.getGroupId()); - Assertions.assertEquals(mockArtifact.getArtifactId(), mockProductModuleContent.getArtifactId()); - Assertions.assertEquals(mockArtifact.getName(), mockProductModuleContent.getName()); - Assertions.assertEquals(mockArtifact.getType(), mockProductModuleContent.getType()); + assertEquals(mockArtifact.getGroupId(), mockProductModuleContent.getGroupId()); + assertEquals(mockArtifact.getArtifactId(), mockProductModuleContent.getArtifactId()); + assertEquals(mockArtifact.getName(), mockProductModuleContent.getName()); + assertEquals(mockArtifact.getType(), mockProductModuleContent.getType()); } @Test void testRemoveFirstLine() { - Assertions.assertEquals(StringUtils.EMPTY, ProductContentUtils.removeFirstLine(null)); - Assertions.assertEquals(StringUtils.EMPTY, ProductContentUtils.removeFirstLine(" ")); - Assertions.assertEquals(StringUtils.EMPTY, ProductContentUtils.removeFirstLine("#")); - Assertions.assertEquals("Second line", ProductContentUtils.removeFirstLine("#First line\nSecond line")); + assertEquals(StringUtils.EMPTY, ProductContentUtils.removeFirstLine(null)); + assertEquals(StringUtils.EMPTY, ProductContentUtils.removeFirstLine(" ")); + assertEquals(StringUtils.EMPTY, ProductContentUtils.removeFirstLine("#")); + assertEquals("Second line", ProductContentUtils.removeFirstLine("#First line\nSecond line")); } @Test void testGetReadmeFileLocale() { - Assertions.assertEquals(StringUtils.EMPTY, ProductContentUtils.getReadmeFileLocale("README.md")); - Assertions.assertEquals("DE", ProductContentUtils.getReadmeFileLocale("README_DE.md")); + assertEquals(StringUtils.EMPTY, ProductContentUtils.getReadmeFileLocale("README.md")); + assertEquals("DE", ProductContentUtils.getReadmeFileLocale("README_DE.md")); + } + + @Test + void testReplaceImageDirWithImageCustomId() { + String readmeContents = getMockReadmeContent(); + Map imageUrls = new HashMap<>(); + imageUrls.put("slash-command.png", MOCK_IMAGE_ID_FORMAT_1); + imageUrls.put("create-slash-command.png", MOCK_IMAGE_ID_FORMAT_2); + + String expectedResult = readmeContents.replace("images/slash-command.png", + MOCK_IMAGE_ID_FORMAT_1).replace("images/create-slash-command.png", + MOCK_IMAGE_ID_FORMAT_2); + String updatedContents = ProductContentUtils.replaceImageDirWithImageCustomId(imageUrls, readmeContents); + + assertEquals(expectedResult, updatedContents); } } \ No newline at end of file diff --git a/marketplace-service/src/test/resources/README.md b/marketplace-service/src/test/resources/README.md index ced1d2e07..90a2001d8 100644 --- a/marketplace-service/src/test/resources/README.md +++ b/marketplace-service/src/test/resources/README.md @@ -1,37 +1,63 @@ -# Employee Onboarding solution - -Axon Ivy’s Employee Onboarding solution provides best practice guidance to HR -specialists, ensuring that provisioning and all other aspects of the employee -onboarding process are handled quickly and efficiently. In addition, HR managers -and their superiors can capture all the information required to automatically -set up employees in HR systems. The solution: - -- ensures timely and personalized communication with new employees from their - first day on the job (and even before) -- guarantees no tasks are left undone -- helps new hires become productive much faster -- makes sure that required materials are procured and ready for employees in - advance -- increases employee retention rates -- contributes to a positive company image - -### Summary - -You only have one chance to make a first impression. Failing to deliver a smooth -employee onboarding experience can contribute to high turnover rates and -inefficiency. A structured onboarding process ensures that employees have all -the necessary materials and information available when they start work, which -increases employee satisfaction. Axon Ivy’s Employee Onboarding Solution not -only coordinates processes within HR departments, it also automates functions -across external departments and process owners. - -### Information - -- Industry: All Industries -- Compatible Version(s): 8.0.x, 10.0.x +# Mattermost Connector -## Demo +Axon Ivy’s mattermost connector helps you to accelerate process automation initiatives by integrating Mattermost features into your process application within no time. + +This connector: -![Screen 1](screen1.png "Screen 1") +- supports you with a demo implementation to reduce your integration effort. +- gives you full power to the [Mattermost's APIs](https://api.mattermost.com/). +- allow you to start the Axon Ivy process by hitting the slash command key from the mattermost's channel. +- allow you to send a message to the mattermost's channel from the Axon Ivy workplace. +- notifies users on the channel for new Axon Ivy workflow Tasks. + +## Demo -![Screen 2](screen2.png "Screen 2") \ No newline at end of file +1. Hit the slash command key on the channel's chat. + The Axon Ivy process will be triggered and create a new task. + The task's information will be sent to the channel by a message. + +![call-slash-command](images/slash-command.png) + +### Setup + +Mattermost Instance + +1. Ref to [Deploy Mattermost](https://docs.mattermost.com/guides/deployment.html). +2. Create Team, User, ... +3.Enable Bot Account Creation and create a bot account for sending notification to the channel Axon Ivy. E.g. + axonivy-bot +4.Create a slash command in the Integrations menu. + ![create-slash-command](images/create-slash-command.png) + +Add the following `Variables` to your `variables.yaml`: + +- `Variables.mattermost.baseUrl` +- `Variables.mattermost.accessToken` +- `Variables.mattermost.teamName` +- `Variables.mattermost.botName` + +and replace the values with your given setup. + +``` +# == Variables == +# +# You can define here your project Variables. +# If you want to define/override a Variable for a specific Environment, +# add an additional ‘variables.yaml’ file in a subdirectory in the ‘Config’ folder: +# '/Config/_/variables.yaml +# +Variables: +# myVariable: value + mattermost: + # The base URL of matter most + baseUrl: "" + # Personal access tokens function similarly to session tokens and can be used by integrations to authenticate against the REST API. + accessToken: "" + # The team name + teamName: "" + # The name of bot that will inform the task on the channel + botName: "" + # This variable is used for getting incoming webhook list per page + incomingWebhookPerPage: 200 + +```