{-# LANGUAGE ImpredicativeTypes #-}
{-# LANGUAGE Trustworthy #-}
{-# OPTIONS_GHC -Wno-missing-role-annotations #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-# OPTIONS_GHC -Wno-term-variable-capture #-}

-- |
-- Module      : Effectful.Hspec
-- Copyright   : (c) 2026 Institute for Digital Autonomy
-- License     : EUPL-1.2
-- Maintainer  : IDA
--
-- Effectful bindings for the <http://hackage.haskell.org/package/hspec Hspec library>
-- built on top of @<http://hackage.haskell.org/package/hunit-effectful hunit-effectful>@.
--
-- = Overview
--
-- This library provides @Hspec@'s test combinators expressed in terms of the 'Hspec' effect.
-- This effect allows you to intersperse test assertions with arbitrary other effects.
--
-- = Example usage
--
-- Suppose we wish to test stateful operations on an account balance:
--
-- > deposit :: (State Int :> es) => Int -> Eff es ()
-- > deposit amount = modify (+ amount)
-- >
-- > balance :: (State Int :> es) => Eff es Int
-- > balance = get
--
-- > withdraw :: (State Int :> es) => Int -> Eff es Bool
-- > withdraw amount = do
-- >     funds <- balance
-- >     if funds < amount
-- >         then pure False
-- >         else do
-- >             put $ funds - amount
-- >             pure True
--
-- Use 'describe' to group related examples, 'it' to state individual expectations
-- and setup/teardown combinators such as 'before_', 'after_', or 'around_' to
-- run the examples from a known initial state:
--
-- > accountSpec :: (State Int :> es, Hspec :> es) => Eff es ()
-- > accountSpec = describe "account" . before_ (put @Int 0) $ do
-- >     it "accumulates deposits" $ do
-- >         deposit 100
-- >         deposit 50
-- >         balance `shouldReturn` 150
-- >
-- >     it "checks for sufficient funds before withdrawing" $ do
-- >         deposit 100
-- >         withdraw 30 `shouldReturn` True
-- >         withdraw 1000 `shouldReturn` False
-- >         balance `shouldReturn` 70
--
-- Finally, run the spec with 'runHspec', which also resolves the underlying 'HUnit' effect:
--
-- > main :: IO ()
-- > main = runEff . runHspec . evalState @Int 0 $ accountSpec
module Effectful.Hspec
    ( -- * Effect
      Hspec
    , Expectation
    , runHspecWith'
    , runHspecWith
    , runHspec'
    , runHspec
    , runHUnit

      -- * Spec construction
    , describe
    , context
    , it
    , specify
    , pending
    , pendingWith

      -- * Skipping
    , xit
    , xspecify
    , xdescribe
    , xcontext

      -- * Focusing
    , focus
    , fit
    , fspecify
    , fdescribe
    , fcontext
    , parallel
    , sequential

      -- * Setup / Teardown
    , before_
    , beforeAll_
    , after_
    , afterAll_
    , around_
    , aroundAll_

      -- * Expectations
    , expectationFailure
    , shouldBe
    , shouldSatisfy
    , shouldStartWith
    , shouldEndWith
    , shouldContain
    , shouldMatchList
    , shouldReturn
    , shouldNotBe
    , shouldNotSatisfy
    , shouldNotContain
    , shouldNotReturn
    , shouldThrow
    , anyException
    , Config (..)
    , defaultConfig
    , Hspec.Spec
    , HasCallStack

      -- * Properties
    , prop
    , xprop
    , fprop
    )
where

import Control.Monad (unless)
import Data.List qualified as List
import Data.Typeable (typeOf)
import Effectful
import Effectful.Dispatch.Static
import Effectful.Environment (runEnvironment, withArgs)
import Effectful.Exception (Exception, throwIO, try)
import Effectful.HUnit as HUnit
import Test.Hspec qualified as Hspec
import Test.Hspec.Core.Spec (ResultStatus (..))
import Test.Hspec.Expectations (Selector, anyException)
import Test.Hspec.Expectations.Pretty.Matcher (matchList)
import Test.Hspec.QuickCheck qualified as Hspec
import Test.Hspec.Runner (Config (..), defaultConfig)
import Test.Hspec.Runner qualified as Hspec
import Test.QuickCheck qualified as QuickCheck
import Prelude

data Hspec :: Effect

type instance DispatchOf Hspec = 'Static 'WithSideEffects

data instance StaticRep Hspec = Hspec
    { StaticRep Hspec -> Spec
spec :: Hspec.Spec
    , StaticRep Hspec -> forall r. Eff '[HUnit] r -> IO r
unlift :: forall r. Eff '[HUnit] r -> IO r
    }

type Expectation es = Assertion es

runHspecWith' :: (IOE :> es, HUnit :> es) => Config -> Eff (Hspec ': es) a -> Eff es a
runHspecWith' :: forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es, HUnit :> es) =>
Config -> Eff (Hspec : es) a -> Eff es a
runHspecWith' Config
config Eff (Hspec : es) a
action = do
    (a
a, Hspec{Spec
spec :: StaticRep Hspec -> Spec
spec :: Spec
spec}) <- UnliftStrategy
-> ((forall r. Eff es r -> IO r) -> IO (a, StaticRep Hspec))
-> Eff es (a, StaticRep Hspec)
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, IOE :> es) =>
UnliftStrategy
-> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
withEffToIO (Persistence -> Limit -> UnliftStrategy
ConcUnlift Persistence
Ephemeral Limit
Unlimited) \forall r. Eff es r -> IO r
unlift ->
        Eff es (a, StaticRep Hspec) -> IO (a, StaticRep Hspec)
forall r. Eff es r -> IO r
unlift
            (Eff es (a, StaticRep Hspec) -> IO (a, StaticRep Hspec))
-> (Eff (Hspec : es) a -> Eff es (a, StaticRep Hspec))
-> Eff (Hspec : es) a
-> IO (a, StaticRep Hspec)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StaticRep Hspec
-> Eff (Hspec : es) a -> Eff es (a, StaticRep Hspec)
forall (e :: (* -> *) -> * -> *) (sideEffects :: SideEffects)
       (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects,
 MaybeIOE sideEffects es) =>
StaticRep e -> Eff (e : es) a -> Eff es (a, StaticRep e)
runStaticRep
                Hspec
                    { spec :: Spec
spec = () -> Spec
forall a. a -> SpecM () a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
                    , unlift :: forall r. Eff '[HUnit] r -> IO r
unlift = Eff es r -> IO r
forall r. Eff es r -> IO r
unlift (Eff es r -> IO r)
-> (Eff '[HUnit] r -> Eff es r) -> Eff '[HUnit] r -> IO r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff '[HUnit] r -> Eff es r
forall (subEs :: [(* -> *) -> * -> *]) (es :: [(* -> *) -> * -> *])
       a.
Subset subEs es =>
Eff subEs a -> Eff es a
inject
                    }
            (Eff (Hspec : es) a -> Eff es (a, StaticRep Hspec))
-> (Eff (Hspec : es) a -> Eff (Hspec : es) a)
-> Eff (Hspec : es) a
-> Eff es (a, StaticRep Hspec)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff (Hspec : es) a -> Eff (Hspec : es) a
forall (subEs :: [(* -> *) -> * -> *]) (es :: [(* -> *) -> * -> *])
       a.
Subset subEs es =>
Eff subEs a -> Eff es a
inject
            (Eff (Hspec : es) a -> IO (a, StaticRep Hspec))
-> Eff (Hspec : es) a -> IO (a, StaticRep Hspec)
forall a b. (a -> b) -> a -> b
$ Eff (Hspec : es) a
action
    Eff (Environment : es) () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, IOE :> es) =>
Eff (Environment : es) a -> Eff es a
runEnvironment (Eff (Environment : es) () -> Eff es ())
-> (IO () -> Eff (Environment : es) ()) -> IO () -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> Eff (Environment : es) () -> Eff (Environment : es) ()
forall (es :: [(* -> *) -> * -> *]) a.
(Environment :> es) =>
[String] -> Eff es a -> Eff es a
withArgs [] (Eff (Environment : es) () -> Eff (Environment : es) ())
-> (IO () -> Eff (Environment : es) ())
-> IO ()
-> Eff (Environment : es) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> Eff (Environment : es) ()
forall a. IO a -> Eff (Environment : es) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Eff es ()) -> IO () -> Eff es ()
forall a b. (a -> b) -> a -> b
$ Config -> Spec -> IO ()
Hspec.hspecWith Config
config Spec
spec
    pure a
