aboutsummaryrefslogtreecommitdiff
path: root/shared/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'shared/src/test')
-rw-r--r--shared/src/test/scala/CoproductTypeFormatTests.scala79
-rw-r--r--shared/src/test/scala/FormatTests.scala19
-rw-r--r--shared/src/test/scala/ImplicitDerivedFormatTests.scala24
-rw-r--r--shared/src/test/scala/ProductTypeFormatTests.scala77
4 files changed, 199 insertions, 0 deletions
diff --git a/shared/src/test/scala/CoproductTypeFormatTests.scala b/shared/src/test/scala/CoproductTypeFormatTests.scala
new file mode 100644
index 0000000..de73967
--- /dev/null
+++ b/shared/src/test/scala/CoproductTypeFormatTests.scala
@@ -0,0 +1,79 @@
+package spray.json
+
+import org.scalatest._
+
+class CoproductTypeFormatTests
+ extends FlatSpec
+ with FormatTests
+ with DefaultJsonProtocol
+ with DerivedFormats {
+
+ sealed trait Expr
+ case class Zero() extends Expr
+ case class Value(x: Int) extends Expr
+ case class Plus(lhs: Expr, rhs: Expr) extends Expr
+ case object One extends Expr
+
+ implicit val exprFormat: RootJsonFormat[Expr] = jsonFormat[Expr]
+
+ "No-parameter case class child" should behave like checkRoundtrip[Expr](
+ Zero(),
+ """{"type":"Zero"}"""
+ )
+
+ "Simple parameter case class child" should behave like checkRoundtrip[Expr](
+ Value(42),
+ """{"type":"Value","x":42}"""
+ )
+
+ "Nested parameter case class child" should behave like checkRoundtrip[Expr](
+ Plus(Value(42), One),
+ """{"type":"Plus","lhs":{"type":"Value","x":42},"rhs":{"type":"One"}}"""
+ )
+
+ "Case object child" should behave like checkRoundtrip[Expr](
+ One,
+ """{"type": "One"}"""
+ )
+
+ @gadt("kind")
+ sealed abstract class Keyword(`type`: String)
+ case class If(`type`: String) extends Keyword(`type`)
+
+ implicit val keywordFormat: RootJsonFormat[Keyword] = jsonFormat[Keyword]
+
+ "GADT with type field alias" should behave like checkRoundtrip[Keyword](
+ If("class"),
+ """{"kind":"If","type":"class"}"""
+ )
+
+ @gadt("""_`crazy type!`"""")
+ sealed abstract trait Crazy
+ case class CrazyType() extends Crazy
+
+ implicit val crazyFormat: RootJsonFormat[Crazy] = jsonFormat[Crazy]
+
+ "GADT with special characters in type field" should behave like checkRoundtrip[
+ Crazy](
+ CrazyType(),
+ """{"_`crazy type!`\"": "CrazyType"}"""
+ )
+
+ sealed trait Enum
+ case object A extends Enum
+ case object B extends Enum
+
+ implicit val enumFormat: RootJsonFormat[Enum] = jsonFormat[Enum]
+
+ "Enum" should behave like checkRoundtrip[List[Enum]](
+ A :: B :: Nil,
+ """[{"type":"A"}, {"type":"B"}]"""
+ )
+
+ "Serializing as sealed trait and deserializing as child" should "work" in {
+ implicit val plusFormat: RootJsonFormat[Plus] = jsonFormat[Plus]
+ val expr: Expr = Plus(Value(42), Plus(Zero(), One))
+ assert(expr.toJson.convertTo[Plus] == expr)
+ }
+
+}
diff --git a/shared/src/test/scala/FormatTests.scala b/shared/src/test/scala/FormatTests.scala
new file mode 100644
index 0000000..0f56091
--- /dev/null
+++ b/shared/src/test/scala/FormatTests.scala
@@ -0,0 +1,19 @@
+package spray.json
+
+import org.scalatest._
+
+trait FormatTests { self: FlatSpec =>
+
+ def checkRoundtrip[A: RootJsonFormat](a: A, expectedJson: String) = {
+ it should "serialize to the expected JSON value" in {
+ val expected: JsValue = expectedJson.parseJson
+ assert(a.toJson == expected)
+ }
+
+ it should "serialize then deserialize back to itself" in {
+ val reread = a.toJson.convertTo[A]
+ assert(reread == a)
+ }
+ }
+
+}
diff --git a/shared/src/test/scala/ImplicitDerivedFormatTests.scala b/shared/src/test/scala/ImplicitDerivedFormatTests.scala
new file mode 100644
index 0000000..1d54ae9
--- /dev/null
+++ b/shared/src/test/scala/ImplicitDerivedFormatTests.scala
@@ -0,0 +1,24 @@
+package spray.json
+
+import org.scalatest._
+
+class ImplicitDerivedFormatTests
+ extends FlatSpec
+ with FormatTests
+ with ImplicitDerivedFormats
+ with DefaultJsonProtocol {
+
+ case class B(x: Int, b: String, mp: Map[String, Int])
+ case class C(b: B)
+
+ "Simple parameter product" should behave like checkRoundtrip(
+ B(42, "Hello World", Map("a" -> 1, "b" -> -1024)),
+ """{ "x": 42, "b": "Hello World", "mp": { "a": 1, "b": -1024 } }"""
+ )
+
+ "Nested parameter product with custom child format" should behave like checkRoundtrip(
+ C(B(42, "Hello World", Map("a" -> 1, "b" -> -1024))),
+ """{"b" :{ "x": 42, "b": "Hello World", "mp": { "a": 1, "b": -1024 } } }"""
+ )
+
+}
diff --git a/shared/src/test/scala/ProductTypeFormatTests.scala b/shared/src/test/scala/ProductTypeFormatTests.scala
new file mode 100644
index 0000000..ce05000
--- /dev/null
+++ b/shared/src/test/scala/ProductTypeFormatTests.scala
@@ -0,0 +1,77 @@
+package spray.json
+
+import org.scalatest._
+
+class ProductTypeFormatTests
+ extends FlatSpec
+ with FormatTests
+ with DerivedFormats
+ with DefaultJsonProtocol {
+
+ case class A()
+ case class B(x: Int, b: String, mp: Map[String, Int])
+ case class C(b: B)
+ case object D
+ case class E(d: D.type)
+ case class F(x: Int)
+ case class G(f: F)
+
+ implicit val aFormat: RootJsonFormat[A] = jsonFormat[A]
+ implicit val bFormat: RootJsonFormat[B] = jsonFormat[B]
+ implicit val cFormat: RootJsonFormat[C] = jsonFormat[C]
+ implicit val dFormat: RootJsonFormat[D.type] = jsonFormat[D.type]
+ implicit val eFormat: RootJsonFormat[E] = jsonFormat[E]
+
+ "No-parameter product" should behave like checkRoundtrip(A(), "{}")
+
+ "Simple parameter product" should behave like checkRoundtrip(
+ B(42, "Hello World", Map("a" -> 1, "b" -> -1024)),
+ """{ "x": 42, "b": "Hello World", "mp": { "a": 1, "b": -1024 } }"""
+ )
+
+ "Nested parameter product" should behave like checkRoundtrip(
+ C(B(42, "Hello World", Map("a" -> 1, "b" -> -1024))),
+ """{"b" :{ "x": 42, "b": "Hello World", "mp": { "a": 1, "b": -1024 } } }"""
+ )
+
+ "Case object" should behave like checkRoundtrip(
+ D,
+ "{}"
+ )
+
+ "Case object as parameter" should behave like checkRoundtrip(
+ E(D),
+ """{"d":{}}"""
+ )
+
+ // custom format for F, that inverts the value of parameter x
+ implicit val fFormat: RootJsonFormat[F] = new RootJsonFormat[F] {
+ override def write(f: F): JsValue = JsObject("y" -> f.x.toJson)
+ override def read(js: JsValue): F =
+ F(js.asJsObject.fields("y").convertTo[Int])
+ }
+
+ "Overriding with a custom format" should behave like checkRoundtrip(
+ F(2),
+ """{"y":2}"""
+ )
+
+ implicit val gFormat: RootJsonFormat[G] = jsonFormat[G]
+
+ "Derving a format with a custom child format" should behave like checkRoundtrip(
+ G(F(2)),
+ """{"f": {"y":2}}"""
+ )
+
+ case class H(x: Boolean)
+ case class I(h: H)
+
+ // there is no format defined for H, Magnolia will generate one automatically
+ implicit val iFormat: RootJsonFormat[I] = jsonFormat[I]
+
+ "Deriving a format that has no implicit child formats available" should behave like checkRoundtrip(
+ I(H(true)),
+ """{"h": {"x":true}}"""
+ )
+
+}