All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netaporter.precanned.dsl.basic.scala Maven / Gradle / Ivy

There is a newer version: 0.1.2
Show newest version
package com.netaporter.precanned.dsl

import akka.actor.{ ActorRef, ActorRefFactory, ActorSystem, Props }
import akka.http.scaladsl.Http
import akka.pattern.ask
import akka.util.Timeout
import com.netaporter.precanned.HttpServerMock._
import com.netaporter.precanned._

import scala.Function.chain
import scala.concurrent.duration._
import scala.concurrent.{ Await, Future }

object basic extends Expectations with CannedResponses {

  def httpServerMock(af: ActorRefFactory) = {
    val actor = af.actorOf(Props[HttpServerMock])
    Start(actor)
  }

  trait MockDsl {
    def mock: ActorRef

    def expect(es: Expect*) = MockExpects(mock, es)

    def clearExpectations(blockUpTo: FiniteDuration = 3.seconds) = {
      val clearing = mock.ask(ClearExpectations)(Timeout(blockUpTo))
      if (blockUpTo > Duration.Zero) {
        Await.result(clearing, blockUpTo)
      }
      this
    }
  }

  case class Start(mock: ActorRef) extends MockDsl {

    def bind(
      port: Int = 0, interface: String = "127.0.0.1")(implicit as: ActorSystem, t: Timeout = 5.seconds): BindInProgress = {
      val bindFuture = HttpServerMock.startServer(mock, port, interface)
      BindInProgress(mock, bindFuture, t)
    }

  }

  case class BindInProgress(mock: ActorRef, bind: Future[Http.ServerBinding], t: Timeout) extends MockDsl {
    def block = {
      val bound = Await.result(bind, t.duration)
      BoundComplete(mock, bound)
    }
  }

  case class BoundComplete(mock: ActorRef, binding: Http.ServerBinding) extends MockDsl

  case class MockExpects(mock: ActorRef, expects: Seq[Expect]) {
    def andRespondWith(pcs: Precanned*): ExpectationAddInProgress = {
      val expectAndRespond = ExpectAndRespondWith(r => expects.forall(_.apply(r)), chain(pcs)(PrecannedResponse.empty))
      // 60 seconds is a hack for users who want to use `ExpectationAddInProgress.blockFor`. Would be nice to use their
      // timeout specified in the method, but we do not have that yet here
      // Adding an expectation is a fast operation, so it is reasonably safe to assume we will never need to wait longer
      // 60 seconds for this.
      val expectInProgress = mock.ask(expectAndRespond)(Timeout(60.seconds)).mapTo[PrecannedResponseAdded.type]
      ExpectationAddInProgress(expectInProgress)
    }
  }

  case class ExpectationAddInProgress(expectInProgress: Future[PrecannedResponseAdded.type]) {
    def blockFor(blockUpTo: FiniteDuration) = {
      Await.result(expectInProgress, blockUpTo)
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy