{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

{- |
Copyright   : (c) 2020-2021 Tim Emiola
SPDX-License-Identifier: BSD3
Maintainer  : Tim Emiola <adetokunbo@users.noreply.github.com>

An demo @HSpec@ test that use @tmp-proc@
-}
module TmpProc.Example2.IntegrationSpec where

import Control.Exception (onException)
import Data.Either (isLeft)
import Data.Maybe (isJust)
import Data.Proxy (Proxy (..))
import Network.HTTP.Client (newManager)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Servant.Client
  ( BaseUrl (..)
  , ClientEnv
  , Scheme (..)
  , mkClientEnv
  , runClientM
  )
import System.TmpProc.Docker.Postgres
import System.TmpProc.Docker.Redis
import Test.Hspec
import Test.Hspec.TmpProc
  ( AreProcs
  , HasHandle
  , ServerHandle
  , handleOf
  , handles
  , runServer
  , serverPort
  , shutdown
  , tdescribe
  , terminateAll
  , withConnOf
  , (&:&)
  )
import qualified TmpProc.Example2.Cache as Cache
import qualified TmpProc.Example2.Client as Client
import qualified TmpProc.Example2.Database as DB
import TmpProc.Example2.Schema (Contact (..), ContactID)
import TmpProc.Example2.Server (AppEnv (..), waiApp)


-- | The test uses a Postgres database .
dbProc :: TmpPostgres
dbProc :: TmpPostgres
dbProc = [Text] -> TmpPostgres
TmpPostgres [Text
"contacts"] -- 'reset' will empty the contacts table


-- | The test uses Redis as a cache.
cacheProc :: TmpRedis
cacheProc :: TmpRedis
cacheProc = [KeyName] -> TmpRedis
TmpRedis []


-- | Specifies the procs to be launched as test fixtures.
testProcs :: HList '[TmpPostgres, TmpRedis]
testProcs :: HList '[TmpPostgres, TmpRedis]
testProcs = TmpPostgres
dbProc TmpPostgres -> TmpRedis -> HList '[TmpPostgres, TmpRedis]
forall x y. x -> y -> HList '[x, y]
&:& TmpRedis
cacheProc


-- | Specifies the expected behaviour.
spec :: Spec
spec :: Spec
spec = String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
tdescribe String
"Tmp.Proc:Demo of testing of DB/Cache server" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
  IO Fixture -> SpecWith Fixture -> Spec
forall a. HasCallStack => IO a -> SpecWith a -> Spec
beforeAll IO Fixture
mkFixture (SpecWith Fixture -> Spec) -> SpecWith Fixture -> Spec
forall a b. (a -> b) -> a -> b
$ (Fixture -> Expectation) -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => ActionWith a -> SpecWith a -> SpecWith a
afterAll Fixture -> Expectation
shutdown' (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
    String -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"When the database is empty, using the client to fetch a contact" (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
      String
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should throw an error" ((Fixture -> Expectation)
 -> SpecWith (Arg (Fixture -> Expectation)))
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a b. (a -> b) -> a -> b
$ \(ServerHandle '[TmpPostgres, TmpRedis]
_, ClientEnv
clientEnv) ->
        (Either ClientError Contact -> Bool)
-> IO (Either ClientError Contact) -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either ClientError Contact -> Bool
forall a b. Either a b -> Bool
isLeft (ClientM Contact -> ClientEnv -> IO (Either ClientError Contact)
forall a. ClientM a -> ClientEnv -> IO (Either ClientError a)
runClientM (ContactID -> ClientM Contact
Client.fetch ContactID
1) ClientEnv
clientEnv) IO Bool -> Bool -> Expectation
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
`shouldReturn` Bool
True

      String -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"and the contact " (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
        String
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should not be found in the DB" ((Fixture -> Expectation)
 -> SpecWith (Arg (Fixture -> Expectation)))
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a b. (a -> b) -> a -> b
$ \(ServerHandle '[TmpPostgres, TmpRedis]
sh, ClientEnv
_) ->
          ServerHandle '[TmpPostgres, TmpRedis] -> ContactID -> IO Bool
hasInDb ServerHandle '[TmpPostgres, TmpRedis]
sh ContactID
1 IO Bool -> Bool -> Expectation
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
`shouldReturn` Bool
False

        String
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should not be found in the cache" ((Fixture -> Expectation)
 -> SpecWith (Arg (Fixture -> Expectation)))
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a b. (a -> b) -> a -> b
$ \(ServerHandle '[TmpPostgres, TmpRedis]
sh, ClientEnv
_) -> do
          ServerHandle '[TmpPostgres, TmpRedis] -> ContactID -> IO Bool
