How to put logic and assert dynamic data using karate - json

Here is my one response for a particular request
{
"data": {
"foo": [{
"total_value":200,
"applied_value": [{
"type": "A",
"id": 79806,
"value": 200
}]
}]
}
}
Here is my another response for the SAME request
{
"data": {
"foo": [{
"total_value":300,
"applied_value": [{
"type": "A",
"id": 79806,
"value": 200
},
{
"type": "B",
"id": 79809,
"value": 100
}
]
}]
}
}
I am unsure for which scenario will I get which response
So the use case is
Whenever there are 2 values in applied_value add two values and assert
Whenever there is only 1 value in applied_value directly assert

Here's one possible solution:
* def adder = function(array) { var total = 0; for (var i = 0; i < array.length; i++) total += array[i]; return total }
* def response =
"""
{
"data": {
"foo": [{
"total_value":300,
"applied_value": [{
"type": "A",
"id": 79806,
"value": 200
},
{
"type": "B",
"id": 79809,
"value": 100
}
]
}]
}
}
"""
* def expected = get[0] response..total_value
* def values = $response..value
* def total = adder(values)
* match expected == total
Just as an example, an alternate way to implement the adder routine is like this:
* def total = 0
* def add = function(x){ karate.set('total', karate.get('total') + x ) }
* eval karate.forEach(values, add)

Related

How to get the All index values in Groovy JSON xpath

Please find the attached Groovy code which I am using to get the particular filed from the response body.
Query 1 :
It is retrieving the results when the I am using the correct Index value like if the data.RenewalDetails[o], will give output as Value 1 and if the data.RenewalDetails[1], output as Value 2.
But in my real case, I will never know about number of blocks in the response, so I want to get all the values that are satisficing the condition, I tried data.RenewalDetails[*] but it is not working. Can you please help ?
Query 2:
Apart from the above condition, I want to add one more filter, where "FamilyCode": "PREMIUM" in the Itemdetails, Can you help on the same ?
def BoundId = new groovy.json.JsonSlurper().parseText('{"data":{"RenewalDetails":[{"ExpiryDetails":{"duration":"xxxxx","destination":"LHR","from":"AUH","value":2,"segments":[{"valudeid":"xxx-xx6262-xxxyyy-1111-11-11-1111"}]},"Itemdetails":[{"BoundId":"Value1","isexpired":true,"FamilyCode":"PREMIUM","availabilityDetails":[{"travelID":"AAA-AB1234-AAABBB-2022-11-10-1111","quota":"X","scale":"XXX","class":"X"}]}]},{"ExpiryDetails":{"duration":"xxxxx","destination":"LHR","from":"AUH","value":2,"segments":[{"valudeid":"xxx-xx6262-xxxyyy-1111-11-11-1111"}]},"Itemdetails":[{"BoundId":"Value2","isexpired":true,"FamilyCode":"PREMIUM","availabilityDetails":[{"travelID":"AAA-AB1234-AAABBB-2022-11-10-1111","quota":"X","scale":"XXX","class":"X"}]}]}]},"warnings":[{"code":"xxxx","detail":"xxxxxxxx","title":"xxxxxxxx"}]}')
.data.RenewalDetails[0].Itemdetails.find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.length() == 33
}?.BoundId
println "Hello " + BoundId
Something like this:
def txt = '''\
{
"data": {
"RenewalDetails": [
{
"ExpiryDetails": {
"duration": "xxxxx",
"destination": "LHR",
"from": "AUH",
"value": 2,
"segments": [
{
"valudeid": "xxx-xx6262-xxxyyy-1111-11-11-1111"
}
]
},
"Itemdetails": [
{
"BoundId": "Value1",
"isexpired": true,
"FamilyCode": "PREMIUM",
"availabilityDetails": [
{
"travelID": "AAA-AB1234-AAABBB-2022-11-10-1111",
"quota": "X",
"scale": "XXX",
"class": "X"
}
]
}
]
},
{
"ExpiryDetails": {
"duration": "xxxxx",
"destination": "LHR",
"from": "AUH",
"value": 2,
"segments": [
{
"valudeid": "xxx-xx6262-xxxyyy-1111-11-11-1111"
}
]
},
"Itemdetails": [
{
"BoundId": "Value2",
"isexpired": true,
"FamilyCode": "PREMIUM",
"availabilityDetails": [
{
"travelID": "AAA-AB1234-AAABBB-2022-11-10-1111",
"quota": "X",
"scale": "XXX",
"class": "X"
}
]
}
]
}
]
},
"warnings": [
{
"code": "xxxx",
"detail": "xxxxxxxx",
"title": "xxxxxxxx"
}
]
}'''
def json = new groovy.json.JsonSlurper().parseText txt
List<String> BoundIds = json.data.RenewalDetails.Itemdetails*.find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.size() == 33 && itemDetail.FamilyCode == 'PREMIUM'
}?.BoundId
assert BoundIds.toString() == '[Value1, Value2]'
Note, that you will get the BoundIds as a List
If you amend your code like this:
def json = new groovy.json.JsonSlurper().parse(prev.getResponseData()
you would be able to access the number of returned items as:
def size = json.data.RenewalDetails.size()
as RenewalDetails represents a List
Just add as many queries you want using Groovy's && operator:
find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.length() == 33 &&
itemDetail.FamilyCode.equals('PREMIUM')
}
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy: What Is Groovy Used For?

