How to call another features with headers on condition [duplicate] - karate

This question already has an answer here:
How to compare 2 JSON objects that contains array using Karate tool and feature files
(1 answer)
Closed 1 year ago.
I have created a common library with steps.feature source that we used in different repos of tests.
But in one scope of tests we need to use header Datasource-Type: 'test' and in others not.
Sample of feature where we call other steps.feature:
Background:
* header Datasource-Type = 'test'
* def getToken = call read('classpath:com/coommons/karate/token-service.feature')
* configure headers = { Authorization: #(getToken), Datasource-Type : 'test'}
* def createSmth = call read('classpath:com/commons/karate/createSmth.feature')
* def accId = createSmth.accId
* def id = createSmth.id
Scenario: Do Smth
* def createSmthElse = call read('classpath:com/commons/karate/createSmthElse.feature') { Token: #(token) }
* call read('classpath:com/commons/karate/putSmth.feature')
* def createSmthElseAnother = call read('classpath:com/commons/karate/createSmthElseAnother.feature')
Given url featureService
And path '/.../details/employeeSorting'
And request {}
When method post
Then status 200
I am satisfied with the option to globally set this header in one of the projects in karate-config.js, but it does not work correctly.
karate.configure('headers', { 'Datasource-Type': 'test' });
Headers are passed for some reason only for the first call (only for * def getToken = call read('classpath:com/coommons/karate/token-service.feature') )
In case with *configure headers {} my header appears only in Given When Then post featureService, but not in other calling steps.feature.
Please, advice how to set this header Datasource-Type: 'test' everywhere from feature where we call other steps.feature and without hardcoded this header directly in steps.

If you do karate.configure() the headers should apply to all calls, so if it doesn't happen - it can be a bug, so please follow this process: https://github.com/karatelabs/karate/wiki/How-to-Submit-an-Issue
There was a bug related to this, so please ensure you are on the latest version: 1.1.0 or 1.2.0.RC1
Also note that if you set a header to null it will not be passed at all.
And finally let me say that too many calls and re-use can be a bad thing, so please read this: https://stackoverflow.com/a/54126724/143475

Related

karate: Accept = 'application/xml' header not working as expected [duplicate]

I have this header which is in a .js file and I am reading this header using
* configure headers = read('classpath:services/Headers/distheader.js')
Question #1
How can I edit one of the headers in this file at run-time using my scenario data?
I tried setting * header 'xyz' = 'value' but it doesn't edit it.
Question #2
If I want to delete one of the headers, how is it possible?
So 90% of your scenarios are "happy path", and you have a headers JS configured.
Now you need some scenarios to have more (or less headers). One option is to hard-code the headers for those scenarios, note that you can do * configure headers = null to disable the "auto" headers. Then use the header (or headers) keyword and build headers manually.
Another option is that you can invoke the headers function and get a JSON - and then mutate (add / remove keys) before setting headers manually. For example:
# you can disable headers if needed
* configure headers = null
# headers.feature is: function(){ return { a: 1, b: 2 } }
* def fun = read('headers.feature')
* def temp = fun()
* remove temp.a
* set temp.c = 3
Given url 'https://httpbin.org'
And path 'anything'
And headers temp
When method get
Then status 200
So the advantage above is in case your headers routine is complex, you can re-use it - but still have fine-grained control.

Karate: How to check if any of the configured headers are missing [duplicate]

I have this header which is in a .js file and I am reading this header using
* configure headers = read('classpath:services/Headers/distheader.js')
Question #1
How can I edit one of the headers in this file at run-time using my scenario data?
I tried setting * header 'xyz' = 'value' but it doesn't edit it.
Question #2
If I want to delete one of the headers, how is it possible?
So 90% of your scenarios are "happy path", and you have a headers JS configured.
Now you need some scenarios to have more (or less headers). One option is to hard-code the headers for those scenarios, note that you can do * configure headers = null to disable the "auto" headers. Then use the header (or headers) keyword and build headers manually.
Another option is that you can invoke the headers function and get a JSON - and then mutate (add / remove keys) before setting headers manually. For example:
# you can disable headers if needed
* configure headers = null
# headers.feature is: function(){ return { a: 1, b: 2 } }
* def fun = read('headers.feature')
* def temp = fun()
* remove temp.a
* set temp.c = 3
Given url 'https://httpbin.org'
And path 'anything'
And headers temp
When method get
Then status 200
So the advantage above is in case your headers routine is complex, you can re-use it - but still have fine-grained control.

How do use the same variable in background and feature being called

With Karate 1.1.0, you could define a variable in the background, ex "* path = 'www.google.ca', call a "helper" feature at the top of of a scenario, which was using the same variable name inside it, then later in your scenario use the same variable again. Ex., helper feature would have "* path = 'www.google.ca' in it's 1 and only scenario, which would say something like "Given path '/help.html'". Then in your main feature, after you have called the helper feature you would use the variable again, something like "Given path '/fun.html'". When everything ran it would be fine, the helper feature would point to it's path and the main feature would point to it's path.
Now with Karate 1.2.0.RC6, I don't have to declare path in the helper feature, but with that change the path is being concatenated in the main feature/scenario. So when the scenario executes, it calls the helper feature fine, but then instead of it's path being "www.google.ca/fun.html" it comes "www.google.ca/help.html/fun.html". Any ideas why or better how to resolve it?
Here's the actual code:
Feature: Update calls on an account
Background:
* url url
* header Authorization = token
* path 'care/v1.1/account/'
Scenario: theScenario
* def fullResponse = call read('init/movein_ADD.feature') { payloadFilename: 'data/account_id_call_ADD_MOVEIN_No_GovtId.json'}
* def updatePayload = read('data/account_id_call_add_MOVEIN_Both_GovtId.json')
* set updatePayload.callNumber = fullResponse.response.callNumber
* set updatePayload.id = fullResponse.response.id
* set updatePayload.orderNumber = fullResponse.response.orderNumber
* set updatePayload.stagedServices = null
* header Accept = json
* header Content-Type = json
Given path ENCODE('16382-8') + '/call/update'
And request updatePayload
When method POST
Then status 200
Helper feature:
#ignore
Feature: Helper feature file to create Move-In Service order request
Scenario: helper Scenario
* url url
* path 'care/v1.1/account/'
* def payload = read(payloadFilename)
#set up request and execute
* header Accept = json
* header Content-Type = json
Given path 'MTYzODJAQDg=/call/add'
And request payload
When method POST
Then status 200
The answer, change to declare a variable in the background of the main feature file, set the path to that variable in the helper feature scenario and again the main feature scenario right after the call to the helper feature file has worked. Going to cause some big refactoring on our part based on this change.

Can we pass method and path while calling feature from inside another feature

When you call a feature (with a few Scenarios) from inside another feature, I want to pass method and path
as these are common scenarios - called from two different endpoints where base url remain same but path and also the method differ.
This situation arise because I am trying to put the common scenarios in a feature and call that feature from other feature files where the scenarios are all common and they differ only in path and method.
I have referred to this issue: 'https://github.com/intuit/karate/issues/239' and know that it is possible but in my case I need to pass the path and method as arguments while calling the feature file because that is the only thing differing with two modules calling the common scenarios.
So the question is can we pass path and method as parameters while calling a feature file. Currently I am getting error but do not understand why it should fail.
I tried the following:
booking.feature
Background:
* def pathVar = '/bookings'
Scenario: Calling basic validation feature for create booking module
* call read('classpath:feature/basic-validations.feature') {path1: '#(pathVar)', action: 'post'}
basic-validations.feature
Background:
* url baseURL
* header Accept = 'application/json'
* def data = read(datafile)
* header API-Version = 1
* path '#(path1)'
* header Authorization = 'Bearer' + data.booking.token
Scenario: Empty request validation
Given request {}
When method '#(action)'
Then status 400
Scenario: Request-Body element is empty or null.
Given def req = ({ "request_body": null })
And request req
When method '#(action)'
Then status 400
Scenario: When parameter value for name in request body is incorrect.
Given def req = ({ "request_body": [ { "name": "shipment_standard_booking", "action":
"create", "path": "/standardBooking", "body": data.booking.standardBooking.requestBody }]
})
And def name = 'test'
And set req.request_body[*].name = name
And request req
When method '#(action)'
Then status 400
And match $.debugMessage == 'Validations failed due to bad input payload request. WorkItem
name (' +name+ ') is invalid'
The path step can take variables. The method step also can take a variable: https://github.com/intuit/karate#method
* def methodVar = 'post'
* url foo
* request bar
* method methodVar
But I totally don't recommend it - or the approach you are taking. Reasons are explained here, please take some time to read it: https://stackoverflow.com/a/54126724/143475
I think you also have mis-understood embedded expressions, so please read this: https://github.com/intuit/karate#rules-for-embedded-expressions
If you still decide to do this and get stuck, you can assume that either Karate does not support what you want to do - or that you need to contribute code.
Also read this for other ideas: https://stackoverflow.com/a/50350442/143475

Karate: Trying to get global headers working [duplicate]

This question already has an answer here:
Is there a way to update the headers in one feature file and use the Auth token from Karate.config.js?
(1 answer)
Closed 1 year ago.
I'm trying to setup a framework to run Graphql calls and create and E2E environment.
I've got the following setup so far but i can't seem to get the headers part of it working. i have managed to set the auth for each request and it all works but as it logs in for each request it doesn't really work as expected.
I want do the following steps:
run a login Test (different usernames valid/invalid)
run a logout test (Ensure token is removed)
Then login with correct user and extract the "set-cookie" header (to use globally for all future requests)
I was trying to use the following:
Karate-config.js
karate.callSingle('classpath:com/Auth/common-headers.feature', config);
headers.js
function fn() {
var headers = {}
headers["set-cookie"] = sessionAccessId
karate.log('Cookie Value: ', headers)
return headers
}
common-headers.feature
Feature: Login to Application and extract header
Background:
* url serverAuthenticateUri
* header Accept = 'application/json'
Scenario: 'Login to the system given credentials'
Given request { username: '#(username)', password: '#(password)'}
When method post
Then status 200
And match $.success == '#(result)'
And def myResult = response
* def sessionAccessId = responseHeaders['set-cookie'][0]
* configure headers = read('classpath:headers.js')
* print 'headers:', karate.prevRequest.headers
feature-file.feature
Feature: sample test script
Background:
* url serverBaseUri
* def caseResp = call read('classpath:com/E2E/POC/CommonFeatures/CreateCaseRequest.feature')
* def caseReqId = caseResp.response.data.createCaseAndRequest.siblings[0].id
* def caseId = caseResp.response.data.createCaseAndRequest.siblings[0].forensicCaseId
* def graphQlCallsPath = 'classpath:com/E2E/POC/GraphQl/intForensic/'
* def commmonFiles = 'classpath:E2E/CommonFiles/'
Scenario: TC1a - Request Server Details from Config DB (1st Run):
Should handle requesting Server Details Data from Config Database.
* def queryFile = graphQlCallsPath + '20-TC1a_req_req_valid_id.graphql'
* def responseFile = graphQlCallsPath + '20-TC1a_resp_req_valid_id.json'
Given def query = read(queryFile)
And replace query.reqId = caseReqId
And request { query: '#(query)' }
When method post
Then status 200
And json resp = read(responseFile)
And replace resp.reqId = caseReqId
And replace resp.caseID = caseId
And match resp == $
I can log in correctly and i get the set-cookie token but this isn't being passed on the feature-file.feature and i get an error saying "not logged in" in the response.
Any help appreciated! I might be looking at this totally wrong and i have tried to follow the shared-scope as much as i can but can't understand in.
Please make this change and hopefully that works !
headers["set-cookie"] = karate.get('sessionAccessId');
Why is explained here: (read the whole section carefully) https://github.com/intuit/karate#configure-headers
EDIT: one more suggestion:
var temp = karate.callSingle('classpath:com/Auth/common-headers.feature', config);
karate.configure('headers', { 'set-cookie': temp.sessionAccessId });
Some extra suggestions:
If you have just started with Karate - based on your question I would suggest you get one flow working in a single Scenario first without any use of call and with nothing whatsoever in karate-config.js. Hard-code everything and get it working first. Use the header keyword to set any headers you need. I also see you are trying to set a set-cookie header (which may work) but Karate has a special keyword for cookie.
And don't even think about callSingle() to start with :)
Once you get that first "hard-coded" flow working, then attempt to configure headers and then only finally try to do "framework" stuff. You seem to have jumped straight into super-complexity without getting the basics right.
Please read this other answer as well, because I suspect that you or someone in your team is attempting to introduce what I refer to as "too much re-use": https://stackoverflow.com/a/54126724/143475 - try not to do this.
Also note that your question is so complex that I have not been able to follow it, so please ask a simpler or more specifc question next time. If you still are stuck, kindly follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue