Error as "String index out of range: -1" with set keyword in Karate - karate

Below is the code snippet for which I am getting an error.
* def json = {"test" : { "data.a":'value',"data.b":'value2' }}
* print json.test["data.a"] // This line is working getting value 'value'
* set json.tes["data.a"] = 'hello' // This line is failing with error "String index out of range: -1
Response:
[java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1967)
at com.intuit.karate.JsonUtils.setValueByPath(JsonUtils.java:257)
at com.intuit.karate.Script.setValueByPath(Script.java:1519)
at com.intuit.karate.Script.setValueByPath(Script.java:1489)
at com.intuit.karate.Script.setValueByPath(Script.java:1479)
at com.intuit.karate.StepDefs.setNamedByPath(StepDefs.java:572)
at com.intuit.karate.StepDefs.setByPath(StepDefs.java:562)
at ✽.* set json.tes["data.a"] = 'hello' // This line is failing with error "String index out of range: -1
Not able to set value for "data.a" dynamically using SET keyword.
Please help.

This seems to be very badly designed JSON. Make a small change, use eval:
* eval json.test["data.a"] = 'hello'

Related

Karate Api : check if a phrase is available response object array

I've a response
{ errors: [
{
code: 123,
reason: "this is the cause for a random problem where the last part of this string is dynamically generated"
} ,
{
code: 234,
reason: "Some other error for another random reason"
}
...
...
}
Now when I validate this response
I use following
...
...
And match response.errors[*].reason contains "this is the cause"
This validation fails, because there is an equality check for complete String for every reason ,
I all I want is, to validate that inside the errors array, if there is any error object, which has a reason string type property, starting with this is the cause phrase.
I tried few wild cards but didn't work either, how to do it ?
For complex things like this, just switch to JS.
* def found = response.errors.find(x => x.reason.startsWith('this is the cause'))
* match found == { code: 123, reason: '#string' }
# you can also do
* if (found) karate.log('found')
Any questions :)

Mule 4, get uri params with Anypoint application

