Loop through values from GET to next PUT request

Iā€™m using a collection to rename using PUT request for a list of filesystems from GET request response. Getting stuck with receiving only latest value to PUT but not looping through all values. Kindly help on this.

{ā€œfilesystemā€: [{ā€œnameā€: ā€œfs1ā€}, {ā€œnameā€: ā€œfs2ā€}], ā€¦ {ā€œnameā€: ā€œfs10ā€}}

GET request:

From the above response on the console log iā€™m getting all 10 filesystem values

bodyData = JSON.parse(responseBody)
value = bodyData.filesystems;

//for (var i=0; i < value.length; i++) {
var i = 0;
while (i < value.length) {
var name = value[i].name;
pm.environment.set(ā€œfsā€, name)
console.log(name);
i++;
}

console.log giving me all 10 values as expected:
fs1
fs2
fs3
:
fs10

PUT request

PUT /{{fs}}

I need to rename fs1ā€¦10 to new name like newfs1ā€¦10

However only the lastest value (fs10) is being picked for PUT request but not fs1ā€¦9.
How to loop this to rename all fs1ā€¦10 ?

My Pre-request Script:

var fs = pm.environment.get(ā€œfsā€);

Currently, your loop will just run through and the fs variable will always be 10 when the next request is run.

Your put request needs to be inside that loop for this to work. You can do this with sendRequest().

An alternative way, and the way I would do this is to create a flat array of all the file systems from your response and store that in a variable. This can be done using the JavaScript map feature if the value is not already an array. (It has to be an array, not a normal JavaScript object).

Because in the next request, you are going to use another JavaScript feature called Shift() which allows you to take the first element in that array, store it in a variable (that you can use in the request) and then delete the first element from the array, which you can then save back to the stored variable. Used in conjunction an IF statement that checks the length of the array, and setNextRequest, you can get it to run the same request for each element of test data in the array.

Please see this post for a discussion and a working example.

Post Looping through an Array not working - Help - Postman

Thanks for the reply.
I tried using SendRequest(), however it is not resolving dynamic (environment variables) values in ā€œURLā€ path and looking for exact URL path including the loop variable ā€œfsā€ in var loop. Also SendReqest() statement is executing outside the loop, i.e., after GET request.
console.name() is giving expected values but unable to set these to ā€œfsā€ variable correctly in sequenceā€¦

PUT https://{{Host}}/api/storage/v1/host/projects/filesystems/{{fs}}/filesystems/%7B%7Bfs%7D%7D
Error: getaddrinfo ENOTFOUND {{Host}}
{errno: -3008, code: ā€œENOTFOUNDā€, syscall: ā€œgetaddrinfoā€ā€¦}

  1. errno: -3008
  2. code: ā€œENOTFOUNDā€
  3. syscall: ā€œgetaddrinfoā€
  4. hostname: ā€œ{{Host}}ā€

Test script:

bodyData = JSON.parse(responseBody)
value = bodyData.filesystems
for (var i=0; i < value.length; i++) {
var name = value[i].name;
var fs = pm.environment.get(name);

const postRequest = {
url: ā€˜https://{{Host}}/api/storage/v1/host/projects/filesystems/{{fs}}ā€™,
method: ā€˜PUTā€™,
header: {
ā€˜Content-Typeā€™: ā€˜application/jsonā€™
},
body: {
mode: ā€˜rawā€™,
raw: JSON.stringify({
ā€œnameā€: ā€œ{{fs}}ā€,
ā€œmountpointā€:ā€œ{{new_filesystem_name}}ā€
})
}
};
pm.sendRequest(postRequest, (error, response) => {
console.log(error ? error : response.json());
});
console.log(name);
}

You canā€™t access the variable that way in a script.

