@@ -1,13 +1,17 @@
11module Servant.QuickCheck.Internal.Predicates where
22
3−import Data.Monoid ((<>))
4−import GHC.Generics (Generic)
5−import Control.Monad
6−import Network.HTTP.Client (Request, Response, responseStatus, Manager, httpLbs)
7−import Network.HTTP.Types (status500)
3+import Control.Monad
4+import Data.Aeson (Object, decode)
5+import Data.Bifunctor (Bifunctor (..))
86import qualified Data.ByteString.Lazy as LBS
9−import Data.Bifunctor (Bifunctor(..))
10−import Data.Text (Text)
7+import qualified Data.ByteString as SBS
8+import Data.CaseInsensitive (mk)
9+import Data.Monoid ((<>))
10+import Data.Text (Text)
11+import GHC.Generics (Generic)
12+import Network.HTTP.Client (Manager, Request, Response, httpLbs,
13+ responseBody, responseStatus, responseHeaders)
14+import Network.HTTP.Types (status500)
1115
1216-- | @500 Internal Server Error@ should be avoided - it may represent some
1317-- issue with the application code, and it moreover gives the client little
@@ -17,7 +21,6 @@ import Data.Text (Text)
1721not500 :: ResponsePredicate Text Bool
1822not500 = ResponsePredicate "not500" (\resp -> not $ responseStatus resp == status500)
1923
20−{-
2124-- | Returning anything other than an object when returning JSON is considered
2225-- bad practice, as:
2326--
@@ -30,10 +33,13 @@ not500 = ResponsePredicate "not500" (\resp -> not $ responseStatus resp == statu
3033--
3134-- This function checks that any @application/json@ responses only return JSON
3235-- objects (and not arrays, strings, numbers, or booleans) at the top level.
33−onlyJsonObjects :: Response b -> IO Bool
36+onlyJsonObjects :: ResponsePredicate Text Bool
3437onlyJsonObjects
35− = ResponsePredicate "onlyJsonObjects" _
38+ = ResponsePredicate "onlyJsonObjects" (\resp -> case decode (responseBody resp) of
39+ Nothing -> False
40+ Just (_ :: Object) -> True)
3641
42+{-
3743-- | When creating a new resource, it is good practice to provide a @Location@
3844-- header with a link to the created resource.
3945--
@@ -42,9 +48,9 @@ onlyJsonObjects
4248-- requests.
4349--
4450-- References: <RFC 7231, Section 6.3.2 https://tools.ietf.org/html/rfc7231#section-6.3.2>
45−createContainsValidLocation :: Response b -> IO Bool
51+createContainsValidLocation :: ResponsePredicate Text Bool
4652createContainsValidLocation
47− = ResponsePredicate "createContainsValidLocation" _
53+ = ResponsePredicate "createContainsValidLocation" (\resp ->
4854
4955getsHaveLastModifiedHeader :: Response b -> IO Bool
5056getsHaveLastModifiedHeader
@@ -221,3 +227,8 @@ finishPredicates p req mgr = do
221227 resps <- reqResps (reqPreds p) req mgr
222228 let preds = reqPred (reqPreds p) <> respPreds p
223229 return $ mconcat [respPred preds r | r <- resps ]
230+
231+-- * helpers
232+
233+hasHeader :: SBS.ByteString -> Response b -> Bool
234+hasHeader hdr r = mk hdr `elem` (fst <$> responseHeaders r)