Karate framework retry until not working as expected

The retry until expression has to be pure JavaScript and the special Karate match keywords such as contains are not supported, and you can’t do a “deep equals” like how you are trying, as that also is not possible in JS.

EDIT: in 0.9.6. onwards you can do a complex match in JS: https://stackoverflow.com/a/50350442/143475

Also note that JsonPath is not supported, which means * or .. cannot appear in the expression.

So if your response is { "tokens": [ "value1" ] }, you can do this:

And retry until response.tokens.includes('value1')

Or:

And retry until response.tokens[0] == 'value1'

To experiment, you can try expressions like this:

* def response = { "tokens": [ "value1" ] }
* assert response.tokens.includes('value1')

At run time, you can use JS to take care of conditions when the response is not yet ready while polling:

And retry until response.tokens && response.tokens.length

EDIT: actually a more elegant way to do the above is shown below, because karate.get() gracefully handles a JS or JsonPath evaluation failure and returns null:

And retry until karate.get('response.tokens.length')

Or if you are dealing with XML, you can use the karate.xmlPath() API:

And retry until karate.xmlPath(response, '//result') == 5

And if you really want to use the power of Karate’s match syntax, you can use the JS API:

And retry until karate.match(response, { tokens: '##[_ > 0]' }).pass

Note that if you have more complex logic, you can always wrap it into a re-usable function:

* def isValid = function(x){ return karate.match(x, { tokens: '##[_ > 0]' }).pass }
# ...
And retry until isValid(response)

Finally if none of the above works, you can always switch to a custom polling routine: polling.feature

EDIT: also see this answer for an example of how to use karate.filter() instead of JsonPath: https://stackoverflow.com/a/60537602/143475

EDIT: in version 0.9.6 onwards, Karate can do a match in JS, which can simplify some of the above: https://stackoverflow.com/a/50350442/143475

Leave a Comment