packages feed

HMock-0.3.0.0: src/Test/HMock/Rule.hs

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}

-- | This module defines the 'Rule' type, which describes a matcher for methods
-- and a possibly-empty list of responses to use for successive calls to
-- matching methods.  The 'Expectable' type class generalizes 'Rule', so that
-- you can specify a bare 'Matcher' or 'Action' in most situations where a
-- 'Rule' is needed but you don't want to specify the response.
module Test.HMock.Rule
  ( Rule,
    Expectable (..),
    (|->),
    (|=>),
    WholeMethodMatcher (SuchThat),
  )
where

import Test.HMock.Internal.Rule (Rule (..), WholeMethodMatcher (..))
import {-# SOURCE #-} Test.HMock.Internal.State (MockT)
import Test.HMock.Mockable (MockableBase (Action, Matcher))

-- | Class for things that can be expected.  This is includes 'Rule's, but also
-- bare 'Matcher's and 'Action's with no explicit response.
class Expectable cls name m r ex | ex -> cls name m r where
  -- | Converts an expectable to a Rule that means the same thing.
  toRule :: ex -> Rule cls name m r

-- | Attaches a response to an expectation.  This is a flexible response,
-- which can look at arguments, do things in the base monad, set up more
-- expectations, etc.  A matching 'Action' is passed to the response.
(|=>) ::
  Expectable cls name m r ex =>
  ex ->
  (Action cls name m r -> MockT m r) ->
  Rule cls name m r
e |=> r = m :=> (rs ++ [r]) where m :=> rs = toRule e

infixl 1 |=>

-- | Attaches a return value to an expectation.  This is more convenient than
-- '|=>' in the common case where you just want to return a known result.
-- @e '|->' r@ means the same thing as @e '|=>' 'const' ('return' r)@.
(|->) ::
  (Monad m, Expectable cls name m r ex) =>
  ex ->
  r ->
  Rule cls name m r
m |-> r = m |=> const (return r)

infixl 1 |->

instance Expectable cls name m r (Rule cls name m r) where
  toRule = id

instance Expectable cls name m r (Matcher cls name m r) where
  toRule m = JustMatcher m :=> []

instance Expectable cls name m r (WholeMethodMatcher cls name m r) where
  toRule m = m :=> []