-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Experimental Hspec support for testing WAI applications
--   
--   Experimental Hspec support for testing WAI applications
@package hspec-wai
@version 0.11.1

module Test.Hspec.Wai.Matcher
data ResponseMatcher
ResponseMatcher :: Int -> [MatchHeader] -> MatchBody -> ResponseMatcher
[matchStatus] :: ResponseMatcher -> Int
[matchHeaders] :: ResponseMatcher -> [MatchHeader]
[matchBody] :: ResponseMatcher -> MatchBody
data MatchHeader
MatchHeader :: ([Header] -> Body -> Maybe String) -> MatchHeader
data MatchBody
MatchBody :: ([Header] -> Body -> Maybe String) -> MatchBody
type Body = ByteString
(<:>) :: HeaderName -> ByteString -> MatchHeader
bodyEquals :: Body -> MatchBody
match :: SResponse -> ResponseMatcher -> Maybe String
formatHeader :: Header -> String
instance Data.String.IsString Test.Hspec.Wai.Matcher.ResponseMatcher
instance GHC.Num.Num Test.Hspec.Wai.Matcher.ResponseMatcher
instance Data.String.IsString Test.Hspec.Wai.Matcher.MatchBody

module Test.Hspec.Wai.Internal

-- | An expectation in the <a>WaiSession</a> monad. Failing expectations
--   are communicated through exceptions (similar to <a>Expectation</a> and
--   <a>Assertion</a>).
type WaiExpectation st = WaiSession st ()

-- | A <a>WAI</a> test session that carries the <a>Application</a> under
--   test and some client state.
newtype WaiSession st a
WaiSession :: ReaderT st Session a -> WaiSession st a
[unWaiSession] :: WaiSession st a -> ReaderT st Session a
runWaiSession :: WaiSession () a -> Application -> IO a
runWithState :: WaiSession st a -> (st, Application) -> IO a
withApplication :: Application -> WaiSession () a -> IO a
getApp :: WaiSession st Application
getState :: WaiSession st st
formatHeader :: Header -> String
instance Control.Monad.Fail.MonadFail (Test.Hspec.Wai.Internal.WaiSession st)
instance Control.Monad.IO.Class.MonadIO (Test.Hspec.Wai.Internal.WaiSession st)
instance GHC.Base.Monad (Test.Hspec.Wai.Internal.WaiSession st)
instance GHC.Base.Applicative (Test.Hspec.Wai.Internal.WaiSession st)
instance GHC.Base.Functor (Test.Hspec.Wai.Internal.WaiSession st)
instance Test.Hspec.Core.Example.Example (Test.Hspec.Wai.Internal.WaiExpectation st)

module Test.Hspec.Wai.QuickCheck
property :: Testable a => a -> (State a, Application) -> Property
(==>) :: Testable prop => Bool -> prop -> WaiProperty (State prop)
infixr 0 ==>

-- | Random generation and shrinking of values.
--   
--   QuickCheck provides <tt>Arbitrary</tt> instances for most types in
--   <tt>base</tt>, except those which incur extra dependencies. For a
--   wider range of <tt>Arbitrary</tt> instances see the
--   <a>quickcheck-instances</a> package.
class () => Arbitrary a

-- | A generator for values of the given type.
--   
--   It is worth spending time thinking about what sort of test data you
--   want - good generators are often the difference between finding bugs
--   and not finding them. You can use <a>sample</a>, <tt>label</tt> and
--   <tt>classify</tt> to check the quality of your test data.
--   
--   There is no generic <tt>arbitrary</tt> implementation included because
--   we don't know how to make a high-quality one. If you want one,
--   consider using the <a>testing-feat</a> or <a>generic-random</a>
--   packages.
--   
--   The <a>QuickCheck manual</a> goes into detail on how to write good
--   generators. Make sure to look at it, especially if your type is
--   recursive!
arbitrary :: Arbitrary a => Gen a

