Postman send multiple requests - postman

I've got a PATCH request that looks like this:
{{host}}/api/invoice/12345678/withdraw
host is a variable determining the environment.
For this request I need to add a unique authorization token.
The problem is I need to send dozens of such requests. Two things change for each request:
id of invoice (for this case is '12345678')
auth token (herebetoken1).
How can I automate it?

You can use Postman Runner for your problem. In Runner, you can send specified requests in specified iterations and delay with data (json or csv file).
For more info, I suggest you take a look at the links below.
Importing Data Files in Postman
Using CSV and JSON Data Files
Request:
Runner:
Data: (You can choose one of them)
Json Data: (data.json)
csv Data: (data.csv)
Preview Data in Runner:
Result:

use the below pre-request script , and call replace id in url and auth in authorization with {{id}} and {{token}} variables . Use collection runner to execute it .
Replace the hashmap with what you requires
hashmap = {
"1234": "authtoken1",
"2222": "authtoken2"
}
pm.variables.get("count") === undefined ? pm.variables.set("count", 0) : null
let keyval = Object.entries(hashmap)
let count = pm.variables.get("count")
if (count < keyval.length) {
pm.variables.set("id", keyval[pm.variables.get("count")][0])
pm.variables.set("token", keyval[pm.variables.get("count")][1])
pm.variables.set("count", ++count)
keyval.length===count? null:postman.setNextRequest(pm.info.requestName)
}
Example collection:
https://www.getpostman.com/collections/43deac65a6de60ac46b3 , click inport and import by link

Related

Postman tests send multiple requests

I want to make a postman request that returns a list of IDs.
The returned list can contain 1 or multiple IDs.
In tests section i want to use these returned IDs to make new requests.
Is it possible to send requests from tests section in for loop and check their returned data BEFORE sending another request?
I tried using simple for loop and pm.sendRequest but due to async this did not work.
Is this possible using Postman?
You can achieve that by using postman.setNextRequest("request_name")
For example:
Request 1: Tab Tests Get the ids and save ids to environment
pm.environment.set("ids", JSON.stringify(pm.response.json().ids));
Request 2:
Tab Pre-req
let ids = JSON.parse(pm.environment.get("ids"));
if(ids.length > 0){
let id = ids.shift();
pm.environment.set("ids", JSON.stringify(ids));
pm.variables.set("id", id);
}
Tab Tests
let ids = JSON.parse(pm.environment.get("ids"));
if(ids.length > 0){
postman.setNextRequest("Req2");
}
Result:

Flask cannot parse JSON in Tabulator AJAX request (using advanced configuration)

I regularly use Tabulator's setData() method. I usually set parameters in the URL args, and have no problems with it. But I now have a complex use case that will be easier to solve if I can put a JSON payload into the request.
I've followed the Tabulator documentation for an advanced configuration.
I've made a series of attempts (putting the JSON in various places, using quotes/double quotes in the JSON, etc) at trying to work out the problem. The Flask server always returns this error:
Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)
What makes me suspect the problem is with Tabulator, not Flask, is because I printed request.__dict__ and couldn't find the JSON in the request. (I.e. that seems to the reason for the error.)
The below example, which triggers the same error, is taken from the Fetch documentation (Tabulator uses the Fetch API).
Is there anything wrong with the below or should I be looking harder at Flask?
const data = { username: 'example' };
var ajaxURL = "/data/results";
var ajaxConfig = {
method:"POST",
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrf_token,
},
body: JSON.stringify(data)
};
ResultsTable.setData( ajaxURL, {}, ajaxConfig);
Notes:
I'm using the latest version of Tabulator (4.9).
ResultsTable is set elsewhere in the code and is successfully loading default data when the page loads. The use case kicks in when the user sets their own parameters for the data.
The CSRF token, which is set elsewhere in the code, is there because Flask requires it.
The reason that is failing is that Tabulator will build out its own request body when it builds a request and that will override your config.
In your usage case, you will need to override the build in ajax request promise and add your own function that makes the ajax request and then resolves the data.
You can do this using the ajaxRequestFunc.
Checkout the Ajax Request Documentation for full details

Is there to run only part of requests in Postman?

