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

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(_)' }

Related

How to define schema for array which get repeat multiple time which mark my test case fail [duplicate]

Is possible to match each element of a nested array response (using contains) using just one schema?
I have a set of yml files with request params and response schemas, like this one:
response:
appId: '#string'
attributes: '#array'
login: '#string'
permissions: '#array'
metadata:
roles: '##array'
userData:
description: '#string'
employeeId: '#string'
employeeNumber: '##string'
id: '#string'
login: '#string'
mail: '#string'
name: '#string'
and then, in a reusable feature:
* def req = read(<testDataFile>)
* match response contains req.response
I can match nested objects with just one schema but I'm not sure if it's possible use the schema to match nested arrays
maybe like:
response:
appId: '##string'
attributes: '##array'
attributes[*]:
key: '#string'
or any other expression
Thanks a lot
You can't do this with a single "schema" and you have to declare the repeating element separately, as a Karate variable: https://github.com/intuit/karate#schema-validation
* def foo = { a: '#number' }
* def bar = { baz: [{ a: 1 }, { a: 2 }, { a: 3 }] }
* match each bar.baz == foo
* match bar == { baz: '#[] foo' }

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.

Schema validation: string from specific list of values

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(_)' }

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

Cannot match schema from a file which has nested array [duplicate]

This question already has an answer here:
Karate Tests: How to match contains each nested array response with just one schema
(1 answer)
Closed 1 year ago.
Assume that I have a response-Json look like below
def resJson =
"""
{
"id": 1,
"code": "OU82883",
"features":
[
{
"id": 12,
"class": "OU8811",
"school": "parent",
"course": "abc",
"sortOrder": 123
}
]
}
"""
To be easily manage file to compare, I am placing the expected schema - expected result in a file ("getCourseDetails.txt"), with structure below
{
id: '#number',
code: '#string',
features: ##[{
id: '#number',
class: '##string',
school: '##string',
course: '##string',
sortOrder: '#number'
}
]
}
Then in executed feature file, perform the code as
* json expSchema= read ('../Data/Schema/getCourseDetails.txt')
* match resJson == expSchema
The system informs AssertionFailed Error
To find another way to validate schema, I kept only the structure inside of "features" in "getCourseDetails". The outside of "features", I put into executed feature file. So my code now is:
GetCourseDetails file:
{
id: '#number',
class: '##string',
school: '##string',
course: '##string',
sortOrder: '#number'
}
Feature file:
* json courseDetails= read ('../Data/Schema/getCourseDetails.txt')
* def expSchema = {id: '#number', code: '#string', features: '##[] courseDetails'}
* match resJson == expSchema
There is no error and validate works well, but this approach is not my expected.
I would like to know is there a way to centralize all things in a file, and user just calls the file to validate against actual response's schema
Thank you so much.
I think you are over-engineering your tests, but you can use JS to do advanced set-up and building the schema the way you want, and it will be re-usable. For example:
first.json:
{ "foo": "#string" }
second.json:
{ "value": "#number" }
schema.js:
function() {
var first = read('first.json');
karate.set('second', read('second.json'));
first.bar = '##[] second';
return first;
}
now your feature file can be:
* def schema = call read('schema.js')
* def response = { foo: 'test', bar: [{value: 1}, {value: 2}] }
* match response == schema
Above, if you * print schema you will see:
{
"foo": "#string",
"bar": "##[] second"
}
And if you want a one-liner - * match response == call read('schema.js') should work !