Karate - Reading data from json file and assing it to a dynamically generated request - karate

I have following data.json file:
{
"ids": {
"id": "a2mx8m6yvksgu3605c7c1a61d"
},
"second": {
"name": "test2"
},
"third": {
"name": "test3"
}
}
I did fetch a variable for the id from the json.
* def id = data.ids.id
I want to use this variable id (defined above) to a request.
Request defined below is dynamically being sent to the xml file i.e xml request is being generated with but the below doesnt work when i try to pass the variable id.
This however works when i hardcode the id value.
* def ARG = {attr: [ { regex: '#(ids)', value: '<id>"#(id)"</id>'} ] }
Please help me how can i pass the data being read from json to the above line of code.

Read the docs: https://github.com/intuit/karate#rules-for-embedded-expressions
* def id = 'foo'
* def val = '<id>' + id + '</id>'
* def arg = { value: '#(val)' }
* match arg == { value: '<id>foo</id>' }

Related

Unable to update dynamic JSON element in called feature [duplicate]

I have a JSON file as given below:
{
"lastname": {
"displayName": "lastname"
},
"#(dynamicKey)": {
"displayName": "#(dynamicKey)"
}
}
When I try to read the file, the key and values are not getting updated but when I use JSON like below, value got replaced by the def values. If I give dynamic key both key and value are not getting updated. :-(
{
"lastname": {
"displayName": "lastname"
},
"someKey": {
"displayName": "#(dynamicKey)"
}
}
Could you please help me on how to replace dynamic key and value?
This is how you can handle dynamic keys. The #(dynamicKey) embedded-expression approach will not work.
* def dynamicKey = 'bar'
* def test = { someKey: 'foo' }
* test[dynamicKey] = 'baz'
* match test == { someKey: 'foo', bar: 'baz' }

Comparing json array item against the response which has random order of the json arrary items

This file (getAllDomain.json) has known/valid response but the order of domain_name /domain_code is random which has to compare against api output..
means .. X3 may come first or last and there is no define order.
I was trying to verify each data array element against the response. But its not working.
IS there any way to just verify arrary and all other element other than "data" can be ignored.
* def expected = read('getAllDomain.json')
* def response =
"""
{
"status":"SUCCESS",
"totalCount":3,
"statusCode":"OK",
"ResultData":{
"data":[
{
"domain_code":"X3",
"domain_name":"BMW"
},
{
"domain_code":"Q5",
"domain_name":"AUDI"
},
{
"domain_code":"MDX",
"domain_name":"ACURA"
}
]
}
}
"""
And match response.ResultData.data[*] contains any expected.ResultData.data[0]
Here you go. And try to read the docs, it will actually help you:
* def expected =
"""
[
{
"domain_code": "MDX",
"domain_name": "ACURA"
},
{
"domain_code": "X3",
"domain_name": "BMW"
},
{
"domain_code": "Q5",
"domain_name": "AUDI"
}
]
"""
* def response =
"""
{
"status":"SUCCESS",
"totalCount":3,
"statusCode":"OK",
"ResultData":{
"data":[
{
"domain_code":"X3",
"domain_name":"BMW"
},
{
"domain_code":"Q5",
"domain_name":"AUDI"
},
{
"domain_code":"MDX",
"domain_name":"ACURA"
}
]
}
}
"""
* match response.ResultData.data contains only expected

Getting JSON key as a text

Trying to get the json key text within karate feature script.
HI, I am new to karate and going through all the documentation of karate..
When I am getting GET response as show below in the code, I am not sure what all keys a response will have. So whenever in the response there is key text is domain_name , then I want to retrieve domain_code
{
"status":"SUCCESS",
"totalCount":1,
"statusCode":"OK",
"ResultData":{
"data":[
{"domain_code":"X3","domain_name":"BMW"},
{"domain_code":"Q5","domain_name":"AUDI"},
{"domain_code":"G450","domain_name":"LEXUS"}
]
}
Here you go. Read the docs if any part is not clear, starting with JsonPath:
* def response =
"""
{
"status": "SUCCESS",
"totalCount": 1,
"statusCode": "OK",
"ResultData": {
"data": [
{"domain_code": "X3", "domain_name": "BMW" },
{"domain_code": "Q5", "domain_name": "AUDI" },
{"domain_code": "G450", "domain_name": "LEXUS" }
]
}
}
"""
* def data = get[0] response..data[?(#.domain_name)]
* def keys = karate.keysOf(data)
* keys.remove('domain_name')
* print keys[0]

Un-named JSON array field validation in Karate

I have a un-named JSON array like this from the response and would like to check whether it contains "confirmationNumber": "pqrs" or not. May I know how can I check that in Karate?
[
{
"id": 145,
"confirmationNumber": "abcd"
},{
"id": 723
"confirmationNumber": "pqrs"
}
,{
"id": 7342
"confirmationNumber": "sfeq"
}
]
karate.filter() is good for these situations:
* def response =
"""
[
{
"id":145,
"confirmationNumber":"abcd"
},
{
"id":723,
"confirmationNumber":"pqrs"
},
{
"id":7342,
"confirmationNumber":"sfeq"
}
]
"""
* def fun = function(x){ return x.confirmationNumber == 'pqrs' }
* def found = karate.filter(response, fun)
* match found == '#[1]'
Also see examples of JsonPath: https://github.com/intuit/karate#jsonpath-filters
EDIT: apologies, there is a much simpler way, please read the docs !
* match response contains { id: '#number', confirmationNumber: 'pqrs' }
* def item = { confirmationNumber: 'pqrs' }
* match response contains '#(^item)'

Karate: when I want to set value to $..somewhereInJsonPath I get Path must not end with a '

I want to update a value of somewhereInJsonPath field in my JSON file.
I am using for this: * set myBody $..someWhereInJsonPath = 'AAA'. And when I run test I get: Path must not end with a '.'
But when I am using * set myBody $..firstHere.someWhereInJsonPath = 'AAA' it is working.
I think in first case, where we want to update first value in $.., it must working too.
To clarify:
For example we have JSON:
{
"store": {
"book": [
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"something": 12.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
And when I do: $.store.book[0].something = 13 it is working.
BUT when I do: $..something = 13 it is not working.
Why? And how can I update this?
At http://jsonpath.com/ when I want to find $..something it is find this value. But when I use $..something in karate it is not working.
Realted with https://stackoverflow.com/questions/54928387/karate-jsonpath-wildcards-didnt-work-or-partly-didnt-work
Actually the set command is not really designed for JsonPath wildcards. For example $[*].foo or $..foo are examples of wildcards. And $[0].foo, $.foo or response.foo are pure JS expressions.
So please stick to pure JS expressions like this. Here below, set is interchangeable with eval which is more useful in case you want to use dynamic / variables for e.g. * eval response[foo] where foo is a string.
* def response = { foo: { somePath: 'abc' } }
* eval response.foo.somePath = 'xyz'
* match response == { foo: { somePath: 'xyz' } }
If you really do need to do "bulk" updates, use a transform function:
* def response = [{}, {}]
* def fun = function(x, i){ return { foo: 'bar', index: ~~(i + 1) } }
* def res = karate.map(response, fun)
* match res == [{ foo: 'bar', index: 1 }, { foo: 'bar', index: 2 }]