How to use js EXPR with XML in Karate - karate

I have to modify an xml expression and match it to a json. Below is the code I have written. I need to validate ind is true or false. For this, I cannot use '#boolean' because <ns4:ind>true</ns4:ind> behaves as a string.
XML File:
<ns9:parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns5:parent">
<ns4:ind>true</ns4:ind>
<ns4:description>Some text</ns4:description>
</ns9:parent>
Code:
* def Test = call read ('classpath:Path/Test.xml)
* def Check = $Test/parent
* set Downstream.parent
| path | value |
| ind | '#?_ == "true" || _== "false"' |
| description | $Check/parent/description |
* def Match =
"""
{
"parent": {
"ind": "true",
"description": "Some text"
}
}
"""
* match Match == Downstream
Tried with '#boolean' as well, doesn't work.
| ind | '#boolean' |
I get below error;
com.intuit.karate.exception.KarateException: Test.feature:20 - javascript evaluation failed: '#?_ == "true", <eval>:1:14 Missing close quote '#?_ == "true"

This should work,
* def Test = call read ('classpath:Path/Test.xml')
* def Check = $Test/parent
* xml Downstream = "<parent></parent>"
* def desc = $Check/parent/description
* set Downstream/parent/ind = '#?_ == "true" || _== "false"'
* set Downstream/parent/description = desc
* match $Test/parent/ind == $Downstream/parent/ind
* match $Test/parent/description == $Downstream/parent/description
Note:
set for XML doesn't seem to support table so use inline set.

Related

how to call a feature file to generated a Get request , for each element in an ArrayList or JsonArray ( Created by Java function )

basically I want to achieve below result , where the list used in Examples: is dynamic
Scenario Outline:
def ss = 'https:testingurl/'+ < spaceCode > + 'trailPath';
Given url ss
And header Authorization = autGetToken()
When method get
Then status 200
Examples:
| spaceCode |
| space1|
| spac2|
| spaceAbc05|
| space.o2|
| spacesacc|
| spacere |
So I created one.feture and tried to call it from other feature file
one.feature
Background:
def ss = 'https:testingurl/'+ < spaceCode > + 'trailPath';
Scenario: need to run this scenario for each member of the spaceList ArrayList / JsonArray
Given url ss
And header Authorization = autGetToken()
When method get
Then status 200
* print response
* def count = response.value.length
* print count
* karate.set('total', karate.get('total') + karate.get('count') )
* print total
question
how to run above file for each element of the "spaceList" which is an Java ArrayList, i am creating this ArrayList by calling method getSpaceList()
i have tried to call it from other feature file like below
Method1
caller.feature
Background:
* def total = 0
* def helper = Java.type('shared.Helper')
Scenario Outline: calling other feature file for each element of the spaceList Array
def result = call read('one.feature')
Examples:
| spaceCode |
| helper.getSpaceList() |
Method2
caller.feature
Background:
* def total = 0
* def helper = Java.type('shared.Helper')
* def spaceList = helper.getSpaceList() // this returns around 20 different elements from a sql
Scenario Outline: calling other feature file for each element of the spaceList Array
def result = call read('one.feature')
Examples:
| spaceCode |
| spaceList |
i have also tried karate.forEach and karate.setUp
Try this example. Note how it will make two POST requests. Once you understand this, you should be able to do what you want.
Feature:
Scenario Outline:
* url 'https://httpbin.org/anything'
* request __row
* method post
* status 200
Examples:
| [{ a: 1 }, { a: 2 }] |

Extract and comparing data from json array not working in karate

I am trying to search a certain value in a JSON array using the value stored in a variable and then comparing somehow this is not working for me. Can you please help. BillerId1 is always returning a blank value
Given url buyerApi
Given url paymentHub
Then path '/BPAY/v' + version + '/billers'
And header Authorization = 'Bearer ' + token
When method get
Then status 200
* def id = response[0].savedBillerId
Then url paymentHub
Then path '/BPAY/v' + version + '/billers/' +id
And header Authorization = 'Bearer ' + token
And request {billerCode:<billerCode>, billerCRN:'<billerCRN>'}
When method put
Then status 200
Then url paymentHub
Then path '/BPAY/v' + version + '/billers'
And header Authorization = 'Bearer ' + token
When method get
Then status 200
* print id
* def billId1 = get[0] response[?(#.savedBillerId==**'#id'**)].savedBillerId
* print billId1
And match billId1 == id
Examples:
| billerCode | billerCRN |
| 65284 | 65112345675 |
Array looks like this
[
{
"savedBillerId": "ebfa2b9f-f49c-4b0c-c6ee-08d7e671944a",
"billerId": "26c67edb-b3dc-44ea-aa74-08d7d6890798",
"billerName": "test case 21c",
"billerCode": 65284,
"crn": "65112345675"
},
{
"savedBillerId": "500dfde7-e31c-408d-c6ef-08d7e671944a",
"billerId": "26c67edb-b3dc-44ea-aa74-08d7d6890798",
"billerName": "test case 21c",
"billerCode": 65284,
"crn": "65112345672"
}
]
#ptrthomas
Please read the docs: https://github.com/intuit/karate#jsonpath-filters
* def id = '500dfde7-e31c-408d-c6ef-08d7e671944a'
* def billId1 = karate.jsonPath(response, "$[?(#.savedBillerId=='" + id + "')].savedBillerId")[0]
* match billId1 == id
Also I feel this is a worthless check. You find by id and again check that id ?

Object.keys(data) Js fu not worked when pass Json object as def in Karate 0.9.5.RC5

Js File with following function
function fn(config) {
config.OAuth2 = function (data) {
var keys = Object.keys(data);
return keys;
}
return config;
}
Feature file with following steps
Feature: Sample Feature
Scenario Outline: Sample Scenario
#This is works
* def a = OAuth2({firstName: '<firstName>',lastName: '<lastName>'})
* print a
#This do not work
And def req = {firstName: '<firstName>',lastName: '<lastName>'}
* def b = OAuth2(req)
* print b
Examples:
| firstName | lastName |
| a | a1 |
Giving error at var keys = Object.keys(data);
javascript evaluation failed: OAuth2(req), TypeError: {firstName=a, lastName=a1} is not an Object in <eval>
Please don't use Object.keys() - use karate.keysOf() instead.

Support passing from Scenario Outline to JSON file

I am going to reuse some features and calling multiple features in a Scenario Outline.
Since the features being called are common, we would like to define its parameters in its own parameter file, while the parameter values are defined in placeholder.
We hope the placeholder can get the value from the Outline Examples.
How to make it?
Feature: verify parameter passing
Scenario Outline: verify 2 calls
* def result1 = call read('baseFeature1.feature')
* def result2 = call read('baseFeature2.feature') result1
* print result2
Examples:
| fooValue |
| value1 |
| value2 |
Feature: feature to verify the parameter passing, no input parameter
Scenario: feature 1
Given def payload = read('classpath:feature_1.json')
* print 'feature 1' + payload
Given def result = { "barValue": "barValue"}
Feature: feature to verify the parameter passing, with input parameter from last step
Scenario: feature 2
Given def payload = read('classpath:feature_2.json')
* print payload
feature_1.json
{
"foo": "#(fooValue)"
}
feature_2.json
{
"foo": "fooValue",
"bar": "#(result1.barValue)"
}
I think the version currently in development will make this possible. Can you take a look at this GitHub issue and see if this addresses your question: https://github.com/intuit/karate/issues/717
It will also be great if you can build from source and try this new capability.
Scenario Outline: magic variables with embedded expressions
* def expected = __num == 0 ? { name: 'Bob', alive: false } : { name: 'Nyan', alive: true }
* match expected == { name: '#(__row.name)', alive: '#(__row.alive)' }
* eval karate.set(__row)
# you can read from a re-usable JSON file instead of the line below
* match expected == { name: '#(name)', alive: '#(alive)' }
Examples:
| name | alive! |
| Bob | false |
| Nyan | true |

XML : trouble with fuzzy matching [duplicate]

This question already has an answer here:
Asserting and using conditions for an array response in Karate
(1 answer)
Closed 2 years ago.
I am having troubles with XML matching, which appears to be working a bit differently from JSON.
I found this code snippet
* def xml = <foo><bar>baz</bar></foo>
* set xml/foo/bar = <hello>world</hello>
* match xml == <foo><bar><hello>world</hello></bar></foo>
But with this, I cannot specify that I'm using a template, and that <hello>world</hello> may be present more than once.
Scenario XML 1 is failing, while the others are working.
Scenario: Scenario XML 1
* def response = <response><foo><bar><msg name="Hello"/><msg name="World"/></bar><bar><msg name="Hello"/><msg name="World"/></bar></foo></response>
* def bar = <bar><msg name="Hello"/><msg name="World"/></bar>
* def foo = <response><foo>#[](bar)</foo></response>
* print foo
* print response
* match response == foo
Scenario: Scenario XML 2
* def response = <response><foo><bar><msg name="Hello"/><msg name="World"/></bar></foo></response>
* def bar = <bar><msg name="Hello"/><msg name="World"/></bar>
* def foo = <response><foo>#(bar)</foo></response>
* print foo
* print response
* match response == foo
Scenario: Scenario JSON 1
* def response = {"response": {"foo": [{"bar": [{"msg": "Hello World"},{"msg": "Hello World"}]}, {"bar": [{"msg": "Hello World"},{"msg": "Hello World"}]}]}}
* def bar = {"bar": [{"msg": "Hello World"},{"msg": "Hello World"}]}
* def foo = {"response": {"foo": #[](bar)}}
* print foo
* print response
* match response == foo
Scenario: Scenario JSON 2
* def response = {"response": {"foo": {"bar": [{"msg": "Hello World"},{"msg": "Hello World"}]}}}
* def bar = {"bar": [{"msg": "Hello World"},{"msg": "Hello World"}]}
* def foo = {"response": {"foo": #(bar)}}
* print foo
* print response
* match response == foo
How can I have Scenario XML 1 working?
I admit this can be considered a gap. The fact that XML repeated elements are so different from JSON doesn't help. The best I could do is this:
* def response = <foo><bar><msg name="Hello"/><msg name="World"/></bar><bar><msg name="Hello"/><msg name="World"/></bar></foo>
* def bar = <bar><msg name="Hello"/><msg name="World"/></bar>
* def foo = <foo>#ignore</foo>
* match response == foo
* match /foo/bar/msg[1]/#name == ['Hello', 'Hello']
* def names = $response/foo/bar/msg[1]/#name
* match each names == 'Hello'
Feel free to submit a feature request and suggest based on your experience with JSON what the ideal syntax should look like.
EDIT: thought about it a little and realized because of how Karate converts XML into JSON-like data internally, you have this option.
* json response = <response><foo><bar><msg name="Hello"/><msg name="World"/></bar><bar><msg name="Hello"/><msg name="World"/></bar></foo></response>
* json bar = <bar><msg name="Hello"/><msg name="World"/></bar>
* match each response.response.foo.bar == bar.bar
* match response == { response: { foo: { bar: '#[] bar.bar' } } }
I know it may be a little hard to understand, but will work :) I was looking at the code right now, and because of how involved the JSON matching is - it is unlikely to get re-factored to support XML repeated elements.
EDIT2: actually we made a fix now so this should be possible also:
* match response == <response><foo><bar>#[] bar.bar</bar></foo></response>
https://github.com/intuit/karate/issues/653