1

I have to automate these-

  1. Get a list of employees in the USA:

    GET /emps/usa

  2. Get each user's details:

    GET /emps/empid

The first API returns data like this:

[
  {
    "id": "1",
    "firstName": "Tom",
    "lastName": "Cruise"
  },
  {
    "id": "2",
    "firstName": "Maria",
    "lastName": "Sharapova"
  },
  {
    "id": "3",
    "firstName": "James",
    "lastName": "Bond"
  }
]

Now, for each employee I need to call a 2nd API to get details per id.

Problem: I created a collection with above mentioned API's. After the first API call, in Postman's Tests section I am reading the response values in a loop. My problem is: how can I read and hold data for each employee id and then call the 2nd API in the collection as many times I have received an employee id? Is there any way to call an API from Postman's Tests section? Or any other working idea?

Henke
  • 4,445
  • 3
  • 31
  • 44
Sam
  • 859
  • 3
  • 12
  • 23

3 Answers3

2

Have you tried passing data from file(csv or json) at collection runner.
This solution will work if you have all your id's for which you want details in file
Then pass number of iterations accordingly.

Efficient solution (when you get different ids in response of first request) will be using newman command-line collection runner for Postman.
You need to create two separate collection in postman app

  1. Get Id's : which will have GET /emps/usa request

Get all id's from "GET /emps/usa" and store it in environment variable as "," seperated string,
To do this you can parse your JSON response
Create empty string variable which will be appended every Id string in iteration according to size of array which you get in response
Then set the result string which will look like "1,2,3" to environment variable

postman.setEnvironmentVariable("allIds",result);

Once you get expected string in environment variable, you done with postman step1 :)
Now its time export collection and run this collection from commanline tool
exported collection and environment from postman is in json format
let say getData.json is your collection file and env.json is your environment file
from cmd prompt or shell execute following:

newman run getData.json -e env.json --export-environment expEnv.json

when you execute this you will get expEnv.json which will have id data generated during execution
Now scary part comes (process expEnv.json)
Here you need to write a program in programming language you like which will take this expEnv.json process/parse it and create csv file
format of csv will be like:
Id
1
2
3
Once you get this thing in csv then you can move to step 2.

2. Get each user details: GET /emps/empid request
In postman app create a collection with get detail request
In Pre Request Script you need to set value from file to environment variable
Your pre req script will look like:
postman.setEnvironmentVariable('usrId',data['Id']);//refer answer for details
Now change your URL by adding usrId in url from environment variable
url will look like GET /emps/{{usrId}} instead of GET /emps/empid
Then export this collection and run it from newman
let say getDetails.json is exported collection from postman you can use same env.json here

newman run getDetails.json -e env.json -d yourGeneratedCSVFile.csv
Community
  • 1
  • 1
Pratik Charwad
  • 697
  • 10
  • 19
1

Did you tried to use postman control workflow ? You have a great example with Cooper's meal plan. The keys are :

  1. Implement a standard loop, but persist your index in environment variable.
  2. Do whatever you need, check for persisted index and while needed use postman.setNextRequest("<requestName>").
AMichel
  • 11
  • 1
0

I have a working solution to this question.

1. Prerequisites

My two APIs / endpoints are as follows.

{
  "US-employees": [
    {
      "id": "Q37079",
      "name": "Tom Cruise"
    },
    {
      "id": "Q844",
      "name": "James Bond"
    },
    {
      "id": "Q11666",
      "name": "Maria Sharapova"
    }
  ]
}
{
  "US-portraits": [
    {
      "id": "Q844",
      "description": "Fictional British spy",
      "image": "https://upload.wikimedia.org/ [...] _Bangalore_144323.jpg"
    },
    {
      "id": "Q11666",
      "description": "Russian tennis player",
      "image": "https://upload.wikimedia.org/ [...] _%2843186339350%29.jpg"
    },
    {
      "id": "Q37079",
      "description": "American actor and producer",
      "image": "https://upload.wikimedia.org/ [...] _Skidmore_2.jpg"
    }
  ]
}

where I have truncated the links of the images for better readability.
(Just click the /emps/empid link to see the unabbreviated version.)

Notice in the first endpoint how each object / person has a unique id and a name, nothing more. The second API has – for each object in the first endpoint – the same unique identifier, along with a description and a link to an image / portrait. Thus, neither of the two APIs on its own contains information on both the name and the image link.

2. The result

Obviously, the problem is solved if the data in the two APIs can be combined together in such a way that – for each identifier – both the name and the image link are supplied. Like so:

[
  {
    "id": "Q37079",
    "name": "Tom Cruise",
    "description": "American actor and producer",
    "image": "https://upload.wikimedia.org/ [...] _Skidmore_2.jpg"
  },
  {
    "id": "Q844",
    "name": "James Bond",
    "description": "Fictional British spy",
    "image": "https://upload.wikimedia.org/ [...] _Bangalore_144323.jpg"
  },
  {
    "id": "Q11666",
    "name": "Maria Sharapova",
    "description": "Russian tennis player",
    "image": "https://upload.wikimedia.org/ [...] _%2843186339350%29.jpg"
  }
]

