Postman API requests are not synchronized

//PreRequest:

const moment = require('moment');
const today = moment();
var todate = today.format();
pm.globals.set("toDate", todate);
console.log(todate)
var fromdate = moment().subtract(5, 'days');
pm.globals.set("fromDate", fromdate.format());
console.log('fromDate')

//Main API Get Request.
URL: get https\mydashboard.com\dahboard_id
//Code in Test tab of postman API get request.
//This is to get panels query array which will be used in post call body.

var dashboardData = JSON.parse(responseBody);
const myArray = [];
const q_Array = [];
var completedReq = 0;
var qcount = 0;
for (var i = 0; i < dashboardData.panels.length; i++) {
    if (dashboardData.panels[i].queries) {
        const querystrng = dashboardData.panels[i].queries[0].queryString
        var QVAL = JSON.stringify(querystrng)
        var queryval = QVAL.replace(/\n/g, "\n").replace(/{{Site}}/g, "*")
        //This is to add each query string into an array list
        q_Array.push(queryval)
    }
}

//This section is used to get the next post call url and prerequest details

var searchURL = pm.environment.get("srhURL")
let frmDte = pm.globals.get("fromDate")
let toDte = pm.globals.get("toDate")

//This is post call request in the same Test tab of main get call request.

pm.test("Status code is 202", function () {
    q_Array.forEach((qv, index) => {
        console.log("arrrrr", q_Array[index]);
        pm.sendRequest({
            url: '${ searchURL } ? from = ${ frmDte } & timeZone=IST & to=${ toDte }',
            method: 'POST',
            header: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': pm.environment.get("AuthToken")
            },
            body: {
                mode: 'raw',
                raw: JSON.stringify({
                    'username': '******n', 'password': '*******', 'from': pm.globals.get("fromDate"), 'to': pm.globals.get("toDate"), "timeZone": "IST",
                    "byReceiptTime": true, 'query': qv,
                })
            }
        }, function (error, response) {
            if (error) {
                console.error("Error in get: ", error);
            }
            else {
                console.log("Getdata: ", response)
                pm.expect(response).to.have.property("code", 202);
                pm.expect(response).to.have.property("status", "Accepted");
                const dbresponse = response.json();
                console.log("Mytestdata: ", dbresponse.id);
                const ids = dbresponse.id;
                myArray[index] = ids;
                pm.environment.set("idArray", JSON.stringify(myArray));
            }
            SecondRequest();
        }//post call fun end
        );
    });
});

//This is next get request in the same main Get request Test tab.

function SecondRequest() {
    pm.test('JOB ID calls:', function () {
        //Here I am parsing the jobid array list which we got from each post call response and saved as env variable.
        const arrID = JSON.parse(pm.environment.get('idArray'));
        arrID.forEach((jid) => {
            pm.sendRequest({
                url: 'https://api.us2.sumologic.com/api/v1/search/jobs/' + jid,
                method: 'GET',
                header: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                }

            },
                (err, res) => {
                    if (err) {
                        console.error(err);
                    }
                    else {
                        console.log(res);
                        const searchidData = res.json();
                        const warningMsg = searchidData.pendingWarnings[0]
                        console.log("Warning Messages:", JSON.stringify(warningMsg));

                    }
                }
            );
        });
    });
    completedReq++;
    console.log('Completed post:', completedReq)
}

Here, I am expecting first main get response execute and it gives the array of query list and that will be used in next post requests body and each post request will run and give the array list of jobid which will be used in the next get call urls and each jid will be appended in the get calls.

This is working and giving us the jid list.
Problem
Get call is running randomly and sometimes it executes within the post call or runs more than the 200 times

Can you please edit your question and ensure the code is correctly aligned using the preformatted text option.

You might need to break the code into different code blocks so you can add your comments.

Can you please clearly show what code is where. Pre-request script for request 1, tests tab for request 2, etc.

I suspect this is because of the asynchronous nature of sendRequest and the fact you can’t guarantee what order the requests will run in, but hard to tell with the code showing as it is.

