In Karate, how can I assert that an array does not contain a matching string? - karate

Let's say I'm writing a Karate test for a service whose response might look like tha following...
{
"messages": [
"The blurfl is wop",
"The zog is ipfy",
"The wuxhat is neet"
]
}
Is there some syntax for match to assert that none of those messages starts with "The baz "? Or is there a more gereral way to test that in Karate?

This worked for me:
* def response =
"""
{
"messages": [
"The blurfl is wop",
"The zog is ipfy",
"The wuxhat is neet"
]
}
"""
* match each response.messages != '#regex ^The baz .+'
You could also do this:
* match each response.messages == "#? !_.startsWith('The baz ')"
And for completeness:
* def filtered = response.messages.filter(x => x.startsWith('The baz '))
* assert filtered.length == 0

Related

How to use OR operator with contains to assert/ match in Karate [duplicate]

I am trying to use a match contains to verify my schema response and data types and sometimes it returns a null and sometimes it will return a string, as an example. I am trying the following but I am getting the assertion failed because it did not evaluate to true.
I am trying the following:
* match each $response.data.Results contains
"""
{
"providerID": '#number',
"firstName": "#? _ == '#string' || _ == '#null'",
"lastName": '#string',
"mI": "#? _ == '#string' || _ == '#null'",
"title": '#string',
"name": '#string',
"nameLFMT": '#string',
"status": '#string',
"specialties": '#array',
"locations": '#array',
"institutions": '#array',
"acceptNewPatient": '#string',
"imageUri": '#string',
"nearestLatitude": '#number',
"nearestLongitude": '#number'
}
"""
The data returned for "firstName" for example is "firstName":null,
Prior to the match each I am sending this:
Scenario: SearchResults
#Verify 200 response status returned
Given text query =
"""
{
Results: getSearchResults(searchLatitude:"48.942833",
searchLongitude: "-119.984549",
providerType: "Primary Care Physicians",
sortBy: "distance",
maxDistance:"600",
skip: 0,
take: 10) {
providerID
firstName
lastName
mI
title
name
nameLFMT
status
specialties
locations
institutions
acceptNewPatient
imageUri
nearestLatitude
nearestLongitude
}
}
"""
And request { query: '#(query)' }
When method post
Then status 200
I am not defining the schema, I have yet to figure out how to do this so I am not sure if that is my issue. I know this is probably how I should do this but I'm still learning.
Thanks for any help.
Ok I see one problem here:
"firstName": "#? _ == '#string' || _ == '#null'"
That's not going to work. The part that follows the #? has to be a valid JavaScript expression. This may be hard to understand if you are not familiar with JS but #string and friends are specific to the Karate match keyword and not something that works in JavaScript.
So what the above line is doing is checking if the value of firstName is equal to the literal string #string.
Fortunately Karate has a solution: (refer doc for 'fuzzy matching'):
"firstName": "##string"
Which is a convenience, the double ## means 'optional' that will match for both a string or null.
EDIT: for advanced cases, please read this: https://stackoverflow.com/a/50350442/143475

is it possible to extract the value of one of the key value pairs in request to be asserted

peter had provided me a solution to use karate 0.9.3 to apply assertion from examples
Trying to do some assertion from request, which will be present in response
i was wondering if it is possible to assert a value from request instead of full request.
**Background:**
* configure headers = read('classpath:merchantServiceheaders.js')
Given url MservUrl
And path 'XXXXXX'
And request Data
When method POST
Then status 200
And match response != null
And match $ contains {serviceName: 'XXXXX'Service', responseMessage:
'Success' }
And match each $.clauses..responseMessage == 'Success'
And match each $..predicate != null
And match each $..predicate == '#present'
And match each $..predicate == '#regex [^0-9]+[0-9]*$'
And match $..predicate contains Data.clauses.subject
Examples:
|Data! |
|'{"clauses":[{"subject":"XXXX","predicate":"999999"},
{"subject":"XXXXX","predicate":"99999"}]}'|
what i am trying to do is on the And match $..predicate contains Data.clauses.subject
is that possible?
Yes, it is very much possible if Data is defined as a variable. But note that $..predicate will always be a JSON array: https://github.com/intuit/karate#get-plus-index
If you want help, please create a proper simple working example.
Sample Code:
Feature: Validation
Scenario:
* def resp = {predicate : "4325325456545646"}
* def data =
"""
{
"clauses": [
{
"subject": "5432154321543210",
"predicate": "4432154321543210"
},
{
"subject": "4325325456545646",
"predicate": "4325325456545646"
}
]
}
"""
* def sublist = get data.clauses[*].subject
* print sublist
* match sublist contains resp.predicate

karate - how to match partial string of the field in response?

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 + ".*"

Karate API, How do I match 2 different responses

I get 2 different responses from an endpoint depending on it's state and either one of them is fine.
first response:
{"available":'#boolean',"collection":'#boolean'}
second response:
{"code": "#string","message": "#string"}
I'm trying the following but it's not working:
def firstSchema = {"available":'#boolean',"collection":'#boolean'}
def secondSchema = {"code": "#string","message": "#string"}
match response contains any (firstSchema, secondSchema)
Any ideas how to best get this working so either response is fine?
Thanks
Try this:
* def first = { available: true, collection: true }
* def second = { code: 'foo', message: 'bar' }
* def response = second
* def expected = response.code ? { code: '#string', 'message': '#string' } : { available: '#boolean', collection: '#boolean' }
* match response == expected
Also refer to the documentation on "Conditional Logic". You can use JsonPath to "check" what shape the response is and then define expected results.
I get 2 different responses from an endpoint and either one of them is fine.
first response:
response1.xml
second response:
response2.xml
I tried below assertion but it's not working:
And match response == read('response1.xml') || response == read('response2.xml')

How to assert substring in karate framework

I am getting an array of URLs as a response. I want to check that each URL from the array contains a specific word.
How can I check this in karate framework?
My response is :
response {
"docs":[{
"url":"http://url/1.com"
"title": "some title"
},{
"url":"http://url/2.com"
"title":"ABC"
}]
}
}
Now I want to check that each url field value contains word 'url'.How can I check this as match each $.response.docs.url contains 'url' does not work for me.
Please refer to the match each syntax. Here is an example:
* def response = [ 'http://url-one.com', 'http://url-two.com', ]
* match each response contains 'url'
EDIT - after question was edited. Here is your working example:
* def response =
"""
{
"docs":[
{
"url":"http://url/1.com",
"title":"some title"
},
{
"url":"http://url/2.com",
"title":"ABC"
}
]
}
"""
* def urls = $response.docs[*].url
* match each urls contains '/url/'