All that remains is to visualize the data in Postman:

Visualized Result in Postman

3. Methodology

I make the request to the /emps/usa API as a normal GET request in Postman:

GET http://henke.atwebpages.com/postman/chaining/emps/usa

I probably could have made the request to the /emps/empid API as an ordinary Postman request too – and then combined the two requests via Postman's Collection Runner.

But instead I make the request to the /emps/empid API in a Pre-request script, as follows:

const url = 'http://henke.atwebpages.com/postman/chaining/emps/empid';
pm.sendRequest(url, (err, response) => {
  pm.environment.set('US_portraits',
    JSON.stringify(response.json()['US-portraits']));
});

Then, in the Tests section, I combine the two results together, and finally visualize them:

const usEmployees = pm.response.json()['US-employees'];
const usPortraits = JSON.parse(pm.environment.get('US_portraits'));
usEmployees.map(x => Object.assign(x, usPortraits.find(y => y.id === x.id)));
const tblHeader = Object.keys(pm.response.json())[0];
const template = `
<table>
  <tr><th>` + tblHeader + `</th></tr>
  {{#each response}}
  <tr><td>{{name}}<br><img src="{{image}}"></td></tr>
  {{/each}}
</table>`;
pm.visualizer.set(template, {
  response: usEmployees
});

4. How to replicate my solution in Postman

Replicating my results in Postman should be straightforward.
Assuming you are using the desktop version of Postman, do as follows:

  1. Download and save
    http://henke.atwebpages.com/postman/chaining/emps/API-Chaining.pm_coll.json
    in a suitable place on your hard drive.

  2. In Postman, Ctrl + O > Upload Files > API-Chaining.pm_coll.json > Import.
    You should now see API Chaining among your collections in Postman.

  3. Collections > API Chaining > US-empl-request > Send.

  4. In the Postman Response Body, click Visualize.

  5. Done! – If everything worked as intended, you should now see the output as in the image above, starting with the name and image of Tom Cruise.

5. Two questions by the original poster + one extra

Question how can I read and hold data for each employee id and then call the 2nd API in the collection as many times I have received an employee id?

Answer I call the two APIs just once each, and then do whatever needed with the data retrieved.
I get two JavaScript arrays, one from each of the two APIs. The essence of the problem boils down to joining two JavaScript arrays that have a common unique identifier.


Question Is there any way to call an API from Postman's Tests section?

Answer Yes! – In the above solution, I make the necessary API requests before the Tests section kicks in. Then I devote the Tests section to getting the data from the requests – saved in two environment variables – and finally manipulate that data to reach the end goal.

But you can do it all in Tests. See the last section below.


Question But hey, this isn't chaining any more! – There is no second request using information from the first request. Right?

Answer That's right! – It doesn't matter which request is put in the Pre-request script, and which is run as the ordinary request. Swapping them should work just as fine. The point is: the asker of the question thought of the problem as a need to make chaining requests. (And I present one such solution in the next section.) It turns out that chaining requests are not necessary to solve the problem.

6. Doing it all in the Tests section

You can actually do literally everything in the Tests script.

Although chaining requests are not strictly necessary to solve the problem, here is a solution with code only in the Tests section, which does apply a second chaining request.
The second request does not depend on any data from the first request, but the second callback needs data from both requests.
(The main request is just a dummy request never used – except for start running the Tests script.)

Both requests are made in the script, then combined, and finally visualized: 1

const lock = setTimeout(() => {}, 43210);
const urlO = 'http://henke.atwebpages.com/postman/chaining/emps/empid';
const urlI = 'http://henke.atwebpages.com/postman/chaining/emps/usa';
pm.sendRequest(urlO, (_, responseO) => {
  const usPortraits = responseO.json()['US-portraits'];
  pm.sendRequest(urlI, (_, responseI) => {
    clearTimeout(lock); // Unlock the timeout.
    const usEmployees = responseI.json()['US-employees'];
    usEmployees.map(x => Object.assign(x,
      usPortraits.find(y => y.id === x.id)));
    const tblHeader = Object.keys(responseI.json())[0];
    const template = `<table>
      <tr><th>` + tblHeader + `</th></tr>
      {{#each responseI}}
      <tr><td>{{name}}<br><img src="{{image}}"></td></tr>
      {{/each}}
    </table>`;
    pm.visualizer.set(template, { responseI: usEmployees });
  });
});

Postman Collection to replicate this Tests-only version:
http://henke.atwebpages.com/postman/chaining/emps/API-Chain.sendReq.pm_coll.json.

References


1 Don't get confused by the lines const lock = setTimeout(() => {}, 43210); and clearTimeout(lock);. – Their only purpose is to serve as a workaround for a known bug.

Henke
  • 4,445
  • 3
  • 31
  • 44