Hi Mike,
I have edited the post with the required comments basically prerquest details is there and later in test tab of postman I have added two sendrequests

Just so you are aware, I’ve edited your post and reformatted all of the code.

Hi Mike

Can you please tell me where have you edited my post call I am unable to see the changes.

So you have a GET request which will return an array of query strings.

You have POST request that loop through those query strings.

Each POST request will return an array of ID’s, which you also want to loop through in a final GET request.

So a loop within a loop.

I would recommend that your first request in the collection just deals with the first GET request, and all it should achieve is that you save the array to a collection variable. This array will be used to control the outer loop.

I don’t think the date code in the pre-request script needs to be there. It would appear that all of this can go into the tests tab of the GET request.

Also why global variables? Do you really need these date variables available to all of your collections in Postman. Its non confidential information, so I would recommend saving to a Collection variable.

You would then have a proper POST request using the GUI.

To avoid the asynchronous issues you have, you can use setNextRequest and the array shift() method to control the outer loop.

In the pre-request script for the POST request. You will retrieve the array you saved in the GET request.

Using the shift() method which is available to all arrays. You will retrieve the first element in the array and this also removes it from the array.

You will save the item you retrieved from the array to a new collection variable which will be used in the Post request.

You will also re-save the array back to the collection variable, which will now have one less item.

In the tests tab for the Post request, you can have your sendRequest() loop for the final GET request.

After that loop, you will retrieve the array of query strings, and check the length of the array. If the length is more than 0, you will keep looping on the POST request by using setNextRequest with the POST request name. It will only stop running when it runs out of query strings.

Request 1. Get request to produce query string array.
Request 2. Post request looping using array shift and SetNextRequest
Request 3. SendRequest loop in the tests tab of the Post request.

What you are doing is fairly complicated, but the above hopefully will reduce the number of lines of code, and also create a separation between the loops and the initial GET request that returns the query strings. So a bit easier to troubleshoot.

They are there. SHIFT-F5 to refresh, or just refresh the page.

You should see that the code is now properly indented like following.

image

So you have a GET request which will return an array of query strings.
yes

You have POST request that loop through those query strings.
yes, now I have stored environment variable of array list queries from GET request response and using that query in post request body.

Each POST request will return an array of ID’s, which you also want to loop through in a final GET request.

No, each POST request will not give the array of ID’s but each post response have one - one id’s and I have collected them all in an arraylist again.

**NOW, I have organized my code as per your suggestion like **
GET request is normal GUI call and storing it’s queries in arraylist as an environment variable.

In the next call’s prerequest I have added POST call sendRquest and Parsed the query array to use in all post call which is working.

Now I have collected the ID’s from each post call in an array and saved in environment variable. But, Now in the test tab I have to add assertion for the next get call and its Url should run with each of the ID in URL which is not working for me.

Can you share your latest code for this element? As I’m not 100% following the flow you are trying to achieve.

Are you using sendRequest to loop through the ID’s?

If you are looping through the query strings in the Post request and this only return one ID, why can’t you just have a single sendRequest for that in the tests tab for that ID. I’m not sure why you need to collect them all first.

My First get call from GUI which is written in test tab and here I’ve collected queries in array as environment variable which i will use in next post call
var dashboardData = JSON.parse(responseBody);

const q_Array = ;
for(var i = 0; i < dashboardData.panels.length; i++){

q_title = dashboardData.panels[i].title
//console.log("q_title", q_title);  

if(dashboardData.panels[i].queries)
{

const querystrng = dashboardData.panels[i].queries[0].queryString

            //console.log(querystrng)
            var QVAL = JSON.stringify(querystrng)
            var queryval = QVAL.replace(/\\n/g, "\\n")
             .replace(/{{Site}}/g, "\*")
             q_Array.push(queryval);
             pm.environment.set("Qstring",JSON.stringify(q_Array));
             
            
}

}

