git.iko.soy/servant-quickcheck
on master help sign in
Documentation improvements
b5ee965Julian K. Arni
src/Servant/QuickCheck.hs+32−18
@@ -6,14 +6,37 @@
6-- tested itself need not be implemented with @servant-server@ (or indeed,
6-- tested itself need not be implemented with @servant-server@ (or indeed,
7-- written in Haskell).
7-- written in Haskell).
8--
8--
9+-- The documentation of the <#useful-preds Useful predicates> sections is
10+-- meant to serve as a set of helpful pointers for learning more about best
11+-- practices concerning REST APIs.
9module Servant.QuickCheck
12module Servant.QuickCheck
10 (
13 (
11
14
12−
15+ -- * Property testing
13− -- * Test setup helpers
16+ serverSatisfies
14− -- | Helpers to setup and teardown @servant@ servers during tests.
17+ -- ** Predicates
15− withServantServer
18+ -- *** #useful-preds# Useful predicates
16−
19+ -- | The predicates below are often useful. Some check RFC compliance; some are
20+ -- best practice, and some are useful to check that APIs follow in-house
21+ -- best-practices. Included in the documentation for each is a list of
22+ -- references to any relevant RFCs and other links, as well as what type of
23+ -- predicate it is (__RFC Compliance__, __Best Practice__, __Optional__).
24+ --
25+ -- RFCs distinguish between the force of requirements (e.g. __MUST__ vs.
26+ -- __SHOULD__). __RFC Compliance__ includes any absolute requirements present
27+ -- in RFCs. The __Best Practices__ includes, in addition to RFC
28+ -- recommendations, recommendations found elsewhere or generally accepted.
29+ , not500
30+ , onlyJsonObjects
31+ , notAllowedContainsAllowHeader
32+ , unauthorizedContainsWWWAuthenticate
33+ , getsHaveCacheControlHeader
34+ , headsHaveCacheControlHeader
35+ -- *** Predicate utilities and types
36+ , (<%>)
37+ , Predicates
38+ , ResponsePredicate(..)
39+ , RequestPredicate(..)
17
40
18 -- * Equality testing
41 -- * Equality testing
19 , serversEqual
42 , serversEqual
@@ -28,19 +51,10 @@ module Servant.QuickCheck
28 -- ** Response equality type
51 -- ** Response equality type
29 , ResponseEquality(..)
52 , ResponseEquality(..)
30
53
31− -- * Property testing
54+ -- * Test setup helpers
32− , serverSatisfies
55+ -- | Helpers to setup and teardown @servant@ servers during tests.
33− -- ** Predicates
56+ , withServantServer
34− -- *** Useful predicates
57+ , withServantServerAndContext
35− , not500
36− , onlyJsonObjects
37− , notAllowedContainsAllowHeader
38− , unauthorizedContainsWWWAuthenticate
39− -- *** Predicate utilities and types
40− , (<%>)
41− , Predicates
42− , ResponsePredicate(..)
43− , RequestPredicate(..)
44
58
45 -- ** Re-exports
59 -- ** Re-exports
46 , BaseUrl(..)
60 , BaseUrl(..)
src/Servant/QuickCheck/Internal/Predicates.hs+32−19
@@ -1,22 +1,28 @@
1+{-# LANGUAGE MultiWayIf #-}
1module Servant.QuickCheck.Internal.Predicates where
2module Servant.QuickCheck.Internal.Predicates where
2
3
3import Control.Monad
4import Control.Monad
4−import Data.Aeson (Object, decode)
5+import Data.Aeson (Object, decode)
5−import Data.Bifunctor (Bifunctor (..))
6+import Data.Bifunctor (Bifunctor (..))
6−import qualified Data.ByteString.Lazy as LBS
7+import qualified Data.ByteString as SBS
7−import qualified Data.ByteString as SBS
8import qualified Data.ByteString.Char8 as SBSC
8import qualified Data.ByteString.Char8 as SBSC
9+import qualified Data.ByteString.Lazy as LBS
9−import Data.CaseInsensitive (mk)
10+import Data.CaseInsensitive (mk)
10−import Data.Either (isRight)
11+import Data.Either (isRight)
11−import Data.List.Split (wordsBy)
12+import Data.List.Split (wordsBy)
12−import Data.Monoid ((<>))
13+import Data.Maybe (isJust)
14+import Data.Monoid ((<>))
13−import Data.Text (Text)
15+import Data.Text (Text)
14−import GHC.Generics (Generic)
16+import GHC.Generics (Generic)
15−import Network.HTTP.Client (Manager, Request, Response, httpLbs,
17+import Network.HTTP.Client (Manager, Request, Response, httpLbs,
18+ method, responseBody, responseHeaders,
16− responseBody, responseStatus, responseHeaders)
19+ responseStatus)
17−import Network.HTTP.Types (status500, status405, status401, parseMethod)
20+import Network.HTTP.Types (methodGet, methodHead, parseMethod,
18−
21+ status401, renderStdMethod, status405, status500)
22+
23+-- | [__Best Practice__]
24+--
19−-- | @500 Internal Server Error@ should be avoided - it may represent some
25+-- @500 Internal Server Error@ should be avoided - it may represent some
20-- issue with the application code, and it moreover gives the client little
26-- issue with the application code, and it moreover gives the client little
21-- indication of how to proceed or what went wrong.
27-- indication of how to proceed or what went wrong.
22--
28--
@@ -24,7 +30,9 @@ import Network.HTTP.Types (status500, status405, status401, parseMet
24not500 :: ResponsePredicate Text Bool
30not500 :: ResponsePredicate Text Bool
25not500 = ResponsePredicate "not500" (\resp -> not $ responseStatus resp == status500)
31not500 = ResponsePredicate "not500" (\resp -> not $ responseStatus resp == status500)
26
32
33+-- | [__Best Practice__]
34+--
27−-- | Returning anything other than an object when returning JSON is considered
35+-- Returning anything other than an object when returning JSON is considered
28-- bad practice, as:
36-- bad practice, as:
29--
37--
30-- (1) it is hard to modify the returned value while maintaining backwards
38-- (1) it is hard to modify the returned value while maintaining backwards
@@ -66,8 +74,11 @@ getsHaveLastModifiedHeader
66
74
67-}
75-}
68
76
77+-- | [__RFC Compliance__]
78+--
69−-- | When an HTTP request has a method that is not allowed, a 405 response
79+-- When an HTTP request has a method that is not allowed,
70−-- should be returned. Additionally, it is good practice to return an @Allow@
80+-- a 405 response should be returned. Additionally, it is good practice to
81+-- return an @Allow@
71-- header with the list of allowed methods.
82-- header with the list of allowed methods.
72--
83--
73-- This function checks that every @405 Method Not Allowed@ response contains
84-- This function checks that every @405 Method Not Allowed@ response contains
@@ -163,7 +174,9 @@ linkHeadersAreValid
163 = ResponsePredicate "linkHeadersAreValid" _
174 = ResponsePredicate "linkHeadersAreValid" _
164
175
165-}
176-}
177+-- | [__RFC Compliance__]
178+--
166−-- | Any @401 Unauthorized@ response must include a @WWW-Authenticate@ header.
179+-- Any @401 Unauthorized@ response must include a @WWW-Authenticate@ header.
167--
180--
168-- This function checks that, if a response has status code 401, it contains a
181-- This function checks that, if a response has status code 401, it contains a
169-- @WWW-Authenticate@ header.
182-- @WWW-Authenticate@ header.
src/Servant/QuickCheck/Internal/QuickCheck.hs+3−3
@@ -1,4 +1,3 @@
1−-- | This module contains wrappers around lower-level functionality.
2module Servant.QuickCheck.Internal.QuickCheck where
1module Servant.QuickCheck.Internal.QuickCheck where
3
2
4import qualified Data.ByteString.Lazy as LBS
3import qualified Data.ByteString.Lazy as LBS
@@ -8,13 +7,14 @@ import Network.HTTP.Client (Manager, Request, checkStatus,
8 defaultManagerSettings, httpLbs,
7 defaultManagerSettings, httpLbs,
9 newManager)
8 newManager)
10import Network.Wai.Handler.Warp (withApplication)
9import Network.Wai.Handler.Warp (withApplication)
11−import Servant (HasServer, Server, serve)
10+import Servant (Context (EmptyContext), HasServer,
11+ Server, serveWithContext)
12import Servant.Client (BaseUrl (..), Scheme (..))
12import Servant.Client (BaseUrl (..), Scheme (..))
13import System.IO.Unsafe (unsafePerformIO)
13import System.IO.Unsafe (unsafePerformIO)
14import Test.Hspec (Expectation, expectationFailure)
14import Test.Hspec (Expectation, expectationFailure)
15import Test.QuickCheck (Args (..), Result (..),
15import Test.QuickCheck (Args (..), Result (..),
16 quickCheckWithResult)
16 quickCheckWithResult)
17−import Test.QuickCheck.Monadic
17+import Test.QuickCheck.Monadic (assert, forAllM, monadicIO, run)
18
18
19import Servant.QuickCheck.Internal.HasGenRequest
19import Servant.QuickCheck.Internal.HasGenRequest
20import Servant.QuickCheck.Internal.Predicates
20import Servant.QuickCheck.Internal.Predicates