Karate API : Passing variables to other feature file is not working - karate

I am calling login feature file from other feature file from where I am passing url, username and password but it is not working for me. I am not using Background key here and i do not want also.
#CallAnotherFeature
Feature: Call Login Feature
Scenario: Calling Login Test
* def config = { endPointURL: 'https://qa1.testurl.com/login',username: 'user123', password: 'password123' }
* def result= call read('Login.feature') config
* print result.response
* print 'Sign In-'+signIn
* print 'Sign In Reponse-'+signIn.response
Feature: Login Feature
Scenario: Test Login for different users
* print 'Starting Test','#(endPointURL)'
Given url '#(endPointURL)'
* print 'user name','#(username)'
* print 'Password ','#(password)'
#And form field username = '#(username)'
#And form field password = '#(password)'
And request { username: '#(username)', password: '#(password)'}
When method post
Then status 200
* print response
* match response.loginSuccess == true
In Login.feature I tried to pass username and password as form data also even though these did not work. Could someone tell me what mistake I am making here.
I am using latest karate version 0.9.0

I see a few issues in your scripts,
1. Call Login Feature
1.1) I don't see signIn variable initialized anywhere in this feature nor from your login feature but you are trying to print it.
1.2) = Should be placed properly ;)
* def result = call read('Login.feature') config
2. Login Feature
2.1) I think you misunderstood the concept of embedded expressions. only for templating it into a JSON you may use it. but for calling it you can simply use the variable name.
eg.
Given url endPointURL
And form field username = username
And request { username: '#(username)', password: '#(password)'}
NOT
Given url '#(endPointURL)'
And form field username = '#(username)'
I will be more clear for you if you read the karate documentation from here -> karate Doc and refer karate Demos

Related

how to generate auth 2.0 in karate I saw a sample in karate Demo project but in our case we need to send it as "Authorization Code"

How to generate OAuth 2.0 token via karate.
How we have tried in Postman:
On Authorization tab select OAuth 2.0
Select Header Prefix Bearer
Grant-Type is "Authorization Code"
Callback URL is selected as when we will click submit it redirects to a browser where we have to enter credentials and a user is validated once it is validated the browser redirects back to Postman
Add "Auth URL" and "Access Token URL"
Enter "Client ID" and "Client Secret"
Select "Client Authentication" as Send as Basic Auth Header.
Postman then redirects to a browser where we enter username and password and once authenticated it redirects user back to postman with access token.
Question:
When we provide grant_type as "authorization code" in Karate we are getting an error as {"error":"unsupported_grant_type","error_description":"Unsupported grant_type"}. What to provide here as when we provide "password" we are getting 401 and when we provide "authorization code" we are getting 400.
Secondly, Can we automate such scenario where a browser is invoked as well and we have to enter credentials can we achieve it via Karate as then we have to store the token and pass in the APIs?
Background:
* url 'http://localhost:8080/pathdetails'
Scenario: get all users and then get the first user by id
* path 'token'
* form field grant_type = 'authorization code'
* form field client_id = 'ourapiclient'
* form field client_secret = '324243324-3334-334-343-3432423424'
* method post
* status 200
* def accessToken = response.access_token
EDITED**********
I have now tried to send a API request to Auth URL which redirects to the browser and returns HTML page.
Given url 'http://localhost:8080/myurlpath/auth'
* form field response_type = 'code'
* form field client_id = 'abcc'
* form field scope = 'openconnect'
* form field redirect_uri = 'http://localhost:8080/redirecturlpath'
* form field state = 'cEY3R-YfsoM9232diS72COdHTA8uPv9K49pjZaPag5M.8akinzwobn8.abcd4'
* method get
* status 200
* print 'Response is........',response
This returned an HTML page which is exactly the same page I see when I send request from Postman. How to now enter username and password in karate on this html page as this page was returned as part of the response of above API.
I was expecting above will return me a code and after that I will call the request token endpoint but above redirected me to where I enter username and password and then once it is successful it redirects back to Postman and in URL I can see the code as well.
curl --request POST \
--url 'https://YOUR_DOMAIN/oauth/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data 'client_id=YOUR_CLIENT_ID' \
--data client_secret=YOUR_CLIENT_SECRET \
--data code=YOUR_AUTHORIZATION_CODE \
--data 'redirect_uri=https://YOUR_APP/callback'
How to get the code which is needed by the token API?
I tried sending Auth API to access like below but no code or token got returned in the response.
Given driver 'http://localhost:8080/myurlpath/auth?scope=openconnect&state=cEY3R-YfsoM9232diS72COdHTA8uPv9K49pjZaPag5M.8akinzwobn8.abcd4&response_type=code&client_id=abcc&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fauth%2Fmyurlpath'
* fullscreen()
And input('#username', 'username')
And input('#password', 'password')
When click('#login')
The above doesn't return any error but it doesn't return the code I am looking for as well
#Maddy To see grant types You need access to auth0, or ask your devs to tell You what grants are implemented here you can read more:
https://auth0.com/docs/configure/applications/application-grant-types
And here You can read how to implement autorization-code flow:
https://auth0.com/docs/login/authentication/add-login-auth-code-flow
To make Your life easier You could ask devs to implement Password-realm-grant but this is not recommended.
Here is how rectify one of oAuth 2.0 token generation
* def cid = 'client_id'
* def csec = 'token_secret'
* def AuthCode = Java.type('com.test.qa.aut.authCode')
* print AuthCode.Code()
* def authentication = 'Basic ' + AuthCode.Code(cid, csec)
* print authentication
* url 'https://acpint.online.com/default/np/oauth2/'
* header Authorization = authentication
And header Content-Type = 'application/x-www-form-urlencoded; charset=utf-8'
* form field grant_type = 'client_credentials'
Then method post
And status 200
Then print response
Java class:
package com.test.qa.aut;
import java.util.Base64;
public class authCode {
public static String Code(String clientId, String clientSecret) {
String auth = clientId + ":" + clientSecret;
String authentication = Base64.getEncoder().encodeToString(auth.getBytes());
return authentication;
}
}

