How to partially match a JSON key in Karate - karate

I have a response that looks this
{
"metadata": {
"Customer_x0020_Folder": "Test"
}
}
I would like the assert key Customer_x0020_Folder is equal to 'Test'. However I don't care about the x0020 portion of they key and would like to ignore that part. I would like to do something like:
match response contains { metadata: {'Customer_' + '#ignore' + '_Folder': 'Test'} }
How can I perform this assertion in Karate?

Use karate.keysOf():
* def response = { "metadata": { "Customer_x0020_Folder": "Test" } }
* def keys = karate.keysOf(response.metadata)
* match keys[0] == '#regex Customer_.*_Folder'

Related

Karate Nested Schema contains "Not Required" not working?

i'm trying to understand karat schema fuzsy validation with contains but is not working
if I use ##string for not required it validates required when is null
this is my example
Scenario: Test
* def payload =
"""
{
nested: {
field: 'not required'
}
}
"""
* def payload2 =
"""
{
nested: null
}
"""
* def schema =
"""
{
nested: {
field: '##string'
}
}
"""
* match payload contains schema
* match payload2 contains schema
I get this error in console
path: $.nested, actual: null, expected: {field=##string}, reason: actual value is null
Thanks for help
Pay attention to the structure. I think this is what you are trying:
* def part = { field: '#string' }
* def schema = { nested: '##(part)' }
* def payload = { nested: { field: 'not required' } }
* match payload == schema
* def payload2 = { nested: null }
* match payload2 == schema
And please refer the docs: https://github.com/intuit/karate#schema-validation
yes thanks, also this works
* def schema =
"""
{
'nested.field': '##string'
}
"""

Karate - Exception raises for invalid jsonpath

I have a Json response like below. The difference here is my Json body has a number as the parent node.
def response =
"""
{
"22388043":[
{
"firstName":"Romin",
"lastName":"Irani",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
}
]
}
"""
I want to return the mobileNumber attribute value from the response body. In this scenario I don't have that attribute in my response. So here I want to get a null value.
So when I use * def mobile = $.22388043[0].mobileNumber, I'm getting below error.
No results for path: $['22388043'][0]['mobileNumber']
Please advise on this.
Karate does give you a way to get the values of JSON keys.
Hopefully this example answers all your other questions as well:
* def response =
"""
{
"22388043":[
{
"firstName":"Romin",
"lastName":"Irani",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
}
]
}
"""
* def id = karate.keysOf(response)[0]
* match id == '22388043'
* def person = response[id][0]
* match person contains { firstName: 'Romin', lastName: 'Irani' }
* match person.mobileNumber == '#notpresent'

How to assert a json property which can be either null(Porp:null) or has a sub schema(Porp:{ denyAny: '#boolean', assertions: '#[]' }) In KARATE DSL?

I have a Json payload to validate. And It has a property which can be either null or a sub json object. But this property exists in the json.
I tried following methods:
01
And def dnyAssertionSchema = { denyAny: '#boolean', assertions: '##[]' }
And match each policyGResponse ==
"""
{
denyAssertions: '##(dnyAssertionSchema)'
}
"""
AND
And match each policyGResponse ==
"""
{
denyAssertions: '##null dnyAssertionSchema'
}
"""
AND
This does not work as the property is not an array so I tried above second method even I couldn't find an example as such.
And match each policyGResponse ==
"""
{
denyAssertions: '##[] dnyAssertionSchema'
}
"""
The Actual response can be either
{
denyAssertions=null
}
OR
{
denyAssertions={ denyAny: true, assertions: ["a","b"] }
}
I use Karate 0.9.1
Error message I get is 'reason: actual value has 1 more key(s) than expected: {denyAssertions=null}' in first try
In second try I get 'assertion failed: path: $[3].denyAssertions, actual: {denyAny=false, assertions=[]}, expected: '##null dnyAssertionSchema', reason: not equal'
Your JSON is still not valid but anyway. Here you go:
* def schema = { denyAny: '#boolean', assertions: '#[]' }
* def response1 = { denyAssertions: { denyAny: true, assertions: ["a","b"] } }
* match response1 == { denyAssertions: '##(schema)' }
* def response2 = { denyAssertions: null }
* match response1 == { denyAssertions: '##(schema)' }

karate: finding index of the particular element value from API response

my code for finding index as below
* def list = nestActual #this is API response value which is given at the end
* def searchFor = { category_name: 'books3'}
* def foundAt = []
* def fun = function(x, i){ if (karate.match(x, searchFor).pass) foundAt.add(i) }
* eval karate.forEach(list, fun)
* print "==========foundAt=======" +foundAt
i have tried the above code for finding index where im getting foundAt index as null.
Below is my response where i want to find index of "category_name":"books3"
[
{
"category_id":1, "parent_cat_id":0, "category_name":"books", "slug_name":"books_1", "popular":true,
}, {
"category_id":2, "parent_cat_id":1, "category_name":"books2", "slug_name":"books_2", "popular":false,
}, {
"category_id":3, "parent_cat_id":1, "category_name":"books3", "slug_name":"books3_2", "popular":false,
}, {
"category_id":4, "parent_cat_id":3, "category_name":"mp3", "slug_name":"mp_3", "popular":false, }, {
"category_id":5, "parent_cat_id":3, "category_name":"mp4", "slug_name":"humoristiska_deckare_mysi_deck_3", "popular":false, }, {
"category_id":6, "parent_cat_id":3, "category_name":"video", "slug_name":"video3", "popular":false,
} ]
Please let me know how to find index of "category_name":"books3" using karate
Guess what, there is a far simpler way, the trick is to convert your search target into an array of primitives. Then you can use the List.indexOf() Java method:
Scenario: using the java indexOf api (will change with graal)
* def response = [{ name: 'a' }, { name: 'b' }, { name: 'c' }]
* def names = $[*].name
* def index = names.indexOf('b')
* match index == 1

How to retrieve all values for a particular key in karate

How to retrieve partNumbers from below response. In below response
"10000061","10000062","10000063"
are dynamic in nature. I have to match these partNumbers with data table partnumbers.( In a response there could be more than 10 part numbers(based on input) and i have to validate them.)
{ "added": true, "lineItems": { "1111111": { "itemCore": { "partNumber":
"10000061" } }, "222222": { "itemCore": { "partNumber": "10000061" } },
"3333333": { "itemCore": { "partNumber": "10000063" } } } }
Tried below
def partNum= get[0] response..itemCore.partNumber[*] but getting empty array.
def partNum= get[0] response..itemCore.partNumber but getting empty value.
My below second approach also giving me empty value.
* def keys = function(obj){ return response.lineItems.keySet() }
* json dynamicValue= keys(response)
* print 'dynamic value '+dynamicValue
* def first = dynamicValue[0]
* print response.lineItems.dynamicValue[0].itemCore.partNumber
* print response.lineItems.first.itemCore.partNumber
For retrieving data for a particular key, you can use deep scan operator in jsonPath,
* def partNumbers = karate.jsonPath(response,"$..partNumber")
Here's another solution, using karate.forEach() which can also operate on a map, not just a list:
* def keys = []
* eval karate.forEach(response.lineItems, function(k){ keys.add(k) })
* print keys