Karate: How to send variable to json file - karate

I'm trying to create a dynamic request that should receive 2 parameters (username and password). To do so, I defined the below JSON file:
{
"grant_type": "password",
"client_id": "myClient",
"username": "#(username)",
"password": "#(password)"
}
To call my JSON, I set the below feature file where my intention is to define a variable for each parameter i want to send
Scenario: Get Sugar access token
Given url baseUrl
And path 'oauth2/token'
And def username = 'user'
And def password = 'password'
And def requestBody = read('classpath:jsonFiles/requests/authRequest.json')
When request requestBody
And method POST
Then status 200
* print 'Response: ', response
Unfortunately, when I run the scenario, i'm getting below error message
10:59:59.111 [main] INFO com.intuit.karate - Karate version: 1.4.0-SNAPSHOT
10:59:59.286 [main] INFO com.intuit.karate.Suite - backed up existing 'target\karate-reports' dir to: target\karate-reports_1672160399285
10:59:59.303 [main] INFO c.intuit.karate.core.FeatureRuntime - found scenario at line: 4
11:00:00.174 [main] ERROR com.intuit.karate - src/test/java/myCompany/testautomation/features/auth/getToken.feature:11
And def requestBody = read('classpath:jsonFiles/requests/authRequest.json')
js failed:
>>>>
01: read('classpath:jsonFiles/requests/authRequest.json')
<<<<
org.graalvm.polyglot.PolyglotException: not found: jsonFiles/requests/seugarAuth/authRequest.json
- com.intuit.karate.resource.ResourceUtils.getResource(ResourceUtils.java:126)
- com.intuit.karate.core.ScenarioFileReader.toResource(ScenarioFileReader.java:129)
- com.intuit.karate.core.ScenarioFileReader.readFileAsStream(ScenarioFileReader.java:99)
- com.intuit.karate.core.ScenarioFileReader.readFileAsString(ScenarioFileReader.java:95)
- com.intuit.karate.core.ScenarioFileReader.readFile(ScenarioFileReader.java:54)
- com.intuit.karate.core.ScenarioEngine.lambda$new$0(ScenarioEngine.java:120)
- <js>.:program(Unnamed:1)
src/test/java/myCompany/testautomation/features/auth/getToken.feature:11

The use of classpath: makes more sense for Java projects. It looks like you are using the Visual Studio code extension, in which case your workspace root folder will be the classpath unless to switch to "Maven mode" or equivalent: https://marketplace.visualstudio.com/items?itemName=karatelabs.karate#run-mode
Or another option is to use a Java "runner" and use the Java extension for VS Code.
If all that above doesn't make sense, for now just keep things simple and use relative paths. For example if authRequest.json is side-by-side with your feature file, this would work:
* def requestBody = read('authRequest.json')
Relative paths and the this: prefix can be used, but I leave that to you to research: https://github.com/karatelabs/karate#path-prefixes

Related

Dynamically using testdata based on env in karate framework

I have test data based on environments. Need to use respecitive environment test data for webservice testing in karate framework.
So I have config file which load variable based on environment. I have edited my feature file as runtime variable to get the path accordingly something like below. It looks I am missing something or might not using right way.
I have kept testdata based on environment in my folders as like below
TestData
|->DEV
|-> applicationFeature_scenorio1_Req.json
|->SIT
|-> applicationFeature_scenorio1_Req.json
|->UAT
|-> applicationFeature_scenorio1_Req.json
|->PROD
|-> applicationFeature_scenorio1_Req.json
Please help me on this how to pick data based on environment.
Config file
dev: {
baseUrl: 'https://applicationsit.company.com',
TestData : 'TestData/DEV'
},
sit: {
baseUrl: 'https://applicationsit.company.com',
TestData : 'TestData/SIT'
},
uat: {
baseUrl: 'https://applicationuat2.company.com',
TestData : 'TestData/UAT'
},
prod: {
baseUrl: 'https://applicationnewprod.company.com',
TestData : 'TestData/PROD'
}
Feature file
Background:
* def testdata = TestData
      
