'Self' Validation Expressions in JSON file (karate framework) - karate

I have two questions concerning 'Self' Validation Expressions:
Question1
In my feature I have
* def isStatus = function(s) { return s ==='SUCCESS' || s ==='ERROR' }
And match response[0] contains { status: '#? isStatus(_)' }
I would like to do this for every item of response like (* instead of 0):
And match response[*] contains { status: '#? isStatus(_)' }
But it doesn't work? Is anything is wrong?
I can't do this without js function like in this example:
* def date = { month: 3 }
* match date == { month: '#? _ > 0 && _ < 13' }
This doesn't work > And match response[*] contains { status: '#? _ == 'SUCCESS' || _ == 'ERROR'' }
Question 2:
I have a json file where I would like to store response types. But when I use 'Self' Validation Expressions in my JSON file it doesn't work?
Thanks for any help.

Search the documentation for match each. try this:
And match each response contains { status: '#? isStatus(_)' }
not able to understand q 2, please ask separately.

Related

How to partially match a JSON key in Karate

I have a response that looks this
{
"metadata": {
"Customer_x0020_Folder": "Test"
}
}
I would like the assert key Customer_x0020_Folder is equal to 'Test'. However I don't care about the x0020 portion of they key and would like to ignore that part. I would like to do something like:
match response contains { metadata: {'Customer_' + '#ignore' + '_Folder': 'Test'} }
How can I perform this assertion in Karate?
Use karate.keysOf():
* def response = { "metadata": { "Customer_x0020_Folder": "Test" } }
* def keys = karate.keysOf(response.metadata)
* match keys[0] == '#regex Customer_.*_Folder'

Karate test - any way to do an "or" match in "match each"?

I have something like the following. Is it possible to get karate to do an "or" match for foo and bar?
Meaning - foo starts with fooStartWithChar OR bar starts with barStartWithChar
And match each response ==
"""
{
foo: '#? { _.charAt(0) == fooStartWithChar}',
bar: '#? { _.charAt(0) == barStartWithChar}',
}
"""
Sometimes plain old JS (+Java) is your friend:
* def response = [{ foo: 'aa', bar: 'bb' }, { foo: 'ax', bar: 'by' }]
* def isValid = function(x){ return x.foo.startsWith('a') || x.bar.startsWith('b') }
* match each response == '#? isValid(_)'
* def nameStartsWith = function(x) { return x.foo.charAt(0) == fooStartWithChar || x.bar.charAt(0) == barStartWithChar}
And match each response == '#? nameStartsWith(_)'

Karate - Exception raises for invalid jsonpath

I have a Json response like below. The difference here is my Json body has a number as the parent node.
def response =
"""
{
"22388043":[
{
"firstName":"Romin",
"lastName":"Irani",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
}
]
}
"""
I want to return the mobileNumber attribute value from the response body. In this scenario I don't have that attribute in my response. So here I want to get a null value.
So when I use * def mobile = $.22388043[0].mobileNumber, I'm getting below error.
No results for path: $['22388043'][0]['mobileNumber']
Please advise on this.
Karate does give you a way to get the values of JSON keys.
Hopefully this example answers all your other questions as well:
* def response =
"""
{
"22388043":[
{
"firstName":"Romin",
"lastName":"Irani",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
}
]
}
"""
* def id = karate.keysOf(response)[0]
* match id == '22388043'
* def person = response[id][0]
* match person contains { firstName: 'Romin', lastName: 'Irani' }
* match person.mobileNumber == '#notpresent'

Array of jsons, for each looping

"someArray": [
{
"somenumber": 23232,
"somestring": "Hello World"
"somemorenumber: 7785454566
},
{
"somenumber": 12345,
"somestring": "Hello World"
"somemorenumber: 542334
},
{
"somenumber": 986767,
"somestring": "Hello World"
"somemorenumber: 242425667
}
]
so i would like to loop each of this Json's and do verification for "somenumber == '#number'", and "somestring == '#string'"
like this
for(int i = 0; i < someArray.length; i++){
match someArray[i].somenumber == '#number'
match someArray[i].somestring == '#string'
}
any ideas how i can achieve it in karate?
i tried
* retry until function(i) someArray[i].somestring == '#string'
but this will stop after first true condition.
Please read the docs for match each: https://github.com/intuit/karate#match-each
* match each response.someArray contains { somenumber: '#number', somestring: '#string' }
Note that you can also use a second feature file, read the docs: https://github.com/intuit/karate#data-driven-features
* call read('second.feature') response.someArray
And in second.feature:
Feature:
Scenario:
match somenumber == '#number'
match somestring == '#string'
But clearly, match each is all you need to do. Please read the docs, it will save you some time :)

Can I use fuzzy matchers with multiple possible types in Karate?

The API I'm testing may return a string or a number for many fields. I've been able to use a self validation expression to check this behavior: { a: '#? typeof _ === "number" || typeof _ === "string"' }.
Is there (or should there be) a way to do this with Karate's fuzzy match markers? Like { a: '#string OR #number'}?
No, I think this is IMO a badly designed API and I don't want to bloat the syntax to solve for these.
Note that you can make this more elegant as follows, so you can write this function once, define it "globally" and re-use to your heart's content:
* def isNumOrStr = function(x){ return typeof x === 'number' || typeof x === 'string' }
* def foo = { a: 1 }
* match foo == { a: '#? isNumOrStr(_)' }
* def bar = { a: 'z' }
* match bar == { a: '#? isNumOrStr(_)' }