You can only use the handlebars {{ in the main request URL and the params\body sections.

In the scripts sections (pre-request and tests tab) you have to do the following.

pm.environment.get("variable_name");

Trying alternate way using map and shift method, however PUT request is picking latest value passed to variable and not looping all values that is displayed on console.log. Not sure where iā€™m going wrong.

Json path is : x.filesystems[0].name

GET: (Test script)
const response = pm.response.json();

const fs = response.filesystems.map(name => name);

console.log(fs);

for (var i=0; i < fs.length; i++) {

var name = fs[i].name;

pm.variables.set(ā€˜nameā€™, name);

console.log(name);

}

PUT (Pre-Script):

var name = pm.variables.get(ā€˜nameā€™);

//pm.variables.set(ā€˜currentnameā€™, name);

//postman.setNextRequest(ā€˜Set_Wallet_sharesā€™);

pm.variables.set(ā€˜currentnameā€™, name.shift());

var currentname = name.shift();

if(Array.isArray(name) && name.length > 0) {

postman.setNextRequest(ā€˜Set_Wallet_sharesā€™);

} else {

postman.setNextRequest(null);

}

Please look through the example again.

The setNextRequest does not go in the pre-request script.

Here is another example.

Send multiple get request and then a single post request - Help - Postman

Thanks for the reply. In my case structure is slightly different, iā€™m finding difficulty in defining the variable ā€œnameā€ from array of filesystems. Thank you,

x.filesystems[i].name

pm.globals.set(ā€œltpā€, response.data.ltp) = > from the example given is data.variable

pm.globals.set(ā€œnameā€, response.filesystems[i].name) => my case is array.variable

@joint-operations-en5

Can you please post your pre-request script and your tests tab scripts. (Please use the preformatted text option in the editor so that the code isnā€™t all aligned to the left).

Can you also post an example response so I can see the structure (also using the preformatted text).

Thanks for looking into this.

Get request to list filesystems under given project

GET request - Body:

{
ā€œnameā€: ā€œ{{project}}ā€,
ā€œmountpointā€: ā€œ/main/{{project path}}ā€
}

Response from GET Request:

{
ā€œfilesystemsā€: [

      {
       "name": "fs1",
        "root_permissions": "775",
        "mountpoint": "/{{ old path }}/fs1"
         ".. .. .."
     },
     {
        "name": "fs2",
        "root_permissions": "775",
        "mountpoint": "/{{ old path }}/fs2"
         ".. .. .."
     },
     :
     :
     :
     {
        "name": "fsn",
        "root_permissions": "775",
        "mountpoint": "/{{ old path }}/fsn"
         ".. .. .."
     }

]
}

GET request - Test script:

const response = pm.response.json();
const fs = response.filesystems.map(name => name);
console.log(fs);

for (var i=0; i < fs.length; i++) {
var name = fs[i].name;
pm.variables.set(ā€˜nameā€™, name);
console.log(name);
}

Put request that needs to be looped to rename the filesystems name (fs1, fs2 ā€¦ fsn) and mountpoint for the given project

PUT request - Body:

{
ā€œnameā€: ā€œ{{currentname}}ā€,
ā€œmountpointā€:ā€œ/{{ newpath }}/{{currentname}}ā€
}

PUT request - Pre-request script:

var name = pm.variables.get(ā€˜nameā€™);
pm.variables.set(ā€˜currentnameā€™, name.shift());
var currentname = name.shift();

if(Array.isArray(name) && name.length > 0) {
postman.setNextRequest(ā€˜ā€™);
} else {
postman.setNextRequest(null);
}

setNextRequest usually goes in the Tests tab (after the request has been sent).

You technically can bail on the request using the pre-request script, but I do this in the tests tab.

Iā€™ve never tested this in the pre-request tab, so I donā€™t know if the current request actually runs or not doing it this way.

If you want to bail on the request using the pre-request script if the array is 0 then you donā€™t need the IF ELSE, just an IF setting it to NULL.

In your situation. You have a GET request which receives an array of file systems, which you are then looping through and setting a variable called name. This will end up with the variable having the last file system in the array. It will always be the last file system in the array. The name variable will not be an array as I think you are expecting it to be. Also please donā€™t call both variables the same ā€œnameā€. Itā€™s hard to read and you can have scope issues. Please set the variable to be collection or environment.

For the GET request, all you really need to do is map the filesystems as you are doing to get an array of file systems and store that as a collection variable which will be the test data for the PUT request, you will need to JSON.stringify() it before storing and PARSE it when retrieving.

In the pre-request script for the PUT request, you will retrieve the array (remember to parse the string using JSON.parse().

This is where you use the array shift.

To get the first element in the array and save it to a variable which you then save as a collection or environment variable to be used in the request.

You also need to write the array back to the collection\environment variables. (Which should now have one less entry in it). Remember to stringify.

At this point, your request should run with the latest variables.

In the Tests tab of the PUT request. You will retrieve the array once again.

This is where I put the logic for checking the array length. After all of your tests.

if (array.length > 0){
postman.setNextRequest("Request1");

} else {
postman.setNextRequest(null);
}

If the array has zero entries in it, it will stop the run at this point.

Not sure what you are doing when posting your code. Please use the preformatted text in this editor.

image

Here is some example code. Iā€™m using Postman Echo with a POST request to emulate your response, with the loop being a GET request with the filesystem being echoed back as a parameter.

image

This is the body Iā€™m working with.

{
"filesystems": [
        {
        "name": "fs1",
            "root_permissions": "775",
            "mountpoint": "/{{ old path }}/fs1"
        },
        {
            "name": "fs2",
            "root_permissions": "775",
            "mountpoint": "/{{ old path }}/fs2"
        },
        {
            "name": "fsn",
            "root_permissions": "775",
            "mountpoint": "/{{ old path }}/fsn"
        }
    ]
}

This is the response that gets echoed back.

{
    "args": {},
    "data": {
        "filesystems": [
            {
                "name": "fs1",
                "root_permissions": "775",
                "mountpoint": "/{{ old path }}/fs1"
            },
            {
                "name": "fs2",
                "root_permissions": "775",
                "mountpoint": "/{{ old path }}/fs2"
            },
            {
                "name": "fsn",
                "root_permissions": "775",
                "mountpoint": "/{{ old path }}/fsn"
            }
        ]
    },
    "files": {},
    "form": {},
    "headers": {
        "x-forwarded-proto": "https",
        "x-forwarded-port": "443",
        "host": "postman-echo.com",
        "x-amzn-trace-id": "Root=1-63c151b5-75fc92ce3eb9423c73f48789",
        "content-length": "426",
        "content-type": "application/json",
        "user-agent": "PostmanRuntime/7.30.0",
        "accept": "*/*",
        "cache-control": "no-cache",
        "postman-token": "adbb7f76-57c9-498c-84b2-6bc49539e7df",
        "accept-encoding": "gzip, deflate, br"
    },
    "json": {
        "filesystems": [
            {
                "name": "fs1",
                "root_permissions": "775",
                "mountpoint": "/{{ old path }}/fs1"
            },
            {
                "name": "fs2",
                "root_permissions": "775",
                "mountpoint": "/{{ old path }}/fs2"
            },
            {
                "name": "fsn",
                "root_permissions": "775",
                "mountpoint": "/{{ old path }}/fsn"
            }
        ]
    },
    "url": "https://postman-echo.com/post"
}

This is the Tests tab on the first POST request.

// Step 1: Status code check

pm.test("Status code is 200", () => {
  pm.response.to.have.status(200);
});

// Step 2:  Parse the response.

const response = pm.response.json().data;

// Step 3: Create an array of the file system names within the response

let fs = response.filesystems.map(name => name.name); // ["fs1","fs2","fsn"]

// Step 4: Store the array as a collection variable.  Remember to stringify.

pm.collectionVariables.set("fileSystems", JSON.stringify(fs));

This is the pre-request script for the request that we want to loop. (Imaginatively called Loop).

// Step 1: Retrieve file systems array

var array = JSON.parse(pm.collectionVariables.get("fileSystems"));

// Step 2: Retrieve first value in array and reduce array

var currentFileSystem = array.shift();

// Step 3: Set fileSystem variable which is set as a paremeter for this request

pm.collectionVariables.set("fileSystem", currentFileSystem);

// Step 4: Save updated array back to the fileSystems collection variable

pm.collectionVariables.set("fileSystems", JSON.stringify(array));

This is the Tests tab.

// Step 1: Retrieve fileSystems array

var array = JSON.parse(pm.collectionVariables.get("fileSystems"));

// Step 2: Retrieve current filesystem to be used in assertion

var expectedResponse = pm.collectionVariables.get("fileSystem");

// Step 3: Retrieve actual name to be used in assertion
var actualResponse = pm.response.json().args.filesystem;

// Step 4:  Test

pm.test(`Response filesystem = ${expectedResponse}`, () => {
    pm.expect(actualResponse).to.eql(expectedResponse); 
});

if (array.length > 0){
postman.setNextRequest("Loop");

} else {
postman.setNextRequest(null);
}

Finally, this is the Collection Runner results and Console log.

image

Wonderful mdjones, it is looping through all filesystems now and works as expected.

My case is to get the list using GET request and loop through PUT request for the list given in GET. Your example helped me to loop through PUT requests.

Many thanks for your dedication in this regard. Really appreciate!!

Note: Though getting 202 Accepted response seeing some AssertionError, (hope i can ignore these)

Thank you so much!

No problem, glad its working.

In relation to the following;

Have a look at the following link.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.