Use comma in path in karate test - karate

With the following test case
Background:
* callonce read('auth.feature')
* url java.lang.System.getenv('TEST_URL')
Scenario: Call the file endpoint without authorization
Given path 'files/123695_11,8'
When method get
Then status 401
I get a parser error about mismatching quotes. The reason is probably that the "path" is confused by the comma, as that can also be used to denote sub-paths.
I thought about just changing the , to %2C, but then karate calls the URL with the % encoded to %25, resulting in a wrong URL 'files/123695_11%252C8' which decodes to literally 'files/123695_11%2C8'.
How can I make this work correctly?

Simplest option, merge into url:
* url 'https://httpbin.org/anything/files/123695_11,8'
* method get
I know you may want to "re-use" stuff in the background, so use variables:
Background:
* def baseUrl = 'https://httpbin.org/anything'
Scenario:
* url baseUrl + '/files/123695_11,8'
* method get
Hacky workaround:
* url 'https://httpbin.org/anything'
* def temp = 'files/123695_11,8'
* path temp
* method get

Related

karate framework save response from 1 request and then use in another request

In karate frame work is it possible to save response from 1 request and then use it in request body of another request?
Example: in Request 1 I send user name and user id in request body and in response I get user address.
In request 2 body, I want to use that address and validate house type.
Is it possible?
Yes it is possible. The hello world example itself shows this.
See how in this example below also the response of the first request is used in the path of the second request. You can cut and paste this and try it:
* url 'https://httpbin.org'
* path 'anything'
* request {"myKey":"myValue"}
* method get
* status 200
* def myResult = response.json.myKey
* path 'anything/' + myResult
* method get
* status 200

How do use the same variable in background and feature being called

With Karate 1.1.0, you could define a variable in the background, ex "* path = 'www.google.ca', call a "helper" feature at the top of of a scenario, which was using the same variable name inside it, then later in your scenario use the same variable again. Ex., helper feature would have "* path = 'www.google.ca' in it's 1 and only scenario, which would say something like "Given path '/help.html'". Then in your main feature, after you have called the helper feature you would use the variable again, something like "Given path '/fun.html'". When everything ran it would be fine, the helper feature would point to it's path and the main feature would point to it's path.
Now with Karate 1.2.0.RC6, I don't have to declare path in the helper feature, but with that change the path is being concatenated in the main feature/scenario. So when the scenario executes, it calls the helper feature fine, but then instead of it's path being "www.google.ca/fun.html" it comes "www.google.ca/help.html/fun.html". Any ideas why or better how to resolve it?
Here's the actual code:
Feature: Update calls on an account
Background:
* url url
* header Authorization = token
* path 'care/v1.1/account/'
Scenario: theScenario
* def fullResponse = call read('init/movein_ADD.feature') { payloadFilename: 'data/account_id_call_ADD_MOVEIN_No_GovtId.json'}
* def updatePayload = read('data/account_id_call_add_MOVEIN_Both_GovtId.json')
* set updatePayload.callNumber = fullResponse.response.callNumber
* set updatePayload.id = fullResponse.response.id
* set updatePayload.orderNumber = fullResponse.response.orderNumber
* set updatePayload.stagedServices = null
* header Accept = json
* header Content-Type = json
Given path ENCODE('16382-8') + '/call/update'
And request updatePayload
When method POST
Then status 200
Helper feature:
#ignore
Feature: Helper feature file to create Move-In Service order request
Scenario: helper Scenario
* url url
* path 'care/v1.1/account/'
* def payload = read(payloadFilename)
#set up request and execute
* header Accept = json
* header Content-Type = json
Given path 'MTYzODJAQDg=/call/add'
And request payload
When method POST
Then status 200
The answer, change to declare a variable in the background of the main feature file, set the path to that variable in the helper feature scenario and again the main feature scenario right after the call to the helper feature file has worked. Going to cause some big refactoring on our part based on this change.

Can we pass method and path while calling feature from inside another feature

