Escape response in karate framework [duplicate] - karate

For some reason a variable with a / character get converted to a \/, how do I prevent this?
I start a echo server that listens on localhost:3000 by running npx http-echo-server
I execute the following:
code:
* def CHALLENGE_USER = '/abc/user'
* def loginJson = { user: '#(CHALLENGE_USER)' , name: 'Some Name'}
* print loginJson
* def TEST_URL = 'http://localhost:3000'
Given url TEST_URL+'/session/loginresponse'
And header Content-Type = 'application/json'
And request loginResponseJson
And method put
Then status 200
It prints { "user": "/abc/user", "name": "Some Name" } like I expect.
The http server logs show "--> {"user":"/schemes/ATT_5_55/CH_1","name":"Some Name"}"
Karate shows the result of the echo {"user":"\/abc\/user","name":"Some Name"}
I have tried:
def CHALLENGE_USER = '/abc/user'
def CHALLENGE_USER = "/abc/user"
def CHALLENGE_USER = '/abc/user'
def CHALLENGE_USER = '//abc//user'
also setting the variable after the fact does not work:
* def loginJson = { name: 'Some Name'}
* loginJson.user = CHALLENGE_USER

Yes this is legal as per the JSON spec: JSON: why are forward slashes escaped?
And the Java libraries we use does that.
Does your server have a problem ? If so - then you have a bug that Karate surfaced.
And if you really want to have full control over the request, please use text but IMO it may be a waste of time: https://stackoverflow.com/a/68344856/143475

A nasty workaround, please forgive me Peter Thomas.
You can convert the json to a string and then remove the \ characters.
I only have one use case for this thank goodness.
* def CHALLENGE_USER = '/abc/user'
* def loginJson = { user: '#(CHALLENGE_USER)' , name: 'Some Name'}
* string json = loginJson
* def loginJsonText = json.replaceAll("\\", "")
* print loginJson
* def TEST_URL = 'http://localhost:3000'
Given url TEST_URL+'/session/loginresponse'
And header Content-Type = 'application/json'
And request loginJsonText
And method put
Then status 200

Related

How to traverse through a Json in Karate

I am trying to have a Karate test where I need to traverse through a json to get the required test data.
I have the below json.
{
"dev":{
"scenario1":{
"data":"data1"
},
"scenario2":{
"data":"data2"
}
},
"qa":{
"scenario1":{
"data":"data1"
},
"scenario2":{
"data":"data2"
}
}
}
Below is my feature file.
Background:
* def env = dev
Scenario:
* Given url someurl
* def inputData = testdata.env.scenario1.data
* And request { input: '#(inputData)'}
* When method post
* Then status 200
I need the test data that matches the value env that I have defined above.
How can I set the json path to my input data. Basically, the json path should take the value from a variable I have defined previously.
For this you don't even need Json-Path, just JS will do:
* def data = { foo: 1, bar: 2 }
* def env = 'bar'
* def res = data[env]
* match res == 2
Also see: https://stackoverflow.com/a/59162760/143475
You can also do dynamic Json-Path, see: https://stackoverflow.com/a/50855425/143475

Set dynamic data for requestBody

I am unable to read request body while running a feature file:
Details:
user.json contains:
{"userId": "", "user": { "userName": "" }}
I am setting these values to some random data generation using func:
util -> common-utilis.featurefunction() {return Java.type('util.Utilities').generateRandomString(4);}
Feature file to set up random values:
setupData.feature
Feature: Set random dataScenario: Set data* def requestBody = read('classpath:../template/user.json')
#random data generation
* set requestBody.userId = "User_ID" + "_" + randomString()
* set requestBody.user.userName = "UserName" + "_" + randomString()
set up header details in seperate feature file:
header.featureFeature: Run Check
Scenario: Run Check* url BASE_URLGiven path 'user'And header Content-Type = 'application/json'And request requestBodyWhen method post
Scenario file:
userTest.feature
Feature: As a user, I want user service to support async call
Background: Setup
* def requestBody = callonce read('../template/setupData.feature')
* print requestBody
* def result = callonce read('../header.feature')
* print result
* def response = result.response
* def responseHeaders = result.responseHeaders
Scenario: Successful response for a request
Then assert result.responseStatus == 200
What I tried so far:
I ran setupData.feature and can see system creates request body with random data successfully
I ran userTest.feature but system is displaying extra {} set
here is o/p while executing my feature file: (request body)
{"requestBody": {"userId": "User_Id_CsmY","user": {"userName": "UserName_PNKP"}}}
I can see extra {} and requestBody text
Not sure why these extra things are populated

Karate websocket send request body replace token failed

