/* * Copyright 2017 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.plugin.access.pluggabletask; import com.google.gson.GsonBuilder; import com.thoughtworks.go.plugin.api.config.Property; import com.thoughtworks.go.plugin.api.response.GoPluginApiResponse; import com.thoughtworks.go.plugin.api.response.execution.ExecutionResult; import com.thoughtworks.go.plugin.api.response.validation.ValidationError; import com.thoughtworks.go.plugin.api.response.validation.ValidationResult; import com.thoughtworks.go.plugin.api.task.*; import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.Test; import java.util.HashMap; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class JsonBasedTaskExtensionHandler_V1Test { @Test public void shouldConvertTaskConfigJsonToTaskConfig() { String json = "{\"URL\":{\"default-value\":\"\",\"secure\":false,\"required\":true,\"display-name\":\"Url\",\"display-order\":\"0\"}," + "\"USER\":{\"default-value\":\"foo\",\"secure\":true,\"required\":false,\"display-order\":\"1\"}," + "\"PASSWORD\":{}," + "\"FOO\":null" + "}"; TaskConfig config = new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig(json); Property url = config.get("URL"); assertThat(url.getOption(Property.REQUIRED), is(true)); assertThat(url.getOption(Property.SECURE), is(false)); assertThat(url.getOption(Property.DISPLAY_NAME), is("Url")); assertThat(url.getOption(Property.DISPLAY_ORDER), is(0)); Property user = config.get("USER"); assertThat(user.getOption(Property.REQUIRED), is(false)); assertThat(user.getOption(Property.SECURE), is(true)); assertThat(user.getOption(Property.DISPLAY_NAME), is("USER")); assertThat(user.getOption(Property.DISPLAY_ORDER), is(1)); Property password = config.get("PASSWORD"); assertThat(password.getOption(Property.REQUIRED), is(true)); assertThat(password.getOption(Property.SECURE), is(false)); assertThat(password.getOption(Property.DISPLAY_NAME), is("PASSWORD")); assertThat(password.getOption(Property.DISPLAY_ORDER), is(0)); Property foo = config.get("FOO"); assertThat(foo.getOption(Property.REQUIRED), is(true)); assertThat(foo.getOption(Property.SECURE), is(false)); assertThat(foo.getOption(Property.DISPLAY_NAME), is("FOO")); assertThat(foo.getOption(Property.DISPLAY_ORDER), is(0)); } @Test public void shouldKeepTheConfigInTheOrderOfDisplayOrder(){ String json = "{\"URL\":{\"default-value\":\"\",\"secure\":false,\"required\":true,\"display-name\":\"Url\",\"display-order\":\"0\"}," + "\"PASSWORD\":{\"display-order\":\"2\"}," + "\"USER\":{\"default-value\":\"foo\",\"secure\":true,\"required\":false,\"display-order\":\"1\"}" + "}"; TaskConfig config = new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig(json); assertThat(config.list().get(0).getKey(), is("URL")); assertThat(config.list().get(1).getKey(), is("USER")); assertThat(config.list().get(2).getKey(), is("PASSWORD")); } @Test public void shouldConvertTaskConfigObjectToJson() { TaskConfig taskConfig = new TaskConfig(); TaskConfigProperty p1 = new TaskConfigProperty("k1", "value1"); p1.with(Property.SECURE, true); p1.with(Property.REQUIRED, true); TaskConfigProperty p2 = new TaskConfigProperty("k2", "value2"); p2.with(Property.SECURE, false); p2.with(Property.REQUIRED, true); taskConfig.add(p1); taskConfig.add(p2); String json = new JsonBasedTaskExtensionHandler_V1().convertTaskConfigToJson(taskConfig); Map taskConfigMap = (Map) new GsonBuilder().create().fromJson(json, Object.class); Map property1 = (Map) taskConfigMap.get("k1"); assertThat(property1.get("value").toString(), is("value1")); assertThat(property1.get("secure"), is(true)); assertThat(property1.get("required"), is(true)); Map property2 = (Map) taskConfigMap.get("k2"); assertThat(property2.get("value").toString(), is("value2")); assertThat(property2.get("secure"), is(false)); assertThat(property2.get("required"), is(true)); } @Test public void shouldThrowExceptionForWrongJsonWhileConvertingJsonToTaskConfig() { String json1 = "{}"; try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig(json1); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: The Json for Task Config cannot be empty.")); } String json2 = "{\"URL\":{\"default-value\":true,\"secure\":false,\"required\":true}}"; try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig(json2); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: Key: 'URL' - The Json for Task Config should contain a not-null 'default-value' of type String.")); } String json3 = "{\"URL\":{\"default-value\":\"some value\",\"secure\":\"string\",\"required\":true}}"; try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig(json3); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: Key: 'URL' - The Json for Task Config should contain a 'secure' field of type Boolean.")); } String json4 = "{\"URL\":{\"default-value\":\"some value\",\"secure\":false,\"required\":\"string\"}}"; try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig(json4); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: Key: 'URL' - The Json for Task Config should contain a 'required' field of type Boolean.")); } String json5 = "{\"URL1\":{\"default-value\":true,\"secure\":null,\"required\":true}," + "\"URL2\":{\"default-value\":\"some value\",\"secure\":\"some-string\",\"required\":false}," + "\"URL3\":{\"default-value\":\"some value\",\"secure\":true,\"required\":\"some-string\"}}"; try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig(json5); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: Key: 'URL1' - The Json for Task Config should contain a not-null 'default-value' of type String, Key: 'URL1' - The Json for Task Config should contain a 'secure' field of type Boolean, Key: 'URL2' - The Json for Task Config should contain a 'secure' field of type Boolean, Key: 'URL3' - The Json for Task Config should contain a 'required' field of type Boolean.")); } assertThat(new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig("{\"URL\":{\"display-order\":\"1\"}}").get("URL").getOption(Property.DISPLAY_ORDER), is(1)); try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig("{\"URL\":{\"display-order\":\"first\"}}"); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: Key: 'URL' - 'display-order' should be a String containing a numerical value.")); } try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig("{\"URL\":{\"display-order\":1}}"); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: Key: 'URL' - 'display-order' should be a String containing a numerical value.")); } assertThat(new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig("{\"URL\":{\"display-name\":\"Uniform Resource Locator\"}}").get("URL").getOption(Property.DISPLAY_NAME), is("Uniform Resource Locator")); try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig("{\"URL\":{\"display-name\":{}}}"); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: Key: 'URL' - 'display-name' should be of type String.")); } try { new JsonBasedTaskExtensionHandler_V1().convertJsonToTaskConfig("{\"URL\":{\"display-name\":1}}"); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task Config. Error: Key: 'URL' - 'display-name' should be of type String.")); } } @Test public void shouldConvertJsonResponseToValidationResultWhenValidationFails() { String jsonResponse = "{\"errors\":{\"key1\":\"err1\",\"key2\":\"err2\"}}"; TaskConfig configuration = new TaskConfig(); TaskConfigProperty property = new TaskConfigProperty("URL", "http://foo"); property.with(Property.SECURE, false); property.with(Property.REQUIRED, true); configuration.add(property); ValidationResult result = new JsonBasedTaskExtensionHandler_V1().toValidationResult(jsonResponse); Assert.assertThat(result.isSuccessful(), CoreMatchers.is(false)); ValidationError error1 = result.getErrors().get(0); ValidationError error2 = result.getErrors().get(1); Assert.assertThat(error1.getKey(), CoreMatchers.is("key1")); Assert.assertThat(error1.getMessage(), CoreMatchers.is("err1")); Assert.assertThat(error2.getKey(), CoreMatchers.is("key2")); Assert.assertThat(error2.getMessage(), CoreMatchers.is("err2")); } @Test public void shouldConvertJsonResponseToValidationResultWhenValidationPasses() { String jsonResponse = "{}"; TaskConfig configuration = new TaskConfig(); TaskConfigProperty property = new TaskConfigProperty("URL", "http://foo"); property.with(Property.SECURE, false); property.with(Property.REQUIRED, true); configuration.add(property); ValidationResult result = new JsonBasedTaskExtensionHandler_V1().toValidationResult(jsonResponse); Assert.assertThat(result.isSuccessful(), CoreMatchers.is(true)); } @Test public void shouldThrowExceptionForWrongJsonWhileConvertingJsonResponseToValidation() { Assert.assertTrue(new JsonBasedTaskExtensionHandler_V1().toValidationResult("{\"errors\":{}}").isSuccessful()); Assert.assertTrue(new JsonBasedTaskExtensionHandler_V1().toValidationResult("{}").isSuccessful()); Assert.assertTrue(new JsonBasedTaskExtensionHandler_V1().toValidationResult("").isSuccessful()); Assert.assertTrue(new JsonBasedTaskExtensionHandler_V1().toValidationResult(null).isSuccessful()); String jsonResponse2 = "{\"errors\":{\"key1\":\"err1\",\"key2\":true}}"; try { new JsonBasedTaskExtensionHandler_V1().toValidationResult(jsonResponse2); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Validation Result. Error: Key: 'key2' - The Json for Validation Request must contain a not-null error message of type String.")); } String jsonResponse3 = "{\"errors\":{\"key1\":null}}"; try { new JsonBasedTaskExtensionHandler_V1().toValidationResult(jsonResponse3); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Validation Result. Error: Key: 'key1' - The Json for Validation Request must contain a not-null error message of type String.")); } String jsonResponse4 = "{\"errors\":{\"key1\":true,\"key2\":\"err2\",\"key3\":null}}"; try { new JsonBasedTaskExtensionHandler_V1().toValidationResult(jsonResponse4); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Validation Result. Error: Key: 'key1' - The Json for Validation Request must contain a not-null error message of type String, Key: 'key3' - The Json for Validation Request must contain a not-null error message of type String.")); } } @Test public void shouldCreateTaskViewFromResponse() { String jsonResponse = "{\"displayValue\":\"MyTaskPlugin\", \"template\":\"<html>junk</html>\"}"; TaskView view = new JsonBasedTaskExtensionHandler_V1().toTaskView(jsonResponse); Assert.assertThat(view.displayValue(), CoreMatchers.is("MyTaskPlugin")); Assert.assertThat(view.template(), CoreMatchers.is("<html>junk</html>")); } @Test public void shouldThrowExceptionForWrongJsonWhileCreatingTaskViewFromResponse() { String jsonResponse1 = "{}"; try { new JsonBasedTaskExtensionHandler_V1().toTaskView(jsonResponse1); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task View. Error: The Json for Task View cannot be empty.")); } String jsonResponse2 = "{\"template\":\"<html>junk</html>\"}"; try { new JsonBasedTaskExtensionHandler_V1().toTaskView(jsonResponse2); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task View. Error: The Json for Task View must contain a not-null 'displayValue' of type String.")); } String jsonResponse3 = "{\"displayValue\":\"MyTaskPlugin\"}"; try { new JsonBasedTaskExtensionHandler_V1().toTaskView(jsonResponse3); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task View. Error: The Json for Task View must contain a not-null 'template' of type String.")); } String jsonResponse4 = "{\"displayValue\":null, \"template\":\"<html>junk</html>\"}"; try { new JsonBasedTaskExtensionHandler_V1().toTaskView(jsonResponse4); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task View. Error: The Json for Task View must contain a not-null 'displayValue' of type String.")); } String jsonResponse5 = "{\"displayValue\":\"MyTaskPlugin\", \"template\":true}"; try { new JsonBasedTaskExtensionHandler_V1().toTaskView(jsonResponse5); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task View. Error: The Json for Task View must contain a not-null 'template' of type String.")); } String jsonResponse6 = "{\"displayValue\":true, \"template\":null}"; try { new JsonBasedTaskExtensionHandler_V1().toTaskView(jsonResponse6); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Task View. Error: The Json for Task View must contain a not-null 'displayValue' of type String, The Json for Task View must contain a not-null 'template' of type String.")); } } @Test public void shouldConstructExecutionResultFromSuccessfulExecutionResponse() { GoPluginApiResponse response = mock(GoPluginApiResponse.class); when(response.responseBody()).thenReturn("{\"success\":true,\"message\":\"message1\"}"); ExecutionResult result = new JsonBasedTaskExtensionHandler_V1().toExecutionResult(response.responseBody()); assertThat(result.isSuccessful(), is(true)); assertThat(result.getMessagesForDisplay(), is("message1")); } @Test public void shouldConstructExecutionResultFromFailureExecutionResponse() { GoPluginApiResponse response = mock(GoPluginApiResponse.class); when(response.responseBody()).thenReturn("{\"success\":false,\"message\":\"error1\"}"); ExecutionResult result = new JsonBasedTaskExtensionHandler_V1().toExecutionResult(response.responseBody()); assertThat(result.isSuccessful(), is(false)); assertThat(result.getMessagesForDisplay(), is("error1")); } @Test public void shouldThrowExceptionForWrongJsonWhileConstructingExecutionResultFromExecutionResponse() { String json1 = "{}"; try { new JsonBasedTaskExtensionHandler_V1().toExecutionResult(json1); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Execution Result. Error: The Json for Execution Result must contain a not-null 'success' field of type Boolean.")); } String json2 = "{\"success\":\"yay\",\"message\":\"error1\"}"; try { new JsonBasedTaskExtensionHandler_V1().toExecutionResult(json2); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Execution Result. Error: The Json for Execution Result must contain a not-null 'success' field of type Boolean.")); } String json3 = "{\"success\":false,\"message\":true}"; try { new JsonBasedTaskExtensionHandler_V1().toExecutionResult(json3); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Execution Result. Error: If the 'message' key is present in the Json for Execution Result, it must contain a not-null message of type String.")); } String json4 = "{\"message\":null}"; try { new JsonBasedTaskExtensionHandler_V1().toExecutionResult(json4); fail("should throw exception"); } catch (Exception e) { assertThat(e.getMessage(), is("Error occurred while converting the Json to Execution Result. Error: The Json for Execution Result must contain a not-null 'success' field of type Boolean, If the 'message' key is present in the Json for Execution Result, it must contain a not-null message of type String.")); } } @Test public void shouldReturnOneDotZeroForVersion() { assertThat(new JsonBasedTaskExtensionHandler_V1().version(), is("1.0")); } @Test public void shouldReturnRequestBodyForTaskExecution() { TaskExecutionContext context = mock(TaskExecutionContext.class); String workingDir = "working-dir"; TaskConfig config = new TaskConfig(); config.add(new TaskConfigProperty("Property1", "Value1")); config.add(new TaskConfigProperty("Property2", "Value2")); when(context.workingDir()).thenReturn(workingDir); when(context.environment()).thenReturn(getEnvironmentVariables()); String requestBody = new JsonBasedTaskExtensionHandler_V1().getTaskExecutionBody(config, context); Map result = (Map) new GsonBuilder().create().fromJson(requestBody, Object.class); Map taskExecutionContextFromRequest = (Map) result.get("context"); assertThat(taskExecutionContextFromRequest.get("workingDirectory"), is(workingDir)); Map environmentVariables = (Map) taskExecutionContextFromRequest.get("environmentVariables"); assertThat(environmentVariables.size(), is(2)); assertThat(environmentVariables.get("ENV1").toString(), is("VAL1")); assertThat(environmentVariables.get("ENV2").toString(), is("VAL2")); Map<String,Object> taskConfigMap = (Map<String,Object>) result.get("config"); assertThat(taskConfigMap.size(), is(2)); Map property1 = (Map) taskConfigMap.get("Property1"); Map property2 = (Map) taskConfigMap.get("Property2"); assertThat(property1.get("value").toString(), is("Value1")); assertThat(property2.get("value").toString(), is("Value2")); } private EnvironmentVariables getEnvironmentVariables() { return new EnvironmentVariables() { @Override public Map<String, String> asMap() { final HashMap<String, String> map = new HashMap<>(); map.put("ENV1", "VAL1"); map.put("ENV2", "VAL2"); return map; } @Override public void writeTo(Console console) { } @Override public Console.SecureEnvVarSpecifier secureEnvSpecifier() { return null; } }; } }