Send a second request nb of times as nb of items returned for first request using Karate - karate

I need to send 2 requests in a Scenario Outline. Ex:
Background:
* url 'someurl'
Scenario Outline:
* path <owner_id>, 'cats'
* method get
* status 200
here I need to get ids of cats from response as {"cats": [{"cat_id": "xx"}, {"cat_id": "yy"}...]}
* path <owner_id>, <cat_id>, 'kittens'
* method get
* status 200
Examples:
|owner_id|
|bill_id |
|kate_id | and so on
Is it possible to send the second request (kittens' retrieving) for each cat_id from the first request and this for each owner_id?
I tried another way:
Background:
* url 'someurl'
Scenario Outline:
* def cats = call read('GetCats.feature')
then store cat_ids as here:
* def catsIds = cats.c[*].id (I get an error "javascript evaluation failed: cats.c[*]id, <eval>:1:6 Expected an operand but found *")
OR
* def catsIds = karate.mapWithKey(cats.c[*].id, 'cat_id')
* path <owner_id>, <cat_id>, 'kittens'
* method get
* status 200
Examples:
|owner_id|
|bill_id |
|kate_id | ...
And here is GetCats.feature
Scenario:
* url 'someurl'
* path 'cats'
* method get
* status 200
* def c = response
I was thinking about karate.repeat but can we use it for this case?

Anything is possible, you can call other features, all data is in scope etc.
You made a mistake here, note the $:
* def catsIds = $cats.c[*].id
Refer: https://github.com/intuit/karate#get

Related

Calling common scenario from another scenario in same feature file where request body is store in json file in karate [duplicate]

This question already has an answer here:
how to dynamically set an value in json read from file in Karate
(1 answer)
Closed 1 year ago.
I am a bit confused and need some clarify on this
Background:
* def successBody = 'util/successRequestBody.json'
#test1 #ignore
Scenario: Verify user
Given url
* def id = id
* def requestBody = read (successBody)
And request requestBody
When method post
Then status 201
#test2
Scenario: First create new user and then delete same user
* def id = '123'
# First call POST user to create a new user
* def postuser = call read('user.feature#test1') {id: id}
Given url
When method delete
Then status 204
I am providing value in request body for creating new user like this in successRequestBody.json
{
"id": "#(id)",
"name": "abc"
}
The above doesn't work. But when I provide like this it works. Please guide how the parameters should be passed in calling a feature from another. I am passing variable name id from test2 while calling test1 but in test1 it is reading id1 not id? Can someone please explain?
Background:
* def successBody = 'util/successRequestBody.json'
#test1 #ignore
Scenario: Verify user
Given url
# I am setting variable name id from test2 but here it is reading id1 not id?
* def id = id1
* def requestBody = read (successBody)
And request requestBody
When method post
Then status 201
#test2
Scenario: First create new user and then delete same user
* def id1 = '123'
# First call POST user to create a new user
* def postuser = call read('user.feature#test1') {id: id1}
Given url
When method delete
Then status 204
The call syntax is wrong, you have to use embedded expressions:
* def postuser = call read('user.feature#test1') { id: '#(id1)' }
Here's a tip. It is not mandatory to pass parameters. Variables in the "caller" will be visible to the "called" feature. This below has the same effect as above.
* def id = id1
* def postuser = call read('user.feature#test1')
Please read the documentation and examples carefully. If still stuck, follow this process: https://github.com/karatelabs/karate/wiki/How-to-Submit-an-Issue

Scenario Outline for json in feature with Karate

Is it possible to use Scenario Outline as in this mode (which is really great!!):
Scenario Outline:
* print 'hello <name>'
Examples:
| (read('cats.json')) |
but with a json or a list in Background? Ex:
Background:
* json temp = cats_ids (ids that I get from an external job as here [111,222,333...])
or
* def temp = cats_ids
Scenario Outline:
* path id from temp
* method get
...
Examples:
| temp |
Yes, please look at karate.mapWithKey() explained here: https://github.com/intuit/karate#json-transforms
* def temp = karate.mapWithKey(cats_ids, 'id')
Scenario Outline:
* print id

How can I set base API? I see double quotes getting added from the first API's response

Given path '/api/metrics/product/ABC'
When method get
* def id = get response
* print id
* def basePathProducts = '/another/api/' + id + '/param'
Given path basePathProducts
When method GET
Then status 200
12:59:28.447 [main] INFO com.intuit.karate.StepDefs - [print] "5ca627bf3edd851238e59c9e" Apr 16, 2019 12:59:28 PM org.glassfish.jersey.logging.LoggingInterceptor log SEVERE: 2 * Sending client request on thread main 2 > GET
http://localhost:8080/API/ANOTHER/API/%225ca627bf3edd851238e59c9e%22/PARAM
I think you are overcomplicating things and you missed that the path syntax is designed for what you commonly need to do.
Don't def basePathProducts and do this, see how the id variable can be easily plugged into a path:
Given path 'another', 'api', id, 'param'
Your post is really hard to comprehend.
Try using
Given url yourURLVariable + 'another/api/'+ id + '/param'
Refer to this for more information : https://stackoverflow.com/a/54477346/10791639
Edit :
There is a problem with your parameter.
* def id = "5ca627bf3edd851238e59c9e"
* print id
Gives :
13:24:19.783 [print] 5ca627bf3edd851238e59c9e
So your variable id is "5ca627bf3edd851238e59c9e" instead of 5ca627bf3edd851238e59c9e
* def newresp = function(id){ return id.slice(1, -1); }
* def id = newresp(response)
I added these to remove the first and last characters from the response which is the double quotes in my case. Thanks for responding guys!

Karate expression to check if value exists in array

Here is my sample feature file:
Feature: Karate expression to check if status within array of status.
Scenario: Test
* def status = "ACTIVE"
* def possibleStatus = ["ACTIVE", "INACTIVE"]
* match status contains possibleStatus ?
Is there a way to check if status is either ACTIVE or INACTIVE using karate expression ?
NOTE: It can definitely be achieved by writing custome JS function.
This is an easy one.
* def status = "ACTIVE"
* def possibleStatus = ["ACTIVE", "INACTIVE"]
* match possibleStatus contains status
Any questions :)

How to get id in responseHeaders location?

For my POST request, in responseHeaders I get 1 < location: /users/123
I would like to print only the id > 123.
When I do * print responseHeaders['location'][0] in my feature file, I get users/123. How I can get only the id?
This is not really a Karate question is it :P
Try this:
* def location = responseHeaders['location'][0]
* def userId = location.substring(location.lastIndexOf('/') + 1)
* print userId
That's right, all the power of JavaScript (or even Java via Java interop) is available to you in Karate !