{-# LANGUAGE DerivingVia #-}

-- | Concrete reader monad over 'Matchers'
--
-- Its 'MonadAWS' instance can be used in tests where you don't have or
-- want your own test-app transformer:
--
-- @
-- import "Amazonka.S3"
-- import "Control.Monad.AWS"
--
-- spec :: Spec
-- spec = do
--   describe "someAction" $ do
--     it "works" $ do
--       let matcher =
--             'SendMatcher' (const @_ @ListBuckets True) -- match all calls
--               $ Right
--               $ 'newListBucketsResponse'               -- return no buckets
--               & 'listBucketsResponse_buckets' ?~ []
--
--       names <- 'runMockT' $ 'withMatcher' matcher $ someAction
--       names `shouldBe` []
--
-- someAction :: (MonadIO m, 'MonadAWS') m => m [BucketName]
-- someAction = do
--   resp <- 'send' 'newListBuckets'
--   pure
--     $ maybe [] (map (^. bucket_name))
--     $ resp ^. listBucketsResponse_buckets
-- @
module Control.Monad.AWS.MockT
  ( MockT
  , runMockT

    -- * Setting up 'Matchers'
  , Matcher (..)
  , withMatcher
  , withMatchers
  ) where

import Prelude

import Control.Monad.AWS.Class
import Control.Monad.AWS.Matchers
import Control.Monad.AWS.ViaMock
import Control.Monad.IO.Unlift
import Control.Monad.Reader

-- |
--
-- @since 0.1.0.0
newtype MockT m a = MockT
  { forall (m :: * -> *) a. MockT m a -> ReaderT Matchers m a
unMockT :: ReaderT Matchers m a
  }
  deriving newtype
    ( (forall a b. (a -> b) -> MockT m a -> MockT m b)
-> (forall a b. a -> MockT m b -> MockT m a) -> Functor (MockT m)
forall a b. a -> MockT m b -> MockT m a
forall a b. (a -> b) -> MockT m a -> MockT m b
forall (m :: * -> *) a b. Functor m => a -> MockT m b -> MockT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> MockT m a -> MockT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> MockT m a -> MockT m b
fmap :: forall a b. (a -> b) -> MockT m a -> MockT m b
$c<$ :: forall (m :: * -> *) a b. Functor m => a -> MockT m b -> MockT m a
<$ :: forall a b. a -> MockT m b -> MockT m a
Functor
    , Functor (MockT m)
Functor (MockT m) =>
(forall a. a -> MockT m a)
-> (forall a b. MockT m (a -> b) -> MockT m a -> MockT m b)
-> (forall a b c.
    (a -> b -> c) -> MockT m a -> MockT m b -> MockT m c)
-> (forall a b. MockT m a -> MockT m b -> MockT m b)
-> (forall a b. MockT m a -> MockT m b -> MockT m a)
-> Applicative (MockT m)
forall a. a -> MockT m a
forall a b. MockT m a -> MockT m b -> MockT m a
forall a b. MockT m a -> MockT m b -> MockT m b
forall a b. MockT m (a -> b) -> MockT m a -> MockT m b
forall a b c. (a -> b -> c) -> MockT m a -> MockT m b -> MockT m c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
forall (m :: * -> *). Applicative m => Functor (MockT m)
forall (m :: * -> *) a. Applicative m => a -> MockT m a
forall (m :: * -> *) a b.
Applicative m =>
MockT m a -> MockT m b -> MockT m a
forall (m :: * -> *) a b.
Applicative m =>
MockT m a -> MockT m b -> MockT m b
forall (m :: * -> *) a b.
Applicative m =>
MockT m (a -> b) -> MockT m a -> MockT m b
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> MockT m a -> MockT m b -> MockT m c
$cpure :: forall (m :: * -> *) a. Applicative m => a -> MockT m a
pure :: forall a. a -> MockT m a
$c<*> :: forall (m :: * -> *) a b.
Applicative m =>
MockT m (a -> b) -> MockT m a -> MockT m b
<*> :: forall a b. MockT m (a -> b) -> MockT m a -> MockT m b
$cliftA2 :: forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> MockT m a -> MockT m b -> MockT m c
liftA2 :: forall a b c. (a -> b -> c) -> MockT m a -> MockT m b -> MockT m c
$c*> :: forall (m :: * -> *) a b.
Applicative m =>
MockT m a -> MockT m b -> MockT m b
*> :: forall a b. MockT m a -> MockT m b -> MockT m b
$c<* :: forall (m :: * -> *) a b.
Applicative m =>
MockT m a -> MockT m b -> MockT m a
<* :: forall a b. MockT m a -> MockT m b -> MockT m a
Applicative
    , Applicative (MockT m)
Applicative (MockT m) =>
(forall a b. MockT m a -> (a -> MockT m b) -> MockT m b)
-> (forall a b. MockT m a -> MockT m b -> MockT m b)
-> (forall a. a -> MockT m a)
-> Monad (MockT m)
forall a. a -> MockT m a
forall a b. MockT m a -> MockT m b -> MockT m b
forall a b. MockT m a -> (a -> MockT m b) -> MockT m b
forall (m :: * -> *). Monad m => Applicative (MockT m)
forall (m :: * -> *) a. Monad m => a -> MockT m a
forall (m :: * -> *) a b.
Monad m =>
MockT m a -> MockT m b -> MockT m b
forall (m :: * -> *) a b.
Monad m =>
MockT m a -> (a -> MockT m b) -> MockT m b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
MockT m a -> (a -> MockT m b) -> MockT m b
>>= :: forall a b. MockT m a -> (a -> MockT m b) -> MockT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
MockT m a -> MockT m b -> MockT m b
>> :: forall a b. MockT m a -> MockT m b -> MockT m b
$creturn :: forall (m :: * -> *) a. Monad m => a -> MockT m a
return :: forall a. a -> MockT m a
Monad
    , Monad (MockT m)
Monad (MockT m) =>
(forall a. IO a -> MockT m a) -> MonadIO (MockT m)
forall a. IO a -> MockT m a
forall (m :: * -> *).
Monad m =>
(forall a. IO a -> m a) -> MonadIO m
forall (m :: * -> *). MonadIO m => Monad (MockT m)
forall (m :: * -> *) a. MonadIO m => IO a -> MockT m a
$cliftIO :: forall (m :: * -> *) a. MonadIO m => IO a -> MockT m a
liftIO :: forall a. IO a -> MockT m a
MonadIO
    , MonadIO (MockT m)
MonadIO (MockT m) =>
(forall b. ((forall a. MockT m a -> IO a) -> IO b) -> MockT m b)
-> MonadUnliftIO (MockT m)
forall b. ((forall a. MockT m a -> IO a) -> IO b) -> MockT m b
forall (m :: * -> *).
MonadIO m =>
(forall b. ((forall a. m a -> IO a) -> IO b) -> m b)
-> MonadUnliftIO m
forall (m :: * -> *). MonadUnliftIO m => MonadIO (MockT m)
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. MockT m a -> IO a) -> IO b) -> MockT m b
$cwithRunInIO :: forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. MockT m a -> IO a) -> IO b) -> MockT m b
withRunInIO :: forall b. ((forall a. MockT m a -> IO a) -> IO b) -> MockT m b
MonadUnliftIO
    , MonadReader Matchers
    )
  deriving (Monad (MockT m)
Monad (MockT m) =>
(forall a.
 (AWSRequest a, Typeable a, Typeable (AWSResponse a)) =>
 a -> MockT m (Either Error (AWSResponse a)))
-> (forall a.
    (AWSRequest a, Typeable a) =>
    Wait a -> a -> MockT m (Either Error Accept))
-> (forall a. (AuthEnv -> MockT m a) -> MockT m a)
-> (forall a. (Env -> Env) -> MockT m a -> MockT m a)
-> MonadAWS (MockT m)
forall a.
(AWSRequest a, Typeable a, Typeable (AWSResponse a)) =>
a -> MockT m (Either Error (AWSResponse a))
forall a.
(AWSRequest a, Typeable a) =>
Wait a -> a -> MockT m (Either Error Accept)
forall a. (AuthEnv -> MockT m a) -> MockT m a
forall a. (Env -> Env) -> MockT m a -> MockT m a
forall (m :: * -> *).
Monad m =>
(forall a.
 (AWSRequest a, Typeable a, Typeable (AWSResponse a)) =>
 a -> m (Either Error (AWSResponse a)))
-> (forall a.
    (AWSRequest a, Typeable a) =>
    Wait a -> a -> m (Either Error Accept))
-> (forall a. (AuthEnv -> m a) -> m a)
-> (forall a. (Env -> Env) -> m a -> m a)
-> MonadAWS m
forall (m :: * -> *). MonadIO m => Monad (MockT m)
forall (m :: * -> *) a.
(MonadIO m, AWSRequest a, Typeable a, Typeable (AWSResponse a)) =>
a -> MockT m (Either Error (AWSResponse a))
forall (m :: * -> *) a.
(MonadIO m, AWSRequest a, Typeable a) =>
Wait a -> a -> MockT m (Either Error Accept)
forall (m :: * -> *) a.
MonadIO m =>
(AuthEnv -> MockT m a) -> MockT m a
forall (m :: * -> *) a.
MonadIO m =>
(Env -> Env) -> MockT m a -> MockT m a
$csendEither :: forall (m :: * -> *) a.
(MonadIO m, AWSRequest a, Typeable a, Typeable (AWSResponse a)) =>
a -> MockT m (Either Error (AWSResponse a))
sendEither :: forall a.
(AWSRequest a, Typeable a, Typeable (AWSResponse a)) =>
a -> MockT m (Either Error (AWSResponse a))
$cawaitEither :: forall (m :: * -> *) a.
(MonadIO m, AWSRequest a, Typeable a) =>
Wait a -> a -> MockT m (Either Error Accept)
awaitEither :: forall a.
(AWSRequest a, Typeable a) =>
Wait a -> a -> MockT m (Either Error Accept)
$cwithAuth :: forall (m :: * -> *) a.
MonadIO m =>
(AuthEnv -> MockT m a) -> MockT m a
withAuth :: forall a. (AuthEnv -> MockT m a) -> MockT m a
$clocalEnv :: forall (m :: * -> *) a.
MonadIO m =>
(Env -> Env) -> MockT m a -> MockT m a
localEnv :: forall a. (Env -> Env) -> MockT m a -> MockT m a
MonadAWS) via (MockAWS (MockT m))

-- |
--
-- @since 0.1.0.0
runMockT :: MockT m a -> m a
runMockT :: forall (m :: * -> *) a. MockT m a -> m a
runMockT MockT m a
f = ReaderT Matchers m a -> Matchers -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (MockT m a -> ReaderT Matchers m a
forall (m :: * -> *) a. MockT m a -> ReaderT Matchers m a
unMockT MockT m a
f) Matchers
forall a. Monoid a => a
mempty