Schema validation: string from specific list of values - karate

I have an endpoint with the following response:
{
"id": 1,
"status": "ACTIVE"
}
The possible values for status are the following: ACTIVE, INACTIVE, DELETED.
To check the schema I tried the following:
* def statusValues = ["ACTIVE", "INACTIVE", "DELETED" ]
* def schema =
"""
{
"id" : #number,
"status" : '#(^*statusValues)'
}
"""
And to validate I use the following sentence:
Then match response == schema
But it doesn't work. This is the error
actual: 'ACTIVE', expected: ["DELETED","ACTIVE","INACTIVE"], reason:
actual value is not list-like
Can you help me, please?

This is probably the simplest option:
* def isValidStatus = function(x){ return statusValues.contains(x) }
* def schema = { id: '#number', status: '#? isValidStatus(_)' }

Related

Check for attribute value from JSON response

I am trying to validate the below conditions in the sample response
Based on subjectType attribute if it is either Person or Organization.
If subjectType is Person, check if it has a birthDate attribute
Sample response:
{
"subject": "ABC",
"subjectType": "Person",
"birthDate": "1951-03-07"
},
{
"subject": "ABC",
"subjectType": "Organization"
}
I tried this, but no luck.
def expected = {subjectType: 'Person', birthDate: '#present'}
def schema = { subjectType: '#? _ == "Person" || _ == "Organization"', birthDate: '#($.subjectType == "Person" ? "#present" : "#present")' }
match expected == schema
Any help is appreciated!
There are many answers that give you solutions, please start here:
https://stackoverflow.com/a/50350442/143475
Since I just came up with a new idea to solve this, I'm posting it below. Note that there is no right answer, and there are many, many ways to do what you want.
* def schemas =
"""
{
Person: { subject: '#string', subjectType: 'Person', birthDate: '#string' },
Organization: { subject: '#string', subjectType: 'Organization' }
}
"""
* def response = { "subject": "ABC", "subjectType": "Person", "birthDate": "1951-03-07" }
* def expected = schemas[response.subjectType]
* match response == expected
Also search slack overflow if you want to validate dates later.

Karate - Reading data from json file and assing it to a dynamically generated request

I have following data.json file:
{
"ids": {
"id": "a2mx8m6yvksgu3605c7c1a61d"
},
"second": {
"name": "test2"
},
"third": {
"name": "test3"
}
}
I did fetch a variable for the id from the json.
* def id = data.ids.id
I want to use this variable id (defined above) to a request.
Request defined below is dynamically being sent to the xml file i.e xml request is being generated with but the below doesnt work when i try to pass the variable id.
This however works when i hardcode the id value.
* def ARG = {attr: [ { regex: '#(ids)', value: '<id>"#(id)"</id>'} ] }
Please help me how can i pass the data being read from json to the above line of code.
Read the docs: https://github.com/intuit/karate#rules-for-embedded-expressions
* def id = 'foo'
* def val = '<id>' + id + '</id>'
* def arg = { value: '#(val)' }
* match arg == { value: '<id>foo</id>' }

Trying to assert 2 dynamic responses

I have 2 different responses:
{
"id": "U204204",
"title": "Safety kit",
"categoryPath": "/equipment/accessories/null",
"keyFeature": false,
"description": "test",
"price": 24.5,
"availability": "optional-extra",
"technologyItems": [],
"bespoke": false
}
or/and
{
"id": "GWW1WW1",
"title": "Winter pack",
"categoryPath": "/comfort & convenience/packs/null",
"keyFeature": false,
"description": "test",
"price": 410,
"availability": "optional-extra",
"technologyItems": [],
"bespoke": false
}
Now what I'm trying to assert is as long as the key price in ANY of the 2 responses above has a value ending in '.5' pass it.
I have tried the following and similar things but not working:
Given path 'endpoint'
And multipart file pdbData = { read: 'json/PostRequest_201_3.json', filename: 'PostRequest_201_3.json', contentType: 'application/json'}
When method post
And status 201
* def NewpdbId = response.id
And path 'endpoint'+NewpdbId+'/V3FOY3DG'
And method GET
And status 200
* string aa = response.options[13].price
* string bb = response.options[16].price
* def expected = aa contains "#redgex .+[.5]+" ? { pass: true }
* def expected = bb contains "#regex .+[.5]+" ? { pass: true }
* string expected = expected
And match expected == { pass: true }
So if the key price ends in '.5' in any of the responses it should be a pass. If key price is a whole number in all of the responses then it should fail.
Any ideas? I have tried so many different ways
There are a few ways. Read the docs for match each also:
First extract only the price values into a list, convert to strings (read the docs for JSON transforms):
* def prices = $response.options[*].price
* def fun = function(x){ return x + '' }
* def prices = karate.map(prices, fun)
* match prices contains '#regex .+[.5]+'

Un-named JSON array field validation in Karate

I have a un-named JSON array like this from the response and would like to check whether it contains "confirmationNumber": "pqrs" or not. May I know how can I check that in Karate?
[
{
"id": 145,
"confirmationNumber": "abcd"
},{
"id": 723
"confirmationNumber": "pqrs"
}
,{
"id": 7342
"confirmationNumber": "sfeq"
}
]
karate.filter() is good for these situations:
* def response =
"""
[
{
"id":145,
"confirmationNumber":"abcd"
},
{
"id":723,
"confirmationNumber":"pqrs"
},
{
"id":7342,
"confirmationNumber":"sfeq"
}
]
"""
* def fun = function(x){ return x.confirmationNumber == 'pqrs' }
* def found = karate.filter(response, fun)
* match found == '#[1]'
Also see examples of JsonPath: https://github.com/intuit/karate#jsonpath-filters
EDIT: apologies, there is a much simpler way, please read the docs !
* match response contains { id: '#number', confirmationNumber: 'pqrs' }
* def item = { confirmationNumber: 'pqrs' }
* match response contains '#(^item)'

Schema Validation - Karate expression to check if value exists in array

Sample Response
{
"data": [
{
"name": "DJ",
"status": "ACTIVE"
}
]
}
Sample Feature File
#ignore
Feature: Sample
#smoke
Scenario: Karate expression to check if value exists in array
Given url url
And path '/test'
When method GET
Then status 200
And def users = response.data
And def possibleStatus = ["ACTIVE", "INACTIVE"]
And def schema =
"""
{
name: '#string',
status: ?
}
"""
And match each users contains schema
Is there a way to check if status is either ACTIVE or INACTIVE using karate expression ?
NOTE: It can be achieved by writing custom JS function.
* def statuses = [ 'ACTIVE', 'INACTIVE' ]
* def response = [{ name: 'DJ', status: 'ACTIVE' }, { name: 'PJ', status: 'INACTIVE' }]
* match each response == { name: '#string', status: '#? statuses.contains(_)' }