How to iterate through each property element in API response in Katalon studio? - groovy

I'm writing test script in katalon studio to verify response body of the API.My response body is of format:
{
"status": "Success",
"correlationCode": "1234-5678",
"type": {
"id": 51247,
"name": "Student",
},
"data": {
"name": "Sara Nieves",
"gender": "Female",
"dob": "1995-08-06",
"libraryCard": {
"id": "11178",
"type": "Seniors"
},
"qualifications": [
{
"id": "45650986546",
"name": "Graduate Certificate in Environmental Engineering Management"
}
]
}
}
I want to verify that none of the elements return 'null' value. Since, the elements returned for the API response are not static(meaning name, gender etc might not get returned every time) therefore, i can't use something like "data.name" to verify if it has null value. So, i want a generic way to loop through each and every attribute returned and check if its value is returned as null or not.
Any help will be much appreciated. Thanks!

You have the error message:
groovy.lang.MissingMethodException: No signature of method: WSVerification1569811424284$_run_closure1.doCall() is applicable for argument types: (com.kms.katalon.core.testobject.ResponseObject) values: [200 1 KB] 22572.groovy:21)
I assume your response object type: com.kms.katalon.core.testobject.ResponseObject
The code to parse response as json and validate it:
import groovy.json.JsonSlurper
/**
* the recursive method to validate that json object does not have null values
* #param obj - the parsed json object (sequence of maps and lists)
* #param path - a variable to know where the error occurred in json data.
*/
void assertNoNullValue(Object obj, String path='ROOT'){
//the main assertion
assert obj!=null : "value in json could not be null: $path"
if(obj instanceof Map){
//iterate each key-value in map and validate the value recursively
obj.each{k,v-> assertNoNullValue(v,path+".$k") }
} else if(obj instanceof List){
//iterate each value in list and validate the value recursively
obj.eachWithIndex{v,i-> assertNoNullValue(v,path+"[$i]") }
}
}
def response = ...
assert response.isJsonContentType()
def responseText = response.getResponseText()
//parse body
def data = new JsonSlurper().parseText(responseText)
assertNoNullValue(data)

This solution is not as precise as the one suggested by #dagget, but it is a quick check:
def response = '''
{
"status": "Success",
"correlationCode": "1234-5678",
"type": {
"id": 51247,
"name": "Student",
},
"data": {
"name": "Sara Nieves",
"gender": "femmina",
"dob": "1995-08-06",
"libraryCard": {
"id": "11178",
"type": "Seniors"
},
"qualifications": [
{
"id": "45650986546",
"name": "Graduate Certificate in Environmental Engineering Management"
}
]
}
}
'''
assert !response.contains("null")

Related

Nested iteration over JSON using groovy closure in REST-assured