403 access denied to the website with proper login/pass through google script

var url = "https://web-site_name/page/?format=json&var_data-organization_dates&xlsexport=true";
var payload =
{
"login" : "login",
"password" : "pass",
};
var options =
{
"method" : "post",
"payload" : payload,
"followRedirects" : false
};
var login = UrlFetchApp.fetch("https://web-site_name/page/" , options);
var sessionDetails = login.getAllHeaders()['Set-Cookie'];
Logger.log(login.getAllHeaders());
here is the part of the code I try to use, to automate export of the data from web-site, i do have proper login and password and able to download file in json (opened in xsl) manually, I've got the address to the downloaded file in network in developer tools, but i have a problem on the first stage - when trying to authorize to the web-site - access denied. I've tried the code, given in answers on stackoverflow, but it still doesn't work.
How to make an url fetch request correctly, depends on the website you want to access and the authentication they uses
In the simplest case, your website requires HTTP basic authentification, in this case the correct syntax would be
var authHeader = 'Basic ' + Utilities.base64Encode(login + ':' + pass);
var options = {
headers: {Authorization: authHeader}
}
If your website uses a different authentication form, you might need to provide an access token.
In any case: the authentication credentials go into headers, not into payload!
payload is the data that you want to post = upload to the website.
If you want export data from the website - that is download data - you do not need a payload and the correct method would be get, not post. Btw., if the method is get, you do not need to specify it.
Please see here for more information and samples.

Handling Basic Authentication in Karate UI scenario

I have just started implementing karate UI (v0.9.5). Have already implemented api testing using karate and it works perfectly.
Following the HTTP basic auth strategy on this page - https://github.com/intuit/karate#http-basic-authentication-example the basic auth handling works for api tests. I set the HTTP headers once and run all api tests.
Now for the UI testing, the URL that I open brings up the basic auth pop-up as shown below:
So I thought that I could use the same strategy that I used for api tests to handle this. In the background section of my feature file, i call the feature file that does the authentication and sets headers as below:
The called feature file to set headers (admin-headers.feature). This feature file gets the token after admin user login is performed via karate-config.js. Then assigns the token along with the Base64 encoded basic auth to the headers calling headers.js. The Base64 user and password are being input as maven arguments and read via karate-config variables.
(/admin-headers.feature)
Feature: karate-config.js will perform one time login for admin and
set the session token for all subsequent requests
Background:
* def session = adminAuthInfo.authSession
* def basic_auth = call read('classpath:basic-auth.js') { username: '#(basicAuthUser)', password: '#(basicAuthPassword)' }
* configure headers = read('classpath:headers.js')
Scenario: One-time login for user and set the
session token in request header
The js code for returning Auth and Cookie to above feature file (/headers.js).
function() {
var session = karate.get('session');
var basic_auth = karate.get('basic_auth');
if(session){
return {
Authorization: basic_auth,
Cookie: "SESSION=" + session
};
} else {
return {};
}
}
My UI test feature file (/ui-test.feature):
Feature: Login test
Background:
# Authorise via api
* callonce read('classpath:common/headers/admin-headers.feature')
* configure driver = { type: 'chrome' }
Scenario: Test login
Given driver 'https://test.internal.mysite.com/names'
Running the above feature file still shows the auth pop-up.
I then tried to set the cookies while I am initialising the driver (which I think is probably not the right way?) as below:
Feature: Login test
Background:
# Authorise via api
* def login = callonce read('classpath:common/headers/admin-headers.feature')
* def uiCookie = { name: 'SESSION', value: '#(login.userAuthInfo.authSession)', domain: 'test.internal.mysite.com' }
* configure driver = { type: 'chrome', cookie: '#(uiCookie)' }
Scenario: Test login
Given driver 'https://test.internal.mysite.com/names'
The above also does not work. What is it that I am doing wrong here? the pop-up keeps coming up because the cookie is not set when the driver is initialised and then opens the specified url?
Help is much appreciated.
I think you raised a very good feature request, that configure driver should take cookies also, so that you can navigate to the page and set cookies in one-shot, and I opened a feature request: https://github.com/intuit/karate/issues/1053
So try this sequence, refer docs for cookie(): https://github.com/intuit/karate/tree/master/karate-core#cookieset
* driver 'about:blank'
* cookie(uiCookie)
* driver 'https://test.internal.mysite.com/names'
And now it should work !
Feature: Windows Authentication feature
Background:
* configure driver = { type: 'chrome' }
Scenario: Windows Authentication Valid Login test case
Given driver 'http://the-internet.herokuapp.com/basic_auth'
And delay(3000)
And screenshot()
* robot {}
* robot.input('admin' + Key.TAB)
* robot.input('admin')
* robot.click('Sign in')
And delay(3000)
And screenshot()
works fine with chrome, edge

