Skip to content

Commit

Permalink
Add Scaladoc to public matcher API
Browse files Browse the repository at this point in the history
  • Loading branch information
ruippeixotog committed Dec 27, 2019
1 parent 1312839 commit a446f22
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,38 @@ import net.ruippeixotog.akka.testkit.specs2.impl.Matchers._

trait AkkaMatchers {

/**
* A `Matcher` expecting a probe to have received a message within the default timeout.
* Additional methods can be chained to constrain the expected message.
*/
def receive: UntypedReceiveMatcher[TestKitBase] = {
akkaClassicReceiveMatcher(
{ msg => s"Received message '$msg'" },
{ timeout => s"Timeout ($timeout) while waiting for message" },
_.remainingOrDefault)
}

/**
* A `Matcher` expecting a probe to have received a message within the provided timeout.
* Additional methods can be chained to constrain the expected message.
*
* @param max the timeout for a message to be received
*/
def receiveWithin(max: FiniteDuration): UntypedReceiveMatcher[TestKitBase] = {
akkaClassicReceiveMatcher(
{ msg => s"Received message '$msg' within $max" },
{ timeout => s"Didn't receive any message within $timeout" },
{ _ => max })
}

/**
* An alias for [[receive]].
*/
def receiveMessage: UntypedReceiveMatcher[TestKitBase] = receive

/**
* An alias for [[receiveWithin]].
*/
def receiveMessageWithin(max: FiniteDuration): UntypedReceiveMatcher[TestKitBase] = receiveWithin(max)

private[this] def akkaClassicReceiveMatcher(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,38 @@ import net.ruippeixotog.akka.testkit.specs2.impl.Matchers.ReceiveMatcherImpl

trait AkkaTypedMatchers {

/**
* A `Matcher` expecting a probe to have received a message within the default timeout.
* Additional methods can be chained to constrain the expected message.
*/
def receive[Msg]: ReceiveMatcher[TestProbe[Msg], Msg] = {
akkaTypedReceiveMatcher[Msg](
{ msg => s"Received message '$msg'" },
{ timeout => s"Timeout ($timeout) while waiting for message" },
_.remainingOrDefault)
}

/**
* A `Matcher` expecting a probe to have received a message within the provided timeout.
* Additional methods can be chained to constrain the expected message.
*
* @param max the timeout for a message to be received
*/
def receiveWithin[Msg](max: FiniteDuration): ReceiveMatcher[TestProbe[Msg], Msg] = {
akkaTypedReceiveMatcher[Msg](
{ msg => s"Received message '$msg' within $max" },
{ timeout => s"Didn't receive any message within $timeout" },
{ _ => max })
}

/**
* An alias for [[receive]].
*/
def receiveMessage[Msg]: ReceiveMatcher[TestProbe[Msg], Msg] = receive

/**
* An alias for [[receiveWithin]].
*/
def receiveMessageWithin[Msg](max: FiniteDuration): ReceiveMatcher[TestProbe[Msg], Msg] = receiveWithin(max)

private[this] def akkaTypedReceiveMatcher[Msg](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,96 @@ import scala.reflect.ClassTag
import org.specs2.execute.AsResult
import org.specs2.matcher.Matcher

/**
* The API used to transform and compose matchers for received messages.
*/
package object api {

trait BaseReceiveMatcher[P, A] extends Matcher[P]

trait SkippableReceiveMatcher[P, A] extends BaseReceiveMatcher[P, A] {

/**
* Skips non-matching messages until a matching one is received or a timeout occurs. Commonly used when the order of
* received messages cannot be guaranteed and the probe may receive other messages, like heartbeats.
*
* @return a new matcher that skips non-matching messages until a matching one is received or a timeout occurs.
*/
def afterOthers: BaseReceiveMatcher[P, A]
}

trait ReceiveMatcher[P, A] extends SkippableReceiveMatcher[P, A] {
def unwrap[B](f: A => B): ReceiveMatcher[P, B]
def unwrapPf[B](f: PartialFunction[A, B]): ReceiveMatcher[P, B]

/**
* Constrains the received messages to be of a given subtype.
*
* @tparam B the expected subtype of messages
* @return a new matcher that expects a probe to have received messages of type `B`.
*/
def ofSubtype[B <: A: ClassTag](implicit ev: A <:< AnyRef): ReceiveMatcher[P, B]

/**
* Checks that the received message is equal to the given value.
*
* @param msg the expected message
* @return a new matcher that expects a probe to have received `msg`.
*/
def apply(msg: A): SkippableReceiveMatcher[P, A]

/**
* Checks that the received message satisfies a predicate or a function applying further checks.
*
* @param f the predicate or function applying further checks
* @return a new matcher that expects a probe to have received messages satisfying `f`.
*/
def which[R: AsResult](f: A => R): SkippableReceiveMatcher[P, A]

/**
* Checks that the received message satisfies a partial predicate or function applying further checks.
*
* @param f the partial predicate or function applying further checks
* @return a new matcher that expects a probe to have received messages satisfying `f`.
*/
def like[R: AsResult](f: PartialFunction[A, R]): SkippableReceiveMatcher[P, A]

/**
* Checks that the probe received a sequence of messages in order. The timeout is applied to the whole sequence and
* not per message (i.e. all the messages have to be received before the timeout duration).
*
* @param msgs the expected sequence of messages
* @return a new matcher that expects a probe to have received all the messages in `msgs` in order.
*/
def allOf(msgs: A*): SkippableReceiveMatcher[P, Seq[A]]

/**
* Applies a function to the received messages before checks. Commonly used to unwrap data in envelope-like
* messages.
*
* @param f the function to apply to messages
* @tparam B the return type of the function
* @return a new matcher that applies `f` to messages before checking them.
*/
def unwrap[B](f: A => B): ReceiveMatcher[P, B]

/**
* Applies a partial function to the received messages before checks. Messages for which the function is undefined
* count as failures. Commonly used to unwrap data in envelope-like messages.
*
* @param f the partial function to apply to messages
* @tparam B the return type of the function
* @return a new matcher that applies `f` to messages before checking them.
*/
def unwrapPf[B](f: PartialFunction[A, B]): ReceiveMatcher[P, B]
}

trait UntypedReceiveMatcher[P] extends ReceiveMatcher[P, Any] {

/**
* Constrains the received messages to be of a given type.
*
* @tparam A the expected type of messages
* @return a new matcher that expects a probe to have received messages of type `A`.
*/
def apply[A: ClassTag]: ReceiveMatcher[P, A]
}
}

0 comments on commit a446f22

Please sign in to comment.