Testing Response code, parsing Reply

I have made this collection to delete a bunch of jobs in our software,
https://www.postman.com/agi-admin/workspace/postman-community/collection/26232016-2db11d96-abc4-4a42-bd79-2379a98c09c5?action=share&creator=26232016
Most of the calls return 201 Created but there are many that return 422 Unprocessable Entry with a Body such as:

{
    "errorType": "Unprocessable Entity",
    "httpCode": 422,
    "message": "Invalid options. Can't delete this job (418) because it has active children. Job Ids: 1841"
}

At this point, I have to:

  1. Manually go through the list of 422 responses.
  2. Copy the list of child job Id’s mentioned at the end of message into a second copy of this collection’s Pre-request Script’s jobArray[] and run that collection. Sometimes there are more 422 responses with child jobId’s there, and so a third collection needs to be made to delete those jobId’s, and so on.
  3. Put the jobId’s that couldn’t be deleted, shown in parenthesis in message, into the Pre-request Script’s jobArray[] and re-run the collection so they can finally get deleted.

I’m fairly certain this could be automated much better by adding some code to the “Tests” page, so that’s what I’ll be working on but in the meantime will appreciate anything you all can offer or contribute as well.

𝒯𝒽𝒶𝓃𝓀 𝒴ℴ𝓊

That looks like a server side error, so I don’t think there is anything we can do to get it through first time.

It would be a case of reading the API documentation to see if there are any other options that might help with this endeavour.

Otherwise, you are in the right ballpark with re-sending using the tests tab.

You shouldn’t need to get the job ID from the message tab, as you already have the job ID as a variable in the post request. Just use that with the Postman setNextRequest to re-send the same request if it fails with a 422.

However, in your tests tab at the collection level, you already have…

const jobArray = pm.collectionVariables.get("jobList");
if (jobArray && jobArray.length > 0){
    postman.setNextRequest("Delete SMRT Link Job");
} else {
    postman.setNextRequest(null);
}
pm.test("Is the status 201 Created?", function () { pm.response.to.have.status(201); });

Which along with the pre-request script isn’t going to play nicely with another setNextRequest().

You could have a couple of IF Statements in your pre-request and tests tab, to test for the current status, and only execute the existing code if the status is a success one. That means it won’t get the next array element if the current request wasn’t successfull.

However, as setNextRequest already requires the runner to execute, I would just use an import file instead. CSV or JSON.

This will run your request once for each line in the CSV file, and referencing the elements is as simple as putting the CSV header into the body, the same way you target any variable.

This means you wouldn’t need to have any of that code freeing up the tests tab to control the re-running of any failed requests which would just be a simple IF statement checking the status code and using setNextRequest to keep re-running the same request until it passes.

Thanks Mike.  I’m back revisiting this.  Yeah I’ve checked our API Reference and this is the best there is as far as job deletion.  I’ve completely rewritten the Tests.  It’s become complicated but I think I’m on the right track.

It starts with trying to delete the first job in the array with dryRun=true.

  • If the response code is positive (201), then unshift() the jobId back to the jobArray and re-run the deletion with dryRun=false.
  • If the response is 422, then parse the message for the child jobs and unshift() the jobId(s) to jobArray then try to delete those jobId(s) with dryRun=true.

The issue I’m running into right now is getting the jobId from the 201 status response to unshift() back to the jobArray.  I’m printing various variables to the console to help debug.

On line 5 I’m successfully printing jsonRespStr which comes out like:

jsonRespStr: {
  "name":"delete-job",
  "updatedAt":"2023-07-31T19:45:15.496-07:00",
  "workflow":"{}",
  "path":"/opt/pacbio/smrtlink/userdata/jobs_root/0000/0000005/0000005677",
  "state":"SUBMITTED",
  "tags":"",
  "uuid":"cf7690a8-64d2-4845-9f79-3ab121a71379",
  "projectId":1,
  "childJobsCount":0,
  "jobTypeId":"delete-job",
  "id":5677,
  "smrtlinkVersion":"12.0.0.177059",
  "comment":"Description for job Delete Job",
  "isNested":false,
  "createdAt":"2023-07-31T19:45:15.496-07:00",
  "isActive":true,
  "isMultiJob":false,
  "jsonSettings":"{\"jobId\":418,\"removeFiles\":true,\"dryRun\":true,\"force\":false}",
  "jobUpdatedAt":"2023-07-31T19:45:15.496-07:00"}

Then on line 7 I’m successfully printing jsonSettings, which comes out like:

jsonSettings: "{\"jobId\":418,\"removeFiles\":true,\"dryRun\":true,\"force\":false}"

However, when I try to get the jobId on line 11 I get back:

jsonSettings.jobId: undefined

which should be 418 instead.  So I’m stuck there for now.

That is because your job ID is contained in an object in a string.

Therefore you will need to parse the sting before you can target the elements in the underlying object…

let jsonSettings = "{\"jobId\":418,\"removeFiles\":true,\"dryRun\":true,\"force\":false}"
let jobId = JSON.parse(jsonSettings).jobId
console.log(jobId); // 418

Thanks Mike! I knew I was close since I named the variable with “Obj” however I think I had only tried adding json() to the end like I did with the initial full response, which wasn’t working…

No problem.

The json() method is specific to Postman and the pm.response function.

JSON.parse() is a core JavaScript function.