Json response validation based on substring presence in Karate Framework [duplicate]

This question already has an answer here:
Karate API json response - How to validate the presence of a key which sometimes come and sometimes not in the API response
(1 answer)
Closed 2 years ago.
I am trying to validate a JSON which has Optional keys depending on a condition.
Json response is as follows:
{ "hits": [
{
"_type": "sessions",
"_source": {
"movie_name": "The Greatest Showman (U/A) - English",
"session_data": {
"freeSeating": false,
"mandatoryItems": [],
"areas": [
{
"seatingType": "fixed"
},
{
"seatingType": "free"
},
{
"seatingType": "mixed"
}
]
}
}
},
{
"_type": "sessions",
"_source": {
"movie_name": "The Greatest Showman (U/A) - English",
"session_data": {
"freeSeating": false,
"mandatoryItems": [],
"areas": [
{
"seatingType": "fixed"
},
{
"seatingType": "free"
}
]
}
}
},
{
"_type": "sessions",
"_source": {
"movie_name": "The Greatest Showman 3D (U/A) - English",
"session_data": {
"freeSeating": false,
"mandatoryItems": [
{
"quantity": 1,
"level": "ticket",
"price": 30,
"type": "3dglasses"
}
],
"areas": [
{
"seatingType": "fixed"
}
]
}
}
}
]
}
If movie_name contains "3D" in it then mandatoryItems = [{"quantity": 1,"level": "ticket", "price": 30, "type": "3dglasses"}]
If movie_name does not contains "3D" in it then mandatoryItems = []
I want to achieve above assertions in my feature file.
Note: "movie_name" and "mandatoryItems" are present each element of an array. So I want to assert this condition on entire array.
Thanks in advance!!
Sorry #Peter for the inconvenience caused by me. I worked on this problem statement by referring all possible sources and wrote following code which is giving me desired output:
Given url api_url
When method Get
And def mandatoryItems_present =
"""
{
"quantity": 1,
"level": "ticket",
"price": '#number',
"type": "3dglasses",
}
"""
Then status 200
And print response
And def source_list = karate.jsonPath(response, '$.._source')
And print source_list
And match each source_list[*].session_data contains {'freeSeating': '#boolean','mandatoryItems':'##[] mandatoryItems_present'}
And def movie_names = get source_list[*].movie_name
And def mandatoryItems_list = get source_list[*].session_data.mandatoryItems
And def name_size = names.size();
And print name_size
And def threeD_movie_list = new ArrayList()
And eval for(var i = 0; i < name_size; i++) {if (names[i].match('3D')) threeD_movie_list.add(names[i])}
And print threeD_movie_list
And def threeD_movies_array_size = threeD_movie_list.size();
And print threeD_movies_array_size
And print expected
And def expected = (threeD_movies_array_size == 0 ? {"mandatoryItems" : []} : {'mandatoryItems' : [mandatoryItems_present]} )
And print expected
And match each response.hits[*]._source.session_data[*].mandatoryItems == expected
Please let me know whether this approach is correct.

