Karate expression to check if value exists in array - karate

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 :)

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

Send a second request nb of times as nb of items returned for first request using 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

karate doesn't match xml obtained from function

I have to verify an XML fragment obtained from a function, but matches fails also when should.
To explain my needs, i have to test a web service that in response sends a soap message containing into the body an xml fragment encoded in base64. In my karate test i decode that fragment with a function and verify it with a fuzzy match, but every match fails also when good.
I made a test where the XML 'A' is explicity defined and the XML 'B' is obtained from a function where A == B. Then i define a XML 'C' that should match both, but instead matches only the one explicity defined.
Feature:
Background:
* def buildXml =
"""
function(param){
return '<root><hello>world</hello><foo>bar</foo></root>';
}
"""
Scenario:
* def a = <root><hello>world</hello><foo>bar</foo></root>
* def b = buildXml()
* def c =
"""
<root>
<hello>world</hello>
<foo>#ignore</foo>
</root>
"""
* match a == b
* match a == c
* match b == c
Last match fails, but should pass.
Just one small change, and you are good:
* xml b = buildXml()
Reason: https://github.com/intuit/karate#type-conversion

Can I run example in scenario outline for n times?

I want to run examples for n times , n is the length of data of getHotelid.
Feature: match rates from ds api to pricing api.
Background:
* url ''
Scenario Outline: Calling production assert feature file.
* def DbNew = Java.type('DbNew')
* def dq = new DbNew()
* def activeHotels = <ds_hotel_id>
* def hotel_id = call read('StringConverter.js') { activeHotels:'#(activeHotels)'}
* print hotel_id
Examples:
|dq.getHotelid()|
This is look a like Karate - Not able to run dynamic scenario outline in a loop
Your Examples should be as below,
Examples:
|dq.getHotelid()|
please read this documentation : Karate dynamic scenario

Dynamically set a XML tag value while building payload

I am trying automate testing using Karate.
I have a XML payload.
I have a static XML payload which I am readying from a file and I want to call my service in loop.
For each call I would like to replace value for a tag name dynamically.
How would I achieve this?
e.g.
Below is my Main Feature which calls my common feature in loop
Feature: Loop Call
Background:
* def common = call read('classpath:CommonFeatures.feature')
Scenario:
* table table
| payload_file | field_tag | field_value |
| 'HappyPath.xml' | 'car_fuel' | 'Gas' |
| 'HappyPath.xml' | 'car_color'| 'Red' |
* def response = call read('classpath:Car.feature') table
Car.feature
Feature: Common
Scenario:
* print payload_file
* print field_tag
* print field_value
* xml payload = read('classpath:/payload/'+payload_file)
* print payload
* set payload/$field_tag = field_value
This is where I have issue setting the field_tag value.
I have other option to do this like writing a small java script method to replace the tag value or a small java class which use DOMParser or SAXParser to perform the same.
However I would like to know if there is any karate in build way to perform the same.
Also while using java script method to replace the tag value if I am using var parser = new DOMParser(); and it seems DOMParser is not available to use. Is there a way to make this available?
I think if you go through this sample, it will answer all your questions:
https://github.com/intuit/karate/blob/master/karate-junit4/src/test/java/com/intuit/karate/junit4/xml/xml.feature
For example this is how you can substitute values, as well replace a whole chunk of XML (which can include tags) using the set keyword:
Scenario: set xml chunks using xpath
* def req = read('envelope1.xml')
* def phone = '123456'
* def search =
"""
<acc:getAccountByPhoneNumber>
<acc:phoneNumber>#(phone)</acc:phoneNumber>
</acc:getAccountByPhoneNumber>
"""
* set req /Envelope/Body = search
* match req ==
"""
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:acc="http://foo/bar">
<soapenv:Header />
<soapenv:Body>
<acc:getAccountByPhoneNumber>
<acc:phoneNumber>123456</acc:phoneNumber>
</acc:getAccountByPhoneNumber>
</soapenv:Body>
</soapenv:Envelope>
"""
And please don't think of using DOMParser etc, you will be able to do anything you need via Karate syntax.
Thanks to Peter for all help and the examples.
I feel this is the best way to achieve this.
Wrote a small javascript function
"""
* def replaceTag =
"""
function(x){
karate.setXml('temp', x.payload);
karate.pretty(karate.get('temp'));
if (x.field_tag) karate.set('temp', x.field_tag, x.field_value);
return karate.get('temp');
}
"""
and calling the same from Car.feature like below and I get the dynamically replaced payload.
Feature: Common
Scenario:
* print payload_file
* print field_tag
* print field_value
* xml payload = read('classpath:/payload/'+payload_file)
* print payload
* def args = { payload: #(payload), field_tag: #(field_tag), field_value: #
(field_value)}
* print args
* xml payload = call common.replaceTag args
Note: I had to upgrade Karate 0.7.0 version in order to use karate.setXml method.