-- | Produces a (possibly) empty list of all the possible immediate shrinks
--   of the given value.
--   
--   The default implementation returns the empty list, so will not try to
--   shrink the value. If your data type has no special invariants, you can
--   enable shrinking by defining <tt>shrink = <a>genericShrink</a></tt>,
--   but by customising the behaviour of <tt>shrink</tt> you can often get
--   simpler counterexamples.
--   
--   Most implementations of <a>shrink</a> should try at least three
--   things:
--   
--   <ol>
--   <li>Shrink a term to any of its immediate subterms. You can use
--   <a>subterms</a> to do this.</li>
--   <li>Recursively apply <a>shrink</a> to all immediate subterms. You can
--   use <a>recursivelyShrink</a> to do this.</li>
--   <li>Type-specific shrinkings such as replacing a constructor by a
--   simpler constructor.</li>
--   </ol>
--   
--   For example, suppose we have the following implementation of binary
--   trees:
--   
--   <pre>
--   data Tree a = Nil | Branch a (Tree a) (Tree a)
--   </pre>
--   
--   We can then define <a>shrink</a> as follows:
--   
--   <pre>
--   shrink Nil = []
--   shrink (Branch x l r) =
--     -- shrink Branch to Nil
--     [Nil] ++
--     -- shrink to subterms
--     [l, r] ++
--     -- recursively shrink subterms
--     [Branch x' l' r' | (x', l', r') &lt;- shrink (x, l, r)]
--   </pre>
--   
--   There are a couple of subtleties here:
--   
--   <ul>
--   <li>QuickCheck tries the shrinking candidates in the order they appear
--   in the list, so we put more aggressive shrinking steps (such as
--   replacing the whole tree by <tt>Nil</tt>) before smaller ones (such as
--   recursively shrinking the subtrees).</li>
--   <li>It is tempting to write the last line as <tt>[Branch x' l' r' | x'
--   &lt;- shrink x, l' &lt;- shrink l, r' &lt;- shrink r]</tt> but this is
--   the <i>wrong thing</i>! It will force QuickCheck to shrink <tt>x</tt>,
--   <tt>l</tt> and <tt>r</tt> in tandem, and shrinking will stop once
--   <i>one</i> of the three is fully shrunk.</li>
--   </ul>
--   
--   There is a fair bit of boilerplate in the code above. We can avoid it
--   with the help of some generic functions. The function
--   <a>genericShrink</a> tries shrinking a term to all of its subterms
--   and, failing that, recursively shrinks the subterms. Using it, we can
--   define <a>shrink</a> as:
--   
--   <pre>
--   shrink x = shrinkToNil x ++ genericShrink x
--     where
--       shrinkToNil Nil = []
--       shrinkToNil (Branch _ l r) = [Nil]
--   </pre>
--   
--   <a>genericShrink</a> is a combination of <a>subterms</a>, which
--   shrinks a term to any of its subterms, and <a>recursivelyShrink</a>,
--   which shrinks all subterms of a term. These may be useful if you need
--   a bit more control over shrinking than <a>genericShrink</a> gives you.
--   
--   A final gotcha: we cannot define <a>shrink</a> as simply
--   <tt><a>shrink</a> x = Nil:<a>genericShrink</a> x</tt> as this shrinks
--   <tt>Nil</tt> to <tt>Nil</tt>, and shrinking will go into an infinite
--   loop.
--   
--   If all this leaves you bewildered, you might try <tt><a>shrink</a> =
--   <a>genericShrink</a></tt> to begin with, after deriving
--   <tt>Generic</tt> for your type. However, if your data type has any
--   special invariants, you will need to check that <a>genericShrink</a>
--   can't break those invariants.
shrink :: Arbitrary a => a -> [a]
class Testable a where {
    type State a;
}
toProperty :: Testable a => a -> WaiProperty (State a)
data WaiProperty st
WaiProperty :: ((st, Application) -> Property) -> WaiProperty st
[unWaiProperty] :: WaiProperty st -> (st, Application) -> Property
instance Test.Hspec.Wai.QuickCheck.Testable (Test.Hspec.Wai.QuickCheck.WaiProperty st)
instance Test.Hspec.Wai.QuickCheck.Testable (Test.Hspec.Wai.Internal.WaiExpectation st)
instance (Test.QuickCheck.Arbitrary.Arbitrary a, GHC.Show.Show a, Test.Hspec.Wai.QuickCheck.Testable prop) => Test.Hspec.Wai.QuickCheck.Testable (a -> prop)


-- | Have a look at the <a>README</a> for an example of how to use this
--   library.
module Test.Hspec.Wai

-- | A <a>WAI</a> test session that carries the <a>Application</a> under
--   test and some client state.
data WaiSession st a

-- | An expectation in the <a>WaiSession</a> monad. Failing expectations
--   are communicated through exceptions (similar to <a>Expectation</a> and
--   <a>Assertion</a>).
type WaiExpectation st = WaiSession st ()

-- | Perform a <tt>GET</tt> request to the application under test.
get :: ByteString -> WaiSession st SResponse

-- | Perform a <tt>POST</tt> request to the application under test.
post :: ByteString -> ByteString -> WaiSession st SResponse

-- | Perform a <tt>PUT</tt> request to the application under test.
put :: ByteString -> ByteString -> WaiSession st SResponse

-- | Perform a <tt>PATCH</tt> request to the application under test.
patch :: ByteString -> ByteString -> WaiSession st SResponse

-- | Perform an <tt>OPTIONS</tt> request to the application under test.
options :: ByteString -> WaiSession st SResponse

-- | Perform a <tt>DELETE</tt> request to the application under test.
delete :: ByteString -> WaiSession st SResponse

