atrium icon indicating copy to clipboard operation
atrium copied to clipboard

assertion functions for Json

Open robstoll opened this issue 5 years ago • 9 comments

Platform (JVM and/or JS): JVM/JS

Code related feature

Yet to be defined how it should look like and how it should behave. Following a suggestion:

assert("{val: "value", obj: {prop: \"value\"}}").isJson {  
  property("obj").isObject {
    property("prop").toBe("value")
  }
}

Where it normally should not matter in which order the properties appear. However, I am not sure how we should treat data which we did not expect (val in the above example). Sometimes even order matters, for such cases we could introduce something like inOrder:

assert("{val: \"value\", obj: {prop1: \"val1\", prop2: \"val2\"}}").isJson.inOrder{  
  property("obj").isObject {
    property("prop").toBe("val2") // does not fail, inOrder is per object
    property("prop").toBe("val1")
  }
  property("val").toBe("value") // fails because not in order  
}

Ideas and feedback are welcome.

robstoll avatar Oct 15 '18 05:10 robstoll

Another use case is comparing a json against a predefined json:

assert(json).isJson(expectedJson)

Meaning we could parse the expectedJson and turn it into the above assertions. In such a case we would certainly want that it fails if there is unexpected data. In case someone needs the properties to be in order, then one could use:

assert(json).isJson.propertiesInOrder.toBe(expectedJson)

I guess failing if there is unexpected data should also be the normal case for isJson {} where we could have an option ignoreUnexpectedProperties:

assert(json).isJson.ignoreUnexpectedProperties.toBe(expectedJson)

Which we could combine with other options as well. Another example with isJson{}

assert("{val: "value", obj: {prop: \"value\"}}").isJson.ignoreUnexpectedProperties {  
  property("obj").isObject.inOrder {
    property("prop").toBe("value")
  }
}

Does not fail even though val was unexpected

robstoll avatar Oct 15 '18 05:10 robstoll

Maybe we should shorten the syntax and use p instead of property so that it resembles closer a json structure?

robstoll avatar Oct 15 '18 05:10 robstoll

Another way to think about ignoreUnexpectedProperties might be something like "contains".

keturn avatar Oct 15 '18 05:10 keturn

@keturn Makes sense if you don't compare against another json. Yet, how would you define on which level it can occur or is it only on the current level (that would be a possibility)? In the sense of, would

assert(json).isJson.contains{ property("a").toBe("b") }

hold if we have { obj: { a: "b" }}? Or how would you expect the syntax looks like?

robstoll avatar Oct 15 '18 05:10 robstoll

A few other edge cases we have to define:

  • what if a json defines a property multiple times -> I suggest we fail as well
  • what if the json is invalid -> I suggest we fail as well

robstoll avatar Oct 15 '18 07:10 robstoll

And naming needs a decision, I saw that others use key instead of property (in the sense of key/value) and the ECMA standard refers to it as name. What should we use?

robstoll avatar Oct 15 '18 07:10 robstoll

I guess something like using JsonPath to select a value/obj/array and make an assertion could be handy as well. No need to support that from the start though, if someone should need it "immediately" then let me know it.

robstoll avatar Oct 17 '18 17:10 robstoll

JsonPath just wouldn't conform with the DSL and is not an assertion language but rather a retreival language... if JsonArray is treated like a List and JsonObject like a map, then regular assertions could be made on its structure. This would be easier to maintain, as all it would need is initial parsing that I suppose most platforms already have in some form or other... what would jsonpath add to this?

dave08 avatar Oct 18 '18 02:10 dave08

I would use JsonPath for retrieval, it could make assertions more readable in certain cases. Following an example:

assert(json).isJson {
  path("/store/book/author").contains("J. R. R. Tolkien", "F. Kafka")
}

This would collect all authors of books and one could make an assertion about them. Of course, one could also do the retrieval beforehand and then assert on the resulting list. This is one of the reasons why this is a low prio feature and I will not add it at the beginning.

robstoll avatar Oct 18 '18 06:10 robstoll