We have a lot of API level automated tests written as collections of requests in Postman.
We have a script to run all collections in automated manner.
Is there a way to label/run only subset of requests e.g. with some label e.g. as smoke suite, without copying requests to new collection(s) and run then explicitly (as this yields the need to maintain same tests in 2 places...)?
There might be labels, groups or some script that skips the request is env variable is set...
you can create folders and organize test like
smoke_and_regression
smoke_only etc
you can specify which folder to run using --folder arguent when using newman as command line tool
you can also control the execution flow using postman.setNextRequest .
and also you can run newman as an npm module.
you just need to write a logic to read the collection file and get all folder names containing "smoke" for eg and pass it as an array
const newman = require('newman'); // require newman in your project
// call newman.run to pass `options` object and wait for callback
newman.run({
collection: require('./sample-collection.json'),
reporters: 'cli',
folder: folders
}, function (err) {
if (err) { throw err; }
console.log('collection run complete!');
});
Just update for the comments:
in old and new UI you can select which folder to execute in collection runner
Get all requests in the collection:
you can also get information about all the requests in a collection by using :
https://api.getpostman.com/collections/{{collection_UUID}}
to get uuid and api key goto :
https://app.getpostman.com
Now for generating api key >
goto account settings > api key and generate api key.
to get collection uuid goto specific workspace and collection and copy the uuid part from url:
Now in your collection
Rename all requests as:
get user details [Regression][Smoke][Somethingelse]
get account details [Regression]
Then Create a new request called initial request and keep it as the first request in your collection:
url: https://api.getpostman.com/collections/8xxxxtheuuidyoucopied
authorization: apikey-header : key: X-Api-Key and value: yourapikey
test-script :
pm.environment.unset("requestToRun")
reqeustlist = pm.response.json().collection.item.map((a) => a.name)
requestToRun = reqeustlist.filter((a) => a.includes(pm.environment.get("tag")))
let val = requestToRun.pop()
pm.environment.set("requestToRun", requestToRun)
val ? postman.setNextRequest(val) : postman.setNextRequest(null)
Now set the envirnoment variable as what you want to look for eg: run script that contains text "Regression" then set pm.environment.set("tag","Regression")
Now in your collection-pre-request add:
if (pm.info.requestName !== "initial request") {
let requestToRun = pm.environment.get("requestToRun")
let val = requestToRun.pop()
pm.environment.set("requestToRun", requestToRun)
val ? postman.setNextRequest(val) : postman.setNextRequest(null)
}
Output:
Example collection:
https://www.getpostman.com/collections/73e771fe61f7781f8598
Ran only reqeusts that has "Copy" in its name

Pass dynamic value to url in Postman

I have 2 requests
1st Request
After did my first request, I get the response where I can parse for a taskId
In my test tab, I will then parse and store it like this
let taskId = pm.response.json().body.result[0].data.task
console.log(taskId)
I can see taskId printing in my console as 938
2nd Request
I require making a GET with this dynamic URL with the taskId that I got from the first one
http://localhost:3000/fortinet/monitor/{{taskId}}
So I set the above URL , set the HTTP verb to GET
in my Pre-request Script tab, I did this
let taskId = pm.globals.get("taskId")
Result
ReferenceError: taskId is not defined
Image Result
How can I debug this further?
The most suggested way is to use :key as in
http://localhost:3000/fortinet/monitor/:taskId
See the colon before taskId. The reason being, URI values sometimes many not be environment dependent. So, based on the usecase, you can use like I said or {{taskId}}
You have to set variable, but you are doing it wrong.
try this:
pm.globals.set("taskID", pm.response.json().body.result[0].data.task)
more you can read here:
https://learning.postman.com/docs/postman/variables-and-environments/variables/
Please note, that URL which ends with resource identified like https://example.com/:pathVariable.xml or https://example.com/:pathVariable.json will not work.
You can go with https://example.com/:pathVariable with Accept: application/json header.
For passing dynamic value, first you have to set it in environment or global variable in Tests tab because tests runs after request and you will get response value after request sent, but because you get response in json you have to first parse it, so what you can write in Tests tab is as follows:
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("taskId", jsonData.token); // OR
postman.setGlobalVariable("taskId", jsonData.token);
Then you can use taskId as {{taskId}} wherever you want in url parameters or in request body or form data wherever.
If you want to know in detail how to extract data from response and chain it to request then you can go to this postman's official blog post which is written by Abhinav Asthana CEO and Co Founder of Postman Company.

how can I fix conflicting query string params for S3 uploads?