-- | Perform a request to the application under test, with specified HTTP
--   method, request path, headers and body.
request :: Method -> ByteString -> [Header] -> ByteString -> WaiSession st SResponse

-- | Perform a <tt>POST</tt> request to the application under test.
--   
--   The specified list of key-value pairs is encoded as
--   <tt>application/x-www-form-urlencoded</tt> and used as request body.
--   
--   In addition the <tt>Content-Type</tt> is set to
--   <tt>application/x-www-form-urlencoded</tt>.
postHtmlForm :: ByteString -> [(String, String)] -> WaiSession st SResponse

-- | Set the expectation that a response matches a specified
--   <a>ResponseMatcher</a>.
--   
--   A <tt>ResponseMatcher</tt> matches a response if:
--   
--   <ul>
--   <li>the specified status matches the HTTP response status code</li>
--   <li>the specified body (if any) matches the response body</li>
--   <li>the response has all of the specified <a>Header</a> fields (the
--   response may have arbitrary additional <a>Header</a> fields)</li>
--   </ul>
--   
--   You can use <tt>ResponseMatcher</tt>'s (broken) <a>Num</a> instance to
--   match for a HTTP status code:
--   
--   <pre>
--   get "/" `shouldRespondWith` 200
--   -- matches if status is 200
--   </pre>
--   
--   You can use <tt>ResponseMatcher</tt>'s <tt>IsString</tt> instance to
--   match for a HTTP status <tt>200</tt> and a body:
--   
--   <pre>
--   get "/" `shouldRespondWith` "foo"
--   -- matches if body is "foo" and status is 200
--   </pre>
--   
--   If you want to match for a different HTTP status, you can use record
--   update notation to specify <a>matchStatus</a> explicitly:
--   
--   <pre>
--   get "/" `shouldRespondWith` "foo" {matchStatus = 404}
--   -- matches if body is "foo" and status is 404
--   </pre>
--   
--   If you want to require a specific header field you can specify
--   <a>matchHeaders</a>:
--   
--   <pre>
--   get "/" `shouldRespondWith` "foo" {matchHeaders = ["Content-Type" &lt;:&gt; "text/plain"]}
--   -- matches if body is "foo", status is 200 and there is a header field "Content-Type: text/plain"
--   </pre>
shouldRespondWith :: HasCallStack => WaiSession st SResponse -> ResponseMatcher -> WaiExpectation st
data ResponseMatcher
ResponseMatcher :: Int -> [MatchHeader] -> MatchBody -> ResponseMatcher
[matchStatus] :: ResponseMatcher -> Int
[matchHeaders] :: ResponseMatcher -> [MatchHeader]
[matchBody] :: ResponseMatcher -> MatchBody
data MatchHeader
MatchHeader :: ([Header] -> Body -> Maybe String) -> MatchHeader
data MatchBody
MatchBody :: ([Header] -> Body -> Maybe String) -> MatchBody
type Body = ByteString
(<:>) :: HeaderName -> ByteString -> MatchHeader

-- | Lift a computation from the <a>IO</a> monad. This allows us to run IO
--   computations in any monadic stack, so long as it supports these kinds
--   of operations (i.e. <a>IO</a> is the base monad for the stack).
--   
--   <h3><b>Example</b></h3>
--   
--   <pre>
--   import Control.Monad.Trans.State -- from the "transformers" library
--   
--   printState :: Show s =&gt; StateT s IO ()
--   printState = do
--     state &lt;- get
--     liftIO $ print state
--   </pre>
--   
--   Had we omitted <tt><a>liftIO</a></tt>, we would have ended up with
--   this error:
--   
--   <pre>
--   • Couldn't match type ‘IO’ with ‘StateT s IO’
--    Expected type: StateT s IO ()
--      Actual type: IO ()
--   </pre>
--   
--   The important part here is the mismatch between <tt>StateT s IO
--   ()</tt> and <tt><a>IO</a> ()</tt>.
--   
--   Luckily, we know of a function that takes an <tt><a>IO</a> a</tt> and
--   returns an <tt>(m a)</tt>: <tt><a>liftIO</a></tt>, enabling us to run
--   the program and see the expected results:
--   
--   <pre>
--   &gt; evalStateT printState "hello"
--   "hello"
--   
--   &gt; evalStateT printState 3
--   3
--   </pre>
liftIO :: MonadIO m => IO a -> m a
with :: IO Application -> SpecWith ((), Application) -> Spec
withState :: IO (st, Application) -> SpecWith (st, Application) -> Spec
getState :: WaiSession st st

-- | A lifted version of <a>pending</a>.
pending :: WaiSession st ()

-- | A lifted version of <a>pendingWith</a>.
pendingWith :: String -> WaiSession st ()
