get the params value from a variable - api

i have one feature file as
Feature: Getting the Token
Background:
header Content-Type 'application/json'
def CookieGenerator = Java.type('com.ade.Helpers.CookiesGenerator');
def endpoints read('classpath: src/test/java/com/ade/resources/endpoints.json')
Given url endpoints.token
Scenario: To check the Schema of the response
Given cookies (new CookieGenerator().getCookieValue())
When method GET
Then status 200
def txnToken = response
#print token
from above code i am getting Token's value as something like this "gdjsgjshjhsjfhsg646"
now i have another feature file where i have to use above Token's value in my query parameter value as
Feature: Testing datent Name and Client
Background:
header Content-Type 'application/json""
def endpoints read('classpath:src/test/java/com/ade/resources/endpoints.json") def CookieGenerator Java.type('com.ade.Helpers.CookiesGenerator");
call read('Token.feature')
Given url baseUrl+endpoints.dit.Client.path
Scenario: To check the Schema of the response
Given def head read('classpath:src/test/java/com/ade/resources/reqpay.json") =
def req head.data[1]
And cookies (new CookieGenerator().getCookieValue())
And request req
And param {txntoken = txnToken}
When method post
Then status 200
from above my endpoint should be like https://something.com/clients?txntoken='gdjsgjshjhsjfhsg646'
but i am getting as https://something.com/clients?txntoken=txnToken
https://something.com/clients?txntoken='gdjsgjshjhsjfhsg646'

Your post is hard to read, as #peter-thomas said, please try formatting it better in the future, or edit the post if I haven't answered your question.
I believe what you're looking for is described in the documentation here
* def signIn = call read('classpath:my-signin.feature') { username: 'john', password: 'secret' }
* def authToken = signIn.authToken
you can see how information can be passed
I also asked a similar question fairly recently here
relevant bit here:
* def key = karate.call('ReadRoundUpSubscription.feature');
* def keyvalue = key.acckey
i prefer to call features like this, and not defining things in the reusable feature.

Related

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

Variables defined at Karate Background is not matching with local Scenario ones

Scenario: I send an image_URL at my Request Body to an endpoint, and I would like to confirm image URL is loaded by asserting from the response (Easy peasy)
Background: Get ready
#Get random image via Java class
* def dataGenerator = Java.type('Com.helpers.DataGenerator')
* def randomImage = dataGenerator.getImage()
Scenario: Pass Image_URL, assert image URL is in the response
Given url myUrl
And request
"""
{
"image": { "upload_url": #(randomImage) },
}
"""
When method POST
* print "=========image URL============== " + response.metadata.image_url
* print "=========random Image============== " + (randomImage)
Then status 201
Then match response.metadata[*].image_url == (randomImage)
The response is something like this:
{
"metadata": {
....,
"image_url": "https://link/image.jpeg",
....}
}
My issue:
`"response.metadata.image_url"` from response is different than `(randomImage)`, hence assertion is failing.
When I manually run from the postman, Response "image_url" is matching with request body "upload url"
From my understanding,
* def randomImage should be called once before Every Scenario, so it should be the exact same entire Scenario during runtime.
Not sure if I am missing some obvious concept. Curious to see any guidance on this one
Versions:
<java.version>1.8</java.version>
<maven.compiler.version>3.8.1</maven.compiler.version>
<maven.surefire.version>2.22.2</maven.surefire.version>
<artifactId>karate-junit5</artifactId>
<karate.version>1.1.0</karate.version>
Also, my Java Helper class is working fine, but I can add it if needed.

How do you make HTTP requests with Raku?

How do you make HTTP requests with Raku? I'm looking for the equivalent of this Python code:
import requests
headers = {"User-Agent": "python"}
url = "http://example.com/"
payload = {"hello": "world"}
res = requests.get(url, headers=headers)
res = requests.post(url, headers=headers, json=payload)
You may want to try out the recent HTTP::Tiny module.
use HTTP::Tiny;
my $response = HTTP::Tiny.new.get( 'https://example.com/' );
say $response<content>.decode
After searching around a bit, I found an answer in the Cro docs.
use Cro::HTTP::Client;
my $resp = await Cro::HTTP::Client.get('https://api.github.com/');
my $body = await $resp.body;
# `$body` is a hash
say $body;
There's more information on headers and POST requests in the link.
I want to contribute a little more. There is a fantastic module named WWW.
It's very convenient to make 'gets' that receive json because it can be parsed automagically.
In their example:
use WWW;
my $response = jget('https://httpbin.org/get?foo=42&bar=x');
You can examine the objects using the basic functionalities of arrays and hashes, for example to extract the values of my response you can use:
$response<object_you_want_of_json><other_nested_object>[1]<the_last_level>
Here the number [1] are a nested list inside a hash, and the properties are the same. Welcome to the raku community !!!

Authenticated api call to VALR - Python 3.8

I'm trying to make an authenticated api call to VALR crypto exchange as first step towards automated trading. They provide most of the code so I thought it would be easy even as a non coding techie. The code below does actually create the correct HMAC SHA512 signature using the API Secret provided for testing but I have a problem in passing this result along to the next section of code to request balances (starting at line 17). If I cut and paste the result/displayed 'signature' and 'timestamp' (after running the code) back into the code it does in fact work. So what changes do I need to make the code automatically pick up the signature and timestamp. The user defined function appears to keep all parameters "secret" from the rest of the code, especially after using return.
import time
import hashlib
import hmac
def sign_request( api_key_secret,timestamp, verb,path,body=""):
payload = "{}{}{}{}".format(timestamp, verb.upper(), path, body)
message = bytearray(payload, 'utf-8')
signature = hmac.new(bytearray(api_key_secret, 'utf-8'), message, digestmod=hashlib.sha512).hexdigest()
print("Signature=",signature)
print ("Timestamp",timestamp)
return signature
sign_request( verb = "GET", timestamp = int(time.time()*1000),path="/v1/account/balances",api_key_secret="4961b74efac86b25cce8fbe4c9811c4c7a787b7a5996660afcc2e287ad864363" )
import requests
url = "https://api.valr.com/v1/account/balances"
payload = {}
headers = {
'X-VALR-API-KEY': '2589fb273e86aeee10bac1445232aa302feb37e27d32c1c599abc3757599139e',
'X-VALR-SIGNATURE': 'signature',
'X-VALR-TIMESTAMP': 'timestamp'
}
response = requests.request("GET", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
Well after some hard thinking I decided to change to using global variables. The hmac still worked fine and gave me a signature. Then I removed the quotes around signature and timestamp and realised they were both integers. I was then able to convert that signature and timestamp to a string and everything started to work perfectly. Maybe someone else will make use of this. If you want to make a POST request remember to put single quotes around anything in the {body} statement to make it a string.
Here is the code that I am currently using for a GET request from VALR. It's been working fine for many months. You will need to change the path and the url to correspond to whatever you are trying to get, and obviously you will need to add your_api_key and your_api_secret.
If you need to send through other request parameters like transaction types etc. then you will ned to include them in the path and the url e.g. https://api.valr.com/v1/account/transactionhistory?skip=0&limit=100&transactionTypes=MARKET_BUY&currency=ZAR
def get_orders(): # to get open orders from valr
timestamp = int(time.time()*1000)
verb = "GET"
path = "/v1/orders/open"
body = ""
api_key_secret = 'your_api_secret'
payload = "{}{}{}".format(timestamp, verb.upper(), path)
message = bytearray(payload, 'utf-8')
signature = hmac.new(bytearray(api_key_secret, 'utf-8'), message, digestmod=hashlib.sha512).hexdigest()
timestamp_str = str(timestamp)
url = "https://api.valr.com/v1/orders/open"
headers = {
'Content-Type': 'application/json',
'X-VALR-API-KEY': 'your_api_key',
'X-VALR-SIGNATURE': signature,
'X-VALR-TIMESTAMP': timestamp_str,
}
response = requests.request("GET", url, headers=headers, data=body)
dict = json.loads(response.text)
dict = pd.DataFrame.from_dict(dict)
print(dict)

is it possible to overwrite parameters in a called feature file, which have been defined in background or scenario?

https://github.com/intuit/karate#calling-other-feature-files
The link above contains an example of calling a feature file in order to reuse the code. The feature file which is reused is called with the inputs
Background:
* configure headers = read('classpath:my-headers.js')
* def signIn = call read('classpath:my-signin.feature') { username:'john', password: 'secret' }
* def authToken = signIn.authToken
The called my-signin.feature:
Scenario:
Given url loginUrlBase
And request { userId: '#(username)', userPass: '#(password)' }
When method post
Then status 200
And def authToken = response
...
In this example the my-signin.feature must be run with the inputs username and password. I know that if you had the following:
Background:
* def username = "foo"
* def password = "secret"
at the top of the my-signing.feature file, the parameters input by the feature attempting to reuse the feature file would be overwritten.
My question is:
If reuse is the main interest of being able to call other feature files, is there a way to have the calling feature file overwrite the username and password parameters if they had been defined in the background?
It seems to me that having the background overwrite the input parameters instead of vice versa makes it harder to reuse *.feature files. I know I found it a little frustrating on my project not being able to reuse tests I had already written without refactoring out the reusable code into another file.
Any called feature in karate will have a magic variable __arg, you can check for this before assigning values to your variables in your called script.
Background:
* def username = (__arg == null) ? "foo" : __arg.username
* def password = (__arg == null)? "secret" : __arg.password
this will check for values passed,
if none passed it will assign default
* def signIn = call read('classpath:my-signin.feature')
if passed with arguments passed arguments will be assigned
* def signIn = call read('classpath:my-signin.feature') { username: 'notfoo', password: 'notsecret' }
For simplicity don't have anyother parameters that need to passed other than this.