I'm attempting to upload raw image data to S3 in the context of a react-native app.
I have the raw data correct and for the most part I think my code inside react native is working correctly to capture image data.
On my rails server, I'm using the amazon ruby gem to build the details of the url and associated authentication data required to post data to the bucket in question which I'm then rendering into react-native just like a regular react web front end.
# inside the rails server controller
s3_data = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public-read', url: 'https://jd-foo.s3-us-west-2.amazonaws.com')
render json: {s3Data: {fields: s3_data.fields, url: s3_data.url}}
At the moment I attempt to post to S3, I'm using ES6 fetch like the below to build my http request.
saveImage(data) {
var url = data.url
var fields = data.fields
var headers = {'Content-Type': 'multipart/form-data'}
var body = `x-amz-algorithm=${encodeURIComponent(fields['x-amz-algorithm'])}&` +
`x-amz-credential=${encodeURIComponent(fields['x-amz-credential'])}&` +
`x-amz-date=${encodeURIComponent(fields['x-amz-date'])}&` +
`x-amz-signature=${encodeURIComponent(fields['x-amz-signature'])}&` +
`acl=${encodeURIComponent(fields['acl'])}&` +
`key=${encodeURIComponent(fields['key'])}&` +
`policy=${encodeURIComponent(fields['policy'])}&` +
`success_action_status=${encodeURIComponent(fields['success_action_status'])}&` +
`file=${encodeURIComponent('12foo')}`
console.log(body);
return fetch(url, {method: 'POST', body: body, headers: headers})
.then((res) => {console.log('s3 inside api res', res['_bodyText']) ; res.json()} );
}
the logging of the body looks like
x-amz-algorithm=AWS4-HMAC-SHA256&x-amz-credential=AKIAJJ22D4PSUNBB5RAQ%2F20151027%2Fus-west-1%2Fs3%2Faws4_request&x-amz-date=20151027T223159Z&x-amz-signature=42b09d7ae134f803b10ef72d220fe74a630a3f826c7f1f625448277d0a6d93c7&acl=public-read&key=uploads%2F46be8ca3-6d3a-4bb7-a658-f2c8e058bc28%2F%24%7Bfilename%7D&policy=eyJleHBpcmF0aW9uIjoiMjAxNS0xMC0yN1QyMzozMTo1OVoiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJqZC1mb28ifSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVwbG9hZHMvNDZiZThjYTMtNmQzYS00YmI3LWE2NTgtZjJjOGUwNThiYzI4LyJdLHsic3VjY2Vzc19hY3Rpb25fc3RhdHVzIjoiMjAxIn0seyJhY2wiOiJwdWJsaWMtcmVhZCJ9LHsieC1hbXotY3JlZGVudGlhbCI6IkFLSUFKSjIyRDRQU1VOQkI1UkFRLzIwMTUxMDI3L3VzLXdlc3QtMS9zMy9hd3M0X3JlcXVlc3QifSx7IngtYW16LWFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7IngtYW16LWRhdGUiOiIyMDE1MTAyN1QyMjMxNTlaIn1dfQ%3D%3D&success_action_status=201&file=12foo
It seems like my problems could be tied to both
Bad format of the post body including problems with special characters
Not providing S3 with enough data in post body including keys and other information, the documentation feels a bit unclear about what is/is not required.
The error back from S3 servers looks like
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>MalformedPOSTRequest</Code><Message>The body of your POST request is not well-formed multipart/form-data.</Message> <RequestId>DCE88AC349D7B2E8</RequestId><HostId>AKE1xctETuZMAhBFLfyuFlDxikYUlbAC7YufkM7h8Z8eVQdtLA25Z0Od/a4cMUbfW1nWnGjc+vM=</HostId></Error>
I'm pretty unclear on what my actual problems are and where I should be digging in.
Any input would be greatly appreciated.
<Message>The body of your POST request is not well-formed multipart/form-data.</Message>
It may not be that you're missing values from the body. The most significant issue here is that the structure of your body does not resemble multipart/form-data.
See RFC 2388 for how multipart/form-data works. (Or find a library that builds this for you.)
What you are sending looks more like the application/x-www-form-urlencoded format, which is used by some AWS APIs, but not S3.
There is an example in the S3 docs showing what an example POST body might look like. You should see a substantial difference there.
Note also that POST is intended for browser based uploads. If you are uoloading from code, you're doing a lot of extra work. PUT Object is much more straightforward. The request body is the binary file contents. Or, if this will eventually be done by a browser, then test it with a browser, and let the browser build your form.