I'm new in Mulesoft, I'm following Quickstart guide. In Step 2 (https://developer.mulesoft.com/guides/quick-start/developing-your-first-mule-application), I need to receive variables from URI in this way:
[{'id' : attributes.uriParams.productId}]
But when I try my GET I have the following error in console:
**Message : "Cannot coerce Array ([{id: "2" as String {class: "java.lang.String"}}]) to Object 1| [{'id' : attributes.uriParams.productId}] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Trace: at main (line: 1, column: 1)" evaluating expression: "[{'id' : attributes.uriParams.productId}]". Error type : MULE:EXPRESSION Element : get:\products(productId):test_daniel-config/processors/1 # test6_db_connection:test_daniel.xml:133 (Select) Element XML : SELECT product.,CONCAT('["', (GROUP_CONCAT(variant.picture SEPARATOR '","')),'"]') AS pictures,CONCAT('[', GROUP_CONCAT('{"',variant.identifierType, '":"', variant.identifier, '"}'),']') AS identifiersFROM product INNER JOIN variant ON product.uuid = variant.productUUIDWHERE product.uuid = :id; #[[{'id' : attributes.uriParams.productId}]] *
Any Ideas? Thanks!
cannot coerce Array to object error pop's up when you are using an array where you were supposed to use an object.
in the exception above the uri-param should be treated as ab object i.e. enclosed in {} but its being treated as an array of objects [{}].
this is causing the error.

Calling karate feature with variable

In karate you can call feature by sending json/list & map. There are multiple ways I have tried to send the value and use it in the called feature but it throws error
For example:
Error thrown : path: $, actual: '', expected:
'30e093da-c4e3-4ee0-b180-e5d0b4302d9f', reason: not a sub-string
Step:* call read('Logcheck.feature') {requestId : "#(responseHeaders['request-id'][0])"}
In the logCheck feature I am trying to get requestId by using #(requestId)
Logcheck feature Step
* def resultFromServiceLog = utils.getResultFromLog(baseUrl,'#(requestId)','service')
I have tried another approach where I have assigned it to
* def x = {requestId : responseHeaders['request-id'][0]}
* call ('logcheck.feature;) x
Another approach where I will send the json
* json req = {requestId : "#(responseHeaders['request-id'][0])"}
* call read('logcheck.feature') req
Step for logcheck.feature
* print req
* def resultFromServiceLog = utils.getResultFromLog(baseUrl,'#(requestId)','service')
For example:
Error thrown : com.intuit.karate.exception.KarateException:
javascript evaluation failed: utils.getResultFromLog(baseUrl,'#>
(requestId)','service'), null
print req output is
[print] {"requestId": "c996f752-c288-40c7-9398-c913254971e6"}
You need to be clear about using embedded expressions, please read the docs again: https://github.com/intuit/karate#rules-for-embedded-expressions
For example this is wrong:
* def resultFromServiceLog = utils.getResultFromLog(baseUrl,'#(requestId)','service')
Instead:
* def resultFromServiceLog = utils.getResultFromLog(baseUrl, requestId, 'service')
And this is wrong:
* call ('logcheck.feature') x
You probably meant:
* call read('logcheck.feature') x

Getting an invalid token on an interpolated string sent from python/jinga2 backend

I'm sending a variable called apiID from a tornado/jinja2 python file to my vuejs template like this:
class SmartAPIUIHandler(BaseHandler):
def get(self, yourApiID):
doc_file = "smartapi-ui.html"
dashboard_template = templateEnv.get_template(doc_file)
dashboard_output = dashboard_template.render(apiID = yourApiID )
self.write(dashboard_output)
then in vuejs I'm interpolating the variable with no problem except it gives me an error
it says: Uncaught SyntaxError: Invalid or unexpected token
I checked on the python handler file and apipID is a string, so I don't see the problem. I'm quite new to python so maybe the answer is more obvious to one of you. I appreciate the help!!
Because of dashboard_output = dashboard_template.render(apiID = yourApiID ), you must have, in your template, something around the code:
this.apiID = {{ apiID }};
Due to the value being not a number but a string, add the 's:
this.apiID = '{{ apiID }}';

How can I signal parsing errors with LPeg?

I'm writing an LPeg-based parser. How can I make it so a parsing error returns nil, errmsg?
I know I can use error(), but as far as I know that creates a normal error, not nil, errmsg.
The code is pretty long, but the relevant part is this:
local eof = lpeg.P(-1)
local nl = (lpeg.P "\r")^-1 * lpeg.P "\n" + lpeg.P "\\n" + eof -- \r for winblows compat
local nlnoeof = (lpeg.P "\r")^-1 * lpeg.P "\n" + lpeg.P "\\n"
local ws = lpeg.S(" \t")
local inlineComment = lpeg.P("`") * (1 - (lpeg.S("`") + nl * nl)) ^ 0 * lpeg.P("`")
local wsc = ws + inlineComment -- comments count as whitespace
local backslashEscaped
= lpeg.P("\\ ") / " " -- escaped spaces
+ lpeg.P("\\\\") / "\\" -- escaped escape character
+ lpeg.P("\\#") / "#"
+ lpeg.P("\\>") / ">"
+ lpeg.P("\\`") / "`"
+ lpeg.P("\\n") -- \\n newlines count as backslash escaped
+ lpeg.P("\\") * lpeg.P(function(_, i)
error("Unknown backslash escape at position " .. i) -- this error() is what I wanna get rid of.
end)
local Line = lpeg.C((wsc + (backslashEscaped + 1 - nl))^0) / function(x) return x end * nl * lpeg.Cp()
I want Line:match(...) to return nil, errmsg when there's an invalid escape.
LPeg itself doesn't provide specific functions to help you with error reporting. A quick fix to your problem would be to make a protected call (pcall) to match like this:
local function parse(text)
local ok, result = pcall(function () return Line:match(text) end)
if ok then
return result
else
-- `result` will contain the error thrown. If it is a string
-- Lua will add additional information to it (filename and line number).
-- If you do not want this, throw a table instead like `{ msg = "error" }`
-- and access the message using `result.msg`
return nil, result
end
end
However, this will also catch any other error, which you probably don't want. A better solution would be to use LPegLabel instead. LPegLabel is an extension of LPeg that adds support for labeled failures. Just replace require"lpeg" with require"lpeglabel" and then use lpeg.T(L) to throw labels where L is an integer from 1-255 (0 is used for regular PEG failures).
local unknown_escape = 1
local backslashEscaped = ... + lpeg.P("\\") * lpeg.T(unknown_escape)
Now Line:match(...) will return nil, label, suffix if there is a label thrown (suffix is the remaining unprocessed input, which you can use to compute for the error position via its length). With this, you can print out the appropriate error message based on the label. For more complex grammars, you would probably want a more systematic way of mapping the error labels and messages. Please check the documentation found in the readme of the LPegLabel repository to see examples of how one may do so.
LPegLabel also allows you to catch the labels in the grammar by the way (via labeled choice); this is useful for implementing things like error recovery. For more information on labeled failures and examples, please check the documentation.