forall (procs :: [*]).
HasHandle TmpRedis procs =>
ServerHandle procs -> ContactID -> IO Bool
hasInCache ServerHandle '[TmpPostgres, TmpRedis]
sh ContactID
1 IO Bool -> Bool -> Expectation
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
`shouldReturn` Bool
False

      String -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"and using the client to insert a contact" (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
        String
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should succeed" ((Fixture -> Expectation)
 -> SpecWith (Arg (Fixture -> Expectation)))
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a b. (a -> b) -> a -> b
$ \(ServerHandle '[TmpPostgres, TmpRedis]
_, ClientEnv
clientEnv) ->
          ((Either ClientError ContactID -> Bool)
-> IO (Either ClientError ContactID) -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either ClientError ContactID -> Bool
forall a b. Either a b -> Bool
isLeft (IO (Either ClientError ContactID) -> IO Bool)
-> IO (Either ClientError ContactID) -> IO Bool
forall a b. (a -> b) -> a -> b
$ ClientM ContactID -> ClientEnv -> IO (Either ClientError ContactID)
forall a. ClientM a -> ClientEnv -> IO (Either ClientError a)
runClientM (Contact -> ClientM ContactID
Client.create Contact
testContact) ClientEnv
clientEnv) IO Bool -> Bool -> Expectation
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
`shouldReturn` Bool
False

    String -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"When the client is used to insert a contact" (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
      String -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"then the contact " (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
        String
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should be found in the DB" ((Fixture -> Expectation)
 -> SpecWith (Arg (Fixture -> Expectation)))
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a b. (a -> b) -> a -> b
$ \(ServerHandle '[TmpPostgres, TmpRedis]
sh, ClientEnv
_) ->
          ServerHandle '[TmpPostgres, TmpRedis] -> ContactID -> IO Bool
hasInDb ServerHandle '[TmpPostgres, TmpRedis]
sh ContactID
1 IO Bool -> Bool -> Expectation
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
`shouldReturn` Bool
True

        String
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should not be found in the cache" ((Fixture -> Expectation)
 -> SpecWith (Arg (Fixture -> Expectation)))
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a b. (a -> b) -> a -> b
$ \(ServerHandle '[TmpPostgres, TmpRedis]
sh, ClientEnv
_) -> do
          ServerHandle '[TmpPostgres, TmpRedis] -> ContactID -> IO Bool
forall (procs :: [*]).
HasHandle TmpRedis procs =>
ServerHandle procs -> ContactID -> IO Bool
hasInCache ServerHandle '[TmpPostgres, TmpRedis]
sh ContactID
1 IO Bool -> Bool -> Expectation
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
`shouldReturn` Bool
False

      String -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"and using the client to fetch the contact" (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
        String
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should succeed" ((Fixture -> Expectation)
 -> SpecWith (Arg (Fixture -> Expectation)))
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a b. (a -> b) -> a -> b
$ \(ServerHandle '[TmpPostgres, TmpRedis]
_, ClientEnv
clientEnv) ->
          ((Either ClientError Contact -> Bool)
-> IO (Either ClientError Contact) -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either ClientError Contact -> Bool
forall a b. Either a b -> Bool
isLeft (IO (Either ClientError Contact) -> IO Bool)
-> IO (Either ClientError Contact) -> IO Bool
forall a b. (a -> b) -> a -> b
$ ClientM Contact -> ClientEnv -> IO (Either ClientError Contact)
forall a. ClientM a -> ClientEnv -> IO (Either ClientError a)
runClientM (ContactID -> ClientM Contact
Client.fetch ContactID
1) ClientEnv
clientEnv) IO Bool -> Bool -> Expectation
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
`shouldReturn` Bool
False

    String -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"After fetching the contact with the client" (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
      String -> SpecWith Fixture -> SpecWith Fixture
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"then the contact " (SpecWith Fixture -> SpecWith Fixture)
-> SpecWith Fixture -> SpecWith Fixture
forall a b. (a -> b) -> a -> b
$ do
        String
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should be found in the cache" ((Fixture -> Expectation)
 -> SpecWith (Arg (Fixture -> Expectation)))
