From e4e507fdd991e872aa6f7070b585e2ab8eab0261 Mon Sep 17 00:00:00 2001 From: jalal Date: Sun, 7 Aug 2016 23:04:29 +0200 Subject: [PATCH] Refactor MVars class to an sealed trait to allow to create different type of MVars. Add support of sequence of string with SeqMVars --- .../models/MandrillJsonProtocol.scala | 26 ++++- .../models/MandrillMessagesRequests.scala | 25 ++++- .../scamandrill/client/InboundCallsTest.scala | 4 - .../scamandrill/client/IspCallsTest.scala | 2 - .../scamandrill/client/MessageCallsTest.scala | 3 - .../scamandrill/client/RejectCallsTest.scala | 4 - .../client/SubaccountCallsTest.scala | 2 - .../scamandrill/client/TagsCallsTest.scala | 5 - .../client/TemplateCallsTest.scala | 2 - .../scamandrill/client/UrlCallsTest.scala | 5 - .../scamandrill/client/WebhookCallsTest.scala | 2 - .../models/MandrillJsonProtocolTest.scala | 104 +++++++++++++----- 12 files changed, 123 insertions(+), 61 deletions(-) diff --git a/src/main/scala/com/joypeg/scamandrill/models/MandrillJsonProtocol.scala b/src/main/scala/com/joypeg/scamandrill/models/MandrillJsonProtocol.scala index ddaef7e..385150c 100644 --- a/src/main/scala/com/joypeg/scamandrill/models/MandrillJsonProtocol.scala +++ b/src/main/scala/com/joypeg/scamandrill/models/MandrillJsonProtocol.scala @@ -16,7 +16,31 @@ object MandrillJsonProtocol extends DefaultJsonProtocol { implicit val MUserInfoResponseJson = jsonFormat7(MInfoResponse) implicit val MAttachmetOrImageJson = jsonFormat3(MAttachmetOrImage) - implicit val MVarsJson = jsonFormat2(MVars) + implicit val StringMVarsJson = jsonFormat2(StringMVars) + implicit val SeqMVarsJson = jsonFormat2(SeqMVars) + implicit val MVarJson: RootJsonFormat[MVars] = new RootJsonFormat[MVars] { + override def read(json: JsValue): MVars = json match { + case obj: JsObject => + obj.getFields("name", "content") match { + case Seq(JsString(name: String), JsArray(values: Vector[JsValue])) => + val strings: Vector[String] = values + .collect { case jsString: JsString => jsString.value } + + SeqMVars(name, strings) + case Seq(JsString(name), JsString(value)) => + StringMVars(name, value) + case _ => + throw new IllegalArgumentException("JsObject should be an json object with property name and value") + } + case _ => + throw new IllegalArgumentException("JsObject should be an json object with property name and value") + } + + override def write(obj: MVars): JsValue = obj match { + case old: StringMVars => StringMVarsJson.write(old) + case custom :SeqMVars => SeqMVarsJson.write(custom) + } + } implicit val MMergeVarsJson = jsonFormat2(MMergeVars) implicit val MToJson = jsonFormat3(MTo) implicit val MSendResponseJson = jsonFormat4(MSendResponse) diff --git a/src/main/scala/com/joypeg/scamandrill/models/MandrillMessagesRequests.scala b/src/main/scala/com/joypeg/scamandrill/models/MandrillMessagesRequests.scala index ee4a46d..b21a076 100644 --- a/src/main/scala/com/joypeg/scamandrill/models/MandrillMessagesRequests.scala +++ b/src/main/scala/com/joypeg/scamandrill/models/MandrillMessagesRequests.scala @@ -235,12 +235,27 @@ case class MAttachmetOrImage(`type`: String, name: String, content: String) */ case class MMergeVars(rcpt: String, vars: List[MVars]) +sealed trait MVars + +/*** A single merge variable + * + * @param name - the merge variable's name. Merge variable names are case-insensitive and may not start with _ + * @param content - the merge variable's content + */ +case class StringMVars(name: String, content: String) extends MVars + /** - * A single merge variable - * @param name - the merge variable's name. Merge variable names are case-insensitive and may not start with _ - * @param content - the merge variable's content - */ -case class MVars(name: String, content: String) + * A sequence of string merge variable + * + * @param name - the merge variable's name. Merge variable names are case-insensitive and may not start with _ + * @param content - a sequence of variable string content + */ +case class SeqMVars(name: String, content: Seq[String]) extends MVars + +object MVars { + def apply(name: String, content: String): MVars = StringMVars(name, content) + def apply(name: String, content: Seq[String]): MVars = SeqMVars(name, content) +} /** * A single recipient's information. diff --git a/src/test/scala/com/joypeg/scamandrill/client/InboundCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/InboundCallsTest.scala index 6abfb56..c7b467b 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/InboundCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/InboundCallsTest.scala @@ -1,8 +1,5 @@ package com.joypeg.scamandrill.client - -import com.joypeg.scamandrill -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.FlatSpec import org.scalatest.Matchers import scala.concurrent.Await @@ -12,7 +9,6 @@ import com.joypeg.scamandrill.utils.SimpleLogger import scala.util.Failure import scala.util.Success - class InboundCallsTest extends FlatSpec with Matchers with SimpleLogger { "InboundAddDomains" should "work getting a valid MInboundDomainResponse (async client)" in { diff --git a/src/test/scala/com/joypeg/scamandrill/client/IspCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/IspCallsTest.scala index 85c17dd..d5b3e6e 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/IspCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/IspCallsTest.scala @@ -1,7 +1,5 @@ package com.joypeg.scamandrill.client -import com.joypeg.scamandrill -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.FlatSpec import org.scalatest.Matchers import scala.concurrent.Await diff --git a/src/test/scala/com/joypeg/scamandrill/client/MessageCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/MessageCallsTest.scala index d5e065f..53cd541 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/MessageCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/MessageCallsTest.scala @@ -1,7 +1,5 @@ package com.joypeg.scamandrill.client -import com.joypeg.scamandrill -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.FlatSpec import org.scalatest.Matchers import scala.concurrent.Await @@ -9,7 +7,6 @@ import com.joypeg.scamandrill.models._ import scala.util.{Failure, Success} import com.joypeg.scamandrill.utils._ - class MessageCallsTest extends FlatSpec with Matchers with SimpleLogger { import com.joypeg.scamandrill.MandrillTestUtils._ diff --git a/src/test/scala/com/joypeg/scamandrill/client/RejectCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/RejectCallsTest.scala index 31da266..ed62b1b 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/RejectCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/RejectCallsTest.scala @@ -1,15 +1,11 @@ package com.joypeg.scamandrill.client -import com.joypeg.scamandrill -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.FlatSpec import org.scalatest.Matchers import scala.concurrent.Await import com.joypeg.scamandrill.models._ -import scala.util.{Failure, Success} import com.joypeg.scamandrill.utils._ import com.joypeg.scamandrill.MandrillTestUtils._ -import com.joypeg.scamandrill.models.MKey import scala.util.Failure import com.joypeg.scamandrill.models.MRejectAdd import scala.util.Success diff --git a/src/test/scala/com/joypeg/scamandrill/client/SubaccountCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/SubaccountCallsTest.scala index 40447d4..ea339ea 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/SubaccountCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/SubaccountCallsTest.scala @@ -1,6 +1,5 @@ package com.joypeg.scamandrill.client -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.FlatSpec import org.scalatest.Matchers import scala.concurrent.Await @@ -10,7 +9,6 @@ import com.joypeg.scamandrill.utils.SimpleLogger import scala.util.Failure import scala.util.Success - class SubaccountCallsTest extends FlatSpec with Matchers with SimpleLogger { "SubaccountAdd" should "work getting a valid MSubaccountsResponse (async client)" in { diff --git a/src/test/scala/com/joypeg/scamandrill/client/TagsCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/TagsCallsTest.scala index 275a602..189848b 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/TagsCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/TagsCallsTest.scala @@ -1,15 +1,10 @@ package com.joypeg.scamandrill.client -import com.joypeg.scamandrill -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.{Matchers, FlatSpec} import com.joypeg.scamandrill.utils.SimpleLogger import scala.concurrent.Await import com.joypeg.scamandrill.models._ -import scala.util.{Failure, Success} import com.joypeg.scamandrill.MandrillTestUtils._ -import scala.util.Failure -import scala.util.Success import com.joypeg.scamandrill.models.MKey import scala.util.Failure import com.joypeg.scamandrill.models.MTagResponse diff --git a/src/test/scala/com/joypeg/scamandrill/client/TemplateCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/TemplateCallsTest.scala index 2f3a852..ce76924 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/TemplateCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/TemplateCallsTest.scala @@ -1,7 +1,5 @@ package com.joypeg.scamandrill.client -import com.joypeg.scamandrill -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.FlatSpec import org.scalatest.Matchers import scala.concurrent.Await diff --git a/src/test/scala/com/joypeg/scamandrill/client/UrlCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/UrlCallsTest.scala index 28099f9..243e760 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/UrlCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/UrlCallsTest.scala @@ -1,18 +1,13 @@ package com.joypeg.scamandrill.client -import com.joypeg.scamandrill -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.FlatSpec import org.scalatest.Matchers import scala.concurrent.Await import com.joypeg.scamandrill.models._ -import scala.util.Success import com.joypeg.scamandrill.utils._ import com.joypeg.scamandrill.MandrillTestUtils._ import scala.util.Failure -import com.joypeg.scamandrill.models.MRejectAdd import scala.util.Success -import com.joypeg.scamandrill.models.MRejectAddResponse class UrlCallsTest extends FlatSpec with Matchers with SimpleLogger { diff --git a/src/test/scala/com/joypeg/scamandrill/client/WebhookCallsTest.scala b/src/test/scala/com/joypeg/scamandrill/client/WebhookCallsTest.scala index eee5179..f5b1708 100644 --- a/src/test/scala/com/joypeg/scamandrill/client/WebhookCallsTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/client/WebhookCallsTest.scala @@ -1,7 +1,5 @@ package com.joypeg.scamandrill.client -import com.joypeg.scamandrill -import com.joypeg.scamandrill.client.UnsuccessfulResponseException import org.scalatest.FlatSpec import org.scalatest.Matchers import scala.concurrent.Await diff --git a/src/test/scala/com/joypeg/scamandrill/models/MandrillJsonProtocolTest.scala b/src/test/scala/com/joypeg/scamandrill/models/MandrillJsonProtocolTest.scala index c8e3a2c..84217d5 100644 --- a/src/test/scala/com/joypeg/scamandrill/models/MandrillJsonProtocolTest.scala +++ b/src/test/scala/com/joypeg/scamandrill/models/MandrillJsonProtocolTest.scala @@ -1,35 +1,87 @@ package com.joypeg.scamandrill.models -import org.scalatest.{Matchers, FlatSpec} +import org.scalatest.{FlatSpec, Matchers} import com.joypeg.scamandrill.utils.SimpleLogger +import spray.json.{JsArray, JsObject, JsString, JsValue} class MandrillJsonProtocolTest extends FlatSpec with Matchers with SimpleLogger { - import com.joypeg.scamandrill.MandrillTestUtils._ - -// "MSendMessageJsonFormat" should "marshall and unmarshall a MSendMessage" in { -// import MandrillJsonProtocol._ -// import spray.httpx.SprayJsonSupport._ -// val jsonized = MSendMsgJsonFormat.write(validMessage.copy(headers = Some(List(MHeader("the", "value"))))) -// println("JSONIZED: " + jsonized) -// //MSendMsgJsonFormat.read(jsonized) shouldBe validMessage -// } -// -// "MHeader" should "marshall correctly" in { -// import MandrillJsonProtocol._ -// import spray.httpx.SprayJsonSupport._ -// val header = MHeader("Reply-To","message.reply@example.com") -// val jsonized = MHeaderJsonFormat.write(header) -// println("JSONIZED: " + jsonized) -// } -// -// "MMetadata" should "marshall correctly" in { -// import MandrillJsonProtocol._ -// import spray.httpx.SprayJsonSupport._ -// val header = MMetadata("Reply-To","message.reply@example.com") -// val jsonized = MMetadataJsonFormat.write(header) -// println("JSONIZED: " + jsonized) -// } + it should "test SeqMVars serialization" in { + val testValues = Seq("one", "two", "three") + val testValue : MVars = SeqMVars("test", testValues) + val jsObj = MandrillJsonProtocol.MVarJson.write(testValue).asJsObject + + jsObj.getFields("name", "content") match { + case Seq(JsString(name), JsArray(values: Vector[JsValue])) => { + val strings: Vector[String] = values + .collect { case jsString: JsString => jsString.value } + + assert(name.toString == "test") + assert(strings.toList == testValues.toList) + } + case _ => throw new IllegalArgumentException("Object is not serialized correctly") + } + } + + it should "test StringMVars serialization" in { + val testValue : MVars = StringMVars("test", "one") + val jsObj = MandrillJsonProtocol.MVarJson.write(testValue).asJsObject + + jsObj.getFields("name", "content") match { + case Seq(JsString(name), JsString(content)) => { + assert(name == "test") + assert(content == "one") + } + case _ => throw new IllegalArgumentException("Object is not serialized correctly") + } + } + + it should "test SeqMVars unserialization" in { + val testContent = Vector("one", "two", "three") + val testValue : MVars = SeqMVars("test", testContent) + val jsValue = MandrillJsonProtocol.MVarJson.write(testValue) + val unserializedObj = MandrillJsonProtocol.MVarJson.read(jsValue) + + unserializedObj match { + case custom: SeqMVars => { + assert(custom.name == "test") + assert(custom.content == testContent) + } + case _ => throw new IllegalArgumentException("Object is not unserialized correctly") + } + } + + it should "test StringMVars unserialization" in { + val testValue : MVars = StringMVars("test", "one") + val jsValue = MandrillJsonProtocol.MVarJson.write(testValue) + val unserializedObj = MandrillJsonProtocol.MVarJson.read(jsValue) + + unserializedObj match { + case old: StringMVars => { + assert(old.name == "test") + assert(old.content == "one") + } + case _ => throw new IllegalArgumentException("Object is not unserialized correctly") + } + } + + it should "test if invalid data cannot be a MVars instance" in { + val testValue = JsObject(Map( + "invalid" -> JsString("test") + )) + + intercept[IllegalArgumentException] { + MandrillJsonProtocol.MVarJson.read(testValue) + } + } + + it should "test if invalid JsValue cannot be a MVars instance" in { + val testValue = JsString("test") + + intercept[IllegalArgumentException] { + MandrillJsonProtocol.MVarJson.read(testValue) + } + } }