How to use loop for response from another feature? - karate

Іssue in the next.
I have a feature response which I check according to schema validation
{
"name": "#string",
"director_first_name": "##string",
"director_last_name": "##string",
"director_phone": "##string",
"director_email": "##string",
"language": {
"id": "#uuid",
"name": "#string",
"code": "#string? _.length == 2"
}
}
Also I have additional feature, which has list of languages
[
{
"id": "fde1312f-2ab2-4fdf-a4f3-a7095dd89a4d",
"name": "English",
"code": "EN"
},
{
"id": "0d4c6626-1010-4dda-8721-665071ec3b28",
"name": "Swedish",
"code": "SV"
}
]
And I need to check the next
Need to take response.language.id from first response and check if this id is represented in the second response. In this case I need to call this second feature.
If it is represented, need to match if id, name, code which belong to first reponse the same as in the second response.

You can do this in one line. I leave it as an exercise to you to get the data from a second feature file if you wish.
* def data =
"""
[
{
"id": "fde1312f-2ab2-4fdf-a4f3-a7095dd89a4d",
"name": "English",
"code": "EN"
},
{
"id": "0d4c6626-1010-4dda-8721-665071ec3b28",
"name": "Swedish",
"code": "SV"
}
]
"""
* def response =
"""
{
"language": {
"id": "fde1312f-2ab2-4fdf-a4f3-a7095dd89a4d",
"name": "English",
"code": "EN"
}
}
"""
* match response.language == data.find(x => x.code == response.language.code)
Take some time to read other answers (and follow the links) for ideas: https://stackoverflow.com/a/70055035/143475

Related

Get the value from the response based on a condition and store it to a variable

I would like to get the value from the response based on a condition and store it to a variable.
In the below JSON, I would like to store the value when the name matches to something I prefer. Is there a way to achieve this using Karate API?
{
"results": [
{
"name": "Sample1",
"email": "sample1#text.com",
"id": "U-123"
},
{
"name": "Sample2",
"email": "sample2#text.com",
"id": "U-456"
},
{
"name": "Sample3",
"email": "sample3#text.com",
"id": "U-789"
}
]
}
So after reading the comment, my interpretation is to "find" the id where name is Sample2. Easy, just use a filter() operation, refer the docs: https://github.com/karatelabs/karate#jsonpath-filters
Instead of using a filter, I'm using the JS Array find() method as a very concise example below:
* def response =
"""
{ "results": [
{ "name": "Sample1", "email": "sample1#text.com", "id": "U-123" },
{ "name": "Sample2", "email": "sample2#text.com", "id": "U-456" },
{ "name": "Sample3", "email": "sample3#text.com", "id": "U-789" }
]
}
"""
* def id = response.results.find(x => x.name == 'Sample2').id
* match id == 'U-456'
Take some time to understand how it works. Talk to someone who knows JS if needed.

How to match string and ignore the case in karate?

There is a case where one value sometimes is lower case and sometimes it's upper case. this is the response coming from an API and we have to match if every field in response is correct by ignoring some values. The error text in response sometimes has one keyword in lower and some scenarios it is upper case. How we can ignore one keyword in a string to not match? I don't want to ignore whole text as it works fine if I ignore whole string but is it possible to ignore one keyword only?
Scenario: string matching
* def test =
"""
{
"sourceType": "Error",
"id": "123456",
"type": "searchuser",
"total": 0,
"value": [
{
"details": "this is the user search case",
"source": {
"sourceType": "Error",
"id": "77200203043",
"issue": [
{
"severity": "high",
"code": "678",
"message": {
"text": "No matching User details found"
},
"errorCode": "ERROR401"
}
]
},
"user": {
"status": "active"
}
}
]
}
"""
* match test ==
"""
{
"sourceType": "Error",
"id": "#present",
"type": "searchuser",
"total": 0,
"value": [
{
"details": "#present",
"source": {
"sourceType": "Error",
"id": "#ignore",
"issue": [
{
"severity": "high",
"code": "678",
"message": {
"text": "No matching User details found"
},
"errorCode": "ERROR401"
}
]
},
"user": {
"status": "active"
}
}
]
}
"""
How to ignore the case only for user here? I tried below but it treats #ignore as a value.
"text": "No matching #ignore details found"
I'm not looking at your payload dump but providing a simple example. Use karate.lowerCase():
* def response = { foo: 'Bar' }
* match karate.lowerCase(response) == { foo: 'bar' }
EDIT: you can also extract one value at a time and do a check only for that:
* def response = { foo: 'Bar' }
* def foo = response.foo
* match karate.lowerCase(foo) == 'bar'

