Can Karate generate multiple query parameters with the same name? - karate

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"]

Related

Karate Gatling report - is it possible to avoid url based aggregation?

I just started to use Karate Gatling for performance tests and facing following problem:
I have a call for the search and would like to evaluate different types of search depending on the parameter e.G. https://example.com/search/facetedSearch
'*'
'keyword1'
'keyword1, keyword2' etc.
The feature file looks something like this:
#performance
Feature: Search
Background:
* url 'https://example.com/'
Scenario Outline: Search -> Simple search for a single word
Given path '/search/facetedSearch'
And param facetedSearchAdditionalFilter[searchAreaID] = -1
And param facetedSearchAdditionalFilter[searchKey] = '<SearchTermSimple>'
When method post
Then status 200
And assert iNumHits >= iNumHitsExpected
Examples:
| read('../testData/performanceTestData.csv') |
Scenario: Search -> Simple search for *
Given path '/search/facetedSearch'
And param facetedSearchAdditionalFilter[searchAreaID] = -1
And param facetedSearchAdditionalFilter[searchKey] = '*'
When method post
Then status 200
And assert iNumHits >= iNumHitsExpected
Scenario Outline: Search -> Search for multiple words
Given path '/search/facetedSearch'
And param facetedSearchAdditionalFilter[searchAreaID] = -1
And param facetedSearchAdditionalFilter[searchKey] = '<SearchTermMultiple>'
When method post
Then status 200
And assert iNumHits >= iNumHitsExpected
Examples:
| read('../testData/performanceTestData.csv') |
I would like to evaluate different types of search separately, as the performance is significantly different. What gatling does - it aggregates all different types of search in one result - "POST /search/facetedSearch".
Is there a possibility to let evaluate every type of search individually in one run?
Thanks in advance,
Sergej
Yes, refer the docs on using a custom nameResolver: https://github.com/karatelabs/karate/tree/master/karate-gatling#nameresolver
For your case you should be able to call req.getParam("facetedSearchAdditionalFilter[searchKey]")[0] or something similar. Or you could choose to use an additional header.

Karate - want to get url along with query params in a variable

Karate version - 1.0.0
I want to get the queryparams and url and want to concat it and save it to a variable.. I'm using following syntax which doesn't work. when I use param in variable it says param not defined. Does anyone have any work around for this?
When I use the following -
Given path '/test/1'
And param product = "abc"
And param country = "usa"
* print param
org.graalvm.polyglot.PolyglotException: ReferenceError: "param" is not defined
How do I concat url and param and get in a variable.
Many thanks!
Following is the example with the corresponding request url & query params for which you can execute this scenario to get the response and GET Request as,
Scenario: Sample File
* def ScenarioEngine = Java.type('com.intuit.karate.core.ScenarioEngine');
Given url 'https://reqres.in'
And path '/api/users'
And param page = 2
And param pages = 1
When method get
And print ScenarioEngine.get().getRequest().getUrl()
For which the response would be printed along with the GET url and query param as,
[print] https://reqres.in/api/users?pages=1&page=2

Karate : passing value as query parameter from one response if that value is not null

i have one response as below
"data":{"books":{"isbn":"97895113132","Bookid":10196333}}
sometimes i will get Bookid as null.
my question is, i have to take this bookid only if it is not null, and then pass to next api as query parameter.
please help to find the solution for this using karate framework
Easy, if you use the params keyword, any value of null is not sent as a param. You can try this:
* def temp = null
Given url 'http://httpbin.org'
And path 'get'
And params { foo: '#(temp)' }
When method get
Then status 200
If you are looking for conditional-logic - please read: https://github.com/intuit/karate#conditional-logic

send array of URL param via karate api

does karate support send an array of parameter in URL param as one of my API was working as this way. Below was one of my API test url concept. It working fine when i do manually on postman. Not sure whether karate support this kind of format or not.
https<URL>?param={"firstname":"XXX","lastname":"XXX"....}
i have tried with param and params. however params will give me & instead of ,. while in param , it will show ?param=%7B%firstname%22%3A%22abc...
Karate can support it, I am still not clear what your request is from your question but let me try. Note that as per the HTTP spec - some special characters WILL be URL-encoded.
Try these:
And param param = '{"firstname":"XXX","lastname":"XXX"}'
And param firstName = ['XXX', 'XXX']
See this demo example for more ideas: params.feature
EDIT: if you need to create dynamic JSON that is possible, please read the docs for the set keyword. And below the JSON is being converted to a string - because that is what it looks like from your description (which I really doesn't make sense to me)
* set data
| path | value |
| firstName | 'XXX' |
| lastName | 'XXX' |
* string data = data
* param param = data

Default values for query parameters

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.