Expression with String placeholder in the filter part of JsonPath using karate - karate

I am trying to filter my response using JSON Path where one of the condition using a value from a variable but I am not able to map variable properly, so my filter not working properly.
Sample response JSON:
{
"response":[
{
"id":"1234",
"confirmationCode":"abcd"
}
]
}
I am using the below script where I am using variable 'code':
* def Code = 'abcd'
* def value = karate.jsonPath($.response[?(#.confirmationCode == ' + Code +')])

Read the docs carefully please:
* def value = karate.jsonPath(response, "$.response[?(#.confirmationCode=='" + Code + "')]")

Related

How to Print Index value for matching JSON data using Karate

I would like to print the index value for matching JSON data using Karate.
For below code the expected answer should be 2, but I got -1, not sure what I am missing
[
{"aaa": 101},
{"bbb": 102},
{"ccc": 103}
]
Feature: Rough
Scenario: Rough
* def myData = read('roughTestData.json')
* print "Index ->>", myData.indexOf('ccc')
You have a JSON object within an array (not a plain string), and the complication here is you are interested in keys not values, so you need to do this instead:
* def response = [{"aaa":101},{"bbb":102},{"ccc":103}]
* def keys = response.map(x => Object.keys(x)[0])
* def index = keys.indexOf('ccc')
* match index == 2
We are using JS array methods such as map(), Object.keys() and indexOf() above
That said, I personally think you are over-complicating things because Karate allows you to match without caring about the order. For example:
* def response = [{"aaa":101},{"bbb":102},{"ccc":103}]
* def expected = [{ccc:'#number'},{bbb:'#number'},{aaa:'#number'}]
* match response contains only expected
So read the docs, and be creative: https://github.com/karatelabs/karate#json-arrays

Modified variable name in karate framework [duplicate]

This question already has an answer here:
Karate Http request add param conditionally
(1 answer)
Closed 1 year ago.
I want to modified param variable for my request(GET/POST) dynamically. As I have 2 different environment which takes different parameters for same request.
I tried below code, but not able to replace param variable(name).
I can replace param value successfully.
This function generate the dynamic param name for different enviornment
public static String paramDynamicVariable(String env, String param) {
String paramValue;
if (env.equals("test")) {
paramValue = '$' + param;
} else {
paramValue = param;
}
return paramValue;
}
Now when I am using paramValue in my test--
Scenario: xyz
Given path URLOfRequest
* print paramDynamicVariable(karate.env,'nameParam')
And param random.paramDynamicVariable(karate.env,'nameParam') = 10
It prints correct value, but in the next line it is not replacing for param name.
Please suggest if any solution is there to dynamic param name.
Please do something like this:
* def nameParam = paramDynamicVariable(karate.env, 'nameParam')
* def paramValues = {}
* paramValues[nameParam] = 10
And then:
* params paramValues
Since params accepts any JSON, all you need to do is create the JSON. Since the key is dynamic, it requires you to do a little more work.

Karate : Trying to convert array to string using js method toString() in karate [duplicate]

This question already has an answer here:
Change type from string to float/double for a key value of any json object in an array
(1 answer)
Closed 1 year ago.
I'm trying to convert an Array to string using a simple js function placed in the reusable feature file. I don't see any reason why the array is not getting converted to a string when I try to run the same function on the console it works without any issue.
Can anyone suggest a way to get this issue sorted?
"""
* def formatter = function(str){
var formatstring = str.toString();
return formatstring
}
"""
feature file
* def format = call read('../common/resuable.feature)
* def result = format.formatter(value)
* print result
Input = ["ID3:Jigglypuff(NORMAL)"]
Actual result = ["ID3:Jigglypuff(NORMAL)"]
Expected result = ID3:Jigglypuff(NORMAL)
[![When tried same on console][1]][1]
[1]: https://i.stack.imgur.com/tAcIz.png
Sorry, if you print an array, it will have square-brackets and all, that's just how it is.
Please unpack arrays if you want the plain string / content:
* def input = ["ID3:Jigglypuff(NORMAL)"]
* def expected = input[0]

Unable to Pass Two Parameters as Argument to Javascript Function

I am trying to use karate.call to invoke function of a JS file receiving two arguments (String, Array of String). However the array of string would not be passed on to the JS file.
The JS file contains:
function(query, fragments) {
// Here lies some code
// One of them includes fragments.length;
}
And I call the JS function on another JS file in this way:
//var query = 'Some string';
//var fragments = ['fragment1', 'fragment2'];
var clean = karate.call('../helper/helper.js', [query, fragments]);
I am able to pass query which is a string. But I was unable to pass the array of string. The error says:
TypeError: Cannot read property "length" from undefined
It seems the array of string did not get passed to the JS function. Any help will be greatly appreciated. Thanks!
You can read you function first and invoke is just like any other js function
var myFun = karate.read('../helper/helper.js');
var funCall = myFun(query, fragments);
or
var myCall = karate.read('../helper/helper.js')(query, fragments);
this should work.
.call takes parameters as comma separated values , you need to use .apply if you want to pass values as an array.
var clean = karate.call('../helper/helper.js', query, fragments);
will work...
The answers here are missing an important clarification:
I often do single arg functions like:
* def concatParams =
"""
function(s) {
return "urldt=" + todaysDate + "&caseid=" + s.caseid
}
"""
And I will call that like so:
* def params = call concatParams {caseid: '3433344'}
But, when I want to do 2 params, I will define a function like so:
* def concatParams =
"""
function(d,s) {
return "urldt=" + d.date + "&caseid=" + s.caseid
}
"""
And unintuitively, neither of these will work:
* def params = call concatParams {date: '01/01/2020', caseid: '3433344'}
* def params = call concatParams '01/01/2020' '3433344'
To get it to work, instead I call it like this:
* def params = concatParams('01/01/2020', '3433344')
Documentation does not clarify this.
var clean = karate.call('../helper/helper.js', query, fragments);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
call method accepts comma separated params and apply accept array so you need to replace call into apply. your code looks like
function karate(query, fragments) {
// Here lies some code
// One of them includes fragments.length;
}
var clean = karate.apply('../helper/helper.js', [query, fragments]);

Unable to Parse the variable value to the array variable

I was trying to pass the variable 'i' value to a array index 'locations[i]' using below karate code. but throwing an error saying unable to parse. Please suggest be for any changes.
Feature: Verify Branches
Background: For loop implementation
Given url ''
When method GET
Then status 200
* def i = 0
* def z = $.locations[i].zip
* def p = $.locations[i].phone
* def fun =
"""
function(locations){
for (var i = 0; i < locations.length; i++)
{
print(i)
print('Element at Location ' + i +':' + p)
}
}
"""
Scenario: Validate the locations
Given url ''
When method GET
Then status 200
* call fun p
It is hard to make out anything since you have not provided the value of the response. There are many things wrong here. But I'll try.
Take this line:
* def z = $.locations[i].zip
This will not work, Karate does not support variables within JsonPath by default, refer the docs: https://github.com/intuit/karate#jsonpath-filters
And I think you are un-necessarily using JsonPath where normal JavaScript would have been sufficient:
* def z = response.locations[i].zip
Also it seems you are just trying to loop over an array and call a feature. Please refer to the documentation on Data Driven Features.
Take some time and read the docs and examples please, it will be worth your time. One more tip - before I leave you to understand Karate a little better. There is a way to convert a JSON array into another JSON array should you need it:
* def fun = function(x){ return { value: x } }
* def list = [1, 2, 3]
* def res = karate.map(list, fun)
* match res == [{ value: 1 }, { value: 2 }, { value: 3 }]
So there should never be a need for you to manually do a for loop at all.