Is there way in karate to get the assertion status like pass or fail in variable for further processing in java? - karate

In feature file i am writing assertion as
match response contains {token_type: '#string' }
Is there a way to get the output status of the above assertion value like true or false,
so that i can extend that into java for further processing?

The whole point of Karate is to avoid Java, and I don't recommend doing anything else.
But since you insist, if you want to get the equivalent of the above, just do something like this. Yes, you have to use "normal" JS fundas.
* def response = { token_type: 'foo' }
* def isString = typeof(response.token_type) === "string"
* match isString == true

Related

Validate json Payload before passing It

HI there I am making post call using karate And for that I am passing json Payload but before i pass it i want to validate is there any null or empty string present and if yes then Abort the post call and print message empty string or null values cant be accepted.
Thanks in advance!
peter thomas Thank you in advance
This doesn't make sense to me, because if you are preparing this payload yourself, you never need to validate it.
That said, you can run a match anytime.
* def body = { myKey: 'myValue' }
* match body == { myKey: '#string' }
* url 'https://httpbin.org/anything'
* request body
* method post
* status 200
* match response contains deep { json: { myKey: 'myValue' } }
See how the second line does a validation.
Also refer this answer to see how you can programmatically run karate.match() for advanced use-cases: https://stackoverflow.com/a/50350442/143475

How to reuse assertions for scenarios in single feature file using Karate?

I want to assert responseTime of all scenarios. But i do not want to repeat the assertion code in every scenario. Below is my feature file:
Feature: Reqres api test cases
Background: base url
Given url base_url
Scenario: list single user get request
Given path single_user_path
When method get
Then status 200
And assert responseTime < 4000
Scenario: create user using post and inline json payload
* def path = '/users'
Given path path
And request {"name": "morpheus","job": "leader"}
When method post
Then status 201
And assert responseTime < 4000
In the above code block, I want to avoid responseTime assertion duplication. How to achieve this in karate?. Please help.
No this is not supported and not planned either. It is unlikely every API call will have the exact same SLA. Also this is what the Gatling integration is for: https://stackoverflow.com/a/55146463/143475
EDIT as an example of how you can do "reuse" of response assertions:
Feature:
Background:
* def validateResponse =
"""
function() {
var contentType = karate.get("responseHeaders['Content-Type'][0]");
if (contentType !== 'application/json') {
karate.fail('content type is not json');
}
var responseType = karate.get('responseType');
if (responseType !== 'json') {
karate.fail('response type is not json');
}
}
"""
Scenario:
* url 'https://httpbin.org/post'
* request { foo: 'bar' }
* method post
* validateResponse()
Please note that I absolutely don't recommend the above approach because of reasons best explained here: https://stackoverflow.com/a/54126724/143475

Is it possible to use embedded expressions inside an afterScenario block?

I have multiple scenarios in a feature file. At the end of each scenario, I need to "clean up" before the start of the next scenario. My clean up function requires a json object to be passed in. Each scenario has a different object. Therefore, I need to use embedded expression, so dynamic data gets erased.
My setup is like this:
* configure afterScenario =
"""
function(){
var deleteData = { customerData: '#(portfolio)' };
karate.call(deleteData.feature#deletePortfolio', deleteData);
}
And scenario may look something like this:
// here we get a brand new, unused "portfolio" value from a related function.
* table customer1
|portfolio | status |
|portfolio | 200 |
* call read(random.feature#random) customer1
So at the end of the above scenario, I expect the afterScenario to kick in and delete the "portfolio" variable value for that scenario. However, because it's a Java interop inside the afterScenario block, it doesn't recognize Karate's embedded expressions. Any way around this?
The moment you are within a JS block, you are "out" of Karate. So embedded expressions don't work, but "JS style" expressions work.
Read this once to be more clear about this: https://github.com/karatelabs/karate#karate-expressions
So this will work:
* configure afterScenario =
"""
function(){
var deleteData = { customerData: portfolio };
karate.call('deleteData.feature#deletePortfolio', deleteData);
}
Or even:
* configure afterScenario = function(){ karate.call('deleteData.feature#deletePortfolio', { customerData: portfolio }) }
One more tip, karate.get('someVariableName') can get you the value of any variable, any time.
And I do think you are over-engineering your tests, please don't:
https://stackoverflow.com/a/46080568/143475
https://stackoverflow.com/a/60944060/143475
https://stackoverflow.com/a/54126724/143475

