Skip to main content

RoundTripTester

import extras.hedgehog.circe.RoundTripTester

import cats._
import io.circe._

import hedgehog._
import hedgehog.runner._

object SomethingSpec extends Properties {
override def tests: List[Test] = List(
property("round-trip test Something JSON Codec", roundTripTest),
property("round-trip test Something JSON Codec - failure case", roundTripTestWithDecodeFailure),
property("round-trip test Something JSON Codec - failure case (indent 4)", roundTripTestWithDecodeFailureIndent4),
)

def roundTripTest: Property =
for {
something <- genSomething.log("something")
} yield {
RoundTripTester(something).test()
}

def roundTripTestWithDecodeFailure: Property =
for {
something <- genSomething
.map(something => SomethingWithDecodeFailure(something.id, something.name))
.log("something")
} yield {
RoundTripTester(something).test()
}

def roundTripTestWithDecodeFailureIndent4: Property =
for {
something <- genSomething
.map(something => SomethingWithDecodeFailure(something.id, something.name))
.log("something")
} yield {
RoundTripTester(something)
.indent(8)
.test()
}

def genSomething: Gen[Something] =
for {
id <- Gen.int(Range.linear(1, 100))
name <- Gen.string(Gen.unicode, Range.linear(3, 20))
} yield Something(id, name)


final case class Something(id: Int, name: String)
object Something {
implicit val somethingShow: Show[Something] =
something => s"Something(id = ${something.id.toString}, name = ${something.name})"

implicit val somethingCodec: Codec[Something] = io.circe.generic.semiauto.deriveCodec
}


final case class SomethingWithDecodeFailure(id: Int, name: String)

object SomethingWithDecodeFailure {
implicit val somethingWithDecodeFailureShow: Show[SomethingWithDecodeFailure] =
somethingWithDecodeFailure =>
List(
s"id = ${somethingWithDecodeFailure.id.toString}",
s"name = ${somethingWithDecodeFailure.name}",
).mkString(
"SomethingWithDecodeFailure(",
", ",
")",
)

implicit val somethingWithDecodeFailureEncoder: Encoder[SomethingWithDecodeFailure] =
io.circe.generic.semiauto.deriveEncoder

implicit val somethingWithDecodeFailureDecoder: Decoder[SomethingWithDecodeFailure] =
Decoder.instance(c =>
for {
id <- c.downField("blah").as[Int]
name <- c.downField("name").as[String]
} yield SomethingWithDecodeFailure(id, name)
)
}

}


// This is only for this document so you don't need this.
SomethingSpec.main(Array.empty)
// Using random seed: 135914046526
// + repl.MdocSession$MdocApp0$SomethingSpec$.round-trip test Something JSON Codec: OK, passed 100 tests
// - repl.MdocSession$MdocApp0$SomethingSpec$.round-trip test Something JSON Codec - failure case: Falsified after 0 passed tests
// > something: SomethingWithDecodeFailure(1,)
// > Round-trip test for SomethingSpec.SomethingWithDecodeFailure failed with error:
// > Error: DecodingFailure at .blah: Attempt to decode value on failed cursor
// > ---
// > Input: SomethingWithDecodeFailure(id = 1, name = )
// > ---
// > JSON: {
// "id" : 1,
// "name" : "\u0000\u0000\u0000"
// }
// >
// - repl.MdocSession$MdocApp0$SomethingSpec$.round-trip test Something JSON Codec - failure case (indent 4): Falsified after 0 passed tests
// > something: SomethingWithDecodeFailure(1,)
// > Round-trip test for SomethingSpec.SomethingWithDecodeFailure failed with error:
// > Error: DecodingFailure at .blah: Attempt to decode value on failed cursor
// > ---
// > Input: SomethingWithDecodeFailure(id = 1, name = )
// > ---
// > JSON: {
// "id" : 1,
// "name" : "\u0000\u0000\u0000"
// }
// >