0

I have an endpoint which returns this JSON response:

{
  "jobs": [
    {
      "name": "job1",
      "id": "d6bd9aa1-0708-436a-81fd-cf22d5042689",
      "status": "pending"
    },
    {
      "name": "job2",
      "id": "4fdaf09f-51de-4246-88fd-08d4daef6c3e",
      "status": "pending"
    }
  ]

I would like to repeatedly GET call this endpoint until the job I care about ("job2") has a "status" of "completed", but I'd like to check this by using a UUID stored in a variable from a previous call.

i.e. by doing something like this:

#NB: code for previous API call is executed
* def uuidVar = response.jobRef
#NB: uuidVar equates to '4fdaf09f-51de-4246-88fd-08d4daef6c3e' for this scenario

* configure retry = { count: 5, interval: 10000 }

Given path /blah
And retry until response.jobs[?(@.id==uuidVar)].status == 'completed'
When method GET

Could anyone suggest the correct syntax for the retry until?

I've tried referencing the fantastic Karate docs & examples (in particular, js-arrays.feature) and some questions on SO (including this one: Karate framework retry until not working as expected) but sadly I haven't been able to get this working.

I also tried using karate.match here as suggested in the link above, but no cigar.

Apologies in advance if I am missing something obvious.

1 Answers1

1

First I recommend you read this answer on Stack Overflow, it is linked from the readme actually, and is intended to be the definitive reference. Let me know if it needs to be improved: https://stackoverflow.com/a/55823180/143475

Short answer, you can't use JsonPath in the retry until expression, it has to be pure JavaScript.

While you can use karate.jsonPath() to bridge the worlds of JsonPath and JS, JsonPath can get very hard to write and comprehend. Which is why I recommend using karate.filter() to do the same thing, but break down the steps into simple, readable chunks. Here is what you can try in a fresh Scenario:. Hint, this is a good way to troubleshoot your code without making any "real" requests.

* def getStatus = function(id){ var temp = karate.filter(response.jobs, function(x){ return x.id == id }); return temp[0].status }
* def response =
"""
{
  "jobs": [
    {
      "name": "job1",
      "id": "d6bd9aa1-0708-436a-81fd-cf22d5042689",
      "status": "pending"
    },
    {
      "name": "job2",
      "id": "4fdaf09f-51de-4246-88fd-08d4daef6c3e",
      "status": "pending"
    }
  ]
}
"""
* def selected = '4fdaf09f-51de-4246-88fd-08d4daef6c3e'
* print getStatus(selected)

So if you have getStatus defined up-front, you can do this:

* retry until getStatus(selected) == 'completed'

Note you can use multiple lines for a JS function if you don't like squeezing it all into one line, or even read it from a file.

Peter Thomas
  • 54,465
  • 21
  • 84
  • 248
  • 1
    PS: regarding your question on the previous SO question: "Let me know if it needs to be improved" > I think your answer covers everything. The mistake I made was not having two statements inside the function (one to check the status, one to return the result). I was trying to be fancy and do everything in one single statement, which is my bad. So, short answer = no, looks good. – karatekid5088 Mar 05 '20 at 07:23
  • @karatekid5088 thanks, I anyway updated that one to link to this one – Peter Thomas Mar 05 '20 at 10:01