JSON matchers

If the exact value of a field is unknown, you can use JSON matchers to make sure it has a certain property or shape.

JSON matchers work more or less like placeholders in practice.

And assert body.ignoring("city", "realName", "publisher.location").is(
  """
  {
    "name": "<favorite-superhero>",
    "hasSuperpowers": *any-boolean*,
    "publisher": {
      "name": *any-string*,
      "foundationYear": *any-positive-integer*
    }
  }
  """
)

You just need to replace the value of the field by one of the built-in JSON matchers without quotes.

Here are the available matchers:

Matchers are not supported for JSON array assertions via asArray.

Custom matchers

You can register your own matchers by overriding registerMatchers in your feature class. A Matcher takes a key (used as *key* in assertions), a description, and a predicate on io.circe.Json:

import com.github.agourlay.cornichon.CornichonFeature
import com.github.agourlay.cornichon.matchers.Matcher
import io.circe.Json

class MyFeature extends CornichonFeature {

  override def registerMatchers: List[Matcher] = List(
    Matcher(
      key = "any-email",
      description = "checks if the field is a valid email address",
      predicate = _.asString.exists(s => s.contains("@") && s.contains("."))
    ),
    Matcher(
      key = "any-positive-number",
      description = "checks if the field is a positive number",
      predicate = _.asNumber.exists(n => n.toDouble > 0)
    )
  )

  def feature = Feature("My API") {
    Scenario("check user response") {
      When I get("/users/1")
      Then assert body.is("""
      {
        "name": *any-string*,
        "email": *any-email*,
        "score": *any-positive-number*
      }
      """)
    }
  }
}

Custom matchers follow the same *key* syntax as built-in matchers and can be mixed freely with them.