Presume I have 2 users and I use basic authentication. I'd like to generate the 2 basic auth tokens once and reuse it per scenario in one feature. On top of that I have scnearios where no authorization is needed. How could I achieve this with the least biolerplate? Currently I have
auth-header.js
function(creds) {
var temp = creds.username + ':' + creds.password;
var Base64 = Java.type('java.util.Base64');
var encoded = Base64.getEncoder().encodeToString(temp.bytes);
return 'Basic ' + encoded;
}
karate-config.js
...
config.apitester1AuthHeader =
karate.call('classpath:auth-headers.js', {username:'apitester1', password:'xxx'});
config.apitester2AuthHeader =
karate.call('classpath:auth-headers.js', {username:'apitester2', password:'xxx'});
...
project-get.feature
Feature: project end-point
Background:
* url baseUrl
Scenario: get projects user has right to
* configure headers = {Authorization : '#(apitester1AuthHeader)'}
Given path 'project'
...
What you have looks reasonable.
Note that if you do:
* configure headers = null
It will have the effect of temporary no authorization. I would recommend stick with what you have and it is quite modular already.
Related
I’m trying to retrieve a JWT from a feature A in a feature B.
For this I have in the feature A:
# create API access for the client
Given url baseUrl
And path 'admin', 'clients', clientApiId, 'accesses', 'api', 'api-key', 'renew'
And header Authorization = 'Bearer ' + authenticationJWT
When method put
Then status 200
* def clientApiJWT = response
And in feature B:
# Create a process with API access
* def clientApiAccess = call read('classpath:karate/common/create-client-api-access.feature')
* clientApiJWT = clientApiAccess.clientApiJWT
With this code I recover the following error:
Thank you for your help
Shouldn't it be:
* def clientApiJWT = clientApiAccess.clientApiJWT
I have feature with multiple scenarios that are building upon each other. Think of it as the first request fetches some data which is then pumped into the second one and so on.
This works fine, as long as all the requests go to the same host. However the last request in the line goes to a different port on the same host, but of course the port which is called from Karate is the wrong one.
Here the the karate-config.js:
function fn() {
karate.configure('connectTimeout', 10000);
karate.configure('readTimeout', 10000);
return {
tenant: 'ipt',
bank: 'ndb',
baseUrl: karate.properties['mws.baseUrl'] ? karate.properties['mws.baseUrl'] : 'http://localhost:8080',
errorIdentifierMatches: function (actualErrorIdentifier, expectedErrorIdentifier) {
return actualErrorIdentifier.startsWith(expectedErrorIdentifier);
},
sleep: function (millis) {
karate.log('Sleeping for ' + millis + ' ms');
java.lang.Thread.sleep(millis)
},
generateUUID: function() {
return java.util.UUID.randomUUID() + '';
}
}
}
This results in the last call going to http://localhost:8080/ipt/registerkey when it should be http://localhost:9390/ipt/registerkey
The relevant part in the feature is defined in the Background:
Background:
Given url baseUrl
* def s2wKeyExchangeEndpoint = ("/mws/v2/" + tenant + "/" + bank + "/s2w/startkeyexchange")
* def s2wVerifyAndSignEndpoint = ("/mws/v2/" + tenant + "/" + bank + "/s2w/verifyandsign")
* def s2wRegisterKey = ("/ipt/registerkey")
Is there a way to change the baseUrl from within my feature? Are there any other options?
You can use the url keyword any time in a Scenario. It is up to you to manage variables and config.
* url 'http://localhost:8080'
* path 'foo', 'bar'
* method get
* url baseUrl
* path 'blah'
* method get
So it sounds to me that you have misunderstood the syntax or have over-complicated things.
Not sure of your application stack, but is it possible to test each call in isolation (by using a mock) then perform limited integrated e2e black box tests?
My apologies it seems repetitive question but it is really troubling me.
I am trying to call one feature file from another feature file along with variable values. and it is not working at all.
Below is the structure I am using.
my request json having variable name. Filename:InputRequest.json
{
"transaction" : "123",
"transactionDateTime" : "#(sTransDateTime)"
}
my featurefile1 : ABC.Feature
Background:
* def envValue = env
* def config = { username: '#(dbUserName)', password: '#(dbPassword)', url: '#(dbJDBCUrl)', driverClassName: "oracle.jdbc.driver.OracleDriver"};
* def dbUtils = Java.type('Common.DbUtils')
* def request1= read(karate.properties['user.dir'] + 'InputRequest.json')
* def endpoint= '/v1/ABC'
* def appDb = new dbUtils(config);
Scenario: ABC call
* configure cookies = null
Given url endpoint
And request request1
When method Post
Then status 200
Feature file from which I am calling ABC.Feature
#tag1
**my featurefile1: XYZ.Feature**
`Background`:
* def envValue = env
Scenario: XYZ call
* def sTransDateTime = function() { var SimpleDateFormat = Java.type('java.text.SimpleDateFormat'); var sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'+00:00'"); return sdf.format(new java.util.Date()); }
* def result = call read(karate.properties['user.dir'] + 'ABC.feature') { sTransDateTime: sTransDateTime }
Problem is,
While executing it, runnerTest has tag1 configured to execute.
Currently, it is ignoring entire ABC.feature to execute and also not generating cucumber report.
If I mention the same tag for ABC.feature (Which is not expected for me as this is just reusable component for me ) then it is being executed but sTransDateTime value is not being passed from XYZ.feature to ABC.feature. Eventually, InputRequest.json should have that value while communicating with the server as a part of the request.
I am using 0.9.4 Karate version. Any help please.
Change to this:
{ sTransDateTime: '#(sTransDateTime)' }
And read this explanation: https://github.com/intuit/karate#call-vs-read
I'm sorry the other part doesn't make sense and shouldn't happen, please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
I discovered after-feature in karate which is very useful. But I didn't find how to pass parameters to after-feature from main feature. Ex: access token to delete a user account or a user_id.
Here is call of after-feature.feature in my main feature:
* configure afterFeature = function(){ karate.call('classpath: AfterFeature.feature'); }
Here is my AfterFeature.feature
Scenario:
* url 'XXX'
* path 'YYY'
* param foo = bar which should come from main feature
* header Authorization = 'Bearer ' + accessToken which should come from main feature
* method delete
* status 204
karate.call() can take parameters.
karate.call('classpath: AfterFeature.feature', { some: 'value' });
How can I add a new user to the ACL for a Google Calendar? I'm trying to send a POST HTTP request. Perhaps there is something wrong with the XML? The code below generates a server error (400). (Edit: Shows the oAuth).
//---------------------------------------------------------------
// Add a rule to the Access Control List for 'Fake Calendar 1.0'
//---------------------------------------------------------------
function addRule() {
// Get Calendar ID, script user's email, and the API Key for access to Calendar API
var calId = '12345calendar.google.com';
var userEmail = Session.getActiveUser().getEmail();
var API_KEY = 'ABC123';
var newUserEmail = 'person#example.net';
// Get authorization to access the Google Calendar API
var apiName = 'calendar';
var scope = 'https://www.googleapis.com/auth/calendar';
var fetchArgs = googleOAuth_(apiName, scope);
fetchArgs.method = 'POST';
var rawXML = "<entry xmlns='http://www.w3.org/2005/Atom' " +
"xmlns:gAcl='http://schemas.google.com/acl/2007'>" +
"<category scheme='http://schemas.google.com/g/2005#kind' " +
"term='http://schemas.google.com/acl/2007#accessRule'/>" +
"<gAcl:role value='owner'/>" +
"<gAcl:scope type='user' value='"+userEmail+"'/>" +
"</entry>";
fetchArgs.payload = rawXML;
fetchArgs.contentType = 'application/atom+xml';
// Get the requested content (the ACL for the calendar)
var base = 'https://www.googleapis.com/calendar/v3/calendars/';
var url = base + calId + '/acl?key=' + API_KEY;
var content = UrlFetchApp.fetch(url, fetchArgs).getContentText();
Logger.log(content);
}
//--------------------------------------------------------------
// Google OAuth
//--------------------------------------------------------------
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey("anonymous");
oAuthConfig.setConsumerSecret("anonymous");
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
Have you gone through the oAuth authorization process before executing this piece of code. Your app has to be explicitly authorized before it can do anything significant with the Calendar API
Srik is right. You need to use oAuth Arguments in your UrlFetchApp.
Given Reference URL shows few examples for using oAuth in Apps script to work with Google's REST APIs
https://sites.google.com/site/appsscripttutorial/urlfetch-and-oauth