a

runHspecWith :: (IOE :> es) => Config -> Eff (Hspec ': es) a -> Eff es a
runHspecWith :: forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es) =>
Config -> Eff (Hspec : es) a -> Eff es a
runHspecWith = (Eff (HUnit : es) a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es) =>
Eff (HUnit : es) a -> Eff es a
runHUnit (Eff (HUnit : es) a -> Eff es a)
-> (Eff (Hspec : es) a -> Eff (HUnit : es) a)
-> Eff (Hspec : es) a
-> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Eff (Hspec : es) a -> Eff (HUnit : es) a)
 -> Eff (Hspec : es) a -> Eff es a)
-> (Config -> Eff (Hspec : es) a -> Eff (HUnit : es) a)
-> Config
-> Eff (Hspec : es) a
-> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Eff (Hspec : HUnit : es) a -> Eff (HUnit : es) a)
-> (Eff (Hspec : es) a -> Eff (Hspec : HUnit : es) a)
-> Eff (Hspec : es) a
-> Eff (HUnit : es) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff (Hspec : es) a -> Eff (Hspec : HUnit : es) a
forall (subEs :: [(* -> *) -> * -> *]) (es :: [(* -> *) -> * -> *])
       a.
Subset subEs es =>
Eff subEs a -> Eff es a
inject) ((Eff (Hspec : HUnit : es) a -> Eff (HUnit : es) a)
 -> Eff (Hspec : es) a -> Eff (HUnit : es) a)
-> (Config -> Eff (Hspec : HUnit : es) a -> Eff (HUnit : es) a)
-> Config
-> Eff (Hspec : es) a
-> Eff (HUnit : es) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> Eff (Hspec : HUnit : es) a -> Eff (HUnit : es) a
forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es, HUnit :> es) =>
Config -> Eff (Hspec : es) a -> Eff es a
runHspecWith'

runHspec' :: (IOE :> es, HUnit :> es) => Eff (Hspec ': es) a -> Eff es a
runHspec' :: forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es, HUnit :> es) =>
Eff (Hspec : es) a -> Eff es a
runHspec' = Config -> Eff (Hspec : es) a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es, HUnit :> es) =>
Config -> Eff (Hspec : es) a -> Eff es a
runHspecWith' Config
defaultConfig (Eff (Hspec : es) a -> Eff es a)
-> (Eff (Hspec : es) a -> Eff (Hspec : es) a)
-> Eff (Hspec : es) a
-> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff (Hspec : es) a -> Eff (Hspec : es) a
forall (subEs :: [(* -> *) -> * -> *]) (es :: [(* -> *) -> * -> *])
       a.