Verify numeric fields in JSON response have values till two decimal points using Karate

JSON Response:
[
{
"actNum": "12345678",
"prodType": "Test",
"period": {
"January": [
{
"name": "Jake",
"rRar": 12.34,
"lRar": 340.45,
"address": "New York"
},
{
"name": "Jorge",
"rRar": 28.78,
"lRar": 250.49,
"address": "Chicago"
}
]
}
}
]
I have to verify that numeric fields in the above response rRar and lRar should have value till two decimal points like 12.78,32.56.
Could anyone please help me if this validation can be done using Karate API?
Here you go:
* def nums = $response..rRar
* def temp = $response..lRar
* karate.appendTo(nums, temp)
* def strs = karate.map(nums, function(x){ return x + '' })
* match each strs == '#regex [0-9].+\\.[0-9]{2}'

How do i validate a dynamic JSON key?

{
"id": "aghysfgagaw365",
"MetricLevelId": "4890718305",
"level": "BUB",
"type": "Mash",
"summary": {
"counts": [
{},
{
"label": {},
"value": 2674,
"labelLoc": {
"192706": {
"ADD": 8977,
"DEL": 3257,
"Count": 59
},
"543419": {
"ADD": 0,
"DEL": 0,
"Count": 1
}
}
}
]
}
}
I read the documentation but i'm still unclear to validate a complex API's like this. a demo to validate this API would help me to solve other API validations...especially this one has a dynamic JSON key.how do i validate ADD,DEL and Cont with "192706" being dynamic.
From the docs, please refer to the documentation on JsonPath. Also recommended is the section on "JSON Transforms". Here is one way:
* def response =
"""
{
"id": "aghysfgagaw365",
"MetricLevelId": "4890718305",
"level": "BUB",
"type": "Mash",
"summary": {
"counts": [
{
},
{
"value": 2674,
"labelLoc": {
"192706": {
"ADD": 8977,
"DEL": 3257,
"Count": 59
},
"543419": {
"ADD": 0,
"DEL": 0,
"Count": 1
}
}
}
]
}
}
"""
* def label = get[0] response..labelLoc
* def vals = get label.*
* match each vals == { ADD: '#number', DEL: '#number', Count: '#number' }
EDIT also this would work:
* json keys = label.keySet()
* match keys == ['192706', '543419']

How to use captured value from URL to select JSON data in Django

Let's assume that I have GET request with URL domain/search/?value=123 and data in JSON:
[
{
"id": 1,
"value": 123,
"value2": 123123
},
{
"id": 2,
"value": 1,
"value2": 214
}
]
I would like to get data where value = 123. In this case:
[
{
"id": 1,
"value": 123,
"value2": 123123
}
]
I have found information how to capture parameters from URL in this post. I wonder what I should do now to find best solution in Django. Thanks in advance.
How can I use it in views.py:
if request.method == 'GET':
myObject = myObjectClass.objects.all()
serializer = myObjectSerializer(myObject, many=True)
return Response(serializer.data)
when data from JSON is not only an integer.
This is how to get it in python:
data = [
{
"id": 1,
"value": 123,
"value2": 123123
},
{
"id": 2,
"value": 1,
"value2": 214
}
]
result = None
for item in data:
if item['value'] == 123:
result = [item]
break
print(result)
Here is a javascript code to do this :-
function test()
{
//alert("Hi");
var text = '[{"id":1,"value":123,"value2":123123},{"id":2,"value":1,"value2":214}]'
json = JSON.parse(text);
var result = [];
for(var i = 0; i < json.length; i++) {
var obj = json[i];
if(obj['value'] == 123){
result.push(obj);
}
}
console.log(result);
}
In views.py , you can get the value of the URL through request object
data = [
{
"id": 1,
"value": 123,
"value2": 123123
},
{
"id": 2,
"value": 1,
"value2": 214
}
]
print [ item for item in data if item['value'] == request.GET.get('value') ]