#smoke #prod
Scenario: This is success scenario
Given url baseUrl
Given path '/cryptoService'
And request read('#(testdata)/applicationFeature_scenorio1_Req.json')
When method POST
Then status 200
* def encryptedPayload = response
Error found in karate
And request read('#(testdata)/applicationFeature_scenorio1_Req.json')
js failed:
>>>>
01: read('#(testdata)/applicationFeature_scenorio1_Req.json')
<<<<
org.graalvm.polyglot.PolyglotException: java.io.FileNotFoundException: /tmp/workspace/application-prod-test/Continous_Testing/KarateConfigDir/#(testdata)/applicationFeature_scenorio1_Req.json (No such file or directory)
- com.intuit.karate.resource.FileResource.getStream(FileResource.java:98)
- com.intuit.karate.core.ScenarioFileReader.readFileAsStream(ScenarioFileReader.java:99)
- com.intuit.karate.core.ScenarioFileReader.readFileAsString(ScenarioFileReader.java:95)
- com.intuit.karate.core.ScenarioFileReader.readFile(ScenarioFileReader.java:53)
- com.intuit.karate.core.ScenarioEngine.lambda$new$0(ScenarioEngine.java:124)
- <js>.:program(Unnamed:1)
The '#(var)' system works only for JSON: https://github.com/karatelabs/karate#rules-for-embedded-expressions
Karate syntax is mostly JS and variables just work normally. With that in mind please make this change:
And request read(testdata + '/applicationFeature_scenorio1_Req.json')

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 can I use location from Response Headers in the next request? [duplicate]

This question already has an answer here:
How to get id in responseHeaders location?
(1 answer)
Closed last year.
I'm perfoming some test using Karate test.
1st a Post that is expecting a 201 and a location.
2nd use the location from response to perfom a get.
Does anyone know how can I do this with Karate?
The following code is my try, after many other.
Given path 'alpha/test'
And request
"""
{
"id": '#(uuid)',
"content": "test",
"isActive": true
}
"""
When method post
Then status 201
And def endpointLocation = responseHeaders['Location']
And print endpointLocation
Given url 'endpointLocation'
When method get
Then status 200
And match response ==
"""
{
"id": '#(uuid)'
}
"""
But i'm getting:
18:30:12.819 [main] ERROR com.intuit.karate - org.apache.http.client.ClientProtocolException, http call failed after 252 milliseconds for URL: endpointLocation
18:30:12.820 [main] ERROR com.intuit.karate - http request failed:
org.apache.http.client.ClientProtocolException
testApi.feature:263 -
org.apache.http.client.ClientProtocolException
I'm not figuring it out why.
[EDIT]
After sugestion from Peter, that I Thanks!
The print return:
08:59:33.610 [main] INFO com.intuit.karate - [print] [
"https://www.test.com/enpoint/4603b043-ea8c-470d-a5a9-2aa50aea4f75"]
Now I'm calling
Given url endpointLocation
and I'm getting
08:59:33.611 [main] ERROR com.intuit.karate - http request failed: java.net.URISyntaxException: Illegal character in scheme name at index 0: ["https://www.test.com/enpoint/4603b043-ea8c-470d-a5a9-2aa50aea4f75"]
fraudMgmtApi.feature:263 - java.net.URISyntaxException: Illegal character in scheme name at index 0: ["https://www.test.com/enpoint/4603b043-ea8c-470d-a5a9-2aa50aea4f75"]
I was trying also to trim the first and last caracters, creating a:
def trim =
"""
function(myText) { result = myText.substring(1, myText.length-1) }
"""
Or myText.slice(1,-1)
From the error message: http call failed after 252 milliseconds for URL: endpointLocation
It is clear you are setting the url wrong. First try hard-coding it, then make this change, if the endpointLocation variable is set correctly. You can print it to check.
Given url endpointLocation

Karate: How to test multipart form-data endpoint? [duplicate]