I have the following JSON response for my REST endpoint:
{
"response": {
"status": 200,
"startRow": 0,
"endRow": 1,
"totalRows": 1,
"next": "",
"data": {
"id": "workflow-1",
"name": "SampleWorkflow",
"tasks": [
{
"id": "task-0",
"name": "AWX",
"triggered_by": ["task-5"]
},
{
"id": "task-1",
"name": "BrainStorming",
"triggered_by": ["task-2", "task-5"]
},
{
"id": "task-2",
"name": "OnHold",
"triggered_by": ["task-0", "task-4", "task-7", "task-8", "task9"]
},
{
"id": "task-3",
"name": "InvestigateSuggestions",
"triggered_by": ["task-6"]
},
{
"id": "task-4",
"name": "Mistral",
"triggered_by": ["task-3"]
},
{
"id": "task-5",
"name": "Ansible",
"triggered_by": ["task-3"]
},
{
"id": "task-6",
"name": "Integration",
"triggered_by": []
},
{
"id": "task-7",
"name": "Tower",
"triggered_by": ["task-5"]
},
{
"id": "task-8",
"name": "Camunda",
"triggered_by": ["task-3"]
},
{
"id": "task-9",
"name": "HungOnMistral",
"triggered_by": ["task-0", "task-7"]
},
{
"id": "task-10",
"name": "MistralIsChosen",
"triggered_by": ["task-1"]
}
]
}
}
}
I am using rest-assured with a groovy gpath expression for an extraction as follows:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('task-3') }.name")
which correctly gives me [Mistral, Ansible, Camunda]
What I am trying to achieve is to find the task names that are triggered by the InvestigateSuggestions task. But I don't know for sure that the taskId I have to pass in to contains() is task-3; I only know its name i.e. InvestigateSuggestions. So I attempt to do:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
which does not work and complains that the parameter "response" was used but not defined.
How do I iterate over the outer collection from inside the findAll closure to find the correct id to pass into contains() ??
You can make use of a dirty secret, the restAssuredJsonRootObject. This is undocumented (and subject to change although it has never change as far as I can remember in the 7 year+ lifespan of REST Assured).
This would allow you to write:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(restAssuredJsonRootObject.response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
If you don't want to use this "hack" then you need to do something similar to what Michael Easter proposed in his answer.
When it comes to generating matchers based on the response body the story is better. See docs here.
I'm not sure if this is idiomatic but one approach is to find the id first and then substitute into another query:
#Test
void testCase1() {
def json = given()
.when()
.get("http://localhost:5151/egg_minimal/stacko.json")
// e.g. id = 'task-3' for name 'InvestigateSuggestions'
def id = json
.then()
.extract()
.path("response.data.tasks.find { it.name == 'InvestigateSuggestions' }.id")
// e.g. tasks have name 'task-3'
def tasks = json
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('${id}') }.name")
assertEquals(['Mistral', 'Ansible', 'Camunda'], tasks)
}

Logic App : Finding element in Json Object array (like XPath fr XML)

In my logic app, I have a JSON object (parsed from an API response) and it contains an object array.
How can I find a specific element based on attribute values... Example below where I want to find the (first) active one
{
"MyList" : [
{
"Descrip" : "This is the first item",
"IsActive" : "N"
},
{
"Descrip" : "This is the second item",
"IsActive" : "N"
},
{
"Descrip" : "This is the third item",
"IsActive" : "Y"
}
]
}
Well... The answer is in plain sight ... There's a FILTER ARRAY action, which works on a JSON Object (from PARSE JSON action).. couple this with an #first() expression will give the desired outcome.
You can use the Parse JSON Task to parse your JSON and a Condition to filter for the IsActive attribute:
Use the following Schema to parse the JSON:
{
"type": "object",
"properties": {
"MyList": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Descrip": {
"type": "string"
},
"IsActive": {
"type": "string"
}
},
"required": [
"Descrip",
"IsActive"
]
}
}
}
}
Here how it looks like (I included the sample data you provided to test it):
Then you can add the Condition:
And perform whatever action you want within the If true section.

Parsing child nodes of JSON response in SOAP UI using groovy json slurper

