callSingle() usage in karate-config.js [duplicate] - karate

I have a .feature file that will receive argument from another feature file as __arg to generate token for oAuth
Given url urlRefreshToken
Given def json = __arg
And header Content-Type = 'application/json; charset=utf-8'
And request json
* header Authorization = 'Bearer' + __arg.refresh_token
When method POST
Then status 200
* def bearer = 'Bearer ' + response.access_token
I am trying to centralise the token generation for only one time on karate-config.js. However I cannot seem to be able to use karate.callSingle() with passed parameters.
I use the feature file to generate token on other feature files as:
* def getToken = call read('classpath:features/Utils/GetToken.feature') refreshTokenRaymond
* header Authorization = getToken.bearer
I am trying to invoke the feature file for generating token on karate-config.js to no avail. I tried to pass in the additional parameter like this on karate-config.js:
var config = {
baseUrl: 'url',
urlRefreshToken: 'url',
refreshToken: '{refreshToken: refreshToken}'
};
var token = karate.callSingle('classpath:features/Utils/GetToken.feature', [config, config.refreshToken])
I wonder if it is possible to pass multiple parameter to karate.callSingle() called from karate-config.js?
Any help will be greatly appreciated. Thanks!

call and karate.callSingle() take only one argument, but you can easily create a new JSON out of other JSONs. Actually since you seem to be passing config as the argument - you can easily access config.refreshToken as __arg.refreshToken.
Your code is very confusing - but hope that this hint is what gets you on your way:
Given def json = __arg.refreshToken
If you need to create a JSON out of other data - I think you already know how to do that:
var temp = { config: config, refreshToken: refreshToken };
var token = karate.callSingle('classpath:features/Utils/GetToken.feature', temp);

Related

Advice for implementing custom authentication scheme [duplicate]

First of all, thanks for build karate it's a very useful for test API's and UI's. We are using it to test a lot of our endpoints but we would like to know if there is a way or which is the best approach to handle requests with signature as part of the request in the header.
In our case we have two headers:
ApiKey: this value is always the same
Signature: this value depends on the request body content
Is there any way to inject the signature value just before the request is executed based on the request body content?
Here you can see two samples of the requests
Sample 1:
* url 'https://dev.sample.com'
* path '/api/user/getAll'
* header Content-Type = 'application/json'
* header ApiKey = 'XXX'
* header Signature = 'YYY'
And request { }
When method POST
Then status 200
Sample 2:
* url 'https://dev.sample.com'
* path '/api/user/getAll'
* header Content-Type = 'application/json'
* header ApiKey = 'XXX'
* header Signature = 'ZZZ'
And request { name: 'John' }
When method POST
Then status 200
Thanks
Karate has a "hook" for generating headers, but as of now it is not "aware" of the currently built request body + headers: https://github.com/intuit/karate#configure-headers
We got a similar request here, and are thinking of adding this capability: How to retrieve raw request contents before making a REST call in Karate DSL?
Maybe the OAuth examples will give you the way forward for your case for now: https://stackoverflow.com/a/55055111/143475
Feel free to raise an enhancement request, and we can get this in to the next version (with your help to test it). I'm thinking - what if you are able to call karate.get('request') from within the header JS function.
But for now all you need to do is do something like this:
* def body = { some: 'json' }
* karate.set('requestBody', body)
* url someUrl
* request body
* method post
And in the header.js function
function fn() {
var body = karate.get('requestBody');
var sign = Utils.sign(body);
return { Signature: sign };
}
EDIT: this will be implemented in Karate 1.0 onwards: https://github.com/intuit/karate/issues/1385

How to handle requests with signatures on karate tests?

First of all, thanks for build karate it's a very useful for test API's and UI's. We are using it to test a lot of our endpoints but we would like to know if there is a way or which is the best approach to handle requests with signature as part of the request in the header.
In our case we have two headers:
ApiKey: this value is always the same
Signature: this value depends on the request body content
Is there any way to inject the signature value just before the request is executed based on the request body content?
Here you can see two samples of the requests
Sample 1:
* url 'https://dev.sample.com'
* path '/api/user/getAll'
* header Content-Type = 'application/json'
* header ApiKey = 'XXX'
* header Signature = 'YYY'
And request { }
When method POST
Then status 200
Sample 2:
* url 'https://dev.sample.com'
* path '/api/user/getAll'
* header Content-Type = 'application/json'
* header ApiKey = 'XXX'
* header Signature = 'ZZZ'
And request { name: 'John' }
When method POST
Then status 200
Thanks
Karate has a "hook" for generating headers, but as of now it is not "aware" of the currently built request body + headers: https://github.com/intuit/karate#configure-headers
We got a similar request here, and are thinking of adding this capability: How to retrieve raw request contents before making a REST call in Karate DSL?
Maybe the OAuth examples will give you the way forward for your case for now: https://stackoverflow.com/a/55055111/143475
Feel free to raise an enhancement request, and we can get this in to the next version (with your help to test it). I'm thinking - what if you are able to call karate.get('request') from within the header JS function.
But for now all you need to do is do something like this:
* def body = { some: 'json' }
* karate.set('requestBody', body)
* url someUrl
* request body
* method post
And in the header.js function
function fn() {
var body = karate.get('requestBody');
var sign = Utils.sign(body);
return { Signature: sign };
}
EDIT: this will be implemented in Karate 1.0 onwards: https://github.com/intuit/karate/issues/1385

