Default values for query parameters - karate

Please forgive me if my question does not make sense.
What im trying to do is to inject in values for query parameters
GET1 File
Scenario:
Given path 'search'
And param filter[id] = id (default value or variable from another feature file)
POST1 File
Scenario:
def newid = new id made by a post call
def checkid = read call(GET1) {id : newid}
like if one of my feature files creates a new id then i want to do a get call with the above scenario. therefore i need a parameter there which takes in the new id.
On the other hand if i do not have an id newly created or the test creating it is not part of the suite. i want to still be able to run the above mentioned scenario but this time it has a default value to it.

Instead of param use params. It is designed so that any keys with null values are ignored.
After the null is set on the first line below, you can make a call to another feature, and overwrite the value of criteria. If it still is null, no params will be set.
* def criteria = null
Given path 'search'
And params { filter: '#(criteria)' }
There are multiple other ways to do this, also refer to this set of examples for data-driven search params: dynamic-params.feature
The doc on conditional logic may also give you some ideas.

Related

Question about why "Set cannot change my json file value"

This is my feature file:
* def Json = read ('1.json')
* print Json.Id
* set Json.Id = Product_Num
* print Json.Id
I want to replace my Id with new Product number. After run Karate, I see the result is correct, new Product_num is put out (by the second print out result)
But id value doesn't update in 1.json file.
How to update 1.json file values? I need to replace id values in 1.json file
You are trying to write to a file. This is normally never needed when you use Karate, and hence is not supported directly. Do you want your test data changing all the time because your tests are updating the files from which test data is being read ? I don't think so.
Please read this answer for details: https://stackoverflow.com/a/54593057/143475

Using call read within a js function

I have a slight problem I want to solve. I have the following lines of code which create 2 users which works. However the issue is that, it creates both users with the same Id from the the first line of code:
def myId = call read('classpath:karate/helpers/guid.js')
def users = function(){ karate.call('classpath:v1/api_CreateUser.feature')}
def usersResult = karate.repeat(2, users )
So I want to be able to create multiple users with different Ids. I tried the following:
* def users =
"""
function(){
var myId = null;
if(myId == null)
{
myId = call read('classpath:karate/helpers/guid.js')
}
karate.call('classpath:v1/api_CreateUser.feature');
}
"""
def usersResult = karate.repeat(2, users )
So the idea is to reset the 'myId' variable everytime to null, check if null which will be true, then call the js function which generates the id and assign the result to 'myId' variable.
Then the variable will be used on the karate.call('classpath:v1/api_CreateUser.feature') line.
Unfortunately I'm getting javascript evaluation failed error.
Anyone could help?
Thanks
Be clear about the slight difference when you are in Karate and when you are in JS. For example:
myId = call read('classpath:karate/helpers/guid.js')
This won't work. What you are looking for is:
myId = karate.call('classpath:karate/helpers/guid.js');
I recommend you read and understand the section on Karate Expressions it will save you a lot of trouble later.
When you use a JS function (that works) you should never need to worry about what you are. Just invoke it wherever, and it will "dispense" a new value. For example if you have:
* def time = function(){ return java.lang.System.currentTimeMillis() + '' }
* def first = time()
* def second = time()
Here first and second will always be different. I think now you have all you need. You are trying to access a JS variable defined in Karate from within a function, this depends on when either was initialized and I don't recommend it if you don't know what you are doing. But if you want to access the latest value of a Karate variable, the right way is to use karate.get(varNameAsString).

Can Karate generate multiple query parameters with the same name?

I need to pass multiple query parameters with the same name in a URL, but I am having problems getting it to work with Karate. In my case, the URL should look like this:
http://mytestapi.com/v1/orders?sort=order.orderNumber&sort=order.customer.name,DESC
Notice 2 query parameters named "sort". I attempted to create these query string parameters with Karate, but only the last "sort" parameter gets created in the query string. Here are the ways I tried to do this:
Given path 'v1/orders'
And param sort = 'order.orderNumber'
And param sort = 'order.customer.name,DESC'
And header Authorization = authInfo.token
And method get
Then status 200
And:
Given path 'v1/orders'
And params sort = { sort: 'order.orderNumber', sort: 'order.customer.name,DESC' }
And header Authorization = authInfo.token
And method get
Then status 200
And:
Given path 'v1/order?sort=order.orderNumber&sort=order.customer.name,DESC'
And header Authorization = authInfo.token
And method get
Then status 200
The first two ways provide the same query string result: ?sort=order.customer.name%2CDESC
The last example does not work because the ? get encoded, which was expected and explained in this post - Karate API Tests - Escaping '?' in the url in a feature file
It's clear that the second "sort" param is overriding the first and only one parameter is being added to the URL. I have gone through the Karate documentation, which is very good, but I have not found a way to add multiple parameters with the same name.
So, is there a way in Karate to set multiple URL query parameters with the same name?
Yes you can generate multiple query parameters with the same name in karate
All values of similar key should be provided in an array.
Given path 'v1/orders'
And params {"sort":["order.orderNumber","order.customer.name,DESC"]}
And header Authorization = authInfo.token
And method get
Then status 200
And for setting single parameter using param it will be like
And param sort = ["order.orderNumber","order.customer.name,DESC"]

Peoplesoft CreateRowset with related display record

According to the Peoplebook here, CreateRowset function has the parameters {FIELD.fieldname, RECORD.recname} which is used to specify the related display record.
I had tried to use it like the following (just for example):
&rs1 = CreateRowset(Record.User, Field.UserId, Record.UserName);
&rs1.Fill();
For &k = 1 To &rs1.ActiveRowCount
MessageBox(0, "", 999999, 99999, &rs1(&k).UserName.Name.Value);
End-for;
(Record.User contains only UserId(key), Password.
Record.UserName contains UserId(key), Name.)
I cannot get the Value of UserName.Name, do I misunderstand the usage of this parameter?
Fill is the problem. From the doco:
Note: Fill reads only the primary database record. It does not read
any related records, nor any subordinate rowset records.
Having said that, it is the only way I know to bulk-populate a standalone rowset from the database, so I can't easily see a use for the field in the rowset.
Simplest solution is just to create a view, but that gets old very soon if you have to do it a lot. Alternative is to just loop through the rowset yourself loading the related fields. Something like:
For &k = 1 To &rs1.ActiveRowCount
&rs1(&k).UserName.UserId.value = &rs1(&k).User.UserId.value;
&rs1(&k).UserName.SelectByKey();
End-for;

Rails 3 after_save old value

How do you work with the old values of a record being updated?
For instance in the following code block how would I run a query using the previous winner_id field after I determine that it has indeed changed?
if self.winner_id_changed?
old_value = self.changed_attributes
User.find(old_value)
#do stuff with the old winner....
end
An example output of self.changed_attributes would be:
{"winner_id"=>6}
Do I really have to convert this to a string and parse out the value in order to perform a query on it? old_value[:winner_id] doesn't seem to do anything.
Use where instead of find, and the following inject method on changes to generate the desired hash:
if self.winner_id_changed?
old_value = self.changes.inject({}) { |h, (k,v)| h[k] = v.first }
old_user = User.where(old_value)
#do stuff with the old user....
end
You can also use ActiveRecord dirty methods such as:
self.winner_id_was
to get specific attribute's old value. Full documentation may be found here.