I'm trying to use postman for some basic API security tests and I have this URL:
http://example.com/api/v1/users/{{userID}}
{{userID}} is set to some user on site, and I want to set three tests that check if request is valid, if request has IDOR and if request has SQL injection.
This is the idea:
// userID is set to 20 ( valid user )
pm.test("Initial valid request", function () {
pm.expect(pm.response.text()).to.include("Peter"); });
*CHANGE THE VALUE OF {{userID}} to 30 to test for IDOR*
* URL should be set to http://example.com/api/v1/users/30 *
pm.test("IDOR protection valid", function () {
pm.expect(pm.response.text()).to.include("User not found."); });
*CHANGE THE VALUE OF {{userID}} to 20'or'1 to test for SQL injection*
* URL should be set to http://example.com/api/v1/users/20'or'1 *
pm.test("SQL injection test", function () {
pm.expect(pm.response.text()).to.include("You have an error"); });
My question is how do I change the values of {{userID}} so that next request uses changed value and not the one from environment variables.
Thanks
From the docs:
Tests will execute after the request runs
So each test will run based on the one request. So doing something like the following in your test
pm.collectionVariables.set('userID', 'IDOR*')
// or
pm.variables.set('userID', 'IDOR*')
Won't have the effect you're after as it doesn't make a request per test.
One potential way to solve this would be to have multiple requests, all of which have set the different variable values in the Pre-request Script. As an example, you might have a request that looks like this:
And then the related test:
Related
Selecting a value and right-clicking enables me to save it as a Global variable.
But there is no option to save it as a collection variable.
In the environments section as well. I can see Globals but my collection is not available.
But as I go through blogs/ articles online I can see some variables that are scoped to a collection.
Can I know a way to achieve this?
Tests tab is all you need
Considering the Stackoverflow GetUser API for Reference.
NOTE: The below-shown response is a part of the original response.
Response:
{
"items": [
{
"user_type": "registered",
"user_id": 12345678,
}
]
}
In the above response let's say we need user_type, and user_id in another API's URL / body / headers.
Before accessing we need to store these variables after receiving the response. This can be done in the Tests tab in postman request.
const jsonData = JSON.parse(responseBody);
const userType = jsonData?.items?.[0]?.user_type;
const userId = jsonData?.items?.[0]?.user_id;
if(userType){
pm.collectionVariables.set("userType",userType)
}
if(userId){
pm.collectionVariables.set("userId", userId)
}
Points to Note:
Postman tests are written in Javascript.
Optional chaining in line 2,3 is to avoid console errors. Possible Scenario: When API fails and returns an error response.
The IF Statements are to avoid null values in case of an Error Response. If statements are not mandatory. In fact without using if statements you will get to know clearly that something went wrong.
How to use collection variables
Once you make a request with the above tests. Postman IntelliSense suggests available collection variables. ( Refer to the image attached )
We are sending the body as a raw JSON in this Test Endpoint. Note that userType is surrounded by double quotes "" whereas userId is not. ( JSON syntax )
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:
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
I'm writing test in Postman and I have multiple requests grouped like this:
Some test title:
Create a user (set of "pre-requests"):
sending a few requests required to create a user, necessary to run tests
Some action on a created user (here I'm testing what is in the test title)
one or more requests
Another test title:
Create a user (set of "pre-requests", the same as in test 1.):
sending a few requests required to create a user, necessary to run tests
Some action on a created user (not related ot test 1.)
one or more requests
To summarize I need to create a user before every request when I want to test something.
My question - How can I re-use "Create a user" set of requests without copying it?
This is how you can re-use the set of requests in pre-testcases and Test by setting environment variable and call it using eval function
pre-test case -
var Create_a_user = () => {
pm.sendRequest("http://mocktarget.apigee.net/json", function(err, res) {
tests["Status code is 200"] = pm.expect(res).to.have.property('code', 200);
console.log('firstName',res.json().firstName);
});
pm.sendRequest("http://mocktarget.apigee.net/json", function(err, res) {
tests["Status code is 200"] = pm.expect(res).to.have.property('code', 200);
console.log("lastName - "+ res.json().lastName);
});
pm.sendRequest("http://mocktarget.apigee.net/json", function(err, res) {
tests["Status code is 200"] = res.code === 200;
console.log("city - "+ res.json().lastName.city);
});
};
pm.environment.set("Create_a_user", Create_a_user.toString());
Test -
eval(pm.environment.get("Create_a_user"))();
output -
firstName - John
lastName - Doe
city - San Jose
Disclaimer -
Use Eval function carefully, it may fizzled up your code or its execution.
If i'm understanding correctly what you want is unfortunately not currently supported. I've been waiting on this feature a while myself.
https://github.com/postmanlabs/postman-app-support/issues/1535
I have a Collection that has three endpoints. The first one creates an asset, the second one adds a file to the asset, and the third one lists all the assets.
How can I run the second one, the one that adds a file to the asset, more than once per each iteration of the Runner?
I'd like the test to create an asset and add multiple files to it for each iteration.
Any suggestions? I know I can duplicate the endpoint, but I was wondering if there was a programmatic way to do it.
Create 2 environment variables:
"Counter" (Number of times you want the request to run)
"RequestNumber" = 1 (To track the current request number)
Add this code to the test section of the request you want to run multiple times:
const counter = pm.environment.get("Counter");
const requestNumber = pm.environment.get("RequestNumber") || 1;
if (requestNumber < counter) {
postman.setNextRequest("RequestName");
requestNumber ++;
pm.environment.set("RequestNumber", requestNumber);
}
else {
pm.environment.set("RequestNumber", 1);
}
Instead of using postman.setNextRequest(), a bit cleaner way to hit the same endpoint is to use pm.sendRequest().
In Test or Pre-request Script, you can create a request object that would describe the request you want to send (URL, HTTP method, headers body, etc.) and put it in pm.sendRequest() function.
Consider:
const requestObject = {
url: 'https://postman-echo.com/post',
method: 'POST',
header: 'headername1:value1',
body: {
mode: 'raw',
raw: JSON.stringify({ key: "this is json" })
}
}
pm.sendRequest(requestObject, (err, res) => {
console.log(res);
});
To run the same request multiple times just put the function in for/for..in/for..of/forEach loop.
Consider:
for(let iteration = 0; iteration < 5; iteration++) {
pm.sendRequest(requestObject, (err, res) => {
console.log(res);
});
}
If you want you can modify the requestObject inside your loop.
Check out the Postman Documentation for more details.
So far, there is no straight forward solution using Postman, to configure several hits for the same request within a folder/collection.
Nevertheless, you can write some code in Pre-request script section, by adding a counter with number of hits you want and call postman.setNextRequest("request_name") method (read more about it from here) with you current request.
Out of Postman app scope, you can export your collection (as JSON file) and write some javascript code using newman which is a Command-line companion utility for Postman (more about newman from here) which gets a run method with a lot of iteration count and data options that would help you (for example, putting your second request in folder and iterates through it).
Hope that helps!