@@ -3,9 +3,10 @@ module Servant.QuickCheck.Internal.Predicates where
3import Data.Monoid ((<>))
3import Data.Monoid ((<>))
4import GHC.Generics (Generic)
4import GHC.Generics (Generic)
5import Control.Monad
5import Control.Monad
6−import Network.HTTP.Client (Request, Response, responseStatus)
6+import Network.HTTP.Client (Request, Response, responseStatus, Manager, httpLbs)
7import Network.HTTP.Types (status500)
7import Network.HTTP.Types (status500)
8import qualified Data.ByteString.Lazy as LBS
8import qualified Data.ByteString.Lazy as LBS
9+import Data.Bifunctor (Bifunctor(..))
9import Data.Text (Text)
10import Data.Text (Text)
11-- | @500 Internal Server Error@ should be avoided - it may represent some
12-- | @500 Internal Server Error@ should be avoided - it may represent some
@@ -13,9 +14,8 @@ import Data.Text (Text)
13-- indication of how to proceed or what went wrong.
14-- indication of how to proceed or what went wrong.
15-- This function checks that the response code is not 500.
16-- This function checks that the response code is not 500.
16−not500 :: ResponsePredicate Text [Text]
17+not500 :: ResponsePredicate Text Bool
17−not500 = ResponsePredicate "not500" (\resp ->
18+not500 = ResponsePredicate "not500" (\resp -> not $ responseStatus resp == status500)
18− if responseStatus resp == status500 then ["not500"] else [])
21-- | Returning anything other than an object when returning JSON is considered
21-- | Returning anything other than an object when returning JSON is considered
@@ -158,6 +158,10 @@ data ResponsePredicate n r = ResponsePredicate
158 , respPred :: Response LBS.ByteString -> r
158 , respPred :: Response LBS.ByteString -> r
159 } deriving (Functor, Generic)
159 } deriving (Functor, Generic)
161+instance Bifunctor ResponsePredicate where
162+ first f (ResponsePredicate a b) = ResponsePredicate (f a) b
161instance (Monoid n, Monoid r) => Monoid (ResponsePredicate n r) where
165instance (Monoid n, Monoid r) => Monoid (ResponsePredicate n r) where
162 mempty = ResponsePredicate mempty mempty
166 mempty = ResponsePredicate mempty mempty
163 a `mappend` b = ResponsePredicate
167 a `mappend` b = ResponsePredicate
@@ -167,15 +171,20 @@ instance (Monoid n, Monoid r) => Monoid (ResponsePredicate n r) where
168data RequestPredicate n r = RequestPredicate
172data RequestPredicate n r = RequestPredicate
169 { reqPredName :: n
173 { reqPredName :: n
170− , reqResps :: Request -> IO [Response LBS.ByteString]
174+ , reqResps :: Request -> Manager -> IO [Response LBS.ByteString]
171 , reqPred :: ResponsePredicate n r
175 , reqPred :: ResponsePredicate n r
172 } deriving (Generic, Functor)
176 } deriving (Generic, Functor)
178+instance Bifunctor RequestPredicate where
179+ first f (RequestPredicate a b c) = RequestPredicate (f a) b (first f c)
182+-- TODO: This isn't actually a monoid
174instance (Monoid n, Monoid r) => Monoid (RequestPredicate n r) where
183instance (Monoid n, Monoid r) => Monoid (RequestPredicate n r) where
175− mempty = RequestPredicate mempty (\_ -> return mempty) mempty
184+ mempty = RequestPredicate mempty (\r m -> return <$> httpLbs r m) mempty
176 a `mappend` b = RequestPredicate
185 a `mappend` b = RequestPredicate
177 { reqPredName = reqPredName a <> reqPredName b
186 { reqPredName = reqPredName a <> reqPredName b
178− , reqResps = \x -> liftM2 (<>) (reqResps a x) (reqResps b x)
187+ , reqResps = \x m -> liftM2 (<>) (reqResps a x m) (reqResps b x m)
179 , reqPred = reqPred a <> reqPred b
188 , reqPred = reqPred a <> reqPred b
@@ -194,17 +203,21 @@ class JoinPreds a where
194 joinPreds :: a -> Predicates [Text] [Text] -> Predicates [Text] [Text]
203 joinPreds :: a -> Predicates [Text] [Text] -> Predicates [Text] [Text]
196instance JoinPreds (RequestPredicate Text Bool) where
205instance JoinPreds (RequestPredicate Text Bool) where
197− joinPreds p (Predicates x y) = Predicates (p <> x) y
206+ joinPreds p (Predicates x y) = Predicates (go <> x) y
207+ where go = let p' = first return p
208+ in fmap (\z -> if z then [] else reqPredName p') p'
199instance JoinPreds (ResponsePredicate Text Bool) where
210instance JoinPreds (ResponsePredicate Text Bool) where
200− joinPreds p (Predicates x y) = Predicates x (p <> y)
211+ joinPreds p (Predicates x y) = Predicates x (go <> y)
212+ where go = let p' = first return p
213+ in fmap (\z -> if z then [] else respPredName p') p'
202infixr 6 <%>
215infixr 6 <%>
203−(<%>) :: JoinPreds a n b r => a -> Predicates n b r -> Predicates n b r
216+(<%>) :: JoinPreds a => a -> Predicates [Text] [Text] -> Predicates [Text] [Text]
204(<%>) = joinPreds
217(<%>) = joinPreds
206−finishPredicates :: Predicates [Text] [Text] -> Request -> IO [Text]
219+finishPredicates :: Predicates [Text] [Text] -> Request -> Manager -> IO [Text]
207−finishPredicates p req = do
220+finishPredicates p req mgr = do
208− resps <- reqResps (reqPreds p) req
221+ resps <- reqResps (reqPreds p) req mgr
209 let preds = reqPred (reqPreds p) <> respPreds p
222 let preds = reqPred (reqPreds p) <> respPreds p
210 return $ mconcat [respPred preds r | r <- resps ]
223 return $ mconcat [respPred preds r | r <- resps ]