How do use fuzzy matching validation for either a non-present key or an empty array? - karate

In karate version 0.9.6 I used the following match statement in a .feature file and it worked for validating the value to be an empty array or a key that was not present.
def example = {}
match example.errors == '##[0]'
In 1.0 the documentation example suggests that this should check for the key being present and null or an empty array and testing this fails with a validation error that the value is not present.
From https://karatelabs.github.io/karate/#schema-validation
# should be null or an array of strings
* match foo == '##[] #string'
This appears to be an undocumented breaking change from pre-1.0 to 1.0.
My question is: how do I construct a validator to cover this case correctly when the key is allowed to be absent but if it is present it must be an empty array?

I've found an undesirable solution for now but am leaving this open in case someone has a better answer.
I'm validating the entire parent object with a minimal schema:
Replace
match $.errors == '##[0]'
With
* match $ == { data: '#object', extensions: '##object', errors: '##[0]' }
While more brittle and verbose it is technically working.

This indeed looks like an in-intended breaking change. Here is another workaround:
* def example = {}
* def expected = example.errors ? '#[0]' : '#notpresent'
* match example.errors == expected
I see you have opened an issue here: https://github.com/karatelabs/karate/issues/1825
EDIT: this might be an improvement over the workaround you came up with in your answer:
* match example contains { errors: '##[0]' }

Related

Karate netty/mock schema match not working [duplicate]

I have a request that is hitting my mock server... the request is in json, but one of the values is a string of about 2,000+ characters.. I am wanting to match the request if the string value (of 2,000+ characters) contains a specific substring value...
for example:
Scenario:
pathMatches('/callService') &&
methodIs('post') && request.clientDescription contains 'blue eyes'
(request.clientDescription = string of 2,000+ characters)
It seems that it does not like the key word contains and I can't seem to find any information on the syntax I would use to search through a given string in a request and see if it contains a specific value.
I understand that I could try to match the entire string value using '==', but I am looking for a way to only match if it contains a substring.
Here's a tip, whatever you see on the right of Scenario: is pure JavaScript, and methodIs() etc. happen to be pre-defined for your convenience.
So this should work, using String.includes()
Scenario: request.clientDescription.includes('blue eyes')
Also please refer this answer for other ideas: https://stackoverflow.com/a/57463815/143475
And one more: https://stackoverflow.com/a/63708918/143475
It did not seem to like when I added "&& request.clientDescription.includes('blue eyes')" in the Scenario, but it did lead me in the right direction, and I did find a solution. thanks!
Error : after adding String.includes to Scenario:
com.intuit.karate - scenario match evaluation failed: evaluation (js) failed: pathMatches('/callService') &&
methodIs('post') && request.clientDescription.includes('blue eyes'), javax.script.ScriptException: TypeError: request.clientDescription.includes is not a function in at line number 2
stack trace: jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:470)
A Solution:
defined a function in the background using karate.match
Code Example of Solution:
Background:
* def isBlueEyed = function(){return karate.match("request.clientDescription contains 'Blue Eyes'").pass}
Scenario:
pathMatches('/callService') &&
methodIs('post') && isBlueEyed()
* def response = read('./***/***/**')

Want to assert that the values are not duplicated in the list

I'm asserting a response like this using karate.
"Ids": ["123456","123456","123457"]
Now I want to assert that my list doesn't contain the duplicate values (If there is a duplicate value, it should fail the test-case), is there any in built function which is supported by Karate or is there any JS who does the trick?
Here you go: https://github.com/karatelabs/karate#karate-distinct
* def response = ["123456","123456","123457"]
* match response == karate.distinct(response)

How to check a length of array in Karate framework?

I have 2 different response from the REST Api as below
1. {"type":null,"title":"Request is invalid","status":"BAD_REQUEST","detail":"Please correct request and try again.","invalidParams":[{"name":"create.arg0.name","reason":"Name is required"}]}
2. {"type":null,"title":"Unicode char u0000 is not allowed","status":"BAD_REQUEST","detail":"Unicode char u0000 is not allowed"}
I wanna write a condtion where if invalidParams present in respose, then compare the contents of array. If not, invalidParams should be null/undefined.
Scenario Outline: Create Asset Model with missing name and status
Given url modelsUrl
And request somedata
When method POST
Then status 400
Then assert response.type == null
Then match response.status == 'BAD_REQUEST'
Then match (response.invalidParams != undefined && response.invalidParams[0].reason contains <reason>) OR (response.invalidParams == undefined)
But comparing against null/undefied & length also not working. How to handle this scenario in Karate? Normal Javascript is not working.
To check if a member exists or to check an array's length you should use assert, not match. I would also recomend breaking your last statement into multiple assertions for transparency.
here are some examples given a response with an array named 'arr':
check array length
...
And assert response.arr.length == 1
...
check array is present
...
And assert response.arr != null
...
check array is absent
...
And assert response.arr == null
...
reference: https://intuit.github.io/karate/#payload-assertions
based on the link shared by riiich, the recommended approach is to do the following for an array length = 2
match response == '#[2]'

Can we use '#ContinueNextStepsOnException' to run all the steps in the Karate script instead of karate.match(actual, expected)

I have a response with hundreds of attributes while matching the attributes the scripts getting failed and further steps are not getting executed. because of this we have to validate the same case multiple times to validate the attribute values. is they a option like #ContinueNextStepsOnException to execute all the steps and it is hard to script using karate.match(actual, expected) for more than 100 attributes I have give actual and expected values if in case of any failure to continue.
No, there is no such option. If your scripts are getting failed - it is because Karate is doing its job correctly !
If you feel you want to skip certain fields, you can easily do so by using match ... contains syntax.
I think you are using multiple lines instead of matching the entire JSON in one-line which you can easily do in Karate. For example:
* def response = { a: 1, b: 2 }
# not recommended
* match response.a == 1
* match response.b == 2
# recommended
* match response == { a: 1, b: 2 }
Is it so hard to create the above match, even in development mode ? Just cut and paste valid JSON, and you are done ! I have hardly ever heard users complain about this.

Fetching few elements using "$.[:2]" operator throws error in karate. might be a bug

Example:
Scenario: test
* def response =
"""
[
"YEN01",
"DP258",
"SA661",
"BT202",
"UR809"
]
"""
* def subset = response.[:2]
* print subset
I tried response..[:2] . and also tried with enclosing in ().
Let me know if any one got this working.
Just adding one character will fix your problem !
* def subset = $response.[:2]
Karate defaults to JavaScript and when you want JsonPath evaluation you need to give a little hint to Karate. This is explained in the docs: https://github.com/intuit/karate#get-short-cut