Match each item in Karate [duplicate] - karate

This question already has an answer here:
Using match each contains for json array items assertion
(1 answer)
Closed 1 year ago.
I would like assert that the price gross is greater than equal to price_net. Can you please tell me how can I achieve this correctly ? This is what I have done atm.
Scenario: Testing
* def response =
"""
{
"prices": [
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" }
]
}
"""
* match each response.prices[*].price_gross == '#? _ >= 0 && _ >= response.prices[*].price_net'
I think the '*' inside the assertion statement is the problem. Because when I run this
* match response.prices[0].price_gross == '#? _ >= 0 && _ >= response.prices[0].price_net'
it works fine. Please suggest. Thanks in Advance.

Sample Code:
Feature: Validation
Scenario: Validation
* def diff =
"""
function (A, B) {
var C = [];
for(var i = 0; i < A.length; i++) {
C.push(parseFloat(A[i]) - parseFloat(B[i]));
}
return C;
}
"""
* def response =
"""
{
"prices": [
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" },
{ "price_net":"10.50", "price_gross":"12.25" }
]
}
"""
* json temp = response
* def pgarr = get temp.prices[*].price_gross
* def pnarr = get temp.prices[*].price_net
* def sub = diff(pgarr,pnarr)
* match each sub == '#? _ >= 0'

Related

Karate - How change key name in JSON

I have the following JSON. I want to change the keyName 'freeDelivery' to 'isFreeDelivery' but I can't figure out how to do it.
{
"result": [
{
"deliverySlots": [
{
"id": "2DNN",
"date": "2022-04-05",
"freeDelivery": false,
"label": "All day delivery 08:30am to 5pm",
"price": "£5.00",
"fullSlotId": "2DNN"
},
{
"id": "2DPM",
"date": "2022-04-05",
"freeDelivery": false,
"label": "Afternoon 12pm to 5pm",
"price": "£10.00",
"fullSlotId": "2DPM"
}
]
},
{
"deliverySlots": [
{
"id": "2DNN",
"date": "2022-04-06",
"freeDelivery": false,
"label": "All day delivery 08:30am to 5pm",
"price": "£5.00",
"fullSlotId": "2DNN"
},
{
"id": "2DPM",
"date": "2022-04-06",
"freeDelivery": false,
"label": "Afternoon 12pm to 5pm",
"price": "£10.00",
"fullSlotId": "2DPM"
}
]
}
]
}
I've looked at the following pages but still can't figure out how to do it. Do I have to do a transorm or is there an easier way?
https://github.com/karatelabs/karate/blob/master/karate-junit4/src/test/java/com/intuit/karate/junit4/demos/js-arrays.feature
https://github.com/karatelabs/karate#json-transforms
Here you go:
* def payload = { before: 'foo' }
* remove payload.before
* payload.after = 'bar'
* match payload == { after: 'bar' }
Instead of remove this will also work (using pure JS):
* eval delete payload.before
EDIT: after seeing the comments, I would treat this as a JSON transform.
* def payload = { before: 'foo' }
* def fun = function(x){ var res = {}; res.after = x.before; return res }
* def result = fun(payload)
* match result == { after: 'foo' }
I'm sure now you'll want to "retain" all the existing data. Fine, here you go:
* def payload = { before: 'foo' }
* def fun = function(x){ var res = x; res.after = x.before; delete res.before; return res }
* def result = fun(payload)
* match result == { after: 'foo' }
And you already know that you can run a transform on all array elements like this:
* def result = karate.map(someArray, fun)
Please note that you can create 2 or 3 transforms - and "nest" them.

Karate - filter a specific json key from response based on another static array

I have the following JSON response (reference name: "list") and
[
{
"key": "101",
"val": {
"portCall": {
"id": 12664978
},
"status": "in-port"
}
},
{
"key": "102",
"val": {
"portCall": {
"id": 12415798
},
"status": "in-port"
}
},
{
"key": "103",
"val": {
"status": "on-voyage",
"voyage": {
"id": "7kynv-7lq85"
}
}
},
{
"key": "104",
"val": {
"status": "on-voyage",
"voyage": {
"id": "7kynv-2385"
}
}
}
]
also, I have an array list of few key values, evImos = [101,102,104]
In that, I have to identify the first key in the "list" response that has status as "on-voyage". So, the result should be "104".
I have tried the following and I need some help to make it work. Any help would be appreciated.
* def function getFirst = function(evImos) { for (let num of evImos) { let results = list.filter(d => d["key"] === num && d["val"]["status"] === "on-voyage"); if(results.length === 1) { karate.log(num); return num; } } }
* list.forEach(getFirst(evImos))
I'll just give you one hint. This one line will convert the whole thing in to a form that is much easier for you to validate:
* def temp = {}
* list.forEach(x => temp[x.key] = x.val.status)
Which gives you:
{
"101": "in-port",
"102": "in-port",
"103": "on-voyage",
"104": "on-voyage"
}
Now you can do:
* def isOnVoyage = function(key){ return temp[key] == 'on-voyage' }
Also read this: https://stackoverflow.com/a/59162760/143475
Thanks, to #Peter.
Based on his hint, I just tweaked it a little bit to match my requirement and it worked for me.
Here is the working copy for anyone to refer in the future.
* def temp = {}
* list.forEach(x => temp[x.key] = x.val.status)
* def isOnVoyage = function(keys){ for (let key of keys) { if(temp[key] == 'on-voyage'){ karate.log(key); karate.set('num', key); break; }}}
* isOnVoyage(evImos)

