diff --git a/pom.xml b/pom.xml index c5687c3..78ec863 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ 2.9.0 3.11.0 - 1.18.2 + 1.18.12 7.7.0 diff --git a/src/assembly/all-assembly.xml b/src/assembly/all-assembly.xml index 9eb64a6..08d969a 100644 --- a/src/assembly/all-assembly.xml +++ b/src/assembly/all-assembly.xml @@ -4,7 +4,6 @@ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> all - zip false diff --git a/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathAddToQueueConnector.java b/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathAddToQueueConnector.java index 1959864..69b9750 100644 --- a/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathAddToQueueConnector.java +++ b/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathAddToQueueConnector.java @@ -19,6 +19,7 @@ import java.time.format.DateTimeParseException; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.stream.Collectors; @@ -39,11 +40,11 @@ public class UIPathAddToQueueConnector extends UIPathConnector { static final String QUEUE_NAME = "queueName"; static final String REFERENCE_INPUT = "reference"; static final String QUEUE_CONTENT = "queueContent"; - private static final String PRIORITY_INPUT = "priority"; - private static final String DUE_DATE_INPUT = "dueDate"; - private static final String DEFER_DATE_INPUT = "deferDate"; - private static final String ITEM_ID_OUTPUT = "itemId"; - private static final String ITEM_KEY_OUTPUT = "itemKey"; + static final String PRIORITY_INPUT = "priority"; + static final String DUE_DATE_INPUT = "dueDate"; + static final String DEFER_DATE_INPUT = "deferDate"; + static final String ITEM_ID_OUTPUT = "itemId"; + static final String ITEM_KEY_OUTPUT = "itemKey"; @Override public void validateInputParameters() throws ConnectorValidationException { @@ -86,9 +87,11 @@ protected void executeBusinessLogic() throws ConnectorException { .setName(getQueueName()) .setPriority(getPriority()); getReference().ifPresent(itemData::setReference); - Optional content = getContent(); + Optional> content = getContent(); if (content.isPresent()) { - Map contentMap = content.get(); + Map contentMap = content.get().entrySet().stream().collect(Collectors.toMap( + entry -> entry.getKey().toString(), + Entry::getValue)); itemData.setContent(contentMap.entrySet() .stream() .collect(Collectors.toMap(Map.Entry::getKey, @@ -124,12 +127,12 @@ Optional getReference() { return Optional.ofNullable((String) getInputParameter(REFERENCE_INPUT)); } - Optional getContent() { + Optional> getContent() { Object inputParameter = getInputParameter(QUEUE_CONTENT); if (inputParameter instanceof List) { return Optional.of(toMap(inputParameter)); } - return Optional.ofNullable((Map) getInputParameter(QUEUE_CONTENT)); + return Optional.ofNullable((Map) getInputParameter(QUEUE_CONTENT)); } String getPriority() { diff --git a/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathConnector.java b/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathConnector.java index e0612ec..4dd532f 100644 --- a/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathConnector.java +++ b/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathConnector.java @@ -48,7 +48,7 @@ public abstract class UIPathConnector extends AbstractConnector { @Override public void validateInputParameters() throws ConnectorValidationException { - checkcloudInput(); + checkCloudInput(); if (isCloud()) { checkMandatoryStringInput(ACCOUNT_LOGICAL_NAME); checkMandatoryStringInput(TENANT_LOGICAL_NAME); @@ -62,7 +62,7 @@ public void validateInputParameters() throws ConnectorValidationException { } } - protected void checkcloudInput() throws ConnectorValidationException { + protected void checkCloudInput() throws ConnectorValidationException { Boolean value = null; try { value = (Boolean) getInputParameter(CLOUD); @@ -153,7 +153,7 @@ protected UIPathService createService() { Builder retrofitBuilder = new Retrofit.Builder() .addConverterFactory(new WrappedAttributeConverter(mapper)) .addConverterFactory(JacksonConverterFactory.create()) - .baseUrl(appendTraillingSlash(getUrl())); + .baseUrl(getUrl()); if (client != null) { retrofitBuilder.client(client); @@ -195,13 +195,14 @@ String getPassword() { } String getUrl() { - return isCloud() - ? String.format("%s/%s/%s", CLOUD_ORCHESTRATOR_BASE_URL, getAccountLogicalName(), getTenantLogicalName()) - : (String) getInputParameter(URL); + return appendTraillingSlash(isCloud() + ? String.format("%s/%s/%s", CLOUD_ORCHESTRATOR_BASE_URL, getAccountLogicalName(), + getTenantLogicalName()) + : (String) getInputParameter(URL)); } - Boolean isCloud() { - return (Boolean) getInputParameter(CLOUD); + boolean isCloud() { + return (boolean) getInputParameter(CLOUD); } String getAccountLogicalName() { diff --git a/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathStartJobsConnector.java b/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathStartJobsConnector.java index 2a28895..2267b71 100644 --- a/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathStartJobsConnector.java +++ b/src/main/java/org/bonitasoft/engine/connector/uipath/UIPathStartJobsConnector.java @@ -102,29 +102,29 @@ Optional getStrategy() { return Optional.ofNullable((String) getInputParameter(STRATEGY)); } - Optional getInputArguments() { + Optional> getInputArguments() { Object inputParameter = getInputParameter(INPUT_ARGS); if (inputParameter instanceof List) { return Optional.of(toMap(inputParameter)); } - return Optional.ofNullable((Map) getInputParameter(INPUT_ARGS)); + return Optional.ofNullable((Map) getInputParameter(INPUT_ARGS)); } void checkArgsInput() throws ConnectorValidationException { - Optional inputArguments = getInputArguments(); + Optional> inputArguments = getInputArguments(); if (inputArguments.isPresent()) { - Map map = inputArguments.get(); - Set nonStringKeys = (Set) map.keySet().stream().filter(key -> !(key instanceof String)) + Map map = inputArguments.get(); + Set nonStringKeys = map.keySet().stream().filter(key -> !(key instanceof String)) .collect(Collectors.toSet()); if (!nonStringKeys.isEmpty()) { throw new ConnectorValidationException( String.format("Only String keys are allowed in job input arguments. Found %s.", nonStringKeys)); } - Set nonSerializableValue = (Set) map.values().stream().filter(value -> { + Set nonSerializableValue = map.values().stream().filter(value -> { try { mapper.writeValueAsString(value); return false; - } catch (Throwable t) { + } catch (Exception e) { return true; } }).collect(Collectors.toSet()); @@ -136,8 +136,8 @@ void checkArgsInput() throws ConnectorValidationException { } } - private Map handleInputArgs() { - return getInputArguments().orElse(new HashMap()); + private Map handleInputArgs() { + return getInputArguments().orElse(new HashMap<>()); } List startJobs(String token, Release release, List robotIds) @@ -167,12 +167,10 @@ List startJobs(String token, Release release, List robotIds) throw new ConnectorException("Failed to start job.", e); } if (!response.isSuccessful()) { - LOGGER.error(response.toString()); - try { - throw new ConnectorException(response.errorBody().string()); - } catch (IOException e) { - throw new ConnectorException("Failed to read response body.", e); + if (LOGGER.isErrorEnabled()) { + LOGGER.error(response.toString()); } + throw new ConnectorException("Failed to start job: " + response.message()); } return response.body(); } @@ -224,11 +222,7 @@ List releases(String token) throws ConnectorException { throw new ConnectorException("Failed to retrieve releases.", e); } if (!response.isSuccessful()) { - try { - throw new ConnectorException(response.errorBody().string()); - } catch (IOException e) { - throw new ConnectorException("Failed to read response body.", e); - } + throw new ConnectorException("Failed to retrieve releases: " + response.message()); } return response.body(); } @@ -241,11 +235,7 @@ List robots(String token) throws ConnectorException { throw new ConnectorException("Failed to retrieve robots.", e); } if (!response.isSuccessful()) { - try { - throw new ConnectorException(response.errorBody().string()); - } catch (IOException e) { - throw new ConnectorException("Failed to read response body.", e); - } + throw new ConnectorException("Failed to retrieve robots: " + response.message()); } return response.body(); } diff --git a/src/main/java/org/bonitasoft/engine/connector/uipath/model/CloudAuthentication.java b/src/main/java/org/bonitasoft/engine/connector/uipath/model/CloudAuthentication.java index 332c297..d978f00 100644 --- a/src/main/java/org/bonitasoft/engine/connector/uipath/model/CloudAuthentication.java +++ b/src/main/java/org/bonitasoft/engine/connector/uipath/model/CloudAuthentication.java @@ -14,6 +14,8 @@ */ package org.bonitasoft.engine.connector.uipath.model; +import com.fasterxml.jackson.annotation.JsonProperty; + import lombok.AllArgsConstructor; import lombok.Data; @@ -21,8 +23,11 @@ @AllArgsConstructor public class CloudAuthentication { - private String grant_type; - private String client_id; - private String refresh_token; + @JsonProperty("grant_type") + private String grantType; + @JsonProperty("client_id") + private String clientId; + @JsonProperty("refresh_token") + private String refreshToken; } diff --git a/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathAddToQueueConnectorTest.java b/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathAddToQueueConnectorTest.java new file mode 100644 index 0000000..5fc6cad --- /dev/null +++ b/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathAddToQueueConnectorTest.java @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2020 Bonitasoft S.A. + * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2.0 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.bonitasoft.engine.connector.uipath; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.spy; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.junit.WireMockRule; + +class UIPathAddToQueueConnectorTest { + + public static WireMockRule uiPathService; + + @BeforeAll + public static void startMockServer() { + uiPathService = new WireMockRule(8888); + uiPathService.start(); + } + + @AfterAll + public static void stopMockServer() { + uiPathService.stop(); + } + + @BeforeEach + public void configureStubs() throws Exception { + uiPathService.stubFor(WireMock.post(WireMock.urlEqualTo("/api/account/authenticate")) + .willReturn(WireMock.aResponse() + .withHeader("Content-Type", "application/json") + .withBodyFile("mock.authenticate.response.json"))); + + uiPathService + .stubFor(WireMock.post(WireMock.urlEqualTo("/odata/Queues/UiPathODataSvc.AddQueueItem")) + .willReturn(WireMock.aResponse() + .withHeader("Content-Type", "application/json") + .withBodyFile("mock.addToQueue.response.json"))); + } + + private UIPathAddToQueueConnector createConnector() throws Exception { + UIPathAddToQueueConnector connector = spy(new UIPathAddToQueueConnector()); + Map parameters = new HashMap<>(); + parameters.put(UIPathConnector.CLOUD, false); + parameters.put(UIPathConnector.URL, "http://localhost:8888"); + parameters.put(UIPathConnector.TENANT, "a_tenant"); + parameters.put(UIPathConnector.USER, "admin"); + parameters.put(UIPathConnector.PASSWORD, "somePassowrd"); + parameters.put(UIPathAddToQueueConnector.QUEUE_NAME, "myQueue"); + Map content = new HashMap<>(); + content.put("hello", "world"); + parameters.put(UIPathAddToQueueConnector.QUEUE_CONTENT, content); + connector.setInputParameters(parameters); + connector.validateInputParameters(); + return connector; + } + + @Test + void should_add_item_to_queue() throws Exception { + UIPathAddToQueueConnector connector = createConnector(); + + connector.connect(); + Map outputs = connector.execute(); + + assertThat(outputs).containsEntry(UIPathAddToQueueConnector.ITEM_ID_OUTPUT, 39578029L) + .containsEntry(UIPathAddToQueueConnector.ITEM_KEY_OUTPUT,"ef306441-f7a6-4fad-ba8a-d09ec1237e2c"); + } + +} diff --git a/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathConnectorTest.java b/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathConnectorTest.java index ddb7629..5539373 100644 --- a/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathConnectorTest.java +++ b/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathConnectorTest.java @@ -1,54 +1,146 @@ package org.bonitasoft.engine.connector.uipath; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.HashMap; +import java.util.Map; + import org.bonitasoft.engine.connector.ConnectorException; import org.bonitasoft.engine.connector.ConnectorValidationException; +import org.bonitasoft.engine.connector.uipath.model.CloudAuthentication; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import retrofit2.Call; +import retrofit2.Response; -public class UIPathConnectorTest { +class UIPathConnectorTest { @Test - public void should_check_inputs_depending_on_cloud_boolean() throws ConnectorValidationException { - UIPathConnector connector = spy(new UIPathConnector() { + void should_validate_cloud_input_parameter() throws Exception { + UIPathConnector connector = newConnector(); - @Override - protected void checkcloudInput() throws ConnectorValidationException { - } + Map parameters = new HashMap<>(); + parameters.put(UIPathConnector.CLOUD, null); + connector.setInputParameters(parameters); + assertThrows(ConnectorValidationException.class, () -> connector.validateInputParameters()); + + parameters.put(UIPathConnector.CLOUD, "true"); + connector.setInputParameters(parameters); + assertThrows(ConnectorValidationException.class, () -> connector.validateInputParameters()); + } + + @Test + void should_validate_mandatory_url_input_parameter() throws Exception { + UIPathConnector connector = newConnector(); - @Override - protected void checkMandatoryStringInput(String input) throws ConnectorValidationException { - } + Map parameters = new HashMap<>(); + parameters.put(UIPathConnector.CLOUD, false); + parameters.put(UIPathConnector.URL, null); + connector.setInputParameters(parameters); + assertThrows(ConnectorValidationException.class, () -> connector.validateInputParameters()); + + parameters.put(UIPathConnector.URL, 123); + connector.setInputParameters(parameters); + assertThrows(ConnectorValidationException.class, () -> connector.validateInputParameters()); + + parameters.put(UIPathConnector.URL, ""); + connector.setInputParameters(parameters); + assertThrows(ConnectorValidationException.class, () -> connector.validateInputParameters()); + } + + @Test + void should_build_on_premise_url() throws Exception { + UIPathConnector connector = newConnector(); + Map parameters = new HashMap<>(); + parameters.put(UIPathConnector.CLOUD, false); + + parameters.put(UIPathConnector.URL, "https://cloud.uipath.com"); + connector.setInputParameters(parameters); + assertThat(connector.getUrl()).isEqualTo("https://cloud.uipath.com/"); + + parameters.put(UIPathConnector.URL, "https://cloud.uipath.com/"); + connector.setInputParameters(parameters); + assertThat(connector.getUrl()).isEqualTo("https://cloud.uipath.com/"); + } + + @Test + void should_build_cloud_url() throws Exception { + UIPathConnector connector = newConnector(); + Map parameters = new HashMap<>(); + parameters.put(UIPathConnector.CLOUD, true); + + parameters.put(UIPathConnector.ACCOUNT_LOGICAL_NAME, "bonita"); + parameters.put(UIPathConnector.TENANT_LOGICAL_NAME, "bonita"); + connector.setInputParameters(parameters); + assertThat(connector.getUrl()).isEqualTo("https://platform.uipath.com/bonita/bonita/"); + } + + @Test + void should_authenticate_on_premise() throws Exception { + UIPathConnector connector = newConnector(); + UIPathService sevrice = Mockito.mock(UIPathService.class); + Call> call = mock(Call.class); + when(call.execute()).thenReturn(Response.success(new HashMap())); + when(sevrice.authenticate(Mockito.notNull(), Mockito.notNull(), Mockito.notNull())).thenReturn(call); + doReturn(sevrice).when(connector).createService(); + + Map parameters = new HashMap<>(); + parameters.put(UIPathConnector.CLOUD, false); + parameters.put(UIPathConnector.URL, "http://localhost:9090"); + parameters.put(UIPathConnector.USER, "bonitasoft"); + parameters.put(UIPathConnector.TENANT, "a_tenant"); + parameters.put(UIPathConnector.PASSWORD, "somePassword"); + connector.setInputParameters(parameters); + connector.validateInputParameters(); + connector.connect(); + connector.authenticate(); + + verify(sevrice).authenticate("a_tenant", "bonitasoft", "somePassword"); + } + + @Test + void should_authenticate_in_the_cloud() throws Exception { + UIPathConnector connector = newConnector(); + UIPathService sevrice = Mockito.mock(UIPathService.class); + Call> call = mock(Call.class); + when(call.execute()).thenReturn(Response.success(new HashMap())); + when(sevrice.authenticateInCloud(Mockito.anyMap(), Mockito.notNull())).thenReturn(call); + doReturn(sevrice).when(connector).createService(); + + Map parameters = new HashMap<>(); + parameters.put(UIPathConnector.CLOUD, true); + parameters.put(UIPathConnector.ACCOUNT_LOGICAL_NAME, "bonitasoft"); + parameters.put(UIPathConnector.TENANT_LOGICAL_NAME, "a_tenant"); + parameters.put(UIPathConnector.USER_KEY, "someToken"); + parameters.put(UIPathConnector.CLIENT_ID, "1234"); + parameters.put(UIPathGetJobConnector.JOB_ID, "268348846"); + connector.setInputParameters(parameters); + connector.validateInputParameters(); + connector.connect(); + connector.authenticate(); + + Map headers = new HashMap<>(); + headers.put("X-UIPATH-TenantName", "a_tenant"); + headers.put("Content-Type", "application/json"); + CloudAuthentication cloudAuthentication = new CloudAuthentication("refresh_token", "1234", "someToken"); + + verify(sevrice).authenticateInCloud(headers, cloudAuthentication); + } + + private UIPathConnector newConnector() { + return spy(new UIPathConnector() { @Override protected void executeBusinessLogic() throws ConnectorException { } }); - - when(connector.isCloud()).thenReturn(true); - connector.validateInputParameters(); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.ACCOUNT_LOGICAL_NAME); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.TENANT_LOGICAL_NAME); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.CLIENT_ID); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.USER_KEY); - verify(connector, times(0)).checkMandatoryStringInput(UIPathConnector.URL); - verify(connector, times(0)).checkMandatoryStringInput(UIPathConnector.PASSWORD); - verify(connector, times(0)).checkMandatoryStringInput(UIPathConnector.USER); - verify(connector, times(0)).checkMandatoryStringInput(UIPathConnector.TENANT); - - when(connector.isCloud()).thenReturn(false); - connector.validateInputParameters(); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.ACCOUNT_LOGICAL_NAME); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.TENANT_LOGICAL_NAME); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.CLIENT_ID); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.USER_KEY); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.URL); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.PASSWORD); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.USER); - verify(connector, times(1)).checkMandatoryStringInput(UIPathConnector.TENANT); } } diff --git a/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathGetJobConnectorTest.java b/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathGetJobConnectorTest.java index dd42b7f..cd187f7 100644 --- a/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathGetJobConnectorTest.java +++ b/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathGetJobConnectorTest.java @@ -14,8 +14,12 @@ */ package org.bonitasoft.engine.connector.uipath; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; @@ -25,24 +29,31 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.github.tomakehurst.wiremock.junit.WireMockRule; -public class UIPathGetJobConnectorTest { +import retrofit2.Call; +import retrofit2.Response; + +class UIPathGetJobConnectorTest { private static WireMockRule uiPathService; @BeforeAll public static void startMockServer() { - uiPathService = new WireMockRule(8888); - uiPathService.start(); + uiPathService = new WireMockRule(8888); + uiPathService.start(); } - + @AfterAll public static void stopMockServer() { uiPathService.stop(); - } + } + + private Object sevrice; @BeforeEach public void configureStubs() throws Exception { @@ -67,7 +78,7 @@ private UIPathGetJobConnector createConnector() throws Exception { } @Test - public void should_get_pending_job() throws Exception { + void should_get_pending_job() throws Exception { uiPathService.stubFor(WireMock.get(WireMock.urlEqualTo("/odata/Jobs(268348846)")) .willReturn(WireMock.aResponse() .withHeader("Content-Type", "application/json") @@ -76,11 +87,11 @@ public void should_get_pending_job() throws Exception { UIPathGetJobConnector createConnector = createConnector(); createConnector.connect(); Map outputs = createConnector.execute(); - assertThat(outputs.get(UIPathGetJobConnector.JOB_STATE)).isEqualTo(JobState.PENDING.toString()); + assertThat(outputs).containsEntry(UIPathGetJobConnector.JOB_STATE, JobState.PENDING.toString()); } @Test - public void should_get_successful_job() throws Exception { + void should_get_successful_job() throws Exception { uiPathService.stubFor(WireMock.get(WireMock.urlEqualTo("/odata/Jobs(268348846)")) .willReturn(WireMock.aResponse() .withHeader("Content-Type", "application/json") @@ -89,7 +100,9 @@ public void should_get_successful_job() throws Exception { UIPathGetJobConnector createConnector = createConnector(); createConnector.connect(); Map outputs = createConnector.execute(); - assertThat(outputs.get(UIPathGetJobConnector.JOB_STATE)).isEqualTo(JobState.SUCCESSFUL.toString()); - assertThat(outputs.get(UIPathGetJobConnector.JOB_OUTPUT_ARGS)).isEqualTo("{\"out1\" : \"ok\"}"); + assertThat(outputs) + .containsEntry(UIPathGetJobConnector.JOB_STATE, JobState.SUCCESSFUL.toString()) + .containsEntry(UIPathGetJobConnector.JOB_OUTPUT_ARGS, "{\"out1\" : \"ok\"}"); } + } diff --git a/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathStartJobsConnectorTest.java b/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathStartJobsConnectorTest.java index 7e032dc..60f6218 100644 --- a/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathStartJobsConnectorTest.java +++ b/src/test/java/org/bonitasoft/engine/connector/uipath/UIPathStartJobsConnectorTest.java @@ -15,16 +15,20 @@ package org.bonitasoft.engine.connector.uipath; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.spy; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.bonitasoft.engine.connector.ConnectorException; import org.bonitasoft.engine.connector.ConnectorValidationException; import org.bonitasoft.engine.connector.uipath.model.Release; import org.bonitasoft.engine.connector.uipath.model.Robot; -import org.junit.Assert; +import org.bonitasoft.engine.connector.uipath.model.Strategy; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -35,20 +39,20 @@ import lombok.Data; -public class UIPathStartJobsConnectorTest { +class UIPathStartJobsConnectorTest { public static WireMockRule uiPathService; - + @BeforeAll public static void startMockServer() { - uiPathService = new WireMockRule(8888); - uiPathService.start(); + uiPathService = new WireMockRule(8888); + uiPathService.start(); } - + @AfterAll public static void stopMockServer() { uiPathService.stop(); - } + } @BeforeEach public void configureStubs() throws Exception { @@ -75,7 +79,7 @@ public void configureStubs() throws Exception { } @Test - public void should_authenticate() throws Exception { + void should_authenticate() throws Exception { UIPathConnector uiPathConnector = createConnector(); uiPathConnector.connect(); String token = uiPathConnector.authenticate(); @@ -84,7 +88,7 @@ public void should_authenticate() throws Exception { } @Test - public void should_retrieve_releases() throws Exception { + void should_retrieve_releases() throws Exception { UIPathStartJobsConnector uiPathConnector = createConnector(); uiPathConnector.connect(); List releases = uiPathConnector.releases("aToken"); @@ -94,10 +98,16 @@ public void should_retrieve_releases() throws Exception { assertThat(release.getId()).isEqualTo(1); assertThat(release.getProcessKey()).isEqualTo("myProcessKey"); assertThat(release.getCurrentVersion().getId()).isEqualTo(2); + + uiPathService.stubFor(WireMock.get(WireMock.urlEqualTo("/odata/Releases")) + .willReturn(WireMock.aResponse().withStatus(500))); + + assertThrows(ConnectorException.class, () -> uiPathConnector.releases("aToken")); } + @Test - public void should_retrieve_robots() throws Exception { + void should_retrieve_robots() throws Exception { UIPathStartJobsConnector uiPathConnector = createConnector(); uiPathConnector.connect(); List robots = uiPathConnector.robots("aToken"); @@ -105,23 +115,39 @@ public void should_retrieve_robots() throws Exception { assertThat(robots).hasSize(1); Robot robot = robots.get(0); assertThat(robot.getId()).isEqualTo(5); + + uiPathService.stubFor(WireMock.get(WireMock.urlEqualTo("/odata/Robots")) + .willReturn(WireMock.aResponse().withStatus(500))); + assertThrows(ConnectorException.class, () -> uiPathConnector.robots("aToken")); + } + + @Test + void should_retrieve_specific_robots() throws Exception { + UIPathStartJobsConnector uiPathConnector = createConnector(Strategy.SPECIFIC,0,Arrays.asList("5")); + uiPathConnector.connect(); + List robots = uiPathConnector.robots("aToken"); + + assertThat(robots).hasSize(1); + Robot robot = robots.get(0); + assertThat(robot.getId()).isEqualTo(5); } + @Test - public void should_start_jobs() throws Exception { + void should_start_jobs() throws Exception { UIPathConnector uiPathConnector = createConnector(); uiPathConnector.connect(); Map outputs = uiPathConnector.execute(); Object startedJobs = outputs.get("startedJobs"); assertThat(startedJobs).isInstanceOf(List.class); - assertThat((List)startedJobs).hasSize(1); + assertThat((List) startedJobs).hasSize(1); String job = (String) ((List) startedJobs).get(0); assertThat(job).contains("54"); } @Test - public void should_throw_a_ConnectorValidationException_if_input_arguments_has_non_string_keys() throws Exception { + void should_throw_a_ConnectorValidationException_if_input_arguments_has_non_string_keys() throws Exception { UIPathStartJobsConnector uiPathConnector = new UIPathStartJobsConnector(); Map inputs = new HashMap<>(); Map inputArgs = new HashMap<>(); @@ -129,15 +155,44 @@ public void should_throw_a_ConnectorValidationException_if_input_arguments_has_n inputArgs.put(1, "value2"); inputs.put(UIPathStartJobsConnector.INPUT_ARGS, inputArgs); uiPathConnector.setInputParameters(inputs); - - Assert.assertThrows("Only String keys are allowed in job input arguments. Found [1].", - ConnectorValidationException.class, - () -> uiPathConnector.checkArgsInput()); + + assertThrows("Only String keys are allowed in job input arguments. Found [1].", + ConnectorValidationException.class, + () -> uiPathConnector.checkArgsInput()); } + @Test + void should_detect_non_serializable_input_arguments() + throws Exception { + UIPathStartJobsConnector uiPathConnector = new UIPathStartJobsConnector(); + Map inputs = new HashMap<>(); + Map inputArgs = new HashMap<>(); + inputArgs.put("key", "value1"); + inputArgs.put("user", new Object()); + inputs.put(UIPathStartJobsConnector.INPUT_ARGS, inputArgs); + uiPathConnector.setInputParameters(inputs); + assertThrows(ConnectorValidationException.class, () -> uiPathConnector.checkArgsInput()); + } + @Test - public void should_validate_input_arguments() + void should_check_job_count_stratregy() + throws Exception { + createConnector(Strategy.JOBS_COUNT, 3, new ArrayList<>()); + assertThrows(ConnectorValidationException.class, () -> createConnector(Strategy.JOBS_COUNT, null, new ArrayList<>())); + assertThrows(ConnectorValidationException.class, () -> createConnector(Strategy.JOBS_COUNT, 0, new ArrayList<>())); + } + + @Test + void should_check_specific_stratregy() + throws Exception { + createConnector(Strategy.SPECIFIC, 0, Arrays.asList("goldorak","optimus")); + assertThrows(ConnectorValidationException.class, () -> createConnector(Strategy.SPECIFIC, null, new ArrayList<>())); + assertThrows(ConnectorValidationException.class, () -> createConnector(Strategy.SPECIFIC, 0, null)); + } + + @Test + void should_validate_input_arguments() throws Exception { UIPathStartJobsConnector uiPathConnector = new UIPathStartJobsConnector(); Map inputs = new HashMap<>(); @@ -157,7 +212,7 @@ public void should_validate_input_arguments() uiPathConnector.checkArgsInput(); } - private UIPathStartJobsConnector createConnector() throws Exception { + private UIPathStartJobsConnector createConnector(Strategy strategy, Integer jobCount, List robotNames) throws Exception { UIPathStartJobsConnector uiPathConnector = spy(new UIPathStartJobsConnector()); Map parameters = new HashMap<>(); parameters.put(UIPathConnector.CLOUD, false); @@ -167,15 +222,24 @@ private UIPathStartJobsConnector createConnector() throws Exception { parameters.put(UIPathConnector.PASSWORD, "somePassowrd"); parameters.put(UIPathStartJobsConnector.PROCESS_NAME, "myProcessKey"); parameters.put(UIPathStartJobsConnector.PROCESS_VERSION, "1.0"); + parameters.put(UIPathStartJobsConnector.STRATEGY, strategy.toString()); + parameters.put(UIPathStartJobsConnector.JOBS_COUNT, jobCount); + parameters.put(UIPathStartJobsConnector.ROBOTS_NAMES, robotNames); uiPathConnector.setInputParameters(parameters); uiPathConnector.validateInputParameters(); return uiPathConnector; } + + private UIPathStartJobsConnector createConnector() throws Exception { + return createConnector(Strategy.ALL,0, new ArrayList<>()); + } @Data class User { + private String name; private String firstname; private User manager; } + } diff --git a/src/test/resources/__files/mock.addToQueue.response.json b/src/test/resources/__files/mock.addToQueue.response.json new file mode 100644 index 0000000..f111ef8 --- /dev/null +++ b/src/test/resources/__files/mock.addToQueue.response.json @@ -0,0 +1,31 @@ +{ + "QueueDefinitionId": 53772, + "OutputData": null, + "AnalyticsData": null, + "Status": "New", + "ReviewStatus": "None", + "ReviewerUserId": null, + "Key": "ef306441-f7a6-4fad-ba8a-d09ec1237e2c", + "Reference": null, + "ProcessingExceptionType": null, + "DueDate": null, + "RiskSlaDate": null, + "Priority": "Normal", + "DeferDate": null, + "StartProcessing": null, + "EndProcessing": null, + "SecondsInPreviousAttempts": 0, + "AncestorId": null, + "RetryNumber": 0, + "SpecificData": "{\"DynamicProperties\":{\"hello\":\"world\"}}", + "CreationTime": "2020-07-02T13:04:56.4929897Z", + "Progress": null, + "RowVersion": "AAAAAAWxogQ=", + "Id": 39578029, + "ProcessingException": null, + "SpecificContent": { + "hello": "world" + }, + "Output": null, + "Analytics": null +} \ No newline at end of file