My payload looks like this :
{
"override_source": "DS",
"property_code": "0078099",
"stay_date": "2018-11-26T00:00:00.000000",
"sku_prices": [
],
"persistent_override": false
}
There is an array dblist ["2","3"] , it would consists of numbers from 1 to 4. Based on the elements present in the list, I want to add key-values {"sku_price":"1500","sku_code":"2"} to my payload. I am using the following code :
* eval if(contains("3",dblist)) karate.set('pushRatesFromDS.sku_prices[]','{ "sku_price": "1500","sku_code":"3" }')
When I execute my feature file, I do not get any errors but, key-values are not added to my payload. However if I move this code to a new feature file and call it, key-value pairs get added to my payload. The code in my new feature file looks like : * set pushRatesFromDS.sku_prices[] = { "sku_price": "1500","sku_code":"2" }
Try this:
* def foo =
"""
{
"override_source": "DS",
"property_code": "0078099",
"stay_date": "2018-11-26T00:00:00.000000",
"sku_prices": [
],
"persistent_override": false
}
"""
* eval karate.set('foo', '$.sku_prices[]', { foo: 'bar' })
Related
I am trying to match a JSON array with a predefined expected json. The problem is that one of the key values in actual JSON is a set of strings delimited by "|". Here is how it looks :
actualJSON = [
{
"a": "varA",
"mix: "X|Y|Z",
},
{
"b": "B",
"c": "C"
} ]
expectedJSON = [
{
"a": "varA",
"mix: "Y|Z|X",
},
{
"b": "B",
"c": "C"
} ]
Issue here is the mix key that represents a set of strings and the value can be any combination of "X|Y|Z" without any specific order like "Z|Y|X" etc. When the value of mix is Y|Z|X then
* match actualJSON contains expectedJSON
works fine but in other cases it fails as expected. Is there a way to do the matching when key value is dynamic?
My first suggestion is as far as possible to write tests where the response is 100% predictable and don't waste time on these weird cases. Also refer: https://stackoverflow.com/a/50350442/143475
That said this is easy to do if you write a JS function:
* def response = { foo: 'X|Y|Z' }
* def hasXyz = function(x){ return x.includes('X') && x.includes('Y') && x.includes('Z') }
* match response == { foo: '#? hasXyz(_)' }
I leave it to you to figure out better logic if you want. Refer: https://github.com/karatelabs/karate#self-validation-expressions
New to Karate, and JSON, for that matter, but I've got a variable like:
response {
entries {
products [
{
names [
"Peter Parker",
"Tony Stark",
"Captain America"
]
},
{
names [
"Thomas Tinker",
"Jimmy Johnson",
"Mama Martha"
]
}
]
}
}
match each response.entries.products[*].names returns a list like:
["Peter Parker","Tony Stark","Captain America","Thomas Tinker","Jimmy Johnson","Mama Martha"]
But I'd like to assign that output to a variable, such as:
* def variable = response.entries.products[*].names
that would hold a similar value. When I use the above line, I get the following error:
Expected an operand but found *
Is it possible to achieve that, or something similar? If so, how?
Thanks!
Yes, there is syntax for that:
* def variable = $response.entries.products[*].names
Read the docs: https://github.com/intuit/karate#get
I am using Karate API framework for the API automation and came across with one scenario, the scenario is when I am hitting a post call it gives me some json response and few of the items are having tags whereas few of them are showing tags as blank to get all the tags below is the feature file scenario line
* def getTags = get response.items[*].resource.tags
It is giving me response as
[
[
],
[
],
[
{
"tags" : "Entertainment"
}
],
[
],
[
{
"tags" : "Family"
}
],
As you can see out of 5 or 6 tags only 2 tags are having the value, so I want to capture if any tags value is showing or not. What would be the logic for the assertion considering these tags can all come as empty and sometimes with come with a string value. In above case "Family" & "Entertainment"
Thanks in advance !
* match each response.items[*].resource.tags == "##string"
This will validate that tags either doesn't exist or is a string.
I think you can use a second variable to strip out the empties, or maybe your original JsonPath should use .., you can experiment:
* def allowed = ['Music', 'Entertainment', 'Documentaries', 'Family']
* def response =
"""
[
[
],
[
],
[
{
"tags":"Entertainment"
}
],
[
],
[
{
"tags":"Family"
}
]
]
"""
* def temp = get response..tags
* print temp
* match each temp == "#? allowed.contains(_)"
My response looks as follows :
{
"data":[
{
"foo":bar1
"user_email":"user#user.com",
"user_id":1
},
{
"foo":bar2
"user_email":"user#user.com",
"user_id":1
}
]
}
* def DBOutput = #fetching values from DB
* match response.data[*].foo contains [DBOutput1[0][0],DBOutput1[1][0]]
DBOutput1 has data as follows : [["bar1"],["bar2"]]
This match fails, for some reasons value passed into the expected list in match statement is DBOutput1[0][0]
This is the error I am getting actual: ["bar1","bar2"], expected: 'DBOutput1[0][0]',
You have some seriously malformed JSON in your example above. The below snippet works, just paste it into a new Scenario:
* def response =
"""
{
"data":[
{
"foo": "bar1",
"user_email":"user#user.com",
"user_id":1
},
{
"foo": "bar2",
"user_email":"user#user.com",
"user_id":1
}
]
}
"""
* match response.data[*].foo contains ['bar1', 'bar2']
Now it is up to you to fix your test, without knowing what your DBOutput is no one can help further.
I iterated over the DBoutput and stored them in a new array list. I then matched the response to the list and it worked.
match response.data[*].foo contains ListFromDB
I have a smallish (~50,00) array of json dictionaries that I want to store/index in ES. My preference is to use python, since the data I want to index is coming from a csv file, loaded and converted to json via python. Alternatively, I would like to skip the step of converting to json, and simply use the array of python dictionaries I have. Anyway, a quick search revealed the bulk indexing functionality of ES. I want to do something like this:
post_url = 'http://localhost:9202/_bulk'
request.post(post_url, data = acc ) # acc a python array of dictionaries
or
post_url = 'http://localhost:9202/_bulk'
request.post(post_url, params = acc ) # acc a python array of dictionaries
both request give a [HTTP 500 error]
My understanding is that you have to have one "command" per line (index, create, delete...) and then some of them (like index) takes a row of data on the next line like so
{'index': ''}\n
{'your': 'data'}\n
{'index': ''}\n
{'other': 'data'}\n
NB the new-lines, even on the last row.
Empty index objects like above works if you POST to ../index/type/_bulk or else you need to specify index and type I think, have not tried that.
You the following function will do it:
def post_request(self, endpoint, data):
endpoint = 'localhost:9200/_bulk'
response = requests.post(endpoint, data=data, headers={'content-type':'application/json', 'charset':'UTF-8'})
return response
As data you need to pass a String such:
{ "index" : { "_index" : "test-index", "_type" : "_doc", "_id" : "1681", "routing" : 0 }}
{ "field1" : ... , ..., "fieldN" : ... }
{ "index" : { "_index" : "test-index", "_type" : "_doc", "_id" : "1684", "routing" : 1 }}
{ "field1" : ... , ..., "fieldN" : ... }
Make sure you add a "\n" at the end of each line.
I don't know much about Python, but did you look at Pyes?
Bulk is supported in Pyes.