Karate.toMap() using 0.9.5.RC4 works with Scenario but not Works with Scenario Outline

As suggested in here Migration form karate 0.9.2 to 0.9.3 Issue - javascript evaluation failed i have update karate verions to 0.9.5.RC4.
JavaScript fun is like
function fn(config) {
var OAuth2 = {};
var userAccessToken = Java.type("com.OAuth2Token");
OAuth2.adminUser = function () {
return userAccessToken.getAuthorizationHeader(name, url, users, "ADMIN");
};
config.OAuth2 = karate.toMap(OAuth2);
return config;
}
Feature file with Scenario **worked*
Scenario: <scenarioName>
Given path 'url'
And header Authorization = OAuth2.adminUser()
And def Authorization = OAuth2.adminUser()
And print Authorization
Feature file with Scenario outline not worked
Scenario Outline: <scenarioName>
Given path 'url'
And header Authorization = OAuth2.adminUser()
And def Authorization = OAuth2.adminUser()
And print Authorization
Examples:
| data |
Error : javascript evaluation failed: OAuth2.adminUser(), TypeError: OAuth2.adminUser is not a function in at line number 1 , I am having same error with 0.9.3 and moving function to common feature file.
This is a bug and will be fixed in the next version: https://github.com/intuit/karate/issues/982
A workaround is that you re-init the function for each loop under the Scenario Outline:
Scenario Outline:
* def OAuth2 = karate.call('classpath:com/utils.feature)

Karate Test Framework -Storing credentials outside of github

I have Karate Tests for the APIs which are on Amazon API Gateway. As such, in my Karate Tests I have to provide client_id and client_secret for authentication. I was wondering if there is a way I could store the credentials outside my github repository and use it at run time. Is it possible to do that in Karate ?
Here is how my tests look like:
Feature: API Test all endpoints using Karate
Background:
* configure ssl = true
* url baseUrl
* def res = (env == 'qa'? 'classpath:endpoints/user-login.feature' : 'classpath:endpoints/user-login-dev.feature')
* def token = call read(res)
* def headerData = {Authorization: #(token.nextGen),Accept: 'application/json;v=1'}
* headers headerData
Here is the user-login.feature file
Feature: API Test using Karate
Background:
* configure ssl = true
Scenario: Get authorization header
Given url 'https://api.cloud.xyz.com/oauth2/token?client_id=****&client_secret=****&grant_type=client_credentials'
When method get
Then status 200
And def tokenType = response.token_type
And def accessToken = response.access_token
* def nextGen = tokenType + ' '+ accessToken
* def headerData = {Authorization: nextGen,Accept: 'application/json;v=1'}
Any pointers on how I can have the client_id and client_secret passed to the tests at run time and not stored in github.
Thanks in advance!
The easiest way would be to pass them as Java system properties via the command-line, which you can very easily do from a test or from a CI triggered run.
Refer to the documentation here: https://github.com/intuit/karate#dynamic-port-numbers
An example of how it could look like in your case:
Given url 'https://api.cloud.xyz.com/oauth2/token'
And param client_id = karate.properties['client.id']
And param client_secret = karate.properties['client.secret']
And param grant_type = 'client_credentials'
And on the command-line:
mvn test -DargLine="-Dclient.id=**** -Dclient.secret=**** -Dkarate.env=qa"