How to match string and ignore the case in karate? - 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'

Related

How to use loop for response from another feature?

І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

How to check a particular value in karate on basis of condition when there are more than one key in response

There are multiple keys present in x.details[0].user so how to compare in such condition. It works fine where there is only one key while when there are more than one key it fails with error as there are multiple keys for user.
Please guide
* def array =
"""
{
"type": "1",
"array": 2,
"details": [
{
"path": "path",
"user": {
"school": {
"name": [
{
"value": "this is school",
"codeable": {
"details": [
{
"hello": "yty",
"condition": "check1"
}
],
"text": "123S"
}
}
]
},
"sample": "test1",
"id": "22222"
},
"data": {
"check": "abc"
}
},
{
"path": "path",
"user": {
"school": {
"name": [
{
"value": "this is school",
"codeable": {
"details": [
{
"hello": "def",
"condition": "check2"
}
],
"text": "123O"
}
}
]
},
"sample": "test",
"id": "11111"
},
"data": {
"check": "xyz"
}
}
]
}
"""
* def lookup = { 'check1': 'yty', 'check2': 'def' }
* match each array.details contains { user: { school: { name[0]: { codeable: { details[0]: { hello: '#(lookup[_$.user.school.name[0].codeable.details[0].condition])' } } } } } }
I have tried multiple ways but not sure how to make it work when there are more than one keys getting returned.
First let me say this. Please, please do not try to be "too clever" in your tests. Read this please: https://stackoverflow.com/a/54126724/143475
Just have simple tests that test for specific, predictable responses and stop there. The maximum complexity should be match contains, that's it. What you are trying to do is in my opinion a waste of time, and will just cause grief for anyone who tries to maintain these tests in future.
That said, I'm giving you a completely different approach here. There are a few different ways, this is just one. Here we attack the problem piece by piece instead of trying to write one massive match.
* def allXyz = array.details.filter(x => x.data.check == 'xyz')
* match each allXyz..details == [{ hello: 'def', condition: 'check2' }]
You should be able to extend this to do all the weird assertions that you want. If you are wondering what allXyz..details does, you can print it like this:
* def temp = $allXyz..details
* print temp

Unexpected behavior of ARRAY_SLICE in Cosmos Db SQL API

I have Cosmos DB collection (called sample) containing the following documents:
[
{
"id": "id1",
"messages": [
{
"messageId": "message1",
"Text": "Value1"
},
{
"messageId": "message2",
"Text": "Value2"
}
]
},
{
"id": "id2",
"messages": [
{
"messageId": "message3",
"Text": "Value3"
},
{
"messageId": "message4",
"Text": "Value1"
}
]
},
{
"id": "id3",
"messages": [
{
"messageId": "message5",
"Text": "Value1"
},
{
"messageId": "message6",
"Text": "Value2"
}
]
},
{
"id": "id4",
"messages": [
{
"messageId": "message7",
"Text": "Value5"
},
{
"messageId": "message8",
"Text": "Value2"
}
]
},
]
I am trying to retrieve all the Documents, having messages and the first message has the field "Text"= 'Value1'.
In this sample the documents with the ids '1' and '3' would be retrieved. Please notice that the document with id='id2' wouldn't be retrieved,
since the value of the text of the first message is 'Value3'.
The collection as mentioned is called sample and I am running the following Query:
"select sample.id, sample.messages, ARRAY_SLICE(sample.messages, 0, 1)[0].Text as valueOfText from sample"
As you can see in the first two images, I retrieve all Documents and every one of them have the field "valueOfText" set to value of the first message, as expected.
Now when I filter the collection (the third image), I retrieve no results at all.
Is this an expected behavior?
Following your sql, got same results:
But why you have to use ARRAY_SLICE,it is used to return truncated array.Since your requirement is specific:
trying to retrieve all the Documents, having messages and the first
message has the field "Text"= 'Value1'
Just use sql:
SELECT c.id,c.messages,c.messages[0].Text as valueOfText FROM c
where c.messages[0].Text = 'Value1'
Output:

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

Extract data from json array in Karate

In the below JSON response, I need to extract the 'cid' for the record that has the 'nationalityDecription' as 'USA'. By using this query as a reference, I used the below loc in the karate feature file, but 1st line itself fails with syntax error(tried different combinations). For now, I'm using the custom javascript as a workaround which is working fine. I need help to check if i'm missing anything in syntax. Thanks
Response:
{
"header": {
"Id": "12345678",
"timeStamp": "2018-09-17T10:09:812.000"
},
"dataRecords": [
{
"cid": "31H678",
"cidMeta": "00",
"nationalityDecription": "CHINA"
},
{
"cid": "31S421",
"cidMeta": "01",
"nationalityDecription": "USA"
}
]
}
Feature file:
* def record= $response.dataRecords[?(#.nationalityDecription=='USA')]
* def cid = record.cid
* def response = { "header": { "Id": "12345678", "timeStamp": "2018-09-17T10:09:812.000" }, "dataRecords": [ { "cid": "31H678", "cidMeta": "00", "nationalityDecription": "CHINA" }, { "cid": "31S421", "cidMeta": "01", "nationalityDecription": "USA" } ] }
* def cid = get[0] response.dataRecords[?(#.nationalityDecription=='USA')].cid
* match cid == '31S421'