Karate - How to validate output with multiple templates? - karate

Is there any way to validate output of a request with one of multiple templates?
for example:
{
"pendingInvitesCount":#number,
"acceptedInvitesCount":#number,
"rejectedInvitesCount":#number
}
or
[]

Not really recommended as testing best practice, but this should give you some ideas:
* def actual = []
* def expected = (actual.size() == 0 ? '#[0]' : { a: '#number', b: '#number' })
* match actual == expected

Related

How to validate a response in karate when you don't know the structure?

I'm trying to write some karate tests that check a response for some expected structure. For example, there is an object that looks like this:
{
'true|true':'disabled',
'true|false':'locked',
'false|false':'enabled',
'false|true':'disabled',
'default':'enabled'
}
However, the keys and values could be any strings. There must be a way to specify this, but I'm at a loss for how to do this in a generic way.
Essentially, what I would like to test is that 1) the object is not empty, 2) each of the keys and values is a string (not an object and not null).
The basic match looks like this:
* def objects = $fields..objects
And match each objects ==
"""
{
key1: '#? isString(_)',
key2: '#? isString(_)'
}
"""
It looks like the names of the keys must be known in advance, so perhaps match expressions are not the appropriate way to test this.
You can extract all keys like this:
* def keys = karate.keysOf(object)
So once you have that, you are in business:
* def foo = { a: 1, b: 2 }
* def keys = karate.keysOf(foo)
* match each keys == '#string'
* assert keys.length > 0
See JSON tranforms for other ideas, e.g. karate.forEach(): https://github.com/intuit/karate#json-transforms

Is there a way to match dynamic object keys?

I'm looking for a simple technique to match objects where the key may not be known in advance (e.g. we may fetch the schema as part of the test). As a contrived example:
Scenario:
* def result = { foo: 'bar' }
* def key = 'foo'
Then match result == { '#(key)': 'bar' }
...which doesn't currently work.
Once you realize there is a JavaScript engine behind the scenes, you will get even more ideas :)
* def result = { foo: 'bar' }
* def key = 'foo'
* def expected = {}
* expected[key] = 'bar'
Then match result == expected
Also do a search for other answers [karate] dynamic you will find many interesting examples such as this one: https://stackoverflow.com/a/57226061/143475

Karate doesn't check cases if expected number is a larger, how do I handle it?

I have given match response as #number
But for a value of 15547786385661 the case just gets skipped.how do I handle it?
You must be making some simple mistake. Try pasting the two lines below into a fresh scenario and see it work:
* def response = { foo: 15547786385661 }
* match response == { foo: '#number' }

Unable to Parse the variable value to the array variable

I was trying to pass the variable 'i' value to a array index 'locations[i]' using below karate code. but throwing an error saying unable to parse. Please suggest be for any changes.
Feature: Verify Branches
Background: For loop implementation
Given url ''
When method GET
Then status 200
* def i = 0
* def z = $.locations[i].zip
* def p = $.locations[i].phone
* def fun =
"""
function(locations){
for (var i = 0; i < locations.length; i++)
{
print(i)
print('Element at Location ' + i +':' + p)
}
}
"""
Scenario: Validate the locations
Given url ''
When method GET
Then status 200
* call fun p
It is hard to make out anything since you have not provided the value of the response. There are many things wrong here. But I'll try.
Take this line:
* def z = $.locations[i].zip
This will not work, Karate does not support variables within JsonPath by default, refer the docs: https://github.com/intuit/karate#jsonpath-filters
And I think you are un-necessarily using JsonPath where normal JavaScript would have been sufficient:
* def z = response.locations[i].zip
Also it seems you are just trying to loop over an array and call a feature. Please refer to the documentation on Data Driven Features.
Take some time and read the docs and examples please, it will be worth your time. One more tip - before I leave you to understand Karate a little better. There is a way to convert a JSON array into another JSON array should you need it:
* def fun = function(x){ return { value: x } }
* def list = [1, 2, 3]
* def res = karate.map(list, fun)
* match res == [{ value: 1 }, { value: 2 }, { value: 3 }]
So there should never be a need for you to manually do a for loop at all.

How to do conditional check in karate response?

Is there any way to check if object is empty then ok if not then check if it matches a fixed structure?
I mean, something like:
* def expectedDelayEntries = response.delayEntries == "{}" ? {} : '#(delayEntries)'
Yes. Refer to the docs: https://github.com/intuit/karate#conditional-logic
Do this in 2 steps.
* def expected = condition ? { foo: '#string' } : { bar: '#number' }
* match response == expected