    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE TypeFamilies #-}
    module Test.Hspec.Wai.QuickCheck (
      property
    , (==>)

    -- * Re-exports
    , Arbitrary (..)
    , module Test.QuickCheck.Gen

    -- * Internals
    , Testable (..)
    , WaiProperty (..)
    ) where

    import           Test.QuickCheck hiding (Testable, property, (==>))
    import qualified Test.QuickCheck as QuickCheck
    import           Test.QuickCheck.Gen
    import           Network.Wai (Application)

    import           Test.Hspec.Wai.Internal

    property :: Testable a => a -> (State a, Application) -> Property
    property :: forall a. Testable a => a -> (State a, Application) -> Property
    property = WaiProperty (State a) -> (State a, Application) -> Property
    forall st. WaiProperty st -> (st, Application) -> Property
    unWaiProperty (WaiProperty (State a) -> (State a, Application) -> Property)
    -> (a -> WaiProperty (State a))
    -> a
    -> (State a, Application)
    -> Property
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> WaiProperty (State a)
    forall a. Testable a => a -> WaiProperty (State a)
    toProperty

    data WaiProperty st = WaiProperty {forall st. WaiProperty st -> (st, Application) -> Property
    unWaiProperty :: (st, Application) -> Property}

    class Testable a where
      type State a
      toProperty :: a -> WaiProperty (State a)

    instance Testable (WaiProperty st) where
      type State (WaiProperty st) = st
      toProperty :: WaiProperty st -> WaiProperty (State (WaiProperty st))
    toProperty = WaiProperty st -> WaiProperty st
    WaiProperty st -> WaiProperty (State (WaiProperty st))
    forall a. a -> a
    id

    instance Testable (WaiExpectation st) where
      type State (WaiExpectation st) = st
      toProperty :: WaiExpectation st -> WaiProperty (State (WaiExpectation st))
    toProperty WaiExpectation st
    action = ((st, Application) -> Property) -> WaiProperty st
    forall st. ((st, Application) -> Property) -> WaiProperty st
    WaiProperty (IO () -> Property
    forall prop. Testable prop => prop -> Property
    QuickCheck.property (IO () -> Property)
    -> ((st, Application) -> IO ()) -> (st, Application) -> Property
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WaiExpectation st -> (st, Application) -> IO ()
    forall st a. WaiSession st a -> (st, Application) -> IO a
    runWithState WaiExpectation st
    action)

    instance (Arbitrary a, Show a, Testable prop) => Testable (a -> prop) where
      type State (a -> prop) = State prop
      toProperty :: (a -> prop) -> WaiProperty (State (a -> prop))
    toProperty a -> prop
    prop = ((State (a -> prop), Application) -> Property)
    -> WaiProperty (State (a -> prop))
    forall st. ((st, Application) -> Property) -> WaiProperty st
    WaiProperty (((State (a -> prop), Application) -> Property)
     -> WaiProperty (State (a -> prop)))
    -> ((State (a -> prop), Application) -> Property)
    -> WaiProperty (State (a -> prop))
    forall a b. (a -> b) -> a -> b
    $ (a -> Property) -> Property
    forall prop. Testable prop => prop -> Property
    QuickCheck.property ((a -> Property) -> Property)
    -> ((State prop, Application) -> a -> Property)
    -> (State prop, Application)
    -> Property
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((a -> (State prop, Application) -> Property)
    -> (State prop, Application) -> a -> Property
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip ((a -> (State prop, Application) -> Property)
     -> (State prop, Application) -> a -> Property)
    -> (a -> (State prop, Application) -> Property)
    -> (State prop, Application)
    -> a
    -> Property
    forall a b. (a -> b) -> a -> b
    $ WaiProperty (State prop) -> (State prop, Application) -> Property
    forall st. WaiProperty st -> (st, Application) -> Property
    unWaiProperty (WaiProperty (State prop) -> (State prop, Application) -> Property)
    -> (a -> WaiProperty (State prop))
    -> a
    -> (State prop, Application)
    -> Property
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . prop -> WaiProperty (State prop)
    forall a. Testable a => a -> WaiProperty (State a)
    toProperty (prop -> WaiProperty (State prop))
    -> (a -> prop) -> a -> WaiProperty (State prop)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> prop
    prop)

    infixr 0 ==>
    (==>) :: Testable prop => Bool -> prop -> WaiProperty (State prop)
    ==> :: forall prop.
    Testable prop =>
    Bool -> prop -> WaiProperty (State prop)
    (==>) = (Bool -> Property -> Property)
    -> Bool -> prop -> WaiProperty (State prop)
    forall prop a.
    Testable prop =>
    (a -> Property -> Property)
    -> a -> prop -> WaiProperty (State prop)
    lift Bool -> Property -> Property
    forall prop. Testable prop => Bool -> prop -> Property
    (QuickCheck.==>)

    lift :: Testable prop => (a -> Property -> Property) -> a -> prop -> WaiProperty (State prop)
    lift :: forall prop a.
    Testable prop =>
    (a -> Property -> Property)
    -> a -> prop -> WaiProperty (State prop)
    lift a -> Property -> Property
    f a
    a prop
    prop = ((State prop, Application) -> Property) -> WaiProperty (State prop)
    forall st. ((st, Application) -> Property) -> WaiProperty st
    WaiProperty (((State prop, Application) -> Property)
     -> WaiProperty (State prop))
    -> ((State prop, Application) -> Property)
    -> WaiProperty (State prop)
    forall a b. (a -> b) -> a -> b
    $ \(State prop, Application)
    app -> a -> Property -> Property
    f a
    a (WaiProperty (State prop) -> (State prop, Application) -> Property
    forall st. WaiProperty st -> (st, Application) -> Property
    unWaiProperty (prop -> WaiProperty (State prop)
    forall a. Testable a => a -> WaiProperty (State a)
    toProperty prop
    prop) (State prop, Application)
    app)