How to check a length of array in Karate framework? - karate

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]'

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 do use fuzzy matching validation for either a non-present key or an empty array?

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]' }

Same asserts for every scenario can be put in a separate file to avoid duplication in karate?

Here are two scenarios , One after the other
Scenario: Positive - Create a discount with ABSOLUTE discount and ROOM_NIGHT_PRICE and search
Given url baseUrl + SEARCH
And request changes
When method post
Then status 200
And match $.data.hotels[0].transaction_discount.discounts[0].discount_id == discountId
And match $.data.hotels[0].transaction_discount.discounts[0].code == couponCode
And match $.data.hotels[0].transaction_discount.discounts[0].discount_value == incentive_value
And match $.data.hotels[0].transaction_discount.discounted_sell_price == (sellPrice-incentive_value)
Scenario: Positive - Create a discount with ABSOLUTE discount and TRANSACTION_PRICE and search
Given url baseUrl + SEARCH
And request changes
When method post
Then status 200
And match $.data.hotels[0].transaction_discount.discounts[0].discount_id == discountId
And match $.data.hotels[0].transaction_discount.discounts[0].code == couponCode
And match $.data.hotels[0].transaction_discount.discounts[0].discount_value == incentive_value
And match $.data.hotels[0].transaction_discount.discounted_sell_price == (sellPrice-incentive_value)
If you notice that assertions are same for these scenarios , I have similar 20 scenarios with exactly same assertions , Can I put it in a separate file to avoid duplication and easy to maintain ?
If Yes then how ?
If No then is there any other way to avoid duplication in karate
I don't see any change on your request either.
If only change in your scenarios are payload
You can try using Scenario Outline:
and pass different payloads from Examples: table
Scenario Outline: Positive - Create a discount and search
Given url baseUrl + SEARCH
And request <changes>
When method post
Then status 200
And match $.data.hotels[0].transaction_discount.discounts[0].discount_id == discountId
And match $.data.hotels[0].transaction_discount.discounts[0].code == couponCode
And match $.data.hotels[0].transaction_discount.discounts[0].discount_value == incentive_value
And match $.data.hotels[0].transaction_discount.discounted_sell_price == (sellPrice-incentive_value)
Examples:
| changes |
|RNP_PAYLOAD|
|TXP_PAYLOAD|
you can create these payloads instances in Background:, this could help you avoid scenario duplication.
OR
If your intention is still to have this on a separate file
You can create a feature file which takes both expected and actual JSON as an input and perform match operation in it.
Then you can call that feature file in all of your scenarios passing the values to the calling feature.

How can I do Null and empty check of arraylist using dw() function in mule?

I tried the following way,
[dw('sizeOf payload.data.accts')>0] but hthis would just check if arraylist is empty or not .So i need a help to how do I null check on "accts" arraylist using dw() function.
I want both null and empty check in dw() function of mule so that I can use it in my choice router to proceed my flow.
I would do something like this in the choice router:
In the 'When' column:
#[payload.data.accts != empty]
In the Route Message to column:
yourFlow
Please refer How to Check null condition in Data weaver : Mule.
Should be applicable to Json as well - try out
Example:(payload.Records.*RecordsEntries.*RecordEntry default [])
You can combine default with sizeOf to achieve this:
#[dw('(sizeOf (payload.data.accts default [])) == 0']
We can break this down into two expressions. The first, payload.data.accts default [] will return an empty list if payload, payload.data or payload.data.accts is null. Otherwise it will just return whatever the value of payload.data.accts is.
The second, (sizeOf <expression>) == 0 will check if the list returned from the above expression is empty or not.