diff --git a/README.md b/README.md index 9942ee6..891fe21 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ScAPI ### How to run api tests -TBD - work in progress +TODO - work in progress ### How to run unit tests Run unit tests from path `{project-root}` diff --git a/testApi/src/main/resources/schema/after.schema.json b/testApi/src/main/resources/schema/after.schema.json index 421bbb7..cb723c2 100644 --- a/testApi/src/main/resources/schema/after.schema.json +++ b/testApi/src/main/resources/schema/after.schema.json @@ -42,10 +42,10 @@ "$ref": "#/definitions/Action" } }, - "assertions": { + "responseActions": { "type": "array", "items": { - "$ref": "#/definitions/Assertion" + "$ref": "#/definitions/ResponseAction" } } }, @@ -53,7 +53,7 @@ "name", "headers", "actions", - "assertions" + "responseActions" ], "title": "Method" }, @@ -100,14 +100,11 @@ ], "title": "Action" }, - "Assertion": { + "ResponseAction": { "type": "object", "additionalProperties": false, "properties": { - "group": { - "type": "string" - }, - "name": { + "method": { "type": "string" } }, @@ -117,11 +114,10 @@ } }, "required": [ - "group", - "name", + "method", "param_1" ], - "title": "Assertion" + "title": "ResponseAction" }, "Param": { "type": "object", diff --git a/testApi/src/main/resources/schema/before.schema.json b/testApi/src/main/resources/schema/before.schema.json index b54982c..f44daee 100644 --- a/testApi/src/main/resources/schema/before.schema.json +++ b/testApi/src/main/resources/schema/before.schema.json @@ -42,10 +42,10 @@ "$ref": "#/definitions/Action" } }, - "assertions": { + "responseActions": { "type": "array", "items": { - "$ref": "#/definitions/Assertion" + "$ref": "#/definitions/ResponseAction" } } }, @@ -53,7 +53,7 @@ "name", "headers", "actions", - "assertions" + "responseActions" ], "title": "Method" }, @@ -100,14 +100,11 @@ ], "title": "Action" }, - "Assertion": { + "ResponseAction": { "type": "object", "additionalProperties": false, "properties": { - "group": { - "type": "string" - }, - "name": { + "method": { "type": "string" } }, @@ -117,11 +114,10 @@ } }, "required": [ - "group", - "name", + "method", "param_1" ], - "title": "Assertion" + "title": "ResponseAction" }, "Param": { "type": "object", diff --git a/testApi/src/main/resources/schema/suite.schema.json b/testApi/src/main/resources/schema/suite.schema.json index d2b7536..9018bdb 100644 --- a/testApi/src/main/resources/schema/suite.schema.json +++ b/testApi/src/main/resources/schema/suite.schema.json @@ -51,10 +51,10 @@ "$ref": "#/definitions/Action" } }, - "assertions": { + "responseActions": { "type": "array", "items": { - "$ref": "#/definitions/Assertion" + "$ref": "#/definitions/ResponseAction" } } }, @@ -63,7 +63,7 @@ "categories", "headers", "actions", - "assertions" + "responseActions" ], "title": "Test" }, @@ -110,14 +110,11 @@ ], "title": "Action" }, - "Assertion": { + "ResponseAction": { "type": "object", "additionalProperties": false, "properties": { - "group": { - "type": "string" - }, - "name": { + "method": { "type": "string" } }, @@ -127,11 +124,10 @@ } }, "required": [ - "group", - "name", + "method", "param_1" ], - "title": "Assertion" + "title": "ResponseAction" }, "Param": { "type": "object", diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/Exceptions.scala b/testApi/src/main/scala/africa/absa/testing/scapi/Exceptions.scala index 449f543..78b1227 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/Exceptions.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/Exceptions.scala @@ -35,8 +35,8 @@ case class SuiteLoadFailed(detail: String) extends Exception(s"Problems during p case class UndefinedHeaderType(undefinedType: String) extends Exception(s"Undefined Header content type: '$undefinedType'") -case class UndefinedAssertionType(undefinedType: String) - extends Exception(s"Undefined Assertion content type: '$undefinedType'") +case class UndefinedResponseActionType(undefinedType: String) + extends Exception(s"Undefined response action content type: '$undefinedType'") case class ContentValidationFailed(value: String, message: String) extends Exception(s"Content validation failed for value: '$value': $message") diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/json/ReferenceResolver.scala b/testApi/src/main/scala/africa/absa/testing/scapi/json/ReferenceResolver.scala index fdc54d2..c15845e 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/json/ReferenceResolver.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/json/ReferenceResolver.scala @@ -198,35 +198,39 @@ case class Action private(methodName: String, url: String, body: Option[String] } /** - * Case class that represents Assertion. - * This class is used to hold test assertions. + * Case class that represents ResponseAction. + * This class is used to hold test response action. * It implements the `ReferenceResolver` trait to support resolution of reference constants. * - * @constructor create a new Assertion with a name and value. - * @param name the name of the assertion. - * @param params the map containing the parameters of the assertion. Each key-value pair in the map + * @constructor create a new ResponseAction with a name and value. + * @param method the "group and name" of the response action. + * @param params the map containing the parameters of the response action. Each key-value pair in the map * represents a parameter name and its corresponding value. */ -case class Assertion private(group: String, - name: String, - params: Map[String, String]) extends ReferenceResolver { +case class ResponseAction private(method: String, + params: Map[String, String]) extends ReferenceResolver { + + private def splitter: Seq[String] = method.split("\\.").toSeq + + def group : String = splitter.head + def name : String = splitter.tail.head /** * Method to resolve references. * * @param references the map of references that may be used to resolve references in the value. - * @return a new Assertion instance with resolved references. + * @return a new ResponseAction instance with resolved references. */ - def resolveReferences(references: Map[String, String]): Assertion = this.copy( + def resolveReferences(references: Map[String, String]): ResponseAction = this.copy( params = this.params.map { case (k, v) => k -> getResolved(v, references) } ) /** * Method to resolve references using Runtime Cache. This method is used when the resolution of a reference is not possible at compile-time. * - * @return A new Assertion instance with resolved references. + * @return A new ResponseAction instance with resolved references. */ - def resolveByRuntimeCache(): Assertion = this.copy( + def resolveByRuntimeCache(): ResponseAction = this.copy( params = this.params.map { case (k, v) => k -> RuntimeCache.resolve(v) } ) } diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/json/Requestable.scala b/testApi/src/main/scala/africa/absa/testing/scapi/json/Requestable.scala index 468b660..9830ae3 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/json/Requestable.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/json/Requestable.scala @@ -23,5 +23,5 @@ trait Requestable { def actions: Set[Action] - def assertions: Set[Assertion] + def responseActions: Set[ResponseAction] } diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/json/SuiteFactory.scala b/testApi/src/main/scala/africa/absa/testing/scapi/json/SuiteFactory.scala index 5a38d5e..8e5a173 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/json/SuiteFactory.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/json/SuiteFactory.scala @@ -259,7 +259,7 @@ object SuiteFactory { /** * This method validates the content of a SuiteBundle. - * It checks the suite's headers, body, parameters, and assertions. + * It checks the suite's headers, body, parameters, and response action. * * @param suiteBundle The SuiteBundle to be validated. */ @@ -269,7 +269,7 @@ object SuiteFactory { test.headers.foreach(header => RequestHeaders.validateContent(header)) RequestBody.validateContent(test.actions.head.body) RequestParams.validateContent(test.actions.head.params) - test.assertions.foreach(assertion => Response.validate(assertion)) + test.responseActions.foreach(responseAction => Response.validate(responseAction)) }) } } @@ -281,7 +281,7 @@ object SuiteJsonProtocol extends DefaultJsonProtocol { implicit val headerFormat: RootJsonFormat[Header] = jsonFormat2(Header) implicit val paramFormat: RootJsonFormat[Param] = jsonFormat2(Param) implicit val testActionFormat: RootJsonFormat[Action] = jsonFormat4(Action) - implicit val assertionFormat: RootJsonFormat[Assertion] = AssertionJsonProtocol.AssertionJsonFormat + implicit val assertionFormat: RootJsonFormat[ResponseAction] = ResponseActionJsonProtocol.ResponseActionJsonFormat implicit val suiteTestFormat: RootJsonFormat[SuiteTestScenario] = jsonFormat6(SuiteTestScenario) implicit val methodFormat: RootJsonFormat[Method] = jsonFormat4(Method) implicit val suiteFormat: RootJsonFormat[Suite] = jsonFormat2(Suite) @@ -301,7 +301,7 @@ object SuiteBeforeJsonProtocol extends DefaultJsonProtocol { implicit val headerFormat: RootJsonFormat[Header] = jsonFormat2(Header) implicit val paramFormat: RootJsonFormat[Param] = jsonFormat2(Param) implicit val testActionFormat: RootJsonFormat[Action] = jsonFormat4(Action) - implicit val assertionFormat: RootJsonFormat[Assertion] = AssertionJsonProtocol.AssertionJsonFormat + implicit val responseActionFormat: RootJsonFormat[ResponseAction] = ResponseActionJsonProtocol.ResponseActionJsonFormat implicit val methodFormat: RootJsonFormat[Method] = jsonFormat4(Method) implicit val suiteBeforeFormat: RootJsonFormat[SuiteBefore] = jsonFormat2(SuiteBefore) } @@ -313,29 +313,28 @@ object SuiteAfterJsonProtocol extends DefaultJsonProtocol { implicit val headerFormat: RootJsonFormat[Header] = jsonFormat2(Header) implicit val paramFormat: RootJsonFormat[Param] = jsonFormat2(Param) implicit val testActionFormat: RootJsonFormat[Action] = jsonFormat4(Action) - implicit val assertionFormat: RootJsonFormat[Assertion] = AssertionJsonProtocol.AssertionJsonFormat + implicit val assertionFormat: RootJsonFormat[ResponseAction] = ResponseActionJsonProtocol.ResponseActionJsonFormat implicit val methodFormat: RootJsonFormat[Method] = jsonFormat4(Method) implicit val suiteAfterFormat: RootJsonFormat[SuiteAfter] = jsonFormat2(SuiteAfter) } /** - * Object that provides implicit JSON format for Assertion class. + * Object that provides implicit JSON format for ResponseAction class. */ -object AssertionJsonProtocol extends DefaultJsonProtocol { +object ResponseActionJsonProtocol extends DefaultJsonProtocol { - implicit object AssertionJsonFormat extends RootJsonFormat[Assertion] { - def write(a: Assertion): JsObject = JsObject( - ("group" -> JsString(a.group)) +: - ("name" -> JsString(a.name)) +: + implicit object ResponseActionJsonFormat extends RootJsonFormat[ResponseAction] { + def write(a: ResponseAction): JsObject = JsObject( + ("method" -> JsString(a.method)) +: a.params.view.mapValues(JsString(_)).toSeq: _* ) - def read(value: JsValue): Assertion = { - value.asJsObject.getFields("group", "name") match { - case Seq(JsString(group), JsString(name)) => + def read(value: JsValue): ResponseAction = { + value.asJsObject.getFields("method") match { + case Seq(JsString(method)) => val params = value.asJsObject.fields.view.filterKeys(_.startsWith("param_")).toMap - Assertion(group, name, params.map { case (k, v) => k -> v.convertTo[String] }) - case _ => throw new DeserializationException("Assertion expected") + ResponseAction(method, params.map { case (k, v) => k -> v.convertTo[String] }) + case _ => throw DeserializationException("Assertion expected") } } } diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/model/Method.scala b/testApi/src/main/scala/africa/absa/testing/scapi/model/Method.scala index 8087c89..224702d 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/model/Method.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/model/Method.scala @@ -16,7 +16,7 @@ package africa.absa.testing.scapi.model -import africa.absa.testing.scapi.json.{Action, Assertion, Header, Requestable} +import africa.absa.testing.scapi.json.{Action, Header, Requestable, ResponseAction} /** * Case class that represents a single method. @@ -24,12 +24,12 @@ import africa.absa.testing.scapi.json.{Action, Assertion, Header, Requestable} * @param name The name of the method. * @param headers The set of header options for the method. * @param actions The set of action objects for the method. - * @param assertions The set of assertion objects for the method. + * @param responseActions The set of responseAction objects for the method. */ case class Method(name: String, headers: Set[Header], actions: Set[Action], - assertions: Set[Assertion]) extends Requestable { + responseActions: Set[ResponseAction]) extends Requestable { /** * Method to resolve references within the Method instance. * @@ -41,7 +41,7 @@ case class Method(name: String, name, headers.map(c => c.resolveReferences(references)), actions.map(c => c.resolveReferences(references)), - assertions.map(c => c.resolveReferences(references)) + responseActions.map(c => c.resolveReferences(references)) ) } } diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/model/SuiteTestScenario.scala b/testApi/src/main/scala/africa/absa/testing/scapi/model/SuiteTestScenario.scala index 3d4a9d3..b01efa7 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/model/SuiteTestScenario.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/model/SuiteTestScenario.scala @@ -16,7 +16,7 @@ package africa.absa.testing.scapi.model -import africa.absa.testing.scapi.json.{Action, Assertion, Header, Requestable} +import africa.absa.testing.scapi.json.{Action, Header, Requestable, ResponseAction} /** * Case class that represents a suite test scenario. @@ -25,14 +25,14 @@ import africa.absa.testing.scapi.json.{Action, Assertion, Header, Requestable} * @param categories The required test categories of the test scenario. * @param headers The set of header options for the test scenario. * @param actions The set of action objects for the test scenario. - * @param assertions The set of assertion objects for the test scenario. + * @param responseActions The set of responseAction objects for the test scenario. * @param only The control if test should be only be running when set to true. */ case class SuiteTestScenario(name: String, categories: Set[String], headers: Set[Header], actions: Set[Action], - assertions: Set[Assertion], + responseActions: Set[ResponseAction], only: Option[Boolean] = Some(false)) extends Requestable { /** * Method to resolve references within the SuiteTestScenario instance. @@ -46,7 +46,7 @@ case class SuiteTestScenario(name: String, categories, headers.map(c => c.resolveReferences(references)), actions.map(c => c.resolveReferences(references)), - assertions.map(c => c.resolveReferences(references)), + responseActions.map(c => c.resolveReferences(references)), only ) } diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseAssertion.scala b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/AssertionResponseAction.scala similarity index 69% rename from testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseAssertion.scala rename to testApi/src/main/scala/africa/absa/testing/scapi/rest/response/AssertionResponseAction.scala index b52b198..574bf0a 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseAssertion.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/AssertionResponseAction.scala @@ -16,60 +16,60 @@ package africa.absa.testing.scapi.rest.response -import africa.absa.testing.scapi.UndefinedAssertionType -import africa.absa.testing.scapi.json.Assertion +import africa.absa.testing.scapi.UndefinedResponseActionType +import africa.absa.testing.scapi.json.ResponseAction import africa.absa.testing.scapi.logging.Logger import africa.absa.testing.scapi.utils.validation.ContentValidator /** - * Object that validates and performs various assertions on the response received. + * Object that validates and performs various assertion response actions on the response received. * It extends the functionality of ResponsePerformer. */ -object ResponseAssertion extends ResponsePerformer { +object AssertionResponseAction extends ResponsePerformer { val STATUS_CODE = "status-code" val BODY_CONTAINS = "body-contains" /** - * Validates the content of an assertion object depending on its type. + * Validates the content of an assertion response action object depending on its type. * - * @param assertion The assertion object to be validated. - * @throws UndefinedAssertionType If the assertion type is not recognized. + * @param responseAction The response action object to be validated. + * @throws UndefinedResponseActionType If the response action type is not recognized. */ - def validateContent(assertion: Assertion): Unit = { - assertion.name.toLowerCase match { + def validateContent(responseAction: ResponseAction): Unit = { + responseAction.name.toLowerCase match { case STATUS_CODE => - assertion.params.get("param_1") match { + responseAction.params.get("param_1") match { case param_1 => ContentValidator.validateIntegerString(param_1.get, s"ResponseAssertion.$STATUS_CODE.param_1") case None => throw new IllegalArgumentException(s"Missing required param_1 for assertion $STATUS_CODE") } case BODY_CONTAINS => - assertion.params.get("param_1") match { + responseAction.params.get("param_1") match { case param_1 => ContentValidator.validateNonEmptyString(param_1.get, s"ResponseAssertion.$BODY_CONTAINS.param_1") case None => throw new IllegalArgumentException(s"Missing required param_1 for assertion $BODY_CONTAINS") } - case _ => throw UndefinedAssertionType(assertion.name) + case _ => throw UndefinedResponseActionType(responseAction.name) } } /** - * Performs assertions on a response depending on the type of assertion provided. + * Performs assertion actions on a response depending on the type of assertion action provided. * * @param response The response to perform the assertions on. - * @param assertion The assertion to perform on the response. + * @param responseAction The assertion response action to perform on the response. * @return Boolean value indicating whether the assertion passed or failed. * @throws IllegalArgumentException If the assertion type is not supported. */ - def performAssertion(response: Response, assertion: Assertion): Boolean = { - assertion.name match { + def performResponseAction(response: Response, responseAction: ResponseAction): Boolean = { + responseAction.name match { case STATUS_CODE => - val param_1 = assertion.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) + val param_1 = responseAction.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) assertStatusCode(response, param_1) case BODY_CONTAINS => - val param_1 = assertion.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) + val param_1 = responseAction.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) assertBodyContains(response, param_1) - case _ => throw new IllegalArgumentException(s"Unsupported assertion[group: assert]: ${assertion.name}") + case _ => throw new IllegalArgumentException(s"Unsupported assertion[group: assert]: ${responseAction.name}") } } diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseExtractJson.scala b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ExtractJsonResponseAction.scala similarity index 66% rename from testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseExtractJson.scala rename to testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ExtractJsonResponseAction.scala index 84bafc6..40ee111 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseExtractJson.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ExtractJsonResponseAction.scala @@ -16,53 +16,53 @@ package africa.absa.testing.scapi.rest.response -import africa.absa.testing.scapi.UndefinedAssertionType -import africa.absa.testing.scapi.json.Assertion +import africa.absa.testing.scapi.UndefinedResponseActionType +import africa.absa.testing.scapi.json.ResponseAction import africa.absa.testing.scapi.logging.Logger import africa.absa.testing.scapi.utils.cache.RuntimeCache import africa.absa.testing.scapi.utils.validation.ContentValidator import spray.json._ /** - * ResponseExtractJson is an object that extends ResponsePerformer. + * ExtractJsonResponseAction is an object that extends ResponsePerformer. * It is designed to extract specific data from a JSON response and perform validations. */ -object ResponseExtractJson extends ResponsePerformer { +object ExtractJsonResponseAction extends ResponsePerformer { val STRING_FROM_LIST = "string-from-list" /** - * This method validates the assertion's content based on the assertion's name. - * It supports the STRING_FROM_LIST type of assertion. + * This method validates the response action's content based on the response action's name. + * It supports the STRING_FROM_LIST type of response action. * - * @param assertion The Assertion instance to be validated. - * @throws UndefinedAssertionType if an unsupported assertion type is encountered. + * @param responseAction The ResponseAction instance to be validated. + * @throws UndefinedResponseActionType if an unsupported assertion type is encountered. */ - def validateContent(assertion: Assertion): Unit = { - assertion.name.toLowerCase match { - case STRING_FROM_LIST => validateStringFromList(assertion) - case _ => throw UndefinedAssertionType(assertion.name) + def validateContent(responseAction: ResponseAction): Unit = { + responseAction.name.toLowerCase match { + case STRING_FROM_LIST => validateStringFromList(responseAction) + case _ => throw UndefinedResponseActionType(responseAction.name) } } /** - * This method performs assertions on a given response based on the assertion's name. - * It supports the STRING_FROM_LIST type of assertion. + * This method performs response actions on a given response based on the response action's name. + * It supports the STRING_FROM_LIST type of response action. * - * @param response The Response instance to perform assertions on. - * @param assertion The Assertion instance containing the assertion details. - * @throws IllegalArgumentException if an unsupported assertion group is encountered. + * @param response The Response instance to perform response action on. + * @param responseAction The ResponseAction instance containing the response action details. + * @throws IllegalArgumentException if an unsupported response action name is encountered. */ - def performAssertion(response: Response, assertion: Assertion): Boolean = { - assertion.name match { + def performResponseAction(response: Response, responseAction: ResponseAction): Boolean = { + responseAction.name match { case STRING_FROM_LIST => - val param_1 = assertion.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) - val param_2 = assertion.params.get("param_2").map(_.toInt).getOrElse(throw new IllegalArgumentException("param_2 is missing")) - val param_3 = assertion.params.getOrElse("param_3", throw new IllegalArgumentException("param_3 is missing")) - val param_4 = assertion.params.getOrElse("param_4", throw new IllegalArgumentException("param_4 is missing")) + val param_1 = responseAction.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) + val param_2 = responseAction.params.get("param_2").map(_.toInt).getOrElse(throw new IllegalArgumentException("param_2 is missing")) + val param_3 = responseAction.params.getOrElse("param_3", throw new IllegalArgumentException("param_3 is missing")) + val param_4 = responseAction.params.getOrElse("param_4", throw new IllegalArgumentException("param_4 is missing")) stringFromList(response, param_1, param_2, param_3, param_4) - case _ => throw new IllegalArgumentException(s"Unsupported assertion[group: extract]: ${assertion.name}") + case _ => throw new IllegalArgumentException(s"Unsupported assertion[group: extract]: ${responseAction.name}") } } @@ -111,13 +111,13 @@ object ResponseExtractJson extends ResponsePerformer { } /** - * This method validates the parameters of the STRING_FROM_LIST type of assertion. + * This method validates the parameters of the STRING_FROM_LIST type of response action. * It ensures none of the required parameters are None and validates that they are non-empty strings. * Additionally, it ensures param_2 is a valid integer. * - * @param assertion The Assertion instance containing the assertion details. + * @param assertion The ResponseAction instance containing the response action details. */ - def validateStringFromList(assertion: Assertion): Unit = { + def validateStringFromList(assertion: ResponseAction): Unit = { val param_1 = assertion.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) val param_2 = assertion.params.getOrElse("param_2", throw new IllegalArgumentException("param_2 is missing")) val param_3 = assertion.params.getOrElse("param_3", throw new IllegalArgumentException("param_3 is missing")) diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/LogResponseAction.scala b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/LogResponseAction.scala new file mode 100644 index 0000000..1ed58bc --- /dev/null +++ b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/LogResponseAction.scala @@ -0,0 +1,82 @@ +/* + * Copyright 2023 ABSA Group Limited + * + * 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 africa.absa.testing.scapi.rest.response + +import africa.absa.testing.scapi.UndefinedResponseActionType +import africa.absa.testing.scapi.json.ResponseAction +import africa.absa.testing.scapi.logging.Logger +import africa.absa.testing.scapi.utils.validation.ContentValidator + +/** + * Singleton object `ResponseLog` that extends the `ResponsePerformer` trait. + * It provides utilities for validating and performing logging messages. + */ +object LogResponseAction extends ResponsePerformer { + + val INFO = "info" + + /** + * This method validates the content of the response action. + * It checks if the response action's name is "info", then validates if its `param_1` is a non-empty string. + * For all other response action names, it throws an `UndefinedAssertionType` exception. + * + * @param responseAction The response action to be validated. + * @throws UndefinedResponseActionType if the response action's name is not recognized. + */ + def validateContent(responseAction: ResponseAction): Unit = { + responseAction.name.toLowerCase match { + case INFO => + responseAction.params.get("param_1") match { + case param_1 => ContentValidator.validateNonEmptyString(param_1.get, s"ResponseLog.$INFO.param_1") + case None => throw new IllegalArgumentException(s"Missing required param_1 for assertion $INFO") + } + case _ => throw UndefinedResponseActionType(responseAction.name) + } + } + + /** + * This method performs the necessary response actions on the response. + * It checks if the response action's name is "info", then logs the `param_1` as info message. + * For all other response action names, it throws an `IllegalArgumentException`. + * + * @param response The response on which the response action are to be performed. + * @param responseAction The responseAction to be performed on the response. + * @throws IllegalArgumentException if the response action's name is not recognized. + */ + def performResponseAction(response: Response, responseAction: ResponseAction): Boolean = { + responseAction.name match { + case INFO => + val param_1 = responseAction.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) + logInfo(param_1) + case _ => throw new IllegalArgumentException(s"Unsupported assertion[group: log]: ${responseAction.name}") + } + } + + /* + dedicated actions + */ + + /** + * This method logs a message at the INFO level. + * + * @param message The message to be logged. + */ + def logInfo(message: String): Boolean = { + Logger.info(message) + true + } +} diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/Response.scala b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/Response.scala index 4bf33ac..df74355 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/Response.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/Response.scala @@ -16,7 +16,7 @@ package africa.absa.testing.scapi.rest.response -import africa.absa.testing.scapi.json.Assertion +import africa.absa.testing.scapi.json.ResponseAction case class Response(statusCode: Int, body: String, headers: Map[String, Seq[String]]) @@ -30,39 +30,39 @@ object Response { val GROUP_LOG: String = "log" /** - * Validates an Assertion based on its group type. + * Validates an ResponseAction based on its group type. * Calls the appropriate group's validateContent method based on group type. * - * @param assertion The assertion to be validated. - * @throws IllegalArgumentException If the assertion group type is not supported. + * @param responseAction The responseAction to be validated. + * @throws IllegalArgumentException If the response action group is not supported. */ - def validate(assertion: Assertion): Unit = { - assertion.group match { - case GROUP_ASSERT => ResponseAssertion.validateContent(assertion) - case GROUP_EXTRACT_JSON => ResponseExtractJson.validateContent(assertion) - case GROUP_LOG => ResponseLog.validateContent(assertion) - case _ => throw new IllegalArgumentException(s"Unsupported assertion group: ${assertion.group}") + def validate(responseAction: ResponseAction): Unit = { + responseAction.group match { + case GROUP_ASSERT => AssertionResponseAction.validateContent(responseAction) + case GROUP_EXTRACT_JSON => ExtractJsonResponseAction.validateContent(responseAction) + case GROUP_LOG => LogResponseAction.validateContent(responseAction) + case _ => throw new IllegalArgumentException(s"Unsupported assertion group: ${responseAction.group}") } } /** * Performs actions on the given Response based on a set of Assertions. - * Each Assertion is resolved by the runtime cache before being used. + * Each response action is resolved by the runtime cache before being used. * The appropriate group's performAssertions method is called based on the group type of each Assertion. * Returns true only if all assertions return true, and false as soon as any assertion returns false. * * @param response The response on which actions will be performed. - * @param assertions The set of assertions that dictate what actions will be performed on the response. - * @return Boolean indicating whether all assertions passed (true) or any assertion failed (false). - * @throws IllegalArgumentException If an assertion group type is not supported. + * @param responseAction The set of response actions that dictate what actions will be performed on the response. + * @return Boolean indicating whether all response actions passed (true) or any response action failed (false). + * @throws IllegalArgumentException If an response action group is not supported. */ - def perform(response: Response, assertions: Set[Assertion]): Boolean = { - assertions.forall { assertion => - val resolvedAssertion: Assertion = assertion.resolveByRuntimeCache() - resolvedAssertion.group match { - case GROUP_ASSERT => ResponseAssertion.performAssertion(response, assertion) - case GROUP_EXTRACT_JSON => ResponseExtractJson.performAssertion(response, assertion) - case GROUP_LOG => ResponseLog.performAssertion(response, assertion) + def perform(response: Response, responseAction: Set[ResponseAction]): Boolean = { + responseAction.forall { assertion => + val resolvedResponseAction: ResponseAction = assertion.resolveByRuntimeCache() + resolvedResponseAction.group match { + case GROUP_ASSERT => AssertionResponseAction.performResponseAction(response, assertion) + case GROUP_EXTRACT_JSON => ExtractJsonResponseAction.performResponseAction(response, assertion) + case GROUP_LOG => LogResponseAction.performResponseAction(response, assertion) case _ => throw new IllegalArgumentException(s"Unsupported assertion group: ${assertion.group}") } } diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseLog.scala b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseLog.scala deleted file mode 100644 index f5bbc4d..0000000 --- a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponseLog.scala +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2023 ABSA Group Limited - * - * 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 africa.absa.testing.scapi.rest.response - -import africa.absa.testing.scapi.UndefinedAssertionType -import africa.absa.testing.scapi.json.Assertion -import africa.absa.testing.scapi.logging.Logger -import africa.absa.testing.scapi.utils.validation.ContentValidator - -/** - * Singleton object `ResponseLog` that extends the `ResponsePerformer` trait. - * It provides utilities for validating and performing assertions, and logging info messages. - */ -object ResponseLog extends ResponsePerformer { - - val INFO = "info" - - /** - * This method validates the content of the assertion. - * It checks if the assertion's name is "info", then validates if its `param_1` is a non-empty string. - * For all other assertion names, it throws an `UndefinedAssertionType` exception. - * - * @param assertion The assertion to be validated. - * @throws UndefinedAssertionType if the assertion's name is not recognized. - */ - def validateContent(assertion: Assertion): Unit = { - assertion.name.toLowerCase match { - case INFO => - assertion.params.get("param_1") match { - case param_1 => ContentValidator.validateNonEmptyString(param_1.get, s"ResponseLog.$INFO.param_1") - case None => throw new IllegalArgumentException(s"Missing required param_1 for assertion $INFO") - } - case _ => throw UndefinedAssertionType(assertion.name) - } - } - - /** - * This method performs the necessary assertions on the response. - * It checks if the assertion's name is "info", then logs the `param_1` as info message. - * For all other assertion names, it throws an `IllegalArgumentException`. - * - * @param response The response on which the assertions are to be performed. - * @param assertion The assertion to be performed on the response. - * @throws IllegalArgumentException if the assertion's name is not recognized. - */ - def performAssertion(response: Response, assertion: Assertion): Boolean = { - assertion.name match { - case INFO => - val param_1 = assertion.params.getOrElse("param_1", throw new IllegalArgumentException("param_1 is missing")) - logInfo(param_1) - case _ => throw new IllegalArgumentException(s"Unsupported assertion[group: log]: ${assertion.name}") - } - } - - /* - dedicated actions - */ - - /** - * This method logs a message at the INFO level. - * - * @param message The message to be logged. - */ - def logInfo(message: String): Boolean = { - Logger.info(message) - true - } -} diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponsePerformer.scala b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponsePerformer.scala index 333dcc1..e430305 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponsePerformer.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/rest/response/ResponsePerformer.scala @@ -16,9 +16,9 @@ package africa.absa.testing.scapi.rest.response -import africa.absa.testing.scapi.json.Assertion +import africa.absa.testing.scapi.json.ResponseAction trait ResponsePerformer { - def validateContent(assertion: Assertion): Unit - def performAssertion(response: Response, assertion: Assertion): Boolean + def validateContent(responseAction: ResponseAction): Unit + def performResponseAction(response: Response, responseAction: ResponseAction): Boolean } diff --git a/testApi/src/main/scala/africa/absa/testing/scapi/suite/runner/SuiteRunner.scala b/testApi/src/main/scala/africa/absa/testing/scapi/suite/runner/SuiteRunner.scala index d9b2da1..3a9ae08 100644 --- a/testApi/src/main/scala/africa/absa/testing/scapi/suite/runner/SuiteRunner.scala +++ b/testApi/src/main/scala/africa/absa/testing/scapi/suite/runner/SuiteRunner.scala @@ -87,7 +87,7 @@ object SuiteRunner { val response: Response = sendRequest(method, environment, restClientCreator) val isSuccess: Boolean = Response.perform( response = response, - assertions = method.assertions + responseAction = method.responseActions ) val testEndTime: Long = System.currentTimeMillis() @@ -120,7 +120,7 @@ object SuiteRunner { val response: Response = sendRequest(test, environment, restClientCreator) val isSuccess: Boolean = Response.perform( response = response, - assertions = test.assertions + responseAction = test.responseActions ) val testEndTime: Long = System.currentTimeMillis() @@ -158,7 +158,7 @@ object SuiteRunner { val response: Response = sendRequest(method, environment, restClientCreator) val isSuccess: Boolean = Response.perform( response = response, - assertions = method.assertions + responseAction = method.responseActions ) val testEndTime: Long = System.currentTimeMillis() diff --git a/testApi/src/test/resources/project_with_issues/suites/aulgui-controller/undefinedConstantIssue.suite.json b/testApi/src/test/resources/project_with_issues/suites/aulgui-controller/undefinedConstantIssue.suite.json index 5be31b9..bf62664 100644 --- a/testApi/src/test/resources/project_with_issues/suites/aulgui-controller/undefinedConstantIssue.suite.json +++ b/testApi/src/test/resources/project_with_issues/suites/aulgui-controller/undefinedConstantIssue.suite.json @@ -16,10 +16,9 @@ "url": "{{ env.url }}/AULGUI/user" } ], - "assertions": [ + "responseActions": [ { - "group": "assert", - "name": "status-code", + "method": "assert.status-code", "param_1": "200" } ] diff --git a/testApi/src/test/resources/test_project/suites/gui-controller/deleteQuestion.suite.json b/testApi/src/test/resources/test_project/suites/gui-controller/deleteQuestion.suite.json index 4b05974..e8fe7f8 100644 --- a/testApi/src/test/resources/test_project/suites/gui-controller/deleteQuestion.suite.json +++ b/testApi/src/test/resources/test_project/suites/gui-controller/deleteQuestion.suite.json @@ -20,10 +20,9 @@ "url": "{{ env.url }}/path/question" } ], - "assertions": [ + "responseActions": [ { - "group": "assert", - "name": "status-code", + "method": "assert.status-code", "param_1": "200" } ] diff --git a/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.after.json b/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.after.json index 22b8ace..9baf46f 100644 --- a/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.after.json +++ b/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.after.json @@ -19,10 +19,9 @@ "url": "{{ env.url }}/AULGUI/user" } ], - "assertions": [ + "responseActions": [ { - "group": "assert", - "name": "statusCode", + "method": "assert.statusCode", "param_1": "200" } ] diff --git a/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.before.json b/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.before.json index a8ae9e2..be62f7e 100644 --- a/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.before.json +++ b/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.before.json @@ -19,10 +19,9 @@ "url": "{{ env.url }}/AULGUI/user" } ], - "assertions": [ + "responseActions": [ { - "group": "assert", - "name": "status-code", + "method": "assert.status-code", "param_1": "200" } ] diff --git a/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.suite.json b/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.suite.json index 7d8dc9c..3cdfce9 100644 --- a/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.suite.json +++ b/testApi/src/test/resources/test_project/suites/gui-controller/getUserCurrent.suite.json @@ -20,10 +20,9 @@ "url": "{{ env.url }}/GUI/user" } ], - "assertions": [ + "responseActions": [ { - "group": "assert", - "name": "status-code", + "method": "assert.status-code", "param_1": "200" } ] diff --git a/testApi/src/test/resources/test_project/suites/gui-controller/postQuestion.suite.json b/testApi/src/test/resources/test_project/suites/gui-controller/postQuestion.suite.json index 6e9c281..12dae5d 100644 --- a/testApi/src/test/resources/test_project/suites/gui-controller/postQuestion.suite.json +++ b/testApi/src/test/resources/test_project/suites/gui-controller/postQuestion.suite.json @@ -27,10 +27,9 @@ ] } ], - "assertions": [ + "responseActions": [ { - "group": "assert", - "name": "status-code", + "method": "assert.status-code", "param_1": "200" } ] diff --git a/testApi/src/test/resources/test_project/suites/gui-controller/putQuestion.suite.json b/testApi/src/test/resources/test_project/suites/gui-controller/putQuestion.suite.json index f1e01df..a206ee6 100644 --- a/testApi/src/test/resources/test_project/suites/gui-controller/putQuestion.suite.json +++ b/testApi/src/test/resources/test_project/suites/gui-controller/putQuestion.suite.json @@ -20,10 +20,9 @@ "url": "{{ env.url }}/path/question" } ], - "assertions": [ + "responseActions": [ { - "group": "assert", - "name": "status-code", + "method": "assert.status-code", "param_1": "200" } ] diff --git a/testApi/src/test/scala/africa/absa/testing/scapi/json/SuiteFactoryTest.scala b/testApi/src/test/scala/africa/absa/testing/scapi/json/SuiteFactoryTest.scala index 6cce77a..2814931 100644 --- a/testApi/src/test/scala/africa/absa/testing/scapi/json/SuiteFactoryTest.scala +++ b/testApi/src/test/scala/africa/absa/testing/scapi/json/SuiteFactoryTest.scala @@ -33,7 +33,7 @@ class SuiteFactoryTest extends FunSuite { private var out: ByteArrayOutputStream = _ private def initTestLogger(): Unit = { - ctx = (LogManager.getContext(false).asInstanceOf[LoggerContext]) + ctx = LogManager.getContext(false).asInstanceOf[LoggerContext] val config = ctx.getConfiguration val layout = PatternLayout.createDefaultLayout(config) out = new ByteArrayOutputStream() @@ -130,15 +130,15 @@ class SuiteFactoryTest extends FunSuite { test("filterOnlyOrAll - only used - once") { val suitesBundles = Set( SuiteBundle(suite = Suite(endpoint = "endpoint1", tests = Set( - SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, assertions = Set.empty, only = Some(false)), - SuiteTestScenario(name = "test2", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, assertions = Set.empty, only = Some(true)) + SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, responseActions = Set.empty, only = Some(false)), + SuiteTestScenario(name = "test2", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, responseActions = Set.empty, only = Some(true)) ))), SuiteBundle(suite = Suite(endpoint = "endpoint1", tests = Set( - SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, assertions = Set.empty, only = Some(false)), - SuiteTestScenario(name = "test2", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, assertions = Set.empty, only = Some(true)) + SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, responseActions = Set.empty, only = Some(false)), + SuiteTestScenario(name = "test2", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, responseActions = Set.empty, only = Some(true)) ))), SuiteBundle(suite = Suite(endpoint = "endpoint2", tests = Set( - SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, assertions = Set.empty, only = Some(false)), + SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, responseActions = Set.empty, only = Some(false)), )))) val filteredSuiteBundles: Set[SuiteBundle] = SuiteFactory.filterOnlyOrAll(suitesBundles) @@ -157,11 +157,11 @@ class SuiteFactoryTest extends FunSuite { test("fromFile - only used - twice") { val suitesBundles = Set( SuiteBundle(suite = Suite(endpoint = "endpoint1", tests = Set( - SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, assertions = Set.empty, only = Some(false)), - SuiteTestScenario(name = "test2", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, assertions = Set.empty, only = Some(true)) + SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, responseActions = Set.empty, only = Some(false)), + SuiteTestScenario(name = "test2", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, responseActions = Set.empty, only = Some(true)) ))), SuiteBundle(suite = Suite(endpoint = "endpoint2", tests = Set( - SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, assertions = Set.empty, only = Some(true)), + SuiteTestScenario(name = "test1", categories = Set("SMOKE"), headers = Set.empty, actions = Set.empty, responseActions = Set.empty, only = Some(true)), )))) val filteredSuiteBundles: Set[SuiteBundle] = SuiteFactory.filterOnlyOrAll(suitesBundles) diff --git a/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseAssertionsTest.scala b/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseAssertionsTest.scala index 618e795..ed6312a 100644 --- a/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseAssertionsTest.scala +++ b/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseAssertionsTest.scala @@ -16,8 +16,8 @@ package africa.absa.testing.scapi.rest.response -import africa.absa.testing.scapi.json.Assertion -import africa.absa.testing.scapi.{ContentValidationFailed, UndefinedAssertionType} +import africa.absa.testing.scapi.json.ResponseAction +import africa.absa.testing.scapi.{ContentValidationFailed, UndefinedResponseActionType} import munit.FunSuite class ResponseAssertionsTest extends FunSuite { @@ -26,69 +26,69 @@ class ResponseAssertionsTest extends FunSuite { validateContent */ test("validateContent - valid status code string") { - val assertion = Assertion(group = Response.GROUP_ASSERT, name = ResponseAssertion.STATUS_CODE, Map("param_1" -> "200")) - ResponseAssertion.validateContent(assertion) + val assertion = ResponseAction(method = s"${Response.GROUP_ASSERT}.${AssertionResponseAction.STATUS_CODE}", Map("param_1" -> "200")) + AssertionResponseAction.validateContent(assertion) } test("validateContent - invalid status code string") { intercept[ContentValidationFailed] { - ResponseAssertion.validateContent(Assertion(group = Response.GROUP_ASSERT, name = ResponseAssertion.STATUS_CODE, Map("param_1" -> "not an integer"))) + AssertionResponseAction.validateContent(ResponseAction(method = s"${Response.GROUP_ASSERT}.${AssertionResponseAction.STATUS_CODE}", Map("param_1" -> "not an integer"))) } } test("validateContent - body is not empty") { - val assertion = Assertion(group = Response.GROUP_ASSERT, name = ResponseAssertion.BODY_CONTAINS, Map("param_1" -> "test content")) - ResponseAssertion.validateContent(assertion) + val assertion = ResponseAction(method = s"${Response.GROUP_ASSERT}.${AssertionResponseAction.BODY_CONTAINS}", Map("param_1" -> "test content")) + AssertionResponseAction.validateContent(assertion) } test("validateContent - body is empty") { intercept[ContentValidationFailed] { - ResponseAssertion.validateContent(Assertion(group = Response.GROUP_ASSERT, name = ResponseAssertion.BODY_CONTAINS, Map("param_1" -> ""))) + AssertionResponseAction.validateContent(ResponseAction(method = s"${Response.GROUP_ASSERT}.${AssertionResponseAction.BODY_CONTAINS}", Map("param_1" -> ""))) } } - test("validateContent - unsupported assertion") { - intercept[UndefinedAssertionType] { - ResponseAssertion.validateContent(Assertion(group = Response.GROUP_ASSERT, name = "unsupported", Map("param_1" -> "value"))) + test("validateContent - unsupported response action") { + intercept[UndefinedResponseActionType] { + AssertionResponseAction.validateContent(ResponseAction(method = s"${Response.GROUP_ASSERT}.unsupported", Map("param_1" -> "value"))) } } /* - performAssertions + performResponseAction */ test("performAssertions - status code assertion - equals") { - val statusCodeAssertion = Assertion(group = Response.GROUP_ASSERT, name = "status-code", Map("param_1" -> "200")) + val statusCodeAssertion = ResponseAction(method = s"${Response.GROUP_ASSERT}.status-code", Map("param_1" -> "200")) val response = Response(200, "Dummy Body", Map.empty) - assert(ResponseAssertion.performAssertion(response, statusCodeAssertion)) + assert(AssertionResponseAction.performResponseAction(response, statusCodeAssertion)) } test("performAssertions - status code assertion - not equals") { - val statusCodeAssertion = Assertion(group = Response.GROUP_ASSERT, name = "status-code", Map("param_1" -> "200")) + val statusCodeAssertion = ResponseAction(method = s"${Response.GROUP_ASSERT}.status-code", Map("param_1" -> "200")) val response = Response(500, "Dummy Body", Map.empty) - assert(!ResponseAssertion.performAssertion(response, statusCodeAssertion)) + assert(!AssertionResponseAction.performResponseAction(response, statusCodeAssertion)) } test("performAssertions - body contains assertion") { - val bodyContainsAssertion = Assertion(group = Response.GROUP_ASSERT, name = "body-contains", Map("param_1" -> "dummy")) + val bodyContainsAssertion = ResponseAction(method = s"${Response.GROUP_ASSERT}.body-contains", Map("param_1" -> "dummy")) val response = Response(200, "This is a dummy body", Map.empty) - assert(ResponseAssertion.performAssertion(response, bodyContainsAssertion)) + assert(AssertionResponseAction.performResponseAction(response, bodyContainsAssertion)) } test("performAssertions - body does not contains assertion") { - val bodyContainsAssertion = Assertion(group = Response.GROUP_ASSERT, name = "body-contains", Map("param_1" -> "dummies")) + val bodyContainsAssertion = ResponseAction(method = s"${Response.GROUP_ASSERT}.body-contains", Map("param_1" -> "dummies")) val response = Response(200, "This is a dummy body", Map.empty) - assert(!ResponseAssertion.performAssertion(response, bodyContainsAssertion)) + assert(!AssertionResponseAction.performResponseAction(response, bodyContainsAssertion)) } test("performAssertions - unsupported assertion") { - val unsupportedAssertion = Assertion(group = Response.GROUP_ASSERT, name = "unsupported-assertion", Map("param_1" -> "value")) + val unsupportedAssertion = ResponseAction(method = s"${Response.GROUP_ASSERT}.unsupported-assertion", Map("param_1" -> "value")) val response = Response(200, "Dummy Body", Map.empty) interceptMessage[IllegalArgumentException]("Unsupported assertion[group: assert]: unsupported-assertion") { - ResponseAssertion.performAssertion(response, unsupportedAssertion) + AssertionResponseAction.performResponseAction(response, unsupportedAssertion) } } } diff --git a/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseExtractTest.scala b/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseExtractTest.scala index 3f86f79..453d1b1 100644 --- a/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseExtractTest.scala +++ b/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseExtractTest.scala @@ -16,15 +16,15 @@ package africa.absa.testing.scapi.rest.response -import africa.absa.testing.scapi.{ContentValidationFailed, UndefinedAssertionType} -import africa.absa.testing.scapi.json.Assertion +import africa.absa.testing.scapi.{ContentValidationFailed, UndefinedResponseActionType} +import africa.absa.testing.scapi.json.ResponseAction import africa.absa.testing.scapi.utils.cache.RuntimeCache import munit.FunSuite class ResponseExtractTest extends FunSuite { - val assertionStringFromList: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "question_id", "param_2" -> "1", "param_3" -> "id", "param_4" -> "suite")) - val assertionUnsupported: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, "Unsupported", Map("param_1" -> "key", "param_2" -> "200", "param_3" -> "jsonKey", "param_4" -> "Test")) + val assertionStringFromList: ResponseAction = ResponseAction(method = s"${Response.GROUP_EXTRACT_JSON}.${ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "question_id", "param_2" -> "1", "param_3" -> "id", "param_4" -> "suite")) + val assertionUnsupported: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.Unsupported", Map("param_1" -> "key", "param_2" -> "200", "param_3" -> "jsonKey", "param_4" -> "Test")) val responseWithID: Response = Response( 200, @@ -44,28 +44,28 @@ class ResponseExtractTest extends FunSuite { */ test("validateContent - STRING_FROM_LIST") { - ResponseExtractJson.validateContent(assertionStringFromList) + ExtractJsonResponseAction.validateContent(assertionStringFromList) } test("validateContent - unsupported option") { - intercept[UndefinedAssertionType] { - ResponseExtractJson.validateContent(assertionUnsupported) + intercept[UndefinedResponseActionType] { + ExtractJsonResponseAction.validateContent(assertionUnsupported) } } /* - performAssertion + performResponseAction */ test("performAssertion - STRING_FROM_LIST") { - val result: Boolean = ResponseExtractJson.performAssertion(responseWithID, assertionStringFromList) + val result: Boolean = ExtractJsonResponseAction.performResponseAction(responseWithID, assertionStringFromList) assert(result) assertEquals("382be85a-1f00-4c15-b607-cbda03ccxxx2", RuntimeCache.get("question_id").get) } test("performAssertion - unsupported assertion") { intercept[IllegalArgumentException] { - ResponseExtractJson.performAssertion(responseWithID, assertionUnsupported) + ExtractJsonResponseAction.performResponseAction(responseWithID, assertionUnsupported) } } @@ -81,7 +81,7 @@ class ResponseExtractTest extends FunSuite { val jsonKey = "id" val runtimeCacheLevel = "Test" interceptMessage[IndexOutOfBoundsException]("10 is out of bounds (min 0, max 2)") { - ResponseExtractJson.stringFromList(responseWithID, cacheKey, listIndex, jsonKey, runtimeCacheLevel) + ExtractJsonResponseAction.stringFromList(responseWithID, cacheKey, listIndex, jsonKey, runtimeCacheLevel) } } @@ -90,7 +90,7 @@ class ResponseExtractTest extends FunSuite { val listIndex = 0 val jsonKey = "ids" val runtimeCacheLevel = "Test" - val result = ResponseExtractJson.stringFromList(responseWithID, cacheKey, listIndex, jsonKey, runtimeCacheLevel) + val result = ExtractJsonResponseAction.stringFromList(responseWithID, cacheKey, listIndex, jsonKey, runtimeCacheLevel) assert(!result) } @@ -100,7 +100,7 @@ class ResponseExtractTest extends FunSuite { val jsonKey = "id" val runtimeCacheLevel = "Test" - val result = ResponseExtractJson.stringFromList(responseNoJsonBody, cacheKey, listIndex, jsonKey, runtimeCacheLevel) + val result = ExtractJsonResponseAction.stringFromList(responseNoJsonBody, cacheKey, listIndex, jsonKey, runtimeCacheLevel) assert(!result) } @@ -110,7 +110,7 @@ class ResponseExtractTest extends FunSuite { val jsonKey = "id" val runtimeCacheLevel = "Test" - val result = ResponseExtractJson.stringFromList(responseJsonNoArrayBody, cacheKey, listIndex, jsonKey, runtimeCacheLevel) + val result = ExtractJsonResponseAction.stringFromList(responseJsonNoArrayBody, cacheKey, listIndex, jsonKey, runtimeCacheLevel) assert(!result) } @@ -121,49 +121,49 @@ class ResponseExtractTest extends FunSuite { // positive test "stringFromList - correct parameters" - tested during "validateContent - STRING_FROM_LIST" test("validateStringFromList - None parameters") { - val assertion1None: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "", "param_2" -> "", "param_3" -> "")) - val assertion2None: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "", "param_2" -> "")) - val assertion3None: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "")) - val assertion4None: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map()) + val assertion1None: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "", "param_2" -> "", "param_3" -> "")) + val assertion2None: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "", "param_2" -> "")) + val assertion3None: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "")) + val assertion4None: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map()) interceptMessage[IllegalArgumentException]("param_1 is missing") { - ResponseExtractJson.validateStringFromList(assertion4None) + ExtractJsonResponseAction.validateStringFromList(assertion4None) } interceptMessage[IllegalArgumentException]("param_2 is missing") { - ResponseExtractJson.validateStringFromList(assertion3None) + ExtractJsonResponseAction.validateStringFromList(assertion3None) } interceptMessage[IllegalArgumentException]("param_3 is missing") { - ResponseExtractJson.validateStringFromList(assertion2None) + ExtractJsonResponseAction.validateStringFromList(assertion2None) } interceptMessage[IllegalArgumentException]("param_4 is missing") { - ResponseExtractJson.validateStringFromList(assertion1None) + ExtractJsonResponseAction.validateStringFromList(assertion1None) } } test("validateStringFromList - empty parameters") { - val assertionParam1: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "", "param_2" -> "", "param_3" -> "", "param_4" -> "")) - val assertionParam2: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "1", "param_2" -> "", "param_3" -> "", "param_4" -> "")) - val assertionParam3: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "1", "param_2" -> "x", "param_3" -> "", "param_4" -> "")) - val assertionParam4: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "1", "param_2" -> "x", "param_3" -> "y", "param_4" -> "")) + val assertionParam1: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "", "param_2" -> "", "param_3" -> "", "param_4" -> "")) + val assertionParam2: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "1", "param_2" -> "", "param_3" -> "", "param_4" -> "")) + val assertionParam3: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "1", "param_2" -> "x", "param_3" -> "", "param_4" -> "")) + val assertionParam4: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "1", "param_2" -> "x", "param_3" -> "y", "param_4" -> "")) interceptMessage[ContentValidationFailed]("Content validation failed for value: '': Received string value of 'ExtractJson.string-from-list.param_1' is empty.") { - ResponseExtractJson.validateStringFromList(assertionParam1) + ExtractJsonResponseAction.validateStringFromList(assertionParam1) } interceptMessage[ContentValidationFailed]("Content validation failed for value: '': Received string value of 'ExtractJson.string-from-list.param_2' is empty.") { - ResponseExtractJson.validateStringFromList(assertionParam2) + ExtractJsonResponseAction.validateStringFromList(assertionParam2) } interceptMessage[ContentValidationFailed]("Content validation failed for value: '': Received string value of 'ExtractJson.string-from-list.param_3' is empty.") { - ResponseExtractJson.validateStringFromList(assertionParam3) + ExtractJsonResponseAction.validateStringFromList(assertionParam3) } interceptMessage[ContentValidationFailed]("Content validation failed for value: '': Received string value of 'ExtractJson.string-from-list.param_4' is empty.") { - ResponseExtractJson.validateStringFromList(assertionParam4) + ExtractJsonResponseAction.validateStringFromList(assertionParam4) } } test("validateStringFromList - not integer in string") { - val assertion: Assertion = Assertion(Response.GROUP_EXTRACT_JSON, ResponseExtractJson.STRING_FROM_LIST, Map("param_1" -> "key", "param_2" -> "x", "param_3" -> "y", "param_4" -> "y")) + val assertion: ResponseAction = ResponseAction(method = s"{Response.GROUP_EXTRACT_JSON}.&{ExtractJsonResponseAction.STRING_FROM_LIST}", Map("param_1" -> "key", "param_2" -> "x", "param_3" -> "y", "param_4" -> "y")) interceptMessage[ContentValidationFailed]("Content validation failed for value: 'x': Received value of 'ExtractJson.string-from-list.param_2' cannot be parsed to an integer: For input string: \"x\"") { - ResponseExtractJson.validateStringFromList(assertion) + ExtractJsonResponseAction.validateStringFromList(assertion) } } diff --git a/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseLogTest.scala b/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseLogTest.scala index 8001b43..aa0ad58 100644 --- a/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseLogTest.scala +++ b/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseLogTest.scala @@ -16,8 +16,8 @@ package africa.absa.testing.scapi.rest.response -import africa.absa.testing.scapi.UndefinedAssertionType -import africa.absa.testing.scapi.json.Assertion +import africa.absa.testing.scapi.UndefinedResponseActionType +import africa.absa.testing.scapi.json.ResponseAction import munit.FunSuite class ResponseLogTest extends FunSuite { @@ -26,33 +26,33 @@ class ResponseLogTest extends FunSuite { validateContent */ test("validateContent - INFO supported") { - val assertionInfo = Assertion(Response.GROUP_LOG, ResponseLog.INFO, Map("param_1" -> "Non-empty string")) + val responseActionInfo = ResponseAction(method = s"${Response.GROUP_LOG}.${LogResponseAction.INFO}", Map("param_1" -> "Non-empty string")) // no exception thrown, meaning validation passed - ResponseLog.validateContent(assertionInfo) + LogResponseAction.validateContent(responseActionInfo) } test("validateContent - not supported validation type") { - val assertion = Assertion(Response.GROUP_LOG, "not_info", Map("param_1" -> "Some string")) - intercept[UndefinedAssertionType] { - ResponseLog.validateContent(assertion) + val responseAction = ResponseAction(method = s"${Response.GROUP_LOG}.not_info", Map("param_1" -> "Some string")) + intercept[UndefinedResponseActionType] { + LogResponseAction.validateContent(responseAction) } } /* - performAssertion + performResponseAction */ test("performAssertion - INFO supported") { - val assertion = Assertion(Response.GROUP_LOG, ResponseLog.INFO, Map("param_1" -> "info message")) + val assertion = ResponseAction(method = s"${Response.GROUP_LOG}.${LogResponseAction.INFO}", Map("param_1" -> "info message")) val response = Response(200, "OK", Map("Content-Type" -> Seq("application/json"))) - assertEquals(ResponseLog.performAssertion(response, assertion), true) + assertEquals(LogResponseAction.performResponseAction(response, assertion), true) } test("performAssertion - not supported validation type") { - val assertion = Assertion(Response.GROUP_LOG, "not_info", Map("param_1" -> "info message")) + val assertion = ResponseAction(method = s"${Response.GROUP_LOG}.not_info", Map("param_1" -> "info message")) val response = Response(200, "OK", Map("Content-Type" -> Seq("application/json"))) intercept[IllegalArgumentException] { - ResponseLog.performAssertion(response, assertion) + LogResponseAction.performResponseAction(response, assertion) } } @@ -61,6 +61,6 @@ class ResponseLogTest extends FunSuite { */ test("logInfo") { - assertEquals(ResponseLog.logInfo("log message"), true) + assertEquals(LogResponseAction.logInfo("log message"), true) } } diff --git a/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseTest.scala b/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseTest.scala index 0d87617..d166efa 100644 --- a/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseTest.scala +++ b/testApi/src/test/scala/africa/absa/testing/scapi/rest/response/ResponseTest.scala @@ -16,7 +16,7 @@ package africa.absa.testing.scapi.rest.response -import africa.absa.testing.scapi.json.Assertion +import africa.absa.testing.scapi.json.ResponseAction import munit.FunSuite class ResponseTest extends FunSuite { @@ -26,7 +26,7 @@ class ResponseTest extends FunSuite { */ test("validate - unsupported group") { - val unsupportedAssertion = Assertion("unsupportedGroup", "not needed", Map("param 1" -> "")) + val unsupportedAssertion = ResponseAction(method = "unsupportedGroup.not needed", Map("param 1" -> "")) intercept[IllegalArgumentException] { Response.validate(unsupportedAssertion) @@ -38,7 +38,7 @@ class ResponseTest extends FunSuite { */ test("perform - unsupported group") { - val unsupportedAssertion = Assertion("unsupportedGroup", "not needed", Map("param 1" -> "")) + val unsupportedAssertion = ResponseAction(method = "unsupportedGroup.not needed", Map("param 1" -> "")) val response = Response(200, "OK", Map.empty) intercept[IllegalArgumentException] { diff --git a/testApi/src/test/scala/africa/absa/testing/scapi/suite/runner/SuiteRunnerTest.scala b/testApi/src/test/scala/africa/absa/testing/scapi/suite/runner/SuiteRunnerTest.scala index b5a6239..ca81c30 100644 --- a/testApi/src/test/scala/africa/absa/testing/scapi/suite/runner/SuiteRunnerTest.scala +++ b/testApi/src/test/scala/africa/absa/testing/scapi/suite/runner/SuiteRunnerTest.scala @@ -16,12 +16,12 @@ package africa.absa.testing.scapi.suite.runner -import africa.absa.testing.scapi.json.{Action, Assertion, Environment, Header} +import africa.absa.testing.scapi.json.{Action, Environment, Header, ResponseAction} import africa.absa.testing.scapi.logging.Logger import africa.absa.testing.scapi.model._ import africa.absa.testing.scapi.rest.RestClient import africa.absa.testing.scapi.rest.request.RequestHeaders -import africa.absa.testing.scapi.rest.response.{Response, ResponseAssertion} +import africa.absa.testing.scapi.rest.response.{AssertionResponseAction, Response} import africa.absa.testing.scapi.utils.cache.RuntimeCache import munit.FunSuite import org.apache.logging.log4j.Level @@ -31,22 +31,22 @@ class SuiteRunnerTest extends FunSuite { val header: Header = Header(name = RequestHeaders.AUTHORIZATION, value = "Basic abcdefg") val action: Action = Action(methodName = "get", url = "nice url") val actionNotSupported: Action = Action(methodName = "wrong", url = "nice url") - val assertion: Assertion = Assertion(group = Response.GROUP_ASSERT, name = ResponseAssertion.STATUS_CODE, Map("param_1" -> "200")) - val method: Method = Method(name = "test", headers = Set(header), actions = Set(action), assertions = Set(assertion)) - val methodNotSupported: Method = Method(name = "test", headers = Set(header), actions = Set(actionNotSupported), assertions = Set(assertion)) + val assertion: ResponseAction = ResponseAction(method = s"${Response.GROUP_ASSERT}.${AssertionResponseAction.STATUS_CODE}", Map("param_1" -> "200")) + val method: Method = Method(name = "test", headers = Set(header), actions = Set(action), responseActions = Set(assertion)) + val methodNotSupported: Method = Method(name = "test", headers = Set(header), actions = Set(actionNotSupported), responseActions = Set(assertion)) val suitesBundles: Set[SuiteBundle] = Set( SuiteBundle(suite = Suite(endpoint = "endpoint1", tests = Set( SuiteTestScenario(name = "test1", categories = Set("SMOKE"), - headers = Set(header), actions = Set(action), assertions = Set(assertion), only = Some(true)), + headers = Set(header), actions = Set(action), responseActions = Set(assertion), only = Some(true)), SuiteTestScenario(name = "test2", categories = Set("SMOKE"), - headers = Set(header), actions = Set(action), assertions = Set(assertion), only = Some(true)) + headers = Set(header), actions = Set(action), responseActions = Set(assertion), only = Some(true)) ))), SuiteBundle( suiteBefore = Some(SuiteBefore(name = "suiteBefore", methods = Set(method))), suite = Suite(endpoint = "endpoint2", tests = Set( SuiteTestScenario(name = "test1", categories = Set("SMOKE"), - headers = Set(header), actions = Set(action), assertions = Set(assertion), only = Some(false)), + headers = Set(header), actions = Set(action), responseActions = Set(assertion), only = Some(false)), )), suiteAfter = Some(SuiteAfter(name = "suiteAfter", methods = Set(method))), )) @@ -55,7 +55,7 @@ class SuiteRunnerTest extends FunSuite { SuiteBundle( suite = Suite(endpoint = "endpoint2", tests = Set( SuiteTestScenario(name = "test1", categories = Set("SMOKE"), - headers = Set(header), actions = Set(action), assertions = Set(assertion), only = Some(false)), + headers = Set(header), actions = Set(action), responseActions = Set(assertion), only = Some(false)), )), suiteAfter = Some(SuiteAfter(name = "suiteAfter", methods = Set(method))), )) @@ -64,7 +64,7 @@ class SuiteRunnerTest extends FunSuite { SuiteBundle( suite = Suite(endpoint = "endpoint2", tests = Set( SuiteTestScenario(name = "test1", categories = Set("SMOKE"), - headers = Set(header), actions = Set(action), assertions = Set(assertion), only = Some(false)), + headers = Set(header), actions = Set(action), responseActions = Set(assertion), only = Some(false)), )), suiteAfter = Some(SuiteAfter(name = "suiteAfter", methods = Set(methodNotSupported))), )) @@ -74,7 +74,7 @@ class SuiteRunnerTest extends FunSuite { suiteBefore = Some(SuiteBefore(name = "suiteBefore", methods = Set(method))), suite = Suite(endpoint = "endpoint2", tests = Set( SuiteTestScenario(name = "test1", categories = Set("SMOKE"), - headers = Set(header), actions = Set(action), assertions = Set(assertion), only = Some(false)), + headers = Set(header), actions = Set(action), responseActions = Set(assertion), only = Some(false)), )))) val constants: Map[String, String] = Map(