I am using karate to test websocket, this worked:
Background:
* def token = TOKEN
* def handler = function(msg){ return msg.startsWith('a[')}
* def socket = karate.webSocket(WS_HOST + 'socket/761/f4t0so3p/websocket', handler)
Scenario: Demo Real
checking dcube-dev
* socket.send('{"type":"1ffe4b5d___AC_GET_MY_AVAILABLE_TASKS___N","token": "myhardcodedtoken","content":{"msg":null,"counter_api_enabled":false}}')
You can see here, I am hard coding the token inside the request body, not good, so I tried to move it out and use environment token instead as below:
Background:
* def token = TOKEN
* def handler = function(msg){ return msg.startsWith('a[')}
* def socket = karate.webSocket(WS_HOST + 'socket/761/f4t0so3p/websocket', handler)
Scenario: Demo Real
checking dcube-dev
* def body = {"type": "1ffe4b5d___AC_GET_MY_AVAILABLE_TASKS___N", "token": '#(token)', "content": {"msg":null,"counter_api_enabled":false} }
* print "Body:", body
* socket.send( '#(body)')
But this is always wrong, seemed the msg never sent out . Can anyone tell me how to resolve this issue?
Thanks
Actually I think you need to make this one change:
* socket.send(body)
Think of the round brackets as being JS - not standard Karate expressions: https://github.com/intuit/karate#enclosed-javascript
Also note, for strings (instead of JSON) you can use replace: https://github.com/intuit/karate#replace
* def text = 'hello <foo> world'
* replace text.foo = 'bar'
* match text == 'hello bar world'

Karate framework variable usage

I have this steps:
...
Then status 200
And match response.requests[0].request.url == "/endpoint"
And json body = response.requests[0].request.body
And match body == { "something": "something"}
To simplify, I tried to put response.requests[0].request in a variable called request:
...
Then status 200
And def request = response.requests[0].request
And match request.url == "/endpoint"
And json body = request.body
And match body == { "something": "something"}
I'm having the following error:
'request' is not a variable, use the form '* request <expression>' instead
I read the documentation and the use of request seems to be fine:
Given def color = 'red '
And def num = 5
Then assert color + num == 'red 5'
What am I doing wrong?
Thanks in advance.
Just make this change:
* def req = response.requests[0].request
# other steps
* request req
We simply disallow def request (using request as a variable name) because a lot of newbie users get confused. The error message has worked 99.9% of the time for users to understand what the problem is, but I guess you fall in the 0.1% :)

call the first feature from the second feature file, failed without specified clue

Run the first.feature file successfully,however, call it from the second.feature failed without any clue to analysis. Do you have any idea help me find the root cause?
The source of my first.feature:
Feature: 采样管理-样本登记
Background: 读取随机生成的条形码、手机号、采样类型等作为入参
* url baseURL
* def randomData = Java.type('utils.RandomData')
* def barcode = randomData.getRandom(11)
* def randomPhone = randomData.getTelephone()
* def sampletype = randomData.getNum(0,1)
Scenario: 输入合法参数进行正常样本登记,确认能够登记成功
Given path 'iEhr/PersonSample'
# * header Content-type = 'application/x-www-form-urlencoded; charset=UTF-8'
* cookies { JSESSIONID: '#(jsessionID)',SESSION: '#(sessionID)', ACMETMP: '#(acmetmpID)'}
* def autoMotherName = "autoMname"+ barcode
# * def confData = {mothername: "#(autoMotherName)", barcode: "#(barcode)", mobile: '#(randomPhone)', sampletype:"#(sampletype)" }
# 设置sampletype为1,已被采样
* def confData = {mothername: "#(autoMotherName)", barcode: "#(barcode)", mobile: '#(randomPhone)', sampletype:"1" }
# 打印入参变量输出
* print confData
# 用例与数据分离
* def paramObj = read('classpath:mainFlow/sampleSaveReqTest.json')
* print paramObj
* form field param = paramObj
When method post
Then status 200
* json result = response[0].result
* def personId = result[0].personid
* def sampleid = result[0].sampleid
* print personId
* print sampleid
The source of my second.feature:
Feature: 提交递送样本
Background:
* def sampleResult = call read('classpath:mainFlow/first.feature')
* print sampleResult
I run the first.feature singly, it works. However, karate reports the error below after running the second.feature. Any idea how can I debug to find the root cause? I have no idea what's wrong with the second read. Many thanks!
* def sampleResult = call read('classpath:mainFlow/first.feature')
-unknown-:14 - javascript evaluation failed: read('classpath:mainFlow/first.feature'), null
Look for some issue with karate-config.js. As Babu said in the comments, it is very hard to make out what the problem is, I suggest you follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
Also try if the latest preview version 0.9.3.RC2 is better at showing what the error is.
If you can replicate the problem as a small example, it will help us - because we really need to do better at showing more useful error logs, instead of just null.