**Now, I have next API request called jobid whre I have to send the post api request with pm.sendRequest() here I post call will run till the total number of queries are there in Qstring. POST req is in prerequest of Jobid api call . **
I have collected number of jobid from each post call and saved as array in environment variable. and in test tab of this call I am trying to pass array in URL

PREREQUEST code
const myArray =
let currentindex = 0;
let currentReq = 0;
let completedReq = 0;
//let currentReq = ‘POST’;
var searchURL = pm.environment.get(“srhURL”)
const moment = require(‘moment’);
const today = moment();
const todate = today.format();
var fromdate = moment().subtract(5, ‘days’);
const fromDate = fromdate.format();

const Q_string = JSON.parse(pm.environment.get(“Qstring”));
console.log(“new”,Q_string);
//Q_string = JSON.parse(pm.collectionVariables.has(“Qstring”)?pm.collectionVariables.get(“Qstring”):);

pm.test(“Status code is 202”, function () {
Q_string.forEach(qv => {
pm.sendRequest({
url: ${searchURL}?from=${fromDate}&timeZone=IST&to=${todate},
method: ‘POST’,
header: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’,
‘Authorization’: pm.environment.get(“AuthToken”)
},

  body: {
    mode: 'raw',
    raw: JSON.stringify({'username': '****','password': '*****','from': fromDate,'to':todate,"timeZone":"IST","byReceiptTime": true,'query':qv}) 
     
    }

},
function(error, response) {

        if(error)
        {
            console.error("Error in get:",error);
            
        }
        else{           
         
        console.log("Postdata:",response)
        pm.expect(response).to.have.property('code', 202);
        pm.expect(response).to.have.property('status', 'Accepted');
        const  dbresponse = response.json(); 
        console.log("Mytestdata:", dbresponse.id);
        const ids = dbresponse.id; 
        //myArray[index] = ids;                          
        myArray.push[ids];            
         pm.environment.set("idArray",JSON.stringify(myArray));
         
        
        }
   });

});

const jidvalues = JSON.parse(pm.environment.get(“idArray”));
if(jidvalues && jidvalues.length > 0){
const urlwitharray = ‘https://api.us2.sumologic.com/api/v1/search/jobs/’;
for(let i = 0; i< jidvalues.length; i++ ){
urlwitharray += jidvalues[i];
if(i < jidvalues.length-1)
{
urlwitharray +=‘/’

}

}
pm.environment.set(“urlarr”,pm.request.url(urlwitharray));
}
else
{
console.error(‘the array is empty’);
}

});
/completedReq++;
console.log(“Completed post:”, completedReq)
/

TEST TAB

const arrID = JSON.parse(pm.environment.get(“idArray”));

        pm.test("JOB ID calls:", function(){ 
                            
            arrID.forEach((jid) => {                       
                 pm.sendRequest({           
                 url:'https://api.us2.sumologic.com/api/v1/search/jobs/'+jid,
                 method: 'GET',
                 header: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json',
                
                        }

            }, 
                (err,res) => 
                {
                    if(err){
                            console.error(err);
                            
                        }    
                    else {
                        console.log(res);               
                        const searchidData = res.json();               
                        const warningMsg = searchidData.pendingWarnings[0]
                        console.log("Warning Messages:",JSON.stringify(warningMsg));      
                        
                        }
       
                }
            );
             });
              });

Now the problem is I am not able to make jobid get call from postman gui where id’s collected in array environment is not used in url section.

I can’t read your code, as half of it is using the pre-formatted text and the other half is not.

It makes it really hard to read.

I’m still not really following your flow.

You have an inital GET request which the end result is an array of query strings.

This bit is working.

You should then have a POST request that is a normal request in the GUI. This is a POST request using a query string that will return a single ID. You control that loop using setNextRequest() and the array shift method.

In the pre-request script of the POST request, you will retreive the previoulsy saved array and use the array shift method to get the first query string in that array, which you will save to a variable to be used in the actual POST request. You will also resave the array, which will now have one less query string in it. So you will have the details you need to make the current POST request and a new array with one less record.

In the tests tab for the POST request, you will retreive the array again, and just check the length, and keep looping using setNextRequest while the array length > 0.

