According to Karate documentation for contains short-cuts The following match arguments should work and do the same:
#test_contains_only
Scenario: Test contains only shortcut
* def expected = [ "a", "b", "c", "d" ]
* def to_match = { "properties": { "additional_information": "Some put-updated info", "types": [ "a", "b", "c", "d" ] } }
* print to_match.properties.relation_types
# This will pass
* match to_match.properties contains deep
"""
{
"additional_information": "Some put-updated info",
"types": [ "a", "b", "c", "d" ]
}
"""
# This will pass
* match to_match.properties.types == '#(^^expected)'
# This will fail
* match to_match.properties contains deep
"""
{
"additional_information": "Some put-updated info",
"types": '#(^^expected)'
}
"""
When executing the above, I get this error:
* match to_match.properties contains deep
"""
{
"additional_information": "Some put-updated info",
"types": '#(^^expected)'
}
"""
match failed: CONTAINS_DEEP
$ | actual does not contain expected | all key-values did not match, expected has un-matched keys - [types] (MAP:MAP)
{"additional_information":"Some put-updated info","types":["a","b","c","d"]}
{"additional_information":"Some put-updated info","types":"#(^^expected)"}
$.types | actual does not contain expected | actual array does not contain expected item - #(^^expected) (LIST:STRING)
["a","b","c","d"]
'#(^^expected)'
$.types[3] | data types don't match (STRING:LIST)
'd'
["a","b","c","d"]
$.types[2] | data types don't match (STRING:LIST)
'c'
["a","b","c","d"]
$.types[1] | data types don't match (STRING:LIST)
'b'
["a","b","c","d"]
$.types[0] | data types don't match (STRING:LIST)
'a'
["a","b","c","d"]
In my opinion, using '#(^^expected)' doesn't work as expected. Or is it happening because I'm using match to_match.properties contains deep together with the ^^ (contains only shortcut)?
I'm using Karate v1.2.0. The same scenario doesn't fail in v1.0.1.
See if this is fixed in 1.2.1.RC2: https://github.com/karatelabs/karate/issues/2007
Else please file an issue. Ideally a PR ;)
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
I have a list:
[{
"a": 1
"b": 2
}]
And I would like to match it this way:
And match response contains
"""
[{
"a": 1
}]
"""
However this does not work since the map inside of the list from the response has more keys. I just want to ignore them. Is there easy way to do it?
There are two ways to do this:
* def response = [{ a: 1, b: 2 }]
* def expected = { a: 1 }
* match response contains '#(^expected)'
Or you could use contains deep:
* match response contains deep { a: 1 }
i have a json response as below where i just want to match the string "harry"
in autoComplete, id in autoCompleteAuthors
Response {"data": {
"autoComplete": [
"Harry Hole"
],
"autoCompleteAuthors": [
{
"id": "search_authors_harry martinson",
"title": "Harry Martinson",
"type": "Authors"
}
]
}
}
Please suggest how to perform this validations using contains?
i tried like below which is not working
* def autoComlete = get response.data.autoComplete[*]
* match autoComlete contains any 'harry'
you can use match each and #regex marker in karate,
Case sensitive matching
* match each $response.data.autoComplete == "#regex .*Harry.*"
Case in sensitive matching
* match each $response.data.autoComplete == "#regex (?i).*harry.*"
Hope this works for your need.
Edit:
As requested on comments to pass name
* def query = 'harry'
* match each $response.data.autoComplete == "#regex (?i).*" + query + ".*"
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(_)"
I applied the GREL expression "value.split(/a/)" to some cells:
abcdef -> [ "", "bcdef" ]
bcdefa -> [ "bcdef" ]
badef -> [ "b", "def" ]
I can't understand why the first cell gives me a "" element in the resulting table. Is it a bug?
Thanks!
I don't know Java enough to comment on the source code for this function, but according to one of the developers of Open Refine this behavior is normal (edit : More details in Owen's comment, below). This is why there are other functions to split a string.
value.smartSplit(/a/), for example, gives a more consistent result when sep is at the begining or at the end of the string:
row value value.smartSplit(/a/)
1. abcdef [ "", "bcdef" ]
2. bcdefa [ "bcdef", "" ]
3. badef [ "b", "def" ]
This is the same result as using partition() with the omitfragment = true option enabled:
row value value.partition(/a/, true)
1. abcdef [ "", "bcdef" ]
2. bcdefa [ "bcdef", "" ]
3. badef [ "b", "def" ]