I am getting a JSON response from an webservice like below . I want to parse all childs of results node using Groovy Json slurper and assert the value is correct.
{
"status": "Healthy",
"results": [
{
"name": "Microservice one",
"status": "Healthy",
"description": "Url check MSOneURI success : status(OK)"
},
{
"name": "Microservice two",
"status": "Healthy",
"description": "Url check MSTwoURI success : status(OK)"
},
{
"name": "Microservice three",
"status": "Healthy",
"description": "Url check MSThreeURI success : status(OK)"
},
{
"name": "Microservice four",
"status": "Healthy",
"description": "Url check MSFourURI success : status(OK)"
},
{
"name": "Microservice five",
"status": "Healthy",
"description": "Url check MSFiveURI success : status(OK)"
}
]
}
This is what I have done - this works .
//imports
import groovy.json.JsonSlurper
import groovy.json.*
//grab the response
def ResponseMessage = messageExchange.response.responseContent
// trim starting and ending double quotes
def TrimResponse =ResponseMessage.replaceAll('^\"|\"$','').replaceAll('/\\/','')
//define a JsonSlurper
def jsonSlurper = new JsonSlurper().parseText(TrimResponse)
//verify the response to be validated isn't empty
assert !(jsonSlurper.isEmpty())
//verify the Json response Shows Correct Values
assert jsonSlurper.status == "Healthy"
def ActualMsNames = jsonSlurper.results*.name.toString()
def ActualMsStatus = jsonSlurper.results*.status.toString()
def ActualMsDescription = jsonSlurper.results*.description.toString()
def ExpectedMsNames = "[Microservice one,Microservice two,Microservice three,Microservice four,Microservice five]"
def ExpectedMsStatus = "[Healthy, Healthy, Healthy, Healthy, Healthy]"
def ExpectedMsDescription = "[Url check MSOneURI success : status(OK),Url check MSTwoURI success : status(OK),Url check MSThreeURI success : status(OK),Url check MSFourURI success : status(OK),Url check MSFiveURI success : status(OK)]"
assert ActualMsNames==ExpectedMsNames
assert ActualMsStatus==ExpectedMsStatus
assert ActualMsDescription==ExpectedMsDescription
But I want to make it better using some kind of for loop which will parse each collection one at a time and assert the value of "name", "status" and "descriptions" at once for each child
Is that possible?
Yes, that's certainly possible.
Without knowing more about your actual data it's not possible to give a perfect example, but you could do something like:
jsonSlurper.results?.eachWithIndex { result, i ->
assert result.name == expectedNames[i]
assert result.status == expectedStatus[i] // or just "Healthy" if that's the only one
assert result.description == expectedDescriptions[i]
}
where expectedWhatever is a list of expected result fields. If your expected results really are based on index like in your example, then you could even calculate them within the loop, but I'm guessing that's not the case for real data.

How to reference parent names in JSON response (with Groovy)

I have the following JSON response in SoapUI
{
"formatted": {
"line1": "14/8 QUAY STREET",
"line2": "14/8 QUAY STREET"
},
"structure": {
"level": null
},
"location": {
"nzX": 1758749.75300025
},
"references": {
"aid": "A1003467096"
}
}
I want the following as the output
formatted, structure, location and references.
I am using Json slurper but i am not able to get all the parent element names.
How do i do it using JSON slurper in groovy.
Assuming the JSON is in a string s, consider the following which illustrates getting the top level keys:
import groovy.json.*
def json = new JsonSlurper().parseText(s)
def parentNames = json.keySet()
parentNames.each { println it }

How to get data from json format using groovy?

i have a request in soapui which returns a json response.
i'm using groovy to retrieve the content of the response.
response :
<item><response>{
"timestamp": "2016-04-01T16:40:34",
"data": [
{
"deleted_at": null,
"userid": "b6d66002-8da4-4c03-928c-46871f084fb8",
"updated_by": null,
"created_at": "2016-03-01T16:40:34",
"updated_at": "2016-03-01T16:40:34",
"created_by": null,
"value": "hBeO",
"setting": "test",
"name": "test2"
}
],
"success": true
}</response></item>
From this response i want to retrieve each node like:
deleted_at
created_at
so i use this groovy
import groovy.json.JsonSlurper
def response = context.expand( '${set_settings#Response#declare namespace ns1=\'https://wato.io/ns/20160131\'; //ns1:set_settings_resp[1]/ns1:item[1]/ns1:response[1]}' )
def slurper = new JsonSlurper()
def result = slurper.parseText(response)
testRunner.testCase.setPropertyValue("user_id", result.data.userid)
and i receive this error message:
groovy.lang.MissingMethodException: No signature of method: com.eviware.soapui.impl.wsdl.WsdlTestCasePro.setPropertyValue() is applicable for argument types: (java.lang.String, java.util.ArrayList) values: [userid, [b6df6662-8da4-4c03-928c-46871f084fb8]] Possible solutions: setPropertyValue(java.lang.String, java.lang.String), getPropertyValue(java.lang.String) error at line: 8
It works only for timestamp node.
any help please.
Thank you
It's because result.data is a list, so it returns a list (containing one item) for userid
You need to just get the first item from the list, so try:
testRunner.testCase.setPropertyValue("user_id", result.data.userid.head())

Resources