How to edit configured headers in karate framework - karate

In my framework I have headers.js file. I am calling that js file on background of every feature file using the command * configure headers = read('headers.js'). This working as expected, some scenarios I need to change the 'client-id' value. For example headers.js has a client-id=xyz, I need to change client-id=abc for couple of scenarios rest all are using client-id as xyz (my headers have 20 different values, I don't want to write that in require feature files) Is there any way to modify one value from the headers.js file and use that as a header for the request?

The configured headers always is the last to be applied. So the best solution for you is to create a second headers-xyz.js and for only those needed scenarios do * configure headers = read('headers-xyz.js').
It is up to you to refactor the js code so that you can re-use most of it. For example, this might work:
function() {
var fun = karate.read('headers.js');
var res = fun();
res['client-id'] = 'xyz';
return res;
}

Related

Flowable - concat dynamic variable and a string in http task (url)

I need to convert the base url according to the production and other environments.
I am using script task before a http task to perform this logic.
baseUrl = http://localhost:8080
baseUrl, is the output of the script task. Now I need to add this base url as a prefix in http task url
Url = ${baseUrl}/application/find (something like this).
I am getting the following issue
Unknown Property used in the expression ${baseUrl}/application/find
Script
var env = execution.getVariable("env")
if(env == "prod") {
var baseUrl = "http://localhost:8080";
execution.setVariable("baseUrl", baseUrl);
}
Please assist.
This typically means that it is unable to find a property in the expression (as the message says). The only expression you are using is baseUrl which means that the issue is around the baseUrl. The concatenation as you have done it is correct and doesn't need to have an adaption.
You should check if the variable really exists, this you can do by introducing a wait state before your HTTP task and check afterwards if the variable is created. Rather than using outputs, you can also use the Java API in your script task to create the variable:
execution.setVariable("baseUrl", "http://localhost:8080");
Assuming you are using Spring Boot, for your specific use-case it would be also an option to use the application.properties to specify your base-url and then refer to the baseUrl with the following expression:
${environment.getProperty("baseUrl")}/application/find
This will allow you to change the baseUrl independent of your process definition.

Cookies aren't applying from karate-config.js

I have faced a problem with setting global cookies from karate-config.js file.
I have two features:
login.feature as helpers
postItem.feature as test, which is also using cookieKey in path.
In login.feature I get this cookieKey like this:
* def cookieKey = responseCookies.user_cookie_key.value
To make postItem, I need to call login.feature, which contains credentials and cookieKey as part of path, to get cookies, which are using for postItem.
If I call login.feature inside postItem.feature in Background section, everything works fine.
But I want to move calling login.feature to karate-config.js because I dont want to put this to each future features.
And what I did in karate-config.js:
var response = karate.call('classpath:/helpers/features/login.feature');
var cookieKey = response.cookieKey;
karate.set('cookieKey', cookieKey);
I receive cookieKey and able to re-use it in my feaure postItem like this:
* def cookieKey = karate.get('cookieKey')
But problem in the next, cookies from login.feature, which is calling from karate-config.js is not applying for postItem because call is covered in variable, but even without variable, they aren't applying.
Could you help me to handle this?
Maybe you just need to use configure cookies: https://github.com/karatelabs/karate#configure
I also think if you use the alternate method signature of karate.call() it will work: https://github.com/karatelabs/karate#call-vs-read
var response = karate.call(true, 'classpath:/helpers/features/login.feature');

Could I get some help on changing auth tokens mid test? [duplicate]

In my framework I have headers.js file. I am calling that js file on background of every feature file using the command * configure headers = read('headers.js'). This working as expected, some scenarios I need to change the 'client-id' value. For example headers.js has a client-id=xyz, I need to change client-id=abc for couple of scenarios rest all are using client-id as xyz (my headers have 20 different values, I don't want to write that in require feature files) Is there any way to modify one value from the headers.js file and use that as a header for the request?
The configured headers always is the last to be applied. So the best solution for you is to create a second headers-xyz.js and for only those needed scenarios do * configure headers = read('headers-xyz.js').
It is up to you to refactor the js code so that you can re-use most of it. For example, this might work:
function() {
var fun = karate.read('headers.js');
var res = fun();
res['client-id'] = 'xyz';
return res;
}

Karate: Call the same feature file with multiple url paths

I need to run the tests in a feature file with multiple endpoint urls. All the tests hit REST endpoints and I need to hit multiple endpoints for the same tests. I came up with the two below working solutions, but they both have maintenance overhead. So I was wondering if there is a better solution.
1. Add a dummy feature file:
Add a new dummy feature file and call the actual feature file with the endpoint url as argument like below. The actual feature file has test data of 100 rows. So when this was executed individually, the cucumber report showed 100 scenarios and it was easy to see how many passed/failed. But when executed with the dummy feature file, the report shows only 1 scenario from the dummy feature file and shows all the 100 test cases underneath it.
Scenario: Call actual feature file with internal URL
* def params = { endpoint_url: 'internal' }
* karate.callSingle('actualTestCases.feature', params);
Scenario: Call actual feature file with public URL
* def params = { endpoint_url: 'public' }
* karate.callSingle('actualTestCases.feature', params);
2. Duplicate the test data rows and add a new column endpoint_url:
In the test data, add duplicate test data rows, and add a column 'endpoint_url' with values like 'internal', 'public'. Use this column data in the actual feature file. This has the overhead that test data needs to be duplicated. I have more than 3000 rows of test data.
|testcaseName|email|endpoint_url
|"Valid Parameters"|["validtests#test.com"]|"internal"
|"Valid Parameters"|["validtests#test.com"]|"public"
Just use JSON as input file.
If you need to create even more dynamic urls, use karate.map to fill the variable with more values and pass to your feature.
Remember to use Verbs (When, Then, And), so report will show the content.
Otherwise you need to configure manually.
Input file urls.json:
[
{"url" : "https://jsonplaceholder.typicode.com/users/1"},
{"url" : "https://jsonplaceholder.typicode.com/users/2"},
{"url" : "https://jsonplaceholder.typicode.com/users/3"}
]
Main feature file main.feature:
Feature: Test REST
Scenario: Dynamic URL Test
When def urls = read('./urls.json')
Then call read('_sub.feature') urls
Sub feature file _sub.feature:
#ignore
Feature:
Scenario: Call URL
* def keyword = __arg.url
Given driver keyword
Then retry(5, 1000).waitUntil("document.readyState == 'complete'")
Use 2 loops or a Scenario Outline:
Scenario Outline:
* call read('actualTestCases.feature')
Examples:
| endpoint_url |
| internal |
| public |
Note that endpoint_url will be visible to the "called" feature, so you don't need to worry about passing parameters. Actually I think you can do all of this in a single feature file.

Returning Variable from Feature File With Multiple Scenarios - Karate

We already know that scenarios are run paralelly. But we had the case where we need to return variables from feature files (that are gonna be called from another feature file).
We had multiple scenarios in the feature file as below:
#mutation
Feature: Test GraphQL Create Item
Background:
Given url baseUrl
* configure headers = { Authorization: '#(token)' }
#negative
Scenario: Create item unauthorized
* configure headers = { Authorization: ""}
#Features calling function and others
And match response.errors[0].message == errorUnauthorized
Scenario: Create story authorized
#Features calling function and others
And def idItem = response.data.CreateItem.id
We are reusing the feature file above to obtain variable to be used on another feature file. However it seems that the other feature files fail intermittently complaining the variables obtained from the other feature file is null.
My assumption is that the returned variable is not returned properly since there are more than one scenarios on the feature file. We tried deleting the #negative scenario and have only exactly 1 scenario. Suddenly the intermittent failures gone.
Is there any way to avoid this intermittent failures while still retaining the ability to run scenarios paralelly?
Thanks
Can't say without seeing your code. But you can try using the #parallel=false annotation in the "calling" feature file: https://github.com/intuit/karate#parallelfalse
Otherwise this may be a bug in Karate - so please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue