Search code examples
jsonjsonschemakaratejsonschema2pojo

How to check additional values with if condition (using karate framework)?


I would like to check response from GET/birds request with a json schema. In my feature:

* def abs = read (birds.json)
* match response == abs.birdsSchema

I need to put the schema in a json file and not in the feature. I have to check additional values depending on gender. Ex: if gender is male then check if the color is blue and the tail is long or short. if gender is female then check if "sings" is true or false and number of eggs.

So I put in birds.json:

"birdsSchema":{
    "id": "#string",
    "owner": "#number",
    "town": "#? _ == 'New York' || _ == 'Washington'",
    "type": "object",
    "oneOf": [
        {
            "properties": {
                "gender": {"enum": ["male"]},
                "color":"blue",
                "tail": "#? _ == 'long' || _ == 'short'"
            }
        },
        {
            "properties": {
                "gender": {"enum": ["female"]},
                "sings" : "#? _ == true || _ == false"
                "eggs": "##number"
            }
        }
    ]
}

But it doesn't work. Error: com.intuit.karate.exception.KarateException: path: $[0].type, actual: 'female', expected: 'object', reason: not equal. How I can do this conditional check in my json file?


Solution

  • Let's acknowledge that this is extra hard because if I understand your question correctly, the JSON keys you are looking for are dynamic.

    Part of the fun of Karate is that there are at least 5 different ways I can think of to solve this elegantly. Here is just one:

    * def response = { color: 'black', aaa: 'foo' }
    
    * def schema = { color: '#? _ == "black" || _ == "white"' }
    * def extra = (response.color == 'black' ? { aaa: '#string' } : { fff: '#string' })
    
    * match response contains schema
    * match response contains extra
    

    If you create a JS function based on the hint above, you can probably get a better solution. Keep in mind that in a JS function you can use methods like karate.set to dynamically create keys. So there are many possibilities :)

    edit: looks like the example above is wrong, and the keys are not dynamic. Then it is easy, keep in mind that $ refers to the JSON root:

    * def response = { color: 'black', extra: 'foo' }    
    * def schema = { color: '#? _ == "black" || _ == "white"', extra: '#($.color == "black" ? "foo" : "bar")' }    
    * match response == schema