How to obtain response to be used on hooks

I am trying to make a simplified version of test report where I am generating a single HTML file report containing only assertion and error response message when there is any (attempting to not publish all the logs and steps).
I understand that we have hooks in karate. However I have looked for karate objects in the github but unable to found any objects where I can extract the response from (to be passed to the js function called on hook)
What I am doing right now is this:
Config:
//karate-config.js
karate.configure('afterScenario', karate.call('classpath:hooks.js'));
Hook:
//hooks.js
//Looking on how to extract the response and log it here
function(){
var info = karate.tags;
karate.log('Tags', info);
}
Am I missing anything on the karate objects? Or this should be achieved in another way?
Thanks a lot!
Try this:
var response = karate.get('response');
EDIT better example:
Background:
* configure afterScenario = function(){ karate.log('***', karate.get("response.headers['X-Karate']")) }
Scenario:
Given url 'http://httpbin.org'
And path 'headers'
And header X-Karate = 'test'
When method get
# this will fail
Then status 400
I have tried with both karate.get('response') and response directly, and both work. If you use karate.call() pass the response as a parameter.

How to pass multiple parameters to callSingle karate on karate-config.js

I have a .feature file that will receive argument from another feature file as __arg to generate token for oAuth
Given url urlRefreshToken
Given def json = __arg
And header Content-Type = 'application/json; charset=utf-8'
And request json
* header Authorization = 'Bearer' + __arg.refresh_token
When method POST
Then status 200
* def bearer = 'Bearer ' + response.access_token
I am trying to centralise the token generation for only one time on karate-config.js. However I cannot seem to be able to use karate.callSingle() with passed parameters.
I use the feature file to generate token on other feature files as:
* def getToken = call read('classpath:features/Utils/GetToken.feature') refreshTokenRaymond
* header Authorization = getToken.bearer
I am trying to invoke the feature file for generating token on karate-config.js to no avail. I tried to pass in the additional parameter like this on karate-config.js:
var config = {
baseUrl: 'url',
urlRefreshToken: 'url',
refreshToken: '{refreshToken: refreshToken}'
};
var token = karate.callSingle('classpath:features/Utils/GetToken.feature', [config, config.refreshToken])
I wonder if it is possible to pass multiple parameter to karate.callSingle() called from karate-config.js?
Any help will be greatly appreciated. Thanks!
call and karate.callSingle() take only one argument, but you can easily create a new JSON out of other JSONs. Actually since you seem to be passing config as the argument - you can easily access config.refreshToken as __arg.refreshToken.
Your code is very confusing - but hope that this hint is what gets you on your way:
Given def json = __arg.refreshToken
If you need to create a JSON out of other data - I think you already know how to do that:
var temp = { config: config, refreshToken: refreshToken };
var token = karate.callSingle('classpath:features/Utils/GetToken.feature', temp);

how to use embedded expression with classpath

I am trying to pass the absolute value of a file to the read function for classpath.
If I pass absolute path along with classpath it works fine. But when I pass embedded expression its not working
My code is as below
Scenario: create swagger first RAD
Given url appServer
Given param creationMethod = 'SWAGGER_FIRST'
And path '/integration/rest/rad'
And header X-CSRF-TOKEN = csrfToken
* cookie JSESSIONID = jsessionid
* cookie route = routevalue
* configure charset = null
print swaggerDetailsinputFile
print swaggerInputJsonFile
Given multipart file inputData = { read: 'classpath: #(swaggerDetailsinputFile)', filename: 'blob', contentType: 'application/json' }
Given multipart file swaggerFile = { read: 'classpath:ic/feature/RAD/swagger.json', filename: 'blob', contentType: 'application/json' }
And header Content-Type = 'multipart/form-data'
When method post
Need a way to pass embedded expression to classpath value for read function
Try this:
read: '#("classpath:" + swaggerDetailsinputFile)'
Make sure you read this part of the docs: https://github.com/intuit/karate#rules-for-embedded-expressions