Subset subEs es =>
Eff subEs a -> Eff es a
inject

runHspec :: (IOE :> es) => Eff (Hspec ': es) a -> Eff es a
runHspec :: forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es) =>
Eff (Hspec : es) a -> Eff es a
runHspec = Eff (HUnit : es) a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es) =>
Eff (HUnit : es) a -> Eff es a
runHUnit (Eff (HUnit : es) a -> Eff es a)
-> (Eff (Hspec : es) a -> Eff (HUnit : es) a)
-> Eff (Hspec : es) a
-> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff (Hspec : HUnit : es) a -> Eff (HUnit : es) a
forall (es :: [(* -> *) -> * -> *]) a.
(IOE :> es, HUnit :> es) =>
Eff (Hspec : es) a -> Eff es a
runHspec' (Eff (Hspec : HUnit : es) a -> Eff (HUnit : es) a)
-> (Eff (Hspec : es) a -> Eff (Hspec : HUnit : es) a)
-> Eff (Hspec : es) a
-> Eff (HUnit : es) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff (Hspec : es) a -> Eff (Hspec : HUnit : es) a
forall (subEs :: [(* -> *) -> * -> *]) (es :: [(* -> *) -> * -> *])
       a.
Subset subEs es =>
Eff subEs a -> Eff es a
inject

hunit :: (Hspec :> es) => Eff '[HUnit] r -> Eff es r
hunit :: forall (es :: [(* -> *) -> * -> *]) r.
(Hspec :> es) =>
Eff '[HUnit] r -> Eff es r
hunit Eff '[HUnit] r
action = do
    Hspec{forall r. Eff '[HUnit] r -> IO r
unlift :: StaticRep Hspec -> forall r. Eff '[HUnit] r -> IO r
unlift :: forall r. Eff '[HUnit] r -> IO r
unlift} <- Eff es (StaticRep Hspec)
forall (e :: (* -> *) -> * -> *) (sideEffects :: SideEffects)
       (es :: [(* -> *) -> * -> *]).
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
Eff es (StaticRep e)
getStaticRep
    IO r -> Eff es r
