diff --git a/src/main/java/com/dougnoel/sentinel/steps/APISteps.java b/src/main/java/com/dougnoel/sentinel/steps/APISteps.java index 888040df..22b699e3 100644 --- a/src/main/java/com/dougnoel/sentinel/steps/APISteps.java +++ b/src/main/java/com/dougnoel/sentinel/steps/APISteps.java @@ -52,7 +52,7 @@ public static void setAPI(String apiName) { */ @Given("I set the request body to") public static void setRequestBody(String body) { - APIManager.setBody(SentinelStringUtils.replaceStoredVariables(body)); + APIManager.setBody(SentinelStringUtils.parseVariables(body)); log.trace("Body passed: {}", body); } @@ -95,7 +95,7 @@ public static void loadRequestBody(String testdataName) { */ @When("^I add an? (.*?) parameter with the value (.*?)$") public static void addParameter(String parameter, String value) { - APIManager.addParameter(parameter, SentinelStringUtils.replaceStoredVariables(value)); + APIManager.addParameter(parameter, SentinelStringUtils.parseVariables(value)); } @@ -115,7 +115,7 @@ public static void addParameter(String parameter, String value) { */ @When("^I send a (DELETE|GET|POST|PUT) request to the (.*?) endpoint$") public static void sendRequest(String apiCallType, String endpoint) { - APIManager.sendRequest(RequestType.valueOf(apiCallType), SentinelStringUtils.replaceStoredVariables(endpoint)); + APIManager.sendRequest(RequestType.valueOf(apiCallType), SentinelStringUtils.parseVariables(endpoint)); } /** @@ -135,7 +135,7 @@ public static void sendRequest(String apiCallType, String endpoint) { */ @When("^I (DELETE|GET) record (.*) from the (.*?) endpoint$") public static void sendRequest(String apiCallType, String parameter, String endpoint) { - sendRequest(apiCallType, endpoint + "/" + SentinelStringUtils.replaceVariable(parameter)); + sendRequest(apiCallType, endpoint + "/" + SentinelStringUtils.parseVariables(parameter)); } /** @@ -205,7 +205,7 @@ public static void verifyResponseContains(String assertion, String matchType, St */ @When("^I add an? (.*?) header with the value (.*?)$") public static void addHeader(String name, String value) { - APIManager.addHeader(name, SentinelStringUtils.replaceStoredVariables(value)); + APIManager.addHeader(name, SentinelStringUtils.parseVariables(value)); } /** @@ -228,4 +228,4 @@ public void iInitializeTheData(String values) { Configuration.update(item.split(":")[0], item.split(":")[1]); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/dougnoel/sentinel/strings/SentinelStringUtils.java b/src/main/java/com/dougnoel/sentinel/strings/SentinelStringUtils.java index b347b86c..67d93648 100644 --- a/src/main/java/com/dougnoel/sentinel/strings/SentinelStringUtils.java +++ b/src/main/java/com/dougnoel/sentinel/strings/SentinelStringUtils.java @@ -7,14 +7,18 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.dougnoel.sentinel.exceptions.FileException; import org.apache.commons.lang3.CharUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; import org.openqa.selenium.InvalidArgumentException; import com.dougnoel.sentinel.configurations.Configuration; public class SentinelStringUtils extends org.apache.commons.lang3.StringUtils { + private static final Logger log = LogManager.getLogger(SentinelStringUtils.class.getName()); // Create a logger. private static final String SURROUNDING_QUOTES = "^[\"'].*[\"']$"; /** @@ -107,61 +111,79 @@ public static int parseOrdinal(String stringStartingWithInteger){ } /** - * Returns a string with any strings enclosed in curly braces "{}" replaced with values - * stored in the passed YAMLData object under testdata/variables. For example, given the string - * "{first_name} Smith" and the yaml entry in the passed file: - * - * testdata: - * default: - * variables: - * first_name: Bob - * - * This method would return: "Bob Smith". - * If there are no values to replace, this method returns the string intact. + * Depreciated. Please use parseVariables(String text) + *
This function will return the same results as parseVariables() * @param text String the text to search for variable replacement * @return String the string with variables replaced as applicable */ public static String replaceVariable(String text) { - Matcher matcher = Pattern.compile("\\{[^\\}]*+\\}").matcher(text); - while (matcher.find()) { - var variable = matcher.group(); - var variableName = StringUtils.substring(variable, 1, -1); - var value = Configuration.getTestData("variables", variableName); - text = StringUtils.replaceOnce(text, variable, value); //Using replaceOnce so that if we have the same variable name twice we do not run into iteration issues. - } - return text; + return parseVariables(text); } /** - * Returns a string with any strings with pattern "\\{\S*?\\}" replaced with values - * stored in configuration. For example, given the string - * { - * "id": {id}, - * "name": "puppy", - * "category": { - * "id": 1, - * "name": "{category_name}" - * }} - * - * This method would return: - * { - * "id": 10, - * "name": "puppy", - * "category": { - * "id": 1, - * "name": "Dog" - * }}. - * If there are no values to replace, this method returns the string intact. + * Depreciated. Please use parseVariables(String text) + *
This function will return the same results as parseVariables() * @param text String the text to search for variable replacement * @return String the string with variables replaced as applicable */ public static String replaceStoredVariables(String text) { - Matcher matcher = Pattern.compile("\\{\\S[^\\}]*+\\}").matcher(text); + return parseVariables(text); + } + + /** + * Returns a string with any strings enclosed in curly braces "{}" replaced with values + * stored in the passed YAMLData object under testdata/variables. + *
For example, given the string + *
"{first_name} Smith" + *
and the yaml entry in the passed file: + *
+ * testdata:
+ * default:
+ * variables:
+ * first_name: Bob
+ *
+ * This method would return: "Bob Smith". + *
+ * Given the string:
+ * {
+ * "id": {id},
+ * "name": "puppy",
+ * "category": {
+ * "id": 1,
+ * "name": "{category_name}"
+ * }}
+ *
+ * This method would return:
+ * {
+ * "id": 10,
+ * "name": "puppy",
+ * "category": {
+ * "id": 1,
+ * "name": "Dog"
+ * }}.
+ *
+ * If there are no values to replace, this method returns the string intact. + * @param text String the text to search for variable replacement + * @return String the string with variables replaced as applicable + */ + public static String parseVariables(String text) { + Matcher matcher = Pattern.compile("\\{(\\S[^}]+)}").matcher(text); + while (matcher.find()) { - var variable = matcher.group(); - var value = Configuration.toString(variable.substring(1, variable.length() - 1)); - text = StringUtils.replaceOnce(text, variable, value); //Using replaceOnce so that if we have the same variable name twice we do not run into iteration issues. + String variable = matcher.group(); + String variableName = matcher.group(1); + String value = Configuration.toString(variableName); + if (value == null) { + try { + value = Configuration.getTestData("variables", variableName); + } + catch (FileException fe) { + log.info("Could not find configuration or testData for {}. Returning text as is.", variableName); + } } + if(value != null) + text = StringUtils.replaceOnce(text, variable, value); //Using replaceOnce so that if we have the same variable name twice we do not run into iteration issues. + } return text; } -} +} \ No newline at end of file diff --git a/src/test/java/features/89 API Testing.feature b/src/test/java/features/89 API Testing.feature index 6de86ebc..340ab27d 100644 --- a/src/test/java/features/89 API Testing.feature +++ b/src/test/java/features/89 API Testing.feature @@ -120,6 +120,9 @@ Feature: 89 API Testing @89I Scenario: 89I Query String Stored Parameter Test Given I use the API named Pet Store API + And I load soldpuppydata to use as the request body + And I send a POST request to the pet endpoint + And I verify the response code equals 200 When I initialize the configuration values as follows """ dog_status: sold diff --git a/src/test/java/io/swagger/petstore3/PetStoreAPI.yml b/src/test/java/io/swagger/petstore3/PetStoreAPI.yml index 1908ade8..3d1b6da2 100644 --- a/src/test/java/io/swagger/petstore3/PetStoreAPI.yml +++ b/src/test/java/io/swagger/petstore3/PetStoreAPI.yml @@ -1,10 +1,10 @@ -urls: - default: https://petstore3.swagger.io/api/v3/openapi.json -testdata: - default: - variables: - test_id: 10 - puppydata: +urls: + default: https://petstore3.swagger.io/api/v3/openapi.json +testdata: + default: + variables: + test_id: 10 + puppydata: json: | { "id": 10, @@ -23,4 +23,24 @@ testdata: } ], "status": "available" - } \ No newline at end of file + } + soldpuppydata: + json: | + { + "id": 11, + "name": "puppy", + "category": { + "id": 1, + "name": "Dogs" + }, + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "sold" + } \ No newline at end of file