Can i override path in feature file for a test called from another file [duplicate] - karate

I am trying to follow the examples in the demo:
https://github.com/intuit/karate/tree/master/karate-demo/src/test/java/demo/callfeature
I need to do a call from one feature to another, and pass a reference to update. The reference is for a JSON that is read from a file:
Background:
* url url
* header Authorization = token
* def payload = read('event.json')
* set payload.createdByUser = 'karate'
Scenario: Call another feature with arg
* call read('classpath:common/swap-json-elements.feature') payload
* print payload
Inside my swap-json-elements.feature:
Background:
* set new = payload.old
* set payload.new= payload.old
* set payload.old= new
This is not working. It is clear in the documentation that a shared scope is shared when we 'set' is used, while 'def' will create a new variable, and never update the shared one.
What am I missing ?

If you pass an argument, it is passed by value. When you call with "shared scope" you typically don't need to pass arguments. Because all variables are visible anyway. Try a simpler example, and please watch white-space around the = sign.
main.feature:
Feature:
Background:
* def json = { foo: 'bar' }
* call read('called.feature')
Scenario:
* match json == { foo: 'baz' }
called.feature
Feature:
Scenario:
* set json.foo = 'baz'
* match json == { foo: 'baz' }

Related

Karate API Converting String from JSON Response into UPPERCASE [duplicate]

This question already has an answer here:
How to extract value in double quotes from a response header in karate
(1 answer)
Closed 1 year ago.
JSON Response has __typename in the response.
I am defining and storing it so I can use this in the next graphQL Request
def contentType1 = response.data.getPublicList.items[0].__typename
__typename comes back as "Movie"
The next Request requires "Movie" to be "MOVIE"
query {
getContentById(id: "", contentType: "MOVIE") {
Is there a way I can convert/define the entire string value as UPPERCASE?
That should be easy, behind the scenes it is a "Java" string, so there are methods you can use:
* def contentType1 = 'Movie'
* def after = contentType1.toUpperCase()
* match after == 'MOVIE'
EDIT: If you want to convert "in place", just do JS-style operations:
* def data = { foo: 'bar' }
* data.foo = data.foo.toUpperCase()
* match data == { foo: 'BAR' }
If you need more sophistication, please look at the docs for JSON transforms: https://github.com/karatelabs/karate#json-transforms

Replace Json key in Karate [duplicate]

This question already has an answer here:
Karate API function/keyword to substitute JSON placeholder key with argument passed
(1 answer)
Closed 1 year ago.
I need to send a Json to an endpoint but I need to replace a key with a variable.
I've this code
.....
* def idJson = response.id
Given path <mypath>
And headers {Authorization: '#(auth)'}
And request read('classpath:myjson.json')
.....
The myjson.json file is
{
"a":
{
...
"b":false,
"c":true
},
"d":
{
'#(idJson)':
{
"Key":[
.....
]
}
}
}
But the value is not replace in the json. When I perform the request I see that the json contains the string '#(idJson)' instead of the value of the variable. Any idea about how to solve this?
Thank you
Embedded expressions cannot be used to modify a JSON key. You have to use a JS operation like this:
* def idJson = 'foo'
* def body = {}
* body[idJson] = 'bar'
* url 'https://httpbin.org/anything'
* request body
* method post
* status 200
* match response.json == { foo: 'bar' }
Note that d could be replaced like this so you can still read the file and be dynamic:
{ "d": "#(temp)" }
And temp can be JSON that is defined in your feature before reading the file.
If this is too troublesome, please contribute code :)

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]);

how can we pass multiple arguments in the background functions in karate feature file

i am passing the two arguments to my custom function but in background while i am passing the arguments it's skipping first taking second one only arugment.
here is the sample code
* def LoadToTigerGraph =
"""
function(args1,args2) {
var CustomFunctions = Java.type('com.optum.graphplatform.util.CareGiverTest');
var cf = new CustomFunctions();
return cf.testSuiteTrigger(args1,args2);
}"""
#*eval if (karate.testType == "component") karate.call(LoadToTigerGraph '/EndTestSample.json')
* def result = call LoadToTigerGraph "functional","/EndTestSample.json"
output :
test type is ************/EndTestSample.json
path is *************undefined
When you want to pass two arguments, you need to send them as two json key/value.
* def result = call LoadToTigerGraph { var1: "functionnal", var2: "/EndTestSample.json" }
And you just have to use args.var1 and args.var2 in your function function(args)

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.