| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- package controllers
- import scala.concurrent.{Await,Future}
- import scala.language.postfixOps
- import scala.concurrent.duration.{Duration,DurationInt}
- import org.scalatestplus.play._
- import akka.stream.Materializer
- import play.api.mvc._
- import play.api.test._
- import play.api.test.Helpers._
- import play.api.http.Status
- import play.api.http.HeaderNames
- import play.api.libs.json.{JsValue,JsObject,Json,JsString}
- import org.scalatest._
- import org.scalatestplus.play._
- import org.scalatestplus.play.guice._
- import com.github.simplyscala.{MongoEmbedDatabase,MongodProps}
- import org.mongodb.scala.{MongoClient,MongoDatabase,MongoCollection,Observer,Completed};
- import models.Food
- import models.{Mass,Volume}
- class FoodControllerSpec
- extends PlaySpec
- with GuiceOneAppPerTest
- with Injecting
- with MongoEmbedDatabase {
- val testDBPort: Int = 12345
- implicit lazy val materializer: Materializer = app.materializer
- val exampleFood1: Food = Food("1", "Example Food", false, true, false, Map("iron" -> 1.2f, "B" -> 7f),
- "Test Script", Seq("Breakfast", "Asian"), Mass(), 3.2f, 2.7f, 1237, Seq("Scrambled Eggs"))
- val exampleFood2: Food = Food("2", "Food Example", true, false, false, Map("copper" -> .2f, "D" -> 1f),
- "Test Script", Seq("Dinner", "Southern"), Volume(), 1.2f, 2.0f, 73, Seq("Bacon"))
- val exampleJson1: JsValue = Json.parse(
- """{"name": "Example Food",
- |"glutenFree": false,
- |"vegitarian": true,
- |"vegan": false,
- |"nutrients": {"iron": 1.2, "B": 7},
- |"source": "Test Script",
- |"category": ["Breakfast", "Asian"],
- |"primaryMeasure": "mass",
- |"density": 3.2,
- |"mass_p_u": 2.7,
- |"price": 1237,
- |"alternatives": ["Scrambled Eggs"]
- |} """.stripMargin
- )
- val strippedExampleJson1: JsValue = Json.parse(
- """{"name": "Example Food",
- |"vegitarian": true,
- |"nutrients": {"iron": 1.2, "B": 7},
- |"source": "Test Script",
- |"category": ["Breakfast", "Asian"],
- |"primaryMeasure": "mass",
- |"density": 3.2,
- |"mass_p_u": 2.7,
- |"price": 1237,
- |"alternatives": ["Scrambled Eggs"]
- |} """.stripMargin
- )
- val brokenExampleJson1: JsValue = Json.parse(
- """{
- |"glutenFree": false,
- |"vegitarian": true,
- |"vegan": false,
- |"nutrients": {"iron": 1.2, "B": 7},
- |"source": "Test Script",
- |"category": ["Breakfast", "Asian"],
- |"primaryMeasure": "mass",
- |"density": 3.2,
- |"mass_p_u": 2.7,
- |"price": 1237,
- |"alternatives": ["Scrambled Eggs"]
- |} """.stripMargin
- )
- val exampleJson2: JsValue = Json.parse(
- """{"name": "Food Example",
- |"glutenFree": true,
- |"vegitarian": false,
- |"vegan": false,
- |"nutrients": {"copper": 0.2, "D": 1},
- |"source": "Test Script",
- |"category": ["Dinner", "Southern"],
- |"primaryMeasure": "volume",
- |"density": 1.2,
- |"mass_p_u": 2,
- |"price": 73,
- |"alternatives": ["Bacon"]
- |} """.stripMargin
- )
- def getDBColl(): MongoCollection[Food] = {
- val db: MongoDatabase = MongoClient.apply(s"mongodb://localhost:${testDBPort}")
- .getDatabase("recipes")
- .withCodecRegistry(MongoDB.codecRegistry)
- db.createCollection("Food")
- db.getCollection[Food]("Food")
- }
- def initDB(coll: MongoCollection[Food], items: Seq[Food]): MongoCollection[Food] = {
- val futures: Seq[Future[Completed]] = items.map(coll.insertOne(_).toFuture)
- futures.map(Await.ready(_, 5 minutes))
- coll
- }
- "FoodController PUT /food" should {
- "return the resulting food object and insert into the DB" in {
- val fakeRequ: FakeRequest[JsValue] = FakeRequest[JsValue](PUT, "/food", FakeHeaders(), exampleJson1)
- .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
- withEmbedMongoFixture() { mongodProps: MongodProps =>
- val coll: MongoCollection[Food] = getDBColl
- val controller: FoodController = new FoodController(coll)
- val result = controller.put().apply(fakeRequ)
- status(result) mustBe OK
- contentType(result) mustBe Some("application/json")
- val resultJs: JsObject = contentAsJson(result).asInstanceOf[JsObject]
- resultJs - "_id" mustBe exampleJson1
- Await.result(coll.countDocuments().toFuture, 5 minutes) mustBe 1
- Await.result(coll.find().first().toFuture, 5 minutes) mustBe resultJs.as[Food]
- }
- }
- "return an error when given an empty request and not " +
- "insert into the DB" in {
- val fakeRequ = FakeRequest(PUT, "/food", FakeHeaders(), "")
- .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
- withEmbedMongoFixture() { mongodProps: MongodProps =>
- val coll: MongoCollection[Food] = getDBColl
- val controller: FoodController = new FoodController(coll)
- val result = controller.put().apply(fakeRequ)
- status(result) mustBe Status.BAD_REQUEST
- Await.result(coll.countDocuments().toFuture, 5 minutes) mustBe 0
- }
- }
- "return an error when given an invalid request and not " +
- "insert into the DB" in {
- val fakeRequ = FakeRequest(PUT, "/food", FakeHeaders(), brokenExampleJson1)
- .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
- withEmbedMongoFixture() { mongodProps: MongodProps =>
- val coll: MongoCollection[Food] = getDBColl
- val controller: FoodController = new FoodController(coll)
- val result = controller.put().apply(fakeRequ)
- status(result) mustBe Status.BAD_REQUEST
- Await.result(coll.countDocuments().toFuture, 5 minutes) mustBe 0
- }
- }
- "return the resulting object with default values and " +
- "insert into the DB" in {
- val fakeRequ = FakeRequest(PUT, "/food", FakeHeaders(), strippedExampleJson1)
- .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
- withEmbedMongoFixture() { mongodProps: MongodProps =>
- val coll: MongoCollection[Food] = getDBColl
- val controller: FoodController = new FoodController(coll)
- val result = controller.put().apply(fakeRequ)
- status(result) mustBe OK
- contentType(result) mustBe Some("application/json")
- val resultJs: JsObject = contentAsJson(result).asInstanceOf[JsObject]
- resultJs - "_id" mustBe exampleJson1
- Await.result(coll.countDocuments().toFuture, 5 minutes) mustBe 1
- Await.result(coll.find().first().toFuture, 5 minutes) mustBe resultJs.as[Food]
- }
- }
- }
- "FoodController GET /food/:id" should {
- "return the correct food object" in {
- val fakeRequ: FakeRequest[JsValue] = FakeRequest[JsValue](GET, s"/food/${exampleFood1._id}", FakeHeaders(), JsString(""))
- withEmbedMongoFixture() { mongodProps: MongodProps =>
- val coll: MongoCollection[Food] = initDB(getDBColl, Seq(exampleFood1, exampleFood2))
- val controller: FoodController = new FoodController(coll)
- val result = controller.put().apply(fakeRequ)
- status(result) mustBe OK
- contentType(result) mustBe Some("application/json")
- val resultJs: JsObject = contentAsJson(result).asInstanceOf[JsObject]
- resultJs.value.get("_id").toString mustBe exampleFood1._id
- resultJs - "_id" mustBe exampleJson1
- }
- }
- "return an error when given an empty request and not " +
- "insert into the DB" in {
- val fakeRequ: FakeRequest[JsValue] = FakeRequest[JsValue](GET, s"/food/0", FakeHeaders(), JsString(""))
- withEmbedMongoFixture() { mongodProps: MongodProps =>
- val coll: MongoCollection[Food] = getDBColl
- val controller: FoodController = new FoodController(coll)
- val result = controller.put().apply(fakeRequ)
- status(result) mustBe Status.NOT_FOUND
- }
- }
- }
- }
|