This question already has an answer here:
How to upload CSV file as a post request in Karate 0.9.0 version?
(1 answer)
Closed 2 years ago.
I have an file upload endpoint (/document) in a controller defined as follows:
#RestController
public class FileUploadController {
#Autowired
private PersonCSVReaderService personCSVReaderService;
#PostMapping(value = "/document", consumes= {MediaType.MULTIPART_FORM_DATA_VALUE})
public void handleFileUpload3(#RequestPart("file") MultipartFile file, #RequestPart("metadata") DocumentMetadata metadata) {
System.out.println(String.format("uploading file %s of %s bytes", file.getOriginalFilename(), file.getSize()));
personCSVReaderService.readPersonCSV(file, metadata);
}
}
I can test this endpoint using Advanced Rest Client (ARC) or Postman by defining the "file" part referencing the people.csv file and a text part specifying some sample metadata JSON.
Everything works fine and I get a 200 status back with the people.csv file contents being written to the console output by the service method:
uploading file people.csv of 256 bytes
{Address=1, City=2, Date of Birth=6, Name=0, Phone Number=5, State=3, Zipcode=4}
Person{name='John Brown', address='123 Main St.', city='Scottsdale', state='AZ', zipcode='85259', phoneNumber='555-1212', dateOfBirth='1965-01-01'}
Person{name='Jan Black', address='456 University Dr.', city='Atlanta', state='GA', zipcode='30306', phoneNumber='800-1111', dateOfBirth='1971-02-02'}
Person{name='Mary White', address='789 Possum Rd.', city='Nashville', state='TN', zipcode='37204', phoneNumber='888-2222', dateOfBirth='1980-03-03'}
Now, I want to run this as an automated Karate test. I have specified a MockConfig :
#Configuration
#EnableAutoConfiguration
#PropertySource("classpath:application.properties")
public class MockConfig {
// Services ...
#Bean
public PersonCSVReaderService personCSVReaderService() {
return new PersonCSVReaderService();
}
// Controllers ...
#Bean
public FileUploadController fileUploadController() {
return new FileUploadController();
}
}
I also have a MockSpringMvcServlet in the classpath and my karate-config.js is :
function fn() {
var env = karate.env; // get system property 'karate.env'
if (!env) {
env = 'dev';
}
karate.log('karate.env system property was:', env);
var config = {
env: env,
myVarName: 'someValue',
baseUrl: 'http://localhost:8080'
}
if (env == 'dev') {
var Factory = Java.type('MockSpringMvcServlet');
karate.configure('httpClientInstance', Factory.getMock());
//var result = karate.callSingle('classpath:demo/headers/common-noheaders.feature', config);
} else if (env == 'stg') {
// customize
} else if (env == 'prod') {
// customize
}
return config;
}
Other karate tests run ok using the mock servlet.
However, when I try this test to test the /document endpoint:
Feature: file upload end-point
Background:
* url baseUrl
* configure lowerCaseResponseHeaders = true
Scenario: upload file
Given path '/document'
And header Content-Type = 'multipart/form-data'
And multipart file file = { read: 'people.csv', filename: 'people.csv', contentType: 'text/csv' }
And multipart field metadata = { name: "joe", description: "stuff" }
When method post
Then status 200
I get this error:
16:14:42.674 [main] INFO com.intuit.karate - karate.env system property was: dev
16:14:42.718 [main] INFO o.s.mock.web.MockServletContext - Initializing Spring DispatcherServlet ''
16:14:42.719 [main] INFO o.s.web.servlet.DispatcherServlet - Initializing Servlet ''
16:14:43.668 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$a4c7d08f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
16:14:43.910 [main] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.0.14.Final
16:14:44.483 [main] INFO o.s.s.c.ThreadPoolTaskExecutor - Initializing ExecutorService 'applicationTaskExecutor'
16:14:44.968 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 2 endpoint(s) beneath base path '/actuator'
16:14:45.006 [main] INFO o.s.web.servlet.DispatcherServlet - Completed initialization in 2287 ms
16:14:45.066 [main] INFO c.i.k.mock.servlet.MockHttpClient - making mock http client request: POST - http://localhost:8080/document
16:14:45.085 [main] DEBUG c.i.k.mock.servlet.MockHttpClient -
1 > POST http://localhost:8080/document
1 > Content-Type: multipart/form-data
16:14:45.095 [main] ERROR com.intuit.karate - http request failed: null
file-upload.feature:13 - null
HTML report: (paste into browser to view) | Karate version: 0.9.2
I can only assume that the arguments did not conform to what my endpoint was expecting - I never entered the endpoint in debug mode.
I tried this:
And multipart file file = read('people.csv')
And multipart field metadata = { name: "joe", description: "stuff" }
But that was a non-starter as well.
What am I doing wrong? The people.csv is in the same folder as fileupload.feature, so I am assuming it is finding the file. I also looked at upload.feature file in the Karate demo project given here:
Karate demo project upload.feature
But I could not make it work. Any help appreciated. Thanks in advance.
The Postman request looks like this:
EDIT UPDATE:
I could not get the suggested answer to work.
Here is the feature file:
Feature: file upload
Background:
* url baseUrl
* configure lowerCaseResponseHeaders = true
Scenario: upload file
Given path '/document'
And header Content-Type = 'multipart/form-data'
* def temp = karate.readAsString('people.csv')
* print temp
And multipart file file = { value: '#(temp)', filename: 'people.csv', contentType: 'text/csv' }
And multipart field metadata = { value: {name: 'joe', description: 'stuff'}, contentType: 'application/json' }
When method post
Then status 200
And here is the console output from running that test:
09:27:22.051 [main] INFO com.intuit.karate - found scenario at line: 7 - ^upload file$
09:27:22.156 [main] INFO com.intuit.karate - karate.env system property was: dev
09:27:22.190 [main] INFO o.s.mock.web.MockServletContext - Initializing Spring DispatcherServlet ''
09:27:22.190 [main] INFO o.s.web.servlet.DispatcherServlet - Initializing Servlet ''
09:27:23.084 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$a4c7d08f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
09:27:23.327 [main] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.0.14.Final
09:27:23.896 [main] INFO o.s.s.c.ThreadPoolTaskExecutor - Initializing ExecutorService 'applicationTaskExecutor'
09:27:24.381 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 2 endpoint(s) beneath base path '/actuator'
09:27:24.418 [main] INFO o.s.web.servlet.DispatcherServlet - Completed initialization in 2228 ms
09:27:24.435 [main] INFO com.intuit.karate - [print] Name,Address,City,State,Zipcode,Phone Number,Date of Birth
John Brown,123 Main St.,Scottsdale,AZ,85259,555-1212,1965-01-01
Jan Black,456 University Dr.,Atlanta,GA,30306,800-1111,1971-02-02
Mary White,789 Possum Rd.,Nashville,TN,37204,888-2222,1980-03-03
09:27:24.482 [main] INFO c.i.k.mock.servlet.MockHttpClient - making mock http client request: POST - http://localhost:8080/document
09:27:24.500 [main] DEBUG c.i.k.mock.servlet.MockHttpClient -
1 > POST http://localhost:8080/document
1 > Content-Type: multipart/form-data
09:27:24.510 [main] ERROR com.intuit.karate - http request failed: null
file-upload.feature:14 - null
HTML report: (paste into browser to view) | Karate version: 0.9.2
Note: people.csv file reads successfully and prints in console.
Refer to this part of the docs: https://github.com/intuit/karate#read-file-as-string
So make this change:
* def temp = karate.readAsString('people.csv')
And multipart file file = { value: '#(temp)', filename: 'people.csv', contentType: 'text/csv' }
EDIT: my bad, also refer: https://github.com/intuit/karate#multipart-file
Feature: upload csv
Background: And def admin = read('classpath:com/project/data/adminLogin.json')
Scenario:
Given url baseUrl
And header Authorization = admin.token
And multipart file residentDetails = { read:'classpath:com/project/data/ResidentApp_Details.csv', filename: 'ResidentApp_Details.csv' }
When method POST
Then status 200
Note: Add only one extra line i.e And multipart file residentDetails = { read:'classpath:com/project/data/ResidentApp_Details.csv', filename: 'ResidentApp_Details.csv' }

Getting Error. java.lang.RuntimeException: unexpected 'configure' key: 'afterScenario'

here is a similar code that im usein
Feature: Create a company instance
Background: Creating the company instance in background
* url baseUrl
* def login = call read('classpath:blackbook/common/getToken.feature')
* def newCI = call read('../endpoints/create_companyinstance.feature')
* def id = newCI.response.data.id
* configure afterScenario =
"""
function(){
var ciID = karate.get('id');
console.log(ciID);
}
"""
After that i will run it. and the login call and newCI call runs fine but then i will get the following error
[ERROR] Scenario: Doing a get call and then some verifications Time
elapsed: 0.005 s <<< ERROR!
java.lang.RuntimeException: unexpected 'configure' key:
'afterScenario'
Please forgive noobness.
Jawad - apologies as I am responsible for prematurely adding documentation for un-released features.
"After hooks" is available in 0.7.0.RC2 - it would be great if you can try that and confirm if it looks good. Even though it is a "release candidate" - as the dev of Karate, I can confirm it should be good for use - and you will not have any breaking changes when "final" arrives (soon).