Karate: How to remove dynamic element based on value from JSON?

I have a requirement, in the below JSON I have to delete all the id elements,
[
{
"id": "0a7936ed",
"code": "test",
"label": "test",
"type": "sell"
},
{
"id": "7bc1909b2",
"code": "test2",
"label": "test2",
"type": "Buy"
}
]
My JSON should be as below,
[
{
"code": "test",
"label": "test",
"type": "sell"
},
{
"code": "test2",
"label": "test2",
"type": "Buy"
}
]
Standard JS Array operations will work in Karate 1.0 onwards:
* def dest = source.map(x => { delete x.id; return x })
For older versions of Karate, a hint is that you can loop over any JS object key-values using karate.forEach() and you could write conditional logic to ignore id etc.

Karate API json response - How to validate the presence of a key which sometimes come and sometimes not in the API response

I need help in validating the presence of one key in the response. The response of the API looks like -
"persons": [
{
"id": "27",
"source": {
"personId": 281,
"emailAddress": "abc#abc.com",
"firstName": "Steve"
}
},
{
"id": "28",
"source": {
"personId": 353,
"emailAddress": "abcd#abc.com",
"firstName": "John"
"LastName" : "Cena"
}
}
]
}
I want to assert if the source.LastName appears or not and if it does then it should always hold a string value.
The solution should be generic and it should work for 30 or 40 persons object also down the time, currently I am using karate version 0.9.4 and need a resolution for handling such scenarios.
Thanks in advance !
In the schema "##string" validates that the field can be null or a string.
Sample Code:
Feature: Schema validation
Scenario:
* def resp =
"""
{
"persons": [
{
"id": "27",
"source": {
"personId": 281,
"emailAddress": "abc#abc.com",
"firstName": "Steve"
}
},
{
"id": "28",
"source": {
"personId": 353,
"emailAddress": "abcd#abc.com",
"firstName": "John",
"LastName" : "Cena"
}
}
]
}
"""
* def schema =
"""
{
"id": "#string",
"source": {
"personId": "#number",
"emailAddress": "#string",
"firstName": "#string",
"LastName": "##string"
}
}
"""
* match each resp.persons == schema

How to remove an object from an jsonarray based on filter in karate

I want to remove an object from json array based on a filter, tried below code but didn't work
* def json = [ { "id": "0a7936ed", "code": "test", "label": "test", "type": "sell" }, { "id": "7bc1909b2", "code": "test2", "label": "test2", "type": "Buy" } ]
I want remove object where code is equal to test
* def fun = function(){ karate.remove('json', $.[?(#.code=='test')]") }
* call fun
Getting exception as below:
com.intuit.karate.exception.KarateException: javascript function call failed: String index out of range: -1
at com.intuit.karate.Script.evalFunctionCall(Script.java:1622)
at com.intuit.karate.Script.call(Script.java:1573)
at com.intuit.karate.Script.callAndUpdateConfigAndAlsoVarsIfMapReturned(Script.java:1690)
at com.intuit.karate.StepDefs.callAndUpdateConfigAndVars(StepDefs.java:582)
Please suggest me how to filter it and remove the object.
Thanks inadvance..
This use-case is exactly what karate.filter() is designed for:
* def json = [ { "id": "0a7936ed", "code": "test", "label": "test", "type": "sell" }, { "id": "7bc1909b2", "code": "test2", "label": "test2", "type": "Buy" } ]
* def condition = function(x){ return x.code != 'test' }
* def filtered = karate.filter(json, condition)
* match filtered == [{ "id": "7bc1909b2", "code": "test2", "label": "test2", "type": "Buy" }]
Here is the documentation: https://github.com/intuit/karate#the-karate-object