Karate - Replace a value with if condition

I have the following json. I want to replace 'Türkiye' with 'Türkice' if a == "hello". Please help me with the guidance to add replace with the if condition combination
* def a = "hello"
* def expected =
"""
{
"_": {
"country-language-list": {
"country-language": [
{
"_": "English",
"#": {
"languageCode": "en"
}
},
{
"_": "Deutsch",
"#": {
"languageCode": "de"
}
},
{
"_": "Türkiye",
"#": {
"languageCode": "tr"
}
}
]
}
},
"#": {
"countryCode": "TR"
}
}
"""
Here you go:
* if (a == 'hello') expected._['country-language-list']['country-language'][2]._ = 'Türkice'

Comparing json array item against the response which has random order of the json arrary items

This file (getAllDomain.json) has known/valid response but the order of domain_name /domain_code is random which has to compare against api output..
means .. X3 may come first or last and there is no define order.
I was trying to verify each data array element against the response. But its not working.
IS there any way to just verify arrary and all other element other than "data" can be ignored.
* def expected = read('getAllDomain.json')
* def response =
"""
{
"status":"SUCCESS",
"totalCount":3,
"statusCode":"OK",
"ResultData":{
"data":[
{
"domain_code":"X3",
"domain_name":"BMW"
},
{
"domain_code":"Q5",
"domain_name":"AUDI"
},
{
"domain_code":"MDX",
"domain_name":"ACURA"
}
]
}
}
"""
And match response.ResultData.data[*] contains any expected.ResultData.data[0]
Here you go. And try to read the docs, it will actually help you:
* def expected =
"""
[
{
"domain_code": "MDX",
"domain_name": "ACURA"
},
{
"domain_code": "X3",
"domain_name": "BMW"
},
{
"domain_code": "Q5",
"domain_name": "AUDI"
}
]
"""
* def response =
"""
{
"status":"SUCCESS",
"totalCount":3,
"statusCode":"OK",
"ResultData":{
"data":[
{
"domain_code":"X3",
"domain_name":"BMW"
},
{
"domain_code":"Q5",
"domain_name":"AUDI"
},
{
"domain_code":"MDX",
"domain_name":"ACURA"
}
]
}
}
"""
* match response.ResultData.data contains only expected

Karate API : In attached json response how to update json attribute quantity dynamically

In below json response I want to update quantity of all productNumbers, Item count in response varies it could be 1 or more than 1, it depends on the input. how can I do that in Karate. I tried my way it did not work, so please provide a solution.(I provided my approach below please ignore if it is wrong approach)
{
"userProfileId": "12313123123",
"items": {
"47961": {
"products": {
"productNumber": "0000",
"productSummary": {
"productSubTotal": "$68.64",
"quantity": 3,
"productrice": "$22.88"
}
}
},
"47962": {
"products": {
"productNumber": "12345",
"productSummary": {
"productSubTotal": "$68.64",
"quantity": 3,
"productPrice": "$22.88"
}
}
},
"47963": {
"products": {
"productNumber": "1111",
"productSummary": {
"productSubTotal": "$68.64",
"quantity": 3,
"productPrice": "$22.88"
}
}
},
"47964": {
"products": {
"productNumber": "2222",
"productSummary": {
"productSubTotal": "$68.64",
"quantity": 3,
"productPrice": "$22.88"
}
}
}
}
}
I tried with like below by creating JS file and passing required values to it but it failing when I trying to call a feature file withing java script.(may be the way i am calling is incorrect)
Feature: Update
Scenario: Update all items in cart
* print 'config in called function '+upConfig
* print 'in called function '+orderItemIDs
* def updateAttempt =
"""
function(productNumbers,upConfig,firstOrderID){
for(i=0;i<orderItemIDs.length;i++){
karate.log('Run test round: '+(i+1));
var itemID = productNumbers[i];
karate.log('Order Item IDs :'+productNumbers[i]);
karate.log('Config log-'+upConfig);
karate.log('firstOrderItemID-'+firstOrderID);
karate.call('UpdateProductQuantity.feature') upConfig;
}
java.lang.Thread.sleep(1*1000);
}
"""
* def itemPrice = call updateAttempt(orderItemIDs,upConfig,firstOrderID)
Feature: test update
Scenario Outline: Update with all values
* def encodedURL = ''
* def gID = ''
* def upConfig = ''
* def firstOrderItemID = [47961]
* json productNumbers= orderItemIDs
* print 'productNumbers--'+orderItemIDs
* def list = call read('Update.feature') upConfig
* def result = call list productNumbers
* def result = call result firstOrderItemID
* print 'Result -'+result.response
Here you go:
* def response =
"""
{
"userProfileId":"12313123123",
"items": {
"47961": {
"products": {
"productNumber":"0000",
"productSummary": {
"productSubTotal":"$68.64",
"quantity":3,
"productPrice":"$22.88"
}
}
},
"47962": {
"products": {
"productNumber":"12345",
"productSummary": {
"productSubTotal":"$68.64",
"quantity":3,
"productPrice":"$22.88"
}
}
}
}
}
"""
* def fun = function(k, v){ response.items[k].products.productSummary.quantity = 100 }
* eval karate.forEach(response.items, fun)
* match each response..quantity == 100