FoodControllerSpec.scala 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package controllers
  2. import scala.concurrent.Await
  3. import scala.concurrent.duration.Duration
  4. import org.scalatestplus.play._
  5. import akka.stream.Materializer
  6. import play.api.mvc._
  7. import play.api.test._
  8. import play.api.test.Helpers._
  9. import play.api.http.Status
  10. import play.api.http.HeaderNames
  11. import play.api.libs.json.{JsValue,JsObject,Json}
  12. import org.scalatest._
  13. import org.scalatestplus.play._
  14. import org.scalatestplus.play.guice._
  15. import com.github.simplyscala.{MongoEmbedDatabase,MongodProps}
  16. import org.mongodb.scala.{MongoClient,MongoDatabase,MongoCollection,Observer};
  17. import models.Food
  18. class FoodControllerSpec
  19. extends PlaySpec
  20. with GuiceOneAppPerTest
  21. with Injecting
  22. with MongoEmbedDatabase {
  23. val testDBPort: Int = 12345
  24. implicit lazy val materializer: Materializer = app.materializer
  25. def getDBColl(): MongoCollection[Food] = {
  26. val db: MongoDatabase = MongoClient.apply(s"mongodb://localhost:${testDBPort}")
  27. .getDatabase("recipes")
  28. .withCodecRegistry(MongoDB.codecRegistry)
  29. db.createCollection("Food")
  30. db.getCollection[Food]("Food")
  31. }
  32. // def blockingObserver[T](sem: Semaphore, processor: T => Unit) = new Observer[T] {
  33. // override def onNext(result: T) = {println("next");processor(result)}
  34. // override def onError(e: Throwable) = {
  35. // println("error")
  36. // sem.release()
  37. // throw e
  38. // }
  39. // override def onComplete() = {println("complete");sem.release()}
  40. // }
  41. "FoodController PUT /food" should {
  42. "return the resulting food object and insert into the DB" in {
  43. val body: JsValue = Json.parse(
  44. """{"name": "Example Food",
  45. |"glutenFree": false,
  46. |"vegitarian": true,
  47. |"vegan": false,
  48. |"nutrients": {"iron": 1.2, "B": 7},
  49. |"source": "Test Script",
  50. |"category": ["Breakfast", "Asian"],
  51. |"primaryMeasure": "mass",
  52. |"density": 3.2,
  53. |"mass_p_u": 2.7,
  54. |"price": 1237,
  55. |"alternatives": ["Scrambled Eggs"]
  56. |} """.stripMargin
  57. )
  58. val fakeRequ: FakeRequest[JsValue] = FakeRequest[JsValue](PUT, "/food", FakeHeaders(), body)
  59. .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
  60. withEmbedMongoFixture() { mongodProps: MongodProps =>
  61. val coll: MongoCollection[Food] = getDBColl
  62. val controller: FoodController = new FoodController(coll)
  63. val result = controller.put().apply(fakeRequ)
  64. status(result) mustBe OK
  65. contentType(result) mustBe Some("application/json")
  66. val resultJs: JsObject = contentAsJson(result).asInstanceOf[JsObject]
  67. resultJs - "_id" mustBe body
  68. Await.result(coll.countDocuments().toFuture, Duration.Inf) mustBe 1
  69. Await.result(coll.find().first().toFuture, Duration.Inf) mustBe resultJs.as[Food]
  70. }
  71. }
  72. // Removed: not presenting id's to front-end
  73. // "return the resulting food object with a distinct id" in {
  74. // val controller = inject[HomeController]
  75. // val home = controller.index().apply(FakeRequest(GET, "/"))
  76. // status(home) mustBe OK
  77. // contentType(home) mustBe Some("text/html")
  78. // contentAsString(home) must include ("Welcome to Play")
  79. // }
  80. "return an error when given an empty request and not " +
  81. "insert into the DB" in {
  82. val fakeRequ = FakeRequest(PUT, "/food", FakeHeaders(), "")
  83. .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
  84. withEmbedMongoFixture() { mongodProps: MongodProps =>
  85. val coll: MongoCollection[Food] = getDBColl
  86. val controller: FoodController = new FoodController(coll)
  87. val result = controller.put().apply(fakeRequ)
  88. status(result) mustBe Status.BAD_REQUEST
  89. Await.result(coll.countDocuments().toFuture, Duration.Inf) mustBe 0
  90. }
  91. }
  92. "return an error when given an invalid request and not " +
  93. "insert into the DB" in {
  94. val body: JsValue = Json.parse(// Name intentionally moved
  95. """{
  96. |"glutenFree": false,
  97. |"vegitarian": true,
  98. |"vegan": false,
  99. |"nutrients": {"iron": 1.2, "B": 7},
  100. |"source": "Test Script",
  101. |"category": ["Breakfast", "Asian"],
  102. |"primaryMeasure": "mass",
  103. |"density": 3.2,
  104. |"mass_p_u": 2.7,
  105. |"price": 1237,
  106. |"alternatives": ["Scrambled Eggs"]
  107. |} """.stripMargin
  108. )
  109. val fakeRequ = FakeRequest(PUT, "/food", FakeHeaders(), body)
  110. .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
  111. withEmbedMongoFixture() { mongodProps: MongodProps =>
  112. val coll: MongoCollection[Food] = getDBColl
  113. val controller: FoodController = new FoodController(coll)
  114. val result = controller.put().apply(fakeRequ)
  115. status(result) mustBe Status.BAD_REQUEST
  116. Await.result(coll.countDocuments().toFuture, Duration.Inf) mustBe 0
  117. }
  118. }
  119. "return the resulting object with default values and " +
  120. "insert into the DB" in {
  121. val body: JsValue = Json.parse(
  122. """{"name": "Example Food",
  123. |"vegitarian": true,
  124. |"nutrients": {"iron": 1.2, "B": 7},
  125. |"source": "Test Script",
  126. |"category": ["Breakfast", "Asian"],
  127. |"primaryMeasure": "mass",
  128. |"density": 3.2,
  129. |"mass_p_u": 2.7,
  130. |"price": 1237,
  131. |"alternatives": ["Scrambled Eggs"]
  132. |} """.stripMargin
  133. )
  134. val expected: JsValue = Json.parse(
  135. """{"name": "Example Food",
  136. |"glutenFree": false,
  137. |"vegitarian": true,
  138. |"vegan": false,
  139. |"nutrients": {"iron": 1.2, "B": 7},
  140. |"source": "Test Script",
  141. |"category": ["Breakfast", "Asian"],
  142. |"primaryMeasure": "mass",
  143. |"density": 3.2,
  144. |"mass_p_u": 2.7,
  145. |"price": 1237,
  146. |"alternatives": ["Scrambled Eggs"]
  147. |} """.stripMargin
  148. )
  149. val fakeRequ = FakeRequest(PUT, "/food", FakeHeaders(), body)
  150. .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
  151. withEmbedMongoFixture() { mongodProps: MongodProps =>
  152. val coll: MongoCollection[Food] = getDBColl
  153. val controller: FoodController = new FoodController(coll)
  154. val result = controller.put().apply(fakeRequ)
  155. status(result) mustBe OK
  156. contentType(result) mustBe Some("application/json")
  157. val resultJs: JsObject = contentAsJson(result).asInstanceOf[JsObject]
  158. resultJs - "_id" mustBe expected
  159. Await.result(coll.countDocuments().toFuture, Duration.Inf) mustBe 1
  160. Await.result(coll.find().first().toFuture, Duration.Inf) mustBe resultJs.as[Food]
  161. }
  162. }
  163. }
  164. }