-> (Fixture -> Expectation)
-> SpecWith (Arg (Fixture -> Expectation))
forall a b. (a -> b) -> a -> b
$ \(ServerHandle '[TmpPostgres, TmpRedis]
sh, ClientEnv
_) -> do
          ServerHandle '[TmpPostgres, TmpRedis] -> ContactID -> IO Bool
forall (procs :: [*]).
HasHandle TmpRedis procs =>
ServerHandle procs -> ContactID -> IO Bool
hasInCache ServerHandle '[TmpPostgres, TmpRedis]
sh ContactID
1 IO Bool -> Bool -> Expectation
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
`shouldReturn` Bool
True


{- | Simplifies the test cases

Note the use of the 'HasHandle' constraint to indicate what TmpProcs the function uses.
-}
hasInCache :: HasHandle TmpRedis procs => ServerHandle procs -> ContactID -> IO Bool
hasInCache :: forall (procs :: [*]).
HasHandle TmpRedis procs =>
ServerHandle procs -> ContactID -> IO Bool
hasInCache ServerHandle procs
sh ContactID
cid = forall {k} (idx :: k) (procs :: [*]) namedConn b.
(HandleOf idx procs namedConn, Connectable namedConn) =>
Proxy idx -> HandlesOf procs -> (Conn namedConn -> IO b) -> IO b
forall idx (procs :: [*]) namedConn b.
(HandleOf idx procs namedConn, Connectable namedConn) =>
Proxy idx -> HandlesOf procs -> (Conn namedConn -> IO b) -> IO b
withConnOf @TmpRedis Proxy TmpRedis
forall {k} (t :: k). Proxy t
Proxy (ServerHandle procs -> HandlesOf procs
forall (procs :: [*]).
AreProcs procs =>
ServerHandle procs -> HandlesOf procs
handles ServerHandle procs
sh) ((Conn TmpRedis -> IO Bool) -> IO Bool)
-> (Conn TmpRedis -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Conn TmpRedis
cache ->
  (Maybe Contact -> Bool) -> IO (Maybe Contact) -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe Contact -> Bool
forall a. Maybe a -> Bool
isJust (IO (Maybe Contact) -> IO Bool) -> IO (Maybe Contact) -> IO Bool
forall a b. (a -> b) -> a -> b
$ Connection -> ContactID -> IO (Maybe Contact)
Cache.loadContact Connection
Conn TmpRedis
cache ContactID
cid


{- | Simplifies the test cases

Here, ServerHandle specifies the full list of types required by the calling test code.
-}
hasInDb :: ServerHandle ('[TmpPostgres, TmpRedis]) -> ContactID -> IO Bool
hasInDb :: ServerHandle '[TmpPostgres, TmpRedis] -> ContactID -> IO Bool
hasInDb ServerHandle '[TmpPostgres, TmpRedis]
sh ContactID
cid = do
  let dbUriOf :: ServerHandle '[TmpPostgres, TmpRedis] -> KeyName
dbUriOf = ProcHandle TmpPostgres -> KeyName
forall a. ProcHandle a -> KeyName
hUri (ProcHandle TmpPostgres -> KeyName)
-> (ServerHandle '[TmpPostgres, TmpRedis]
    -> ProcHandle TmpPostgres)
-> ServerHandle '[TmpPostgres, TmpRedis]
-> KeyName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (a :: k) (procs :: [*]) b.
HandleOf a procs b =>
Proxy a -> HandlesOf procs -> ProcHandle b
forall (a :: Symbol) (procs :: [*]) b.
HandleOf a procs b =>
Proxy a -> HandlesOf procs -> ProcHandle b
handleOf @"a-postgres-db" Proxy "a-postgres-db"
forall {k} (t :: k). Proxy t
Proxy (HList (Proc2Handle '[TmpPostgres, TmpRedis])
 -> ProcHandle TmpPostgres)
-> (ServerHandle '[TmpPostgres, TmpRedis]
    -> HList (Proc2Handle '[TmpPostgres, TmpRedis]))
-> ServerHandle '[TmpPostgres, TmpRedis]
-> ProcHandle TmpPostgres
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ServerHandle '[TmpPostgres, TmpRedis]
-> HList (Proc2Handle '[TmpPostgres, TmpRedis])
forall (procs :: [*]).
AreProcs procs =>
ServerHandle procs -> HandlesOf procs
handles
  (Maybe Contact -> Bool) -> IO (Maybe Contact) -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe Contact -> Bool
forall a. Maybe a -> Bool
isJust (IO (Maybe Contact) -> IO Bool) -> IO (Maybe Contact) -> IO Bool
forall a b. (a -> b) -> a -> b
$ (KeyName -> ContactID -> IO (Maybe Contact))
-> ContactID -> KeyName -> IO (Maybe Contact)
forall a b c. (a -> b -> c) -> b -> a -> c
flip KeyName -> ContactID -> IO (Maybe Contact)
DB.fetch ContactID
cid (KeyName -> IO (Maybe Contact)) -> KeyName -> IO (Maybe Contact)
forall a b. (a -> b) -> a -> b
$ ServerHandle '[TmpPostgres, TmpRedis] -> KeyName
dbUriOf ServerHandle '[TmpPostgres, TmpRedis]
sh


{- | The full test fixture.

It allows tests to

- use the servant client to invoke the backend
- check the state of service backends via the @ProcHandles@ in the 'ServerHandle'.
-}
type Fixture = (ServerHandle ('[TmpPostgres, TmpRedis]), ClientEnv)


mkFixture :: IO Fixture
mkFixture :: IO Fixture
mkFixture = do
  let mkApp :: HList (Proc2Handle procs) -> IO Application
mkApp HList (Proc2Handle procs)
someHandles = do
        -- handleOf can obtain a handle using either the Proc type ...
        let redisH :: ProcHandle TmpRedis
redisH = forall {k} (a :: k) (procs :: [*]) b.
HandleOf a procs b =>
Proxy a -> HandlesOf procs -> ProcHandle b
forall a (procs :: [*]) b.
HandleOf a procs b =>
Proxy a -> HandlesOf procs -> ProcHandle b
handleOf @TmpRedis Proxy TmpRedis
forall {k} (t :: k). Proxy t
Proxy HList (Proc2Handle procs)
someHandles

            -- or the Name of it's Proc type
            dbLoc :: KeyName
dbLoc = ProcHandle TmpPostgres -> KeyName
forall a. ProcHandle a -> KeyName
hUri (ProcHandle TmpPostgres -> KeyName)
-> ProcHandle TmpPostgres -> KeyName
forall a b. (a -> b) -> a -> b
$ forall {k} (a :: k) (procs :: [*]) b.
HandleOf a procs b =>
Proxy a -> HandlesOf procs -> ProcHandle b
forall (a :: Symbol) (procs :: [*]) b.
HandleOf a procs b =>
Proxy a -> HandlesOf procs -> ProcHandle b
handleOf @"a-postgres-db" Proxy "a-postgres-db"
forall {k} (t :: k). Proxy t
Proxy HList (Proc2Handle procs)
someHandles

        -- Create the database schema
        KeyName -> Expectation
DB.migrateDB KeyName
dbLoc Expectation -> Expectation -> Expectation
forall a b. IO a -> IO b -> IO a
`onException` HList (Proc2Handle procs) -> Expectation
forall (procs :: [*]).
AreProcs procs =>
HandlesOf procs -> Expectation
terminateAll HList (Proc2Handle procs)
someHandles

        -- Determine the redis location
        Connection
cache <- ProcHandle TmpRedis -> IO (Conn TmpRedis)
forall a. Connectable a => ProcHandle a -> IO (Conn a)
openConn ProcHandle TmpRedis
redisH IO Connection -> Expectation -> IO Connection
forall a b. IO a -> IO b -> IO a
`onException` HList (Proc2Handle procs) -> Expectation
forall (procs :: [*]).
AreProcs procs =>
HandlesOf procs -> Expectation
terminateAll HList (Proc2Handle procs)
someHandles

        Application -> IO Application
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Application -> IO Application) -> Application -> IO Application
forall a b. (a -> b) -> a -> b
$ AppEnv -> Application
waiApp (AppEnv -> Application) -> AppEnv -> Application
forall a b. (a -> b) -> a -> b
$ KeyName -> Connection -> AppEnv
AppEnv KeyName
dbLoc Connection
cache

  ServerHandle '[TmpPostgres, TmpRedis]
sh <- HList '[TmpPostgres, TmpRedis]
-> (HList (Proc2Handle '[TmpPostgres, TmpRedis]) -> IO Application)
-> IO (ServerHandle '[TmpPostgres, TmpRedis])
forall (procs :: [*]).
AreProcs procs =>
HList procs
-> (HandlesOf procs -> IO Application) -> IO (ServerHandle procs)
runServer HList '[TmpPostgres, TmpRedis]
testProcs HList (Proc2Handle '[TmpPostgres, TmpRedis]) -> IO Application
forall {procs :: [*]}.
(AreProcs procs,
 MemberKV
   "a-postgres-db"
   (ProcHandle TmpPostgres)
   (Handle2KV (Proc2Handle procs)),
 IsInProof (ProcHandle TmpRedis) (Proc2Handle procs)) =>
HList (Proc2Handle procs) -> IO Application
mkApp
  ClientEnv
clientEnv <- ServerHandle '[TmpPostgres, TmpRedis] -> IO ClientEnv
forall (procs :: [*]).
AreProcs procs =>
ServerHandle procs -> IO ClientEnv
clientEnvOf ServerHandle '[TmpPostgres, TmpRedis]
sh
  Fixture -> IO Fixture
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ServerHandle '[TmpPostgres, TmpRedis]
sh, ClientEnv
clientEnv)


shutdown' :: Fixture -> IO ()
shutdown' :: Fixture -> Expectation
shutdown' (ServerHandle '[TmpPostgres, TmpRedis]
sh, ClientEnv
_) = ServerHandle '[TmpPostgres, TmpRedis] -> Expectation
forall (procs :: [*]).
AreProcs procs =>
ServerHandle procs -> Expectation
shutdown ServerHandle '[TmpPostgres, TmpRedis]
sh


clientEnvOf :: AreProcs procs => ServerHandle procs -> IO ClientEnv
clientEnvOf :: forall (procs :: [*]).
AreProcs procs =>
ServerHandle procs -> IO ClientEnv
clientEnvOf ServerHandle procs
s = do
  Manager
mgr <- ManagerSettings -> IO Manager
newManager ManagerSettings
tlsManagerSettings
  ClientEnv -> IO ClientEnv
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ClientEnv -> IO ClientEnv) -> ClientEnv -> IO ClientEnv
forall a b. (a -> b) -> a -> b
$ Manager -> BaseUrl -> ClientEnv
mkClientEnv Manager
mgr (BaseUrl -> ClientEnv) -> BaseUrl -> ClientEnv
forall a b. (a -> b) -> a -> b
$ Scheme -> String -> Int -> String -> BaseUrl
BaseUrl Scheme
Http String
"localhost" (ServerHandle procs -> Int
forall (procs :: [*]). ServerHandle procs -> Int
serverPort ServerHandle procs
s) String
""


testContact :: Contact
testContact :: Contact
testContact =
  Contact
    { contactName :: Text
contactName = Text
"Bond"
    , contactEmail :: Text
contactEmail = Text
"james@hmss.gov.uk"
    , contactAge :: Int
contactAge = Int
45
    , contactTitle :: Text
contactTitle = Text
"Mr"
    }