Karate: Multiline afterScenario with assertions [duplicate]

This question already has an answer here:
Is it possible to use karate 'match' inside conditional statement?
(1 answer)
Closed 1 year ago.
I have the next code:
* def deleteCallResult = call read('classpath:somepath#deleteCall') { id: #(id) }
Then match deleteCallResult.responseStatus == 204
* def getCallResult = call read('classpath:somepath#getCall') { id: #(id) }
Then match getCallResult.responseStatus == 404
Then match getCallResult.response.title == "Not Found"
And would like to put it in afterScenario snippet (without moving it into a separate feature file):
* configure afterScenario =
"""
function(){ ... }
"""
Does Karate syntax allow to do it? Did not find examples
You may be able to do this if you use the JavaScript match syntax explained here: https://stackoverflow.com/a/50350442/143475
And you can try to call a #ignore Scenario in the same feature. The line below is JS. There is an improvement to this that will be in the next version.
karate.call('same.feature', { some: 'arg' });
But consider what you are asking as not supported. Note that trying to write "clever" tests like this typically lands you in trouble. It is recommended that you keep your main test flows simple.

Using karate built-in functions and api

Ok, so I am going to explain what my scenario is and how I have implemented it using karate. But i am looking for a better way of doing things which make my tests more readable and also want to use karate's api rather than too much javascript.
Scenario: I have a filter parameter for the api endpoint that i am testing and this filter param takes a json object of key-value pairs. So i have done the following:
Have created a filter-template.js as below:
function() {
var filter_params = {
jobId:null,
customerIds:[],
filterValues1:[],
filterValues2:[],
};
return filter_params;
}
I read this template in my karate scenario and because this is a template, at runtime i set the values in this template and run the test. I will have different values for key-value pairs so each test will set its own filter condition.
This is done by writing custom js function that takes the template as argument and also the filter condition values (referring to arg function argument below), sets the passed conditions to specific key's and then returns json object. Code below:
Scenario: Set filter scenario
* def filter_template = call read('filter-template.js')
* def filter_vals_list = [1001,1002]
* def filter_condition = { cnd1: 'foo', cnd2: '#(filter_vals_list)' }
* def setFilter =
"""
function(arg) {
var i;
var filter = arg.template;
filter.jobId = arg.condition.cnd1;
for(i=0;i<arg.condition.cnd2.length;i++)
{
filter.filterValues1.add(arg.condition.cnd2.get(i));
}
return filter;
}
"""
* def getFilter = call setFilter { template: '#(filter_template)',
condition: '#(filter_condition)' }
I then pass the getFilter as a param to my api request.
What I am hoping to understand is:
How can i get away from using JS loops above when setting filter?
Use karate's in-built functions like karate.map(), karate.forEach() to simplify the tests.
Any better approach if possible on tackling this scenario.
Help and guidance much appreciated.
From what I understood, I have simplified your scenario below:
* def filter_vals_list = [ 1001, 1002 ]
* def job_id = 'foo'
* def filter_template =
"""
{
jobId: '#(job_id)',
customerIds: [],
filterValues1: '#(filter_vals_list)',
filterValues2: [],
}
"""
Let me know if I missed anything. Please refer embedded expressions: https://github.com/intuit/karate#embedded-expressions
Now, you can easily use a re-usable JSON for the template, by changing the last step to the below, and yes - embedded expressions work even in re-usable JSON files !
* def filter_template = read('filter-template.json')
You may get even better ideas once you try the data-driven Scenario Outline. So hope that makes it clear how you are un-necessarily complicating things with JS ! You don't even need karate.map() etc.