Replace Json key in Karate [duplicate] - karate

This question already has an answer here:
Karate API function/keyword to substitute JSON placeholder key with argument passed
(1 answer)
Closed 1 year ago.
I need to send a Json to an endpoint but I need to replace a key with a variable.
I've this code
.....
* def idJson = response.id
Given path <mypath>
And headers {Authorization: '#(auth)'}
And request read('classpath:myjson.json')
.....
The myjson.json file is
{
"a":
{
...
"b":false,
"c":true
},
"d":
{
'#(idJson)':
{
"Key":[
.....
]
}
}
}
But the value is not replace in the json. When I perform the request I see that the json contains the string '#(idJson)' instead of the value of the variable. Any idea about how to solve this?
Thank you

Embedded expressions cannot be used to modify a JSON key. You have to use a JS operation like this:
* def idJson = 'foo'
* def body = {}
* body[idJson] = 'bar'
* url 'https://httpbin.org/anything'
* request body
* method post
* status 200
* match response.json == { foo: 'bar' }
Note that d could be replaced like this so you can still read the file and be dynamic:
{ "d": "#(temp)" }
And temp can be JSON that is defined in your feature before reading the file.
If this is too troublesome, please contribute code :)

Related

Karate API Converting String from JSON Response into UPPERCASE [duplicate]

This question already has an answer here:
How to extract value in double quotes from a response header in karate
(1 answer)
Closed 1 year ago.
JSON Response has __typename in the response.
I am defining and storing it so I can use this in the next graphQL Request
def contentType1 = response.data.getPublicList.items[0].__typename
__typename comes back as "Movie"
The next Request requires "Movie" to be "MOVIE"
query {
getContentById(id: "", contentType: "MOVIE") {
Is there a way I can convert/define the entire string value as UPPERCASE?
That should be easy, behind the scenes it is a "Java" string, so there are methods you can use:
* def contentType1 = 'Movie'
* def after = contentType1.toUpperCase()
* match after == 'MOVIE'
EDIT: If you want to convert "in place", just do JS-style operations:
* def data = { foo: 'bar' }
* data.foo = data.foo.toUpperCase()
* match data == { foo: 'BAR' }
If you need more sophistication, please look at the docs for JSON transforms: https://github.com/karatelabs/karate#json-transforms

How to get the value of JSON element having # in the name in Karate [duplicate]

This question already has an answer here:
Get json value with hyphen from response
(1 answer)
Closed 1 year ago.
This is my json response
{
"meta": {
"type": "event-search",
"#href": "https://<ip>:<port>/SentinelRESTServices/objects/event-search/10c21c52229bfe0545BD7802A74E10398534005056869AAA"
}
}
I want to get the value for #href.
When i print meta.type I am able to get the value 'event-search', but same doesn't work for #href.
I tried to escape it using \\ (meta.\\#href) but i got empty value.
Is there a way to escape # and fetch the value?
Please help!!
Please use the square-bracket JS approach to extract nested properties when there are special characters in the key-names.
Example:
* def response = { meta: { '#href': 'foo' } }
* match response.meta['#href'] == 'foo'

Karate - String concatenation of JSON value with a variable [duplicate]

The embedded expressions are not replaced when appended, prepended or surrounded by characters in the following simplified and very basic scenario:
* def jobId = '0001'
* def out =
"""
{
"jobId": "#(jobId)",
"outputMetadata": {
"fileName_OK": "#(jobId)",
"fileName_Fail_1": "some_text_#(jobId)",
"fileName_Fail_2": "#(jobId)-and-some-more-text",
"fileName_Fail_3": "prepend #(jobId) and append"
}
}
"""
* print out
Executing the scenario returns:
{
"jobId": "0001",
"outputMetadata": {
"fileName_OK": "0001",
"fileName_Fail_1": "some_text_#(jobId)",
"fileName_Fail_2": "#(jobId)-and-some-more-text",
"fileName_Fail_3": "prepend #(jobId) and append"
}
}
Is it a feature, a limitation, or a bug? Or, did I miss something?
This is as designed ! You can do this:
"fileName_Fail_2": "#(jobId + '-and-some-more-text')"
Any valid JS expression can be stuffed into an embedded expression, so this is not a limitation. And this works only within JSON string values or when the entire RHS is a string within quotes and keeps the parsing simple. Hope that helps !

Can i override path in feature file for a test called from another file [duplicate]

I am trying to follow the examples in the demo:
https://github.com/intuit/karate/tree/master/karate-demo/src/test/java/demo/callfeature
I need to do a call from one feature to another, and pass a reference to update. The reference is for a JSON that is read from a file:
Background:
* url url
* header Authorization = token
* def payload = read('event.json')
* set payload.createdByUser = 'karate'
Scenario: Call another feature with arg
* call read('classpath:common/swap-json-elements.feature') payload
* print payload
Inside my swap-json-elements.feature:
Background:
* set new = payload.old
* set payload.new= payload.old
* set payload.old= new
This is not working. It is clear in the documentation that a shared scope is shared when we 'set' is used, while 'def' will create a new variable, and never update the shared one.
What am I missing ?
If you pass an argument, it is passed by value. When you call with "shared scope" you typically don't need to pass arguments. Because all variables are visible anyway. Try a simpler example, and please watch white-space around the = sign.
main.feature:
Feature:
Background:
* def json = { foo: 'bar' }
* call read('called.feature')
Scenario:
* match json == { foo: 'baz' }
called.feature
Feature:
Scenario:
* set json.foo = 'baz'
* match json == { foo: 'baz' }

Karate doesn't check cases if expected number is a larger, how do I handle it?

I have given match response as #number
But for a value of 15547786385661 the case just gets skipped.how do I handle it?
You must be making some simple mistake. Try pasting the two lines below into a fresh scenario and see it work:
* def response = { foo: 15547786385661 }
* match response == { foo: '#number' }