forall a (es :: [(* -> *) -> * -> *]). IO a -> Eff es a
unsafeEff_ (IO r -> Eff es r)
-> (Eff '[HUnit] r -> IO r) -> Eff '[HUnit] r -> Eff es r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff '[HUnit] r -> IO r
forall r. Eff '[HUnit] r -> IO r
unlift (Eff '[HUnit] r -> IO r)
-> (Eff '[HUnit] r -> Eff '[HUnit] r) -> Eff '[HUnit] r -> IO r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff '[HUnit] r -> Eff '[HUnit] r
forall (subEs :: [(* -> *) -> * -> *]) (es :: [(* -> *) -> * -> *])
       a.
Subset subEs es =>
Eff subEs a -> Eff es a
inject (Eff '[HUnit] r -> Eff es r) -> Eff '[HUnit] r -> Eff es r
forall a b. (a -> b) -> a -> b
$ Eff '[HUnit] r
action

appendSpec :: (Hspec :> es) => Hspec.Spec -> Eff es ()
appendSpec :: forall (es :: [(* -> *) -> * -> *]).
(Hspec :> es) =>
Spec -> Eff es ()
appendSpec Spec
spec = (StaticRep Hspec -> ((), StaticRep Hspec)) -> Eff es ()
forall (e :: (* -> *) -> * -> *) (sideEffects :: SideEffects)
       (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
(StaticRep e -> (a, StaticRep e)) -> Eff es a
stateStaticRep \StaticRep Hspec
hspec -> ((), StaticRep Hspec
hspec{spec = hspec.spec >> spec})

mapSpec :: (HasCallStack, Hspec :> es) => (Hspec.Spec -> Hspec.Spec) -> Eff es a -> Eff es a
mapSpec :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec Spec -> Spec
f Eff es a
action =
    (StaticRep Hspec -> Eff es (a, StaticRep Hspec)) -> Eff es a
forall (e :: (* -> *) -> * -> *) (sideEffects :: SideEffects)
       (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
(StaticRep e -> Eff es (a, StaticRep e)) -> Eff es a
stateStaticRepM \StaticRep Hspec
before -> do
        StaticRep Hspec -> Eff es ()
forall (e :: (* -> *) -> * -> *) (sideEffects :: SideEffects)
       (es :: [(* -> *) -> * -> *]).
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
StaticRep e -> Eff es ()
putStaticRep StaticRep Hspec
before{spec = pure ()}
        a
result <- Eff es a
action
        StaticRep Hspec
after <- forall (e :: (* -> *) -> * -> *) (sideEffects :: SideEffects)
       (es :: [(* -> *) -> * -> *]).
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
Eff es (StaticRep e)
getStaticRep @Hspec
        pure (a
result, StaticRep Hspec
before{spec = before.spec >> f after.spec})

-- | Lifted 'Hspec.describe'.
describe :: (HasCallStack, Hspec :> es) => String -> Eff es a -> Eff es a
describe :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
describe = (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec ((Spec -> Spec) -> Eff es a -> Eff es a)
-> (String -> Spec -> Spec) -> String -> Eff es a -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
Hspec.describe

-- | Lifted 'Hspec.it'.
it :: (HasCallStack, Hspec :> es) => String -> Eff es () -> Eff es ()
it :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
it String
label Eff es ()
action = do
    IO ()
ioAction <-
        Persistence
-> Limit
-> ((forall r. Eff es r -> IO r) -> IO (IO ()))
-> Eff es (IO ())
forall (es :: [(* -> *) -> * -> *]) a.
HasCallStack =>
Persistence
-> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeConcUnliftIO Persistence
Ephemeral Limit
Unlimited \forall r. Eff es r -> IO r
runInIO ->
            IO () -> IO (IO ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Eff es () -> IO ()
forall r. Eff es r -> IO r
runInIO Eff es ()
action)
    Spec -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(Hspec :> es) =>
Spec -> Eff es ()
appendSpec (Spec -> Eff es ()) -> Spec -> Eff es ()
forall a b. (a -> b) -> a -> b
$ String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
label IO ()
ioAction

-- | Lifted 'Hspec.specify'.
specify :: (HasCallStack, Hspec :> es) => String -> Eff es () -> Eff es ()
specify :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
specify = String -> Eff es () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
it

-- | Lifted 'Hspec.context'.
context :: (HasCallStack, Hspec :> es) => String -> Eff es a -> Eff es a
context :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
context = String -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
describe

-- | Lifted 'Hspec.pending'.
pending :: (HasCallStack, Hspec :> es) => Eff es ()
pending :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
Eff es ()
pending = forall (e :: (* -> *) -> * -> *) (sideEffects :: SideEffects)
       (es :: [(* -> *) -> * -> *]).
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
Eff es (StaticRep e)
getStaticRep @Hspec Eff es (StaticRep Hspec) -> Eff es () -> Eff es ()
forall a b. Eff es a -> Eff es b -> Eff es b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO () -> Eff es ()
forall a (es :: [(* -> *) -> * -> *]). IO a -> Eff es a
unsafeEff_ IO ()
HasCallStack => IO ()
Hspec.pending

pending_ :: Eff es ()
pending_ :: forall (es :: [(* -> *) -> * -> *]). Eff es ()
pending_ = ResultStatus -> Eff es ()
forall e (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Exception e) =>
e -> Eff es a
throwIO (ResultStatus -> Eff es ()) -> ResultStatus -> Eff es ()
forall a b. (a -> b) -> a -> b
$ Maybe Location -> Maybe String -> ResultStatus
Pending Maybe Location
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing

-- | Lifted 'Hspec.pendingWith'.
pendingWith :: (HasCallStack, Hspec :> es) => String -> Eff es ()
pendingWith :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es ()
pendingWith = (forall (e :: (* -> *) -> * -> *) (sideEffects :: SideEffects)
       (es :: [(* -> *) -> * -> *]).
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
Eff es (StaticRep e)
getStaticRep @Hspec Eff es (StaticRep Hspec) -> Eff es () -> Eff es ()
forall a b. Eff es a -> Eff es b -> Eff es b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>) (Eff es () -> Eff es ())
-> (String -> Eff es ()) -> String -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> Eff es ()
forall a (es :: [(* -> *) -> * -> *]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (String -> IO ()) -> String -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => String -> IO ()
String -> IO ()
Hspec.pendingWith

-- | Lifted 'Hspec.xit'.
xit :: (HasCallStack, Hspec :> es) => String -> Eff es () -> Eff es ()
xit :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
xit = (Eff es () -> Eff es () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es () -> Eff es a -> Eff es a
before_ Eff es ()
forall (es :: [(* -> *) -> * -> *]). Eff es ()
pending_ (Eff es () -> Eff es ())
-> (Eff es () -> Eff es ()) -> Eff es () -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Eff es () -> Eff es ()) -> Eff es () -> Eff es ())
-> (String -> Eff es () -> Eff es ())
-> String
-> Eff es ()
-> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Eff es () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
it

-- | Lifted 'Hspec.xspecify'.
xspecify :: (HasCallStack, Hspec :> es) => String -> Eff es () -> Eff es ()
xspecify :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
xspecify = String -> Eff es () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
xit

-- | Lifted 'Hspec.xdescribe'.
xdescribe :: (HasCallStack, Hspec :> es) => String -> Eff es a -> Eff es a
xdescribe :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
xdescribe = (Eff es () -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es () -> Eff es a -> Eff es a
before_ Eff es ()
forall (es :: [(* -> *) -> * -> *]). Eff es ()
pending_ (Eff es a -> Eff es a)
-> (Eff es a -> Eff es a) -> Eff es a -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Eff es a -> Eff es a) -> Eff es a -> Eff es a)
-> (String -> Eff es a -> Eff es a)
-> String
-> Eff es a
-> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
describe

-- | Lifted 'Hspec.xcontext'.
xcontext :: (HasCallStack, Hspec :> es) => String -> Eff es a -> Eff es a
xcontext :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
xcontext = String -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
xdescribe

-- | Lifted 'Hspec.focus'.
focus :: (HasCallStack, Hspec :> es) => Eff es a -> Eff es a
focus :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es a -> Eff es a
focus = (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec Spec -> Spec
forall a. SpecWith a -> SpecWith a
Hspec.focus

-- | Lifted 'Hspec.fit'.
fit :: (HasCallStack, Hspec :> es) => String -> Eff es () -> Eff es ()
fit :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
fit = (Eff es () -> Eff es ())
-> (Eff es () -> Eff es ()) -> Eff es () -> Eff es ()
forall a b. (a -> b) -> (Eff es () -> a) -> Eff es () -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Eff es () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es a -> Eff es a
focus ((Eff es () -> Eff es ()) -> Eff es () -> Eff es ())
-> (String -> Eff es () -> Eff es ())
-> String
-> Eff es ()
-> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Eff es () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
it

-- | Lifted 'Hspec.fspecify'.
fspecify :: (HasCallStack, Hspec :> es) => String -> Eff es () -> Eff es ()
fspecify :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
fspecify = String -> Eff es () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es () -> Eff es ()
fit

-- | Lifted 'Hspec.fdescribe'.
fdescribe :: (HasCallStack, Hspec :> es) => String -> Eff es a -> Eff es a
fdescribe :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
fdescribe = (Eff es a -> Eff es a)
-> (Eff es a -> Eff es a) -> Eff es a -> Eff es a
forall a b. (a -> b) -> (Eff es a -> a) -> Eff es a -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es a -> Eff es a
focus ((Eff es a -> Eff es a) -> Eff es a -> Eff es a)
-> (String -> Eff es a -> Eff es a)
-> String
-> Eff es a
-> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
describe

-- | Lifted 'Hspec.fcontext'.
fcontext :: (HasCallStack, Hspec :> es) => String -> Eff es a -> Eff es a
fcontext :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
fcontext = String -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
String -> Eff es a -> Eff es a
fdescribe

-- | Lifted 'Hspec.parallel'.
parallel :: (HasCallStack, Hspec :> es) => Eff es a -> Eff es a
parallel :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es a -> Eff es a
parallel = (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec Spec -> Spec
forall a. SpecWith a -> SpecWith a
Hspec.parallel

-- | Lifted 'Hspec.sequential'.
sequential :: (HasCallStack, Hspec :> es) => Eff es a -> Eff es a
sequential :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es a -> Eff es a
sequential = (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec Spec -> Spec
forall a. SpecWith a -> SpecWith a
Hspec.sequential

-- | Lifted 'Hspec.before_'.
before_ :: (HasCallStack, Hspec :> es) => Eff es () -> Eff es a -> Eff es a
before_ :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es () -> Eff es a -> Eff es a
before_ Eff es ()
setup Eff es a
action = do
    IO ()
ioSetup <-
        Persistence
-> Limit
-> ((forall r. Eff es r -> IO r) -> IO (IO ()))
-> Eff es (IO ())
forall (es :: [(* -> *) -> * -> *]) a.
HasCallStack =>
Persistence
-> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeConcUnliftIO Persistence
Ephemeral Limit
Unlimited \forall r. Eff es r -> IO r
unlift ->
            IO () -> IO (IO ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Eff es () -> IO ()
forall r. Eff es r -> IO r
unlift Eff es ()
setup)
    (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec (IO () -> Spec -> Spec
forall a. IO () -> SpecWith a -> SpecWith a
Hspec.before_ IO ()
ioSetup) Eff es a
action

-- | Lifted 'Hspec.beforeAll_'.
beforeAll_ :: (HasCallStack, Hspec :> es) => Eff es () -> Eff es a -> Eff es a
beforeAll_ :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es () -> Eff es a -> Eff es a
beforeAll_ Eff es ()
setup Eff es a
action = do
    IO ()
ioSetup <-
        Persistence
-> Limit
-> ((forall r. Eff es r -> IO r) -> IO (IO ()))
-> Eff es (IO ())
forall (es :: [(* -> *) -> * -> *]) a.
HasCallStack =>
Persistence
-> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeConcUnliftIO Persistence
Ephemeral Limit
Unlimited \forall r. Eff es r -> IO r
unlift ->
            IO () -> IO (IO ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Eff es () -> IO ()
forall r. Eff es r -> IO r
unlift Eff es ()
setup)
    (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec (IO () -> Spec -> Spec
forall a. HasCallStack => IO () -> SpecWith a -> SpecWith a
Hspec.beforeAll_ IO ()
ioSetup) Eff es a
action

-- | Lifted 'Hspec.after_'.
after_ :: (HasCallStack, Hspec :> es) => Eff es () -> Eff es a -> Eff es a
after_ :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es () -> Eff es a -> Eff es a
after_ Eff es ()
teardown Eff es a
action = do
    IO ()
ioTeardown <-
        Persistence
-> Limit
-> ((forall r. Eff es r -> IO r) -> IO (IO ()))
-> Eff es (IO ())
forall (es :: [(* -> *) -> * -> *]) a.
HasCallStack =>
Persistence
-> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeConcUnliftIO Persistence
Ephemeral Limit
Unlimited \forall r. Eff es r -> IO r
unlift ->
            IO () -> IO (IO ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Eff es () -> IO ()
forall r. Eff es r -> IO r
unlift Eff es ()
teardown)
    (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec (IO () -> Spec -> Spec
forall a. IO () -> SpecWith a -> SpecWith a
Hspec.after_ IO ()
ioTeardown) Eff es a
action

-- | Lifted 'Hspec.afterAll_'.
afterAll_ :: (HasCallStack, Hspec :> es) => Eff es () -> Eff es a -> Eff es a
afterAll_ :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
Eff es () -> Eff es a -> Eff es a
afterAll_ Eff es ()
teardown Eff es a
action = do
    IO ()
ioTeardown <-
        Persistence
-> Limit
-> ((forall r. Eff es r -> IO r) -> IO (IO ()))
-> Eff es (IO ())
forall (es :: [(* -> *) -> * -> *]) a.
HasCallStack =>
Persistence
-> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeConcUnliftIO Persistence
Ephemeral Limit
Unlimited \forall r. Eff es r -> IO r
unlift ->
            IO () -> IO (IO ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Eff es () -> IO ()
forall r. Eff es r -> IO r
unlift Eff es ()
teardown)
    (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec (IO () -> Spec -> Spec
forall a. HasCallStack => IO () -> SpecWith a -> SpecWith a
Hspec.afterAll_ IO ()
ioTeardown) Eff es a
action

-- | Lifted 'Hspec.around_'.
around_ :: (HasCallStack, Hspec :> es) => (Eff es () -> Eff es ()) -> Eff es a -> Eff es a
around_ :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Eff es () -> Eff es ()) -> Eff es a -> Eff es a
around_ Eff es () -> Eff es ()
wrapper Eff es a
action = do
    IO () -> IO ()
ioWrapper <-
        Persistence
-> Limit
-> ((forall r. Eff es r -> IO r) -> IO (IO () -> IO ()))
-> Eff es (IO () -> IO ())
forall (es :: [(* -> *) -> * -> *]) a.
HasCallStack =>
Persistence
-> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeConcUnliftIO Persistence
Ephemeral Limit
Unlimited \forall r. Eff es r -> IO r
unlift ->
            (IO () -> IO ()) -> IO (IO () -> IO ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Eff es () -> IO ()
forall r. Eff es r -> IO r
unlift (Eff es () -> IO ()) -> (IO () -> Eff es ()) -> IO () -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff es () -> Eff es ()
wrapper (Eff es () -> Eff es ())
-> (IO () -> Eff es ()) -> IO () -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> Eff es ()
forall a (es :: [(* -> *) -> * -> *]). IO a -> Eff es a
unsafeEff_)
    (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec ((IO () -> IO ()) -> Spec -> Spec
forall a. (IO () -> IO ()) -> SpecWith a -> SpecWith a
Hspec.around_ IO () -> IO ()
ioWrapper) Eff es a
action

-- | Lifted 'Hspec.aroundAll_'.
aroundAll_ :: (HasCallStack, Hspec :> es) => (Eff es () -> Eff es ()) -> Eff es a -> Eff es a
aroundAll_ :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Eff es () -> Eff es ()) -> Eff es a -> Eff es a
aroundAll_ Eff es () -> Eff es ()
wrapper Eff es a
action = do
    IO () -> IO ()
ioWrapper <-
        Persistence
-> Limit
-> ((forall r. Eff es r -> IO r) -> IO (IO () -> IO ()))
-> Eff es (IO () -> IO ())
forall (es :: [(* -> *) -> * -> *]) a.
HasCallStack =>
Persistence
-> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeConcUnliftIO Persistence
Ephemeral Limit
Unlimited \forall r. Eff es r -> IO r
unlift ->
            (IO () -> IO ()) -> IO (IO () -> IO ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Eff es () -> IO ()
forall r. Eff es r -> IO r
unlift (Eff es () -> IO ()) -> (IO () -> Eff es ()) -> IO () -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff es () -> Eff es ()
wrapper (Eff es () -> Eff es ())
-> (IO () -> Eff es ()) -> IO () -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> Eff es ()
forall a (es :: [(* -> *) -> * -> *]). IO a -> Eff es a
unsafeEff_)
    (Spec -> Spec) -> Eff es a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Hspec :> es) =>
(Spec -> Spec) -> Eff es a -> Eff es a
mapSpec ((IO () -> IO ()) -> Spec -> Spec
forall a.
HasCallStack =>
(IO () -> IO ()) -> SpecWith a -> SpecWith a
Hspec.aroundAll_ IO () -> IO ()
ioWrapper) Eff es a
action

expectationFailure :: (HasCallStack, Hspec :> es) => String -> Expectation es
expectationFailure :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es ()
expectationFailure String
msg = Eff '[HUnit] () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]) r.
(Hspec :> es) =>
Eff '[HUnit] r -> Eff es r
hunit (Eff '[HUnit] () -> Eff es ()) -> Eff '[HUnit] () -> Eff es ()
forall a b. (a -> b) -> a -> b
$ String -> Eff '[HUnit] ()
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, HUnit :> es) =>
String -> Eff es a
HUnit.assertFailure String
msg

expectTrue
    :: (HasCallStack, Hspec :> es)
    => String
    -> Bool
    -> Expectation es
expectTrue :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Bool -> Expectation es
expectTrue String
msg Bool
b = Bool -> Eff es () -> Eff es ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
b (String -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es ()
expectationFailure String
msg)

infix 1 `shouldBe`
        , `shouldSatisfy`
        , `shouldStartWith`
        , `shouldEndWith`
        , `shouldContain`
        , `shouldMatchList`
        , `shouldReturn`
        , `shouldThrow`

infix 1 `shouldNotBe`, `shouldNotSatisfy`, `shouldNotContain`, `shouldNotReturn`

-- | @actual \`shouldBe\` expected@ sets the expectation that @actual@ is equal
-- to @expected@.
shouldBe :: (HasCallStack, Show a, Eq a, Hspec :> es) => a -> a -> Expectation es
a
actual shouldBe :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
a -> a -> Expectation es
`shouldBe` a
expected = Eff '[HUnit] () -> Eff es ()
forall (es :: [(* -> *) -> * -> *]) r.
(Hspec :> es) =>
Eff '[HUnit] r -> Eff es r
hunit (Eff '[HUnit] () -> Eff es ()) -> Eff '[HUnit] () -> Eff es ()
forall a b. (a -> b) -> a -> b
$ a
actual a -> a -> Eff '[HUnit] ()
forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Eq a, Show a, HUnit :> es) =>
a -> a -> Assertion es
@?= a
expected

-- | @v \`shouldSatisfy\` p@ sets the expectation that @p v@ is @True@.
shouldSatisfy :: (HasCallStack, Show a, Hspec :> es) => a -> (a -> Bool) -> Expectation es
a
v shouldSatisfy :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Hspec :> es) =>
a -> (a -> Bool) -> Expectation es
`shouldSatisfy` a -> Bool
p = String -> Bool -> Expectation es
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Bool -> Expectation es
expectTrue (String
"predicate failed on: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
v) (a -> Bool
p a
v)

compareWith
    :: (HasCallStack, Show a, Hspec :> es)
    => (a -> a -> Bool)
    -> String
    -> a
    -> a
    -> Expectation es
compareWith :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Hspec :> es) =>
(a -> a -> Bool) -> String -> a -> a -> Expectation es
compareWith a -> a -> Bool
comparator String
errorDesc a
result a
expected = String -> Bool -> Expectation es
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Bool -> Expectation es
expectTrue String
errorMsg (a -> a -> Bool
comparator a
expected a
result)
  where
    errorMsg :: String
errorMsg = a -> String
forall a. Show a => a -> String
show a
result String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
errorDesc String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
expected

-- | @list \`shouldStartWith\` prefix@ sets the expectation that @list@ starts with @prefix@.
shouldStartWith :: (HasCallStack, Show a, Eq a, Hspec :> es) => [a] -> [a] -> Expectation es
shouldStartWith :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
[a] -> [a] -> Expectation es
shouldStartWith = ([a] -> [a] -> Bool) -> String -> [a] -> [a] -> Expectation es
forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Hspec :> es) =>
(a -> a -> Bool) -> String -> a -> a -> Expectation es
compareWith [a] -> [a] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
List.isPrefixOf String
"does not start with"

-- | @list \`shouldEndWith\` suffix@ sets the expectation that @list@ ends with @suffix@.
shouldEndWith :: (HasCallStack, Show a, Eq a, Hspec :> es) => [a] -> [a] -> Expectation es
shouldEndWith :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
[a] -> [a] -> Expectation es
shouldEndWith = ([a] -> [a] -> Bool) -> String -> [a] -> [a] -> Expectation es
forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Hspec :> es) =>
(a -> a -> Bool) -> String -> a -> a -> Expectation es
compareWith [a] -> [a] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
List.isSuffixOf String
"does not end with"

-- | @list \`shouldContain\` sublist@ sets the expectation that @sublist@ is contained,
-- wholly and intact, anywhere in @list@.
shouldContain :: (HasCallStack, Show a, Eq a, Hspec :> es) => [a] -> [a] -> Expectation es
shouldContain :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
[a] -> [a] -> Expectation es
shouldContain = ([a] -> [a] -> Bool) -> String -> [a] -> [a] -> Expectation es
forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Hspec :> es) =>
(a -> a -> Bool) -> String -> a -> a -> Expectation es
compareWith [a] -> [a] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
List.isInfixOf String
"does not contain"

-- | @xs \`shouldMatchList\` ys@ sets the expectation that @xs@ has the same
-- elements that @ys@ has, possibly in another order.
shouldMatchList :: (HasCallStack, Show a, Eq a, Hspec :> es) => [a] -> [a] -> Expectation es
[a]
xs shouldMatchList :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
[a] -> [a] -> Expectation es
`shouldMatchList` [a]
ys = Expectation es
-> (String -> Expectation es) -> Maybe String -> Expectation es
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> Expectation es
forall a. a -> Eff es a
forall (m :: * -> *) a. Monad m => a -> m a
return ()) String -> Expectation es
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es ()
expectationFailure ([a] -> [a] -> Maybe String
forall a. (Show a, Eq a) => [a] -> [a] -> Maybe String
matchList [a]
xs [a]
ys)

-- | @action \`shouldReturn\` expected@ sets the expectation that @action@
-- returns @expected@.
shouldReturn :: (HasCallStack, Show a, Eq a, Hspec :> es) => Eff es a -> a -> Expectation es
Eff es a
action shouldReturn :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
Eff es a -> a -> Expectation es
`shouldReturn` a
expected = Eff es a
action Eff es a -> (a -> Eff es ()) -> Eff es ()
forall a b. Eff es a -> (a -> Eff es b) -> Eff es b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (a -> a -> Eff es ()
forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
a -> a -> Expectation es
`shouldBe` a
expected)

-- | @actual \`shouldNotBe\` notExpected@ sets the expectation that @actual@ is not
-- equal to @notExpected@.
shouldNotBe :: (HasCallStack, Show a, Eq a, Hspec :> es) => a -> a -> Expectation es
a
actual shouldNotBe :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
a -> a -> Expectation es
`shouldNotBe` a
notExpected = String -> Bool -> Expectation es
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Bool -> Expectation es
expectTrue (String
"not expected: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
actual) (a
actual a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
notExpected)

-- | @v \`shouldNotSatisfy\` p@ sets the expectation that @p v@ is @False@.
shouldNotSatisfy :: (HasCallStack, Show a, Hspec :> es) => a -> (a -> Bool) -> Expectation es
a
v shouldNotSatisfy :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Hspec :> es) =>
a -> (a -> Bool) -> Expectation es
`shouldNotSatisfy` a -> Bool
p = String -> Bool -> Expectation es
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Bool -> Expectation es
expectTrue (String
"predicate succeeded on: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
v) ((Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p) a
v)

-- | @list \`shouldNotContain\` sublist@ sets the expectation that @sublist@ is not
-- contained anywhere in @list@.
shouldNotContain :: (HasCallStack, Show a, Eq a, Hspec :> es) => [a] -> [a] -> Expectation es
[a]
list shouldNotContain :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
[a] -> [a] -> Expectation es
`shouldNotContain` [a]
sublist = String -> Bool -> Expectation es
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Bool -> Expectation es
expectTrue String
errorMsg (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [a]
sublist [a] -> [a] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [a]
list)
  where
    errorMsg :: String
errorMsg = [a] -> String
forall a. Show a => a -> String
show [a]
list String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" does contain " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [a] -> String
forall a. Show a => a -> String
show [a]
sublist

-- | @action \`shouldNotReturn\` notExpected@ sets the expectation that @action@
-- does not return @notExpected@.
shouldNotReturn
    :: (HasCallStack, Show a, Eq a, Hspec :> es)
    => Eff es a
    -> a
    -> Expectation es
Eff es a
action shouldNotReturn :: forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
Eff es a -> a -> Expectation es
`shouldNotReturn` a
notExpected = Eff es a
action Eff es a -> (a -> Eff es ()) -> Eff es ()
forall a b. Eff es a -> (a -> Eff es b) -> Eff es b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (a -> a -> Eff es ()
forall a (es :: [(* -> *) -> * -> *]).
(HasCallStack, Show a, Eq a, Hspec :> es) =>
a -> a -> Expectation es
`shouldNotBe` a
notExpected)

-- | @action \`shouldThrow\` selector@ sets the expectation that @action@ throws
-- an exception.  The precise nature of the expected exception is described
-- with a 'Selector'.
shouldThrow
    :: (HasCallStack, Exception e, Hspec :> es)
    => Eff es a
    -> Selector e
    -> Expectation es
Eff es a
action shouldThrow :: forall e (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, Exception e, Hspec :> es) =>
Eff es a -> Selector e -> Expectation es
`shouldThrow` Selector e
p = do
    Either e a
r <- Eff es a -> Eff es (Either e a)
forall e (es :: [(* -> *) -> * -> *]) a.
Exception e =>
Eff es a -> Eff es (Either e a)
try Eff es a
action
    case Either e a
r of
        Right a
_ ->
            String -> Expectation es
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Eff es ()
expectationFailure (String -> Expectation es) -> String -> Expectation es
forall a b. (a -> b) -> a -> b
$
                String
"did not get expected exception: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
exceptionType
        Left e
e ->
            (String -> Bool -> Expectation es
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, Hspec :> es) =>
String -> Bool -> Expectation es
`expectTrue` Selector e
p e
e) (String -> Expectation es) -> String -> Expectation es
forall a b. (a -> b) -> a -> b
$
                String
"predicate failed on expected exception: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
exceptionType String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ e -> String
forall a. Show a => a -> String
show e
e
  where
    -- a string representation of the expected exception's type
    exceptionType :: String
exceptionType = (TypeRep -> String
forall a. Show a => a -> String
show (TypeRep -> String)
-> (Selector e -> TypeRep) -> Selector e -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> TypeRep
forall a. Typeable a => a -> TypeRep
typeOf (e -> TypeRep) -> (Selector e -> e) -> Selector e -> TypeRep
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selector e -> e
forall a. Selector a -> a
instanceOf) Selector e
p
      where
        instanceOf :: Selector a -> a
        instanceOf :: forall a. Selector a -> a
instanceOf Selector a
_ = String -> a
forall a. HasCallStack => String -> a
error String
"Effectful.Hspec.shouldThrow: broken Typeable instance"

-- | Lifted 'Hspec.prop'.
prop :: (HasCallStack, QuickCheck.Testable prop, Hspec :> es) => String -> prop -> Eff es ()
prop :: forall prop (es :: [(* -> *) -> * -> *]).
(HasCallStack, Testable prop, Hspec :> es) =>
String -> prop -> Eff es ()
prop = (Spec -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(Hspec :> es) =>
Spec -> Eff es ()
appendSpec (Spec -> Eff es ()) -> (prop -> Spec) -> prop -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((prop -> Spec) -> prop -> Eff es ())
-> (String -> prop -> Spec) -> String -> prop -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> prop -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
Hspec.prop

-- | Lifted 'Hspec.xprop'.
xprop :: (HasCallStack, QuickCheck.Testable prop, Hspec :> es) => String -> prop -> Eff es ()
xprop :: forall prop (es :: [(* -> *) -> * -> *]).
(HasCallStack, Testable prop, Hspec :> es) =>
String -> prop -> Eff es ()
xprop = (Spec -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(Hspec :> es) =>
Spec -> Eff es ()
appendSpec (Spec -> Eff es ()) -> (prop -> Spec) -> prop -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((prop -> Spec) -> prop -> Eff es ())
-> (String -> prop -> Spec) -> String -> prop -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> prop -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
Hspec.xprop

-- | Lifted 'Hspec.fprop'.
fprop :: (HasCallStack, QuickCheck.Testable prop, Hspec :> es) => String -> prop -> Eff es ()
fprop :: forall prop (es :: [(* -> *) -> * -> *]).
(HasCallStack, Testable prop, Hspec :> es) =>
String -> prop -> Eff es ()
fprop = (Spec -> Eff es ()
forall (es :: [(* -> *) -> * -> *]).
(Hspec :> es) =>
Spec -> Eff es ()
appendSpec (Spec -> Eff es ()) -> (prop -> Spec) -> prop -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((prop -> Spec) -> prop -> Eff es ())
-> (String -> prop -> Spec) -> String -> prop -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> prop -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
Hspec.fprop