Get this outer loop working first.

The final step appears to just need some code in the tests tab of the POST request to perform the final GET request with the ID returned from the POST request. Which is where you can utlilize an sendRequest(). I really don’t think you need a loop for that element if you just send the GET request after each iteration of the POST.

Or you can reverse this logic, and have the second request in the collection as the final GET request, and put the sendRequest POST to retreive the ID in the pre-request script, but again using setNextRequest to control the loop. You don’t need to send all of the POSTS requests in one go. Do one at a time using the query string to return the single ID.

Ok, But the querystring array that I have collected from the main GUI GET request need to be passed in next call of POST api body
Will it work if i use the shift() and setNextRequest() I have never used that. Not sure how it works But will give it a try.

Post api call for Search API

Pre request
var nextIndexQ = +parseInt(pm.environment.get(‘nextIndexQ’));

newqr = JSON.parse(pm.environment.get(“Qstring”));

console.log(nextIndexQ)

pm.environment.set(‘currentQ’, newqr[nextIndexQ]);

nextIndexQ = nextIndexQ + 1;

if(nextIndexQ < newqr.length){

postman.setNextRequest(‘SearchJob’);

}

else

{

console.log(“No data”)

}

pm.environment.set(“nextIndexQ”, nextIndexQ);

Body
“query”: {{currentQ}},
“from”: “{{fromDate}}”,
“to”: “{{toDate}}”,
“timeZone”: “IST”,
“byReceiptTime”: true
Test tab

collected response and saved ids from each responses and used it in a next job call.

This is separate POST call which will use Qstring arrays

Prerequest
var Q_string = JSON.parse(pm.environment.get(“Qstring”));
if(!Q_string){
Q_string = JSON.parse(pm.environment.get(“Qstring”));
}
var current_q = Q_string.shift();
pm.environment.set(“cv”,current_q )
pm.environment.set(“Q_string”, Q_string)

Body raw values

{
“username”: “****”,
“password”: “*****!”,

“query”: {{cv}},
“from”: “{{fromDate}}”,
“to”: “{{toDate}}”,
“timeZone”: “IST”,
“byReceiptTime”: true
}

Test tab

var Q_string = JSON.parse(pm.environment.get(“Qstring”));
if(Q_string && Q_string.length >0)
{
postman.setNextRequest(“https://urlofmypostrequest/api/v1/search/jobs?from={{fromDate}})”);
}
else{
postman.setNextRequest(null);
}

@Khushboo_Postman

In order to increase the readability of this code, you need to format the code blocks.

This is not easy to read:

The best way to do this is add a new line to the top and bottom of your code block, then add ``` 3 backticks in each of those new lines.

For example:

This post request gives error “Request Accepted | AssertionError: expected response to have status code 202 but got 415”

“query”: {{cv}}, should have changed as I am trying to send multiple post requests with each query values.

any suggestion on that @michaelderekjones

Thanks I have added the new lines

Those lines require the back ticks, to format the string into a code block.

Try putting quotes around the variable name.

"query": "{{cv}}"

To aid in troubleshooting, you can look at the console log to see what was sent and whether its reading the variables correctly or not.

You can also console log the environment variables straight after you set it.

console.log(pm.environment.get("cv"));

This also looks incorrect, and should be the name of the request, not the URL.

postman.setNextRequest("https://urlofmypostrequest/api/v1/search/jobs?from={{fromDate}})");

Thinking through your flow, I think that you could probably get this working by having three normal requests in the GUI.

  1. Get Query Strings.
  2. Post Query String
  3. Get ID.

The first request runs once and you will end up with an environment variable with an array of query strings.

In the pre-request tab for the Post request, you retrieve the array and set the current query string using the array shift() method (and also re-save the array with one less entry).

In the tests tab for the Post request, you parse the response and save the ID to an environment variable that is going to be used in the final GET request.

The final GET request should be straight forward, and its in the tests tab for this request that you retrieve the query string array and loop using setNextRequest. Calling the name of the POST request.