When you call a feature (with a few Scenarios) from inside another feature, I want to pass method and path
as these are common scenarios - called from two different endpoints where base url remain same but path and also the method differ.
This situation arise because I am trying to put the common scenarios in a feature and call that feature from other feature files where the scenarios are all common and they differ only in path and method.
I have referred to this issue: 'https://github.com/intuit/karate/issues/239' and know that it is possible but in my case I need to pass the path and method as arguments while calling the feature file because that is the only thing differing with two modules calling the common scenarios.
So the question is can we pass path and method as parameters while calling a feature file. Currently I am getting error but do not understand why it should fail.
I tried the following:
booking.feature
Background:
* def pathVar = '/bookings'
Scenario: Calling basic validation feature for create booking module
* call read('classpath:feature/basic-validations.feature') {path1: '#(pathVar)', action: 'post'}
basic-validations.feature
Background:
* url baseURL
* header Accept = 'application/json'
* def data = read(datafile)
* header API-Version = 1
* path '#(path1)'
* header Authorization = 'Bearer' + data.booking.token
Scenario: Empty request validation
Given request {}
When method '#(action)'
Then status 400
Scenario: Request-Body element is empty or null.
Given def req = ({ "request_body": null })
And request req
When method '#(action)'
Then status 400
Scenario: When parameter value for name in request body is incorrect.
Given def req = ({ "request_body": [ { "name": "shipment_standard_booking", "action":
"create", "path": "/standardBooking", "body": data.booking.standardBooking.requestBody }]
})
And def name = 'test'
And set req.request_body[*].name = name
And request req
When method '#(action)'
Then status 400
And match $.debugMessage == 'Validations failed due to bad input payload request. WorkItem
name (' +name+ ') is invalid'
The path step can take variables. The method step also can take a variable: https://github.com/intuit/karate#method
* def methodVar = 'post'
* url foo
* request bar
* method methodVar
But I totally don't recommend it - or the approach you are taking. Reasons are explained here, please take some time to read it: https://stackoverflow.com/a/54126724/143475
I think you also have mis-understood embedded expressions, so please read this: https://github.com/intuit/karate#rules-for-embedded-expressions
If you still decide to do this and get stuck, you can assume that either Karate does not support what you want to do - or that you need to contribute code.
Also read this for other ideas: https://stackoverflow.com/a/50350442/143475

Karate framework default path

In my test all requests use the same url ('http://localhost:8080/example')
I defined that url in background section:
Feature: Some feature
Background:
* url 'http://localhost:8080/example'
Is there a better way to write this?
Scenario:
Given path ''
...
Thanks!
You don't need the Given path ''. You can start with the * request {}.

Encoded path is encoded again

I have to make a request:
* url foo
* path bar
* path code
Code is retrieved from another request and I receive it url encoded.
The problem is when I put it in the path, karate encode it again.
Ex: I receive zxc1J%2BV%2FMnb and in path it becomes zxc1J%252BV%252FMnb.
%2Bis replaced by %252B.
When I decode received code and put it in path, it is not encoded.
My javascript function to decode is :
* def codeDecoded = decodeURIComponent(code)
and encoding function is * def codeEncoded = encodeURIComponent(codeDecoded)
Am I missing smth? What is wrong? How can I manage this? Thanks.
Edit:
#Peter Thomas I try my last chance, because I already showed the prb to someone from server and he didn't understand why karate encodes again smth already encoded and doesn't encode smth decoded.
So my first request is a POST request, which returns an encoded code in responseHeaders. Ex: GVkX1%2FKZEi%2FWQ.
In my second request I have to take this code and put it in the path ex: url/GVkX1%2FKZEi%2FWQ.
The problem is that karate transforms it to url/GVkX1%252FKZEi%252FWQ . And I don't need it. And if I decode url/GVkX1%2FKZEi%2FWQ before to put it in path, the url in karate is url/GVkX1/KZEi/WQ. When put in path, the decoded code is not encoded in karate. I hope it is more understandable.
Yes Karate will always encode the path you provide for your convenience. This is what 99% of users expect anyways.
There is nothing wrong with using a custom function to decode and ensure you pass un-encoded URL / path values to Karate, so by all means, please continue to do so !
Edit: quite likely the way you tried to decode may be wrong, try this:
* def encoded = 'zxc1J%2BV%2FMnb'
* def decoded = java.net.URLDecoder.decode(encoded, 'UTF-8')
* print decoded
Which prints:
[print] zxc1J+V/Mnb