Documentation improvements

This commit is contained in:
Julian K. Arni 2016-04-25 12:31:47 +02:00
parent fe1d87df85
commit b5ee965d1c
3 changed files with 66 additions and 39 deletions

View File

@ -6,14 +6,37 @@
-- tested itself need not be implemented with @servant-server@ (or indeed, -- tested itself need not be implemented with @servant-server@ (or indeed,
-- written in Haskell). -- written in Haskell).
-- --
-- The documentation of the <#useful-preds Useful predicates> sections is
-- meant to serve as a set of helpful pointers for learning more about best
-- practices concerning REST APIs.
module Servant.QuickCheck module Servant.QuickCheck
( (
-- * Property testing
-- * Test setup helpers serverSatisfies
-- | Helpers to setup and teardown @servant@ servers during tests. -- ** Predicates
withServantServer -- *** #useful-preds# Useful predicates
-- | The predicates below are often useful. Some check RFC compliance; some are
-- best practice, and some are useful to check that APIs follow in-house
-- best-practices. Included in the documentation for each is a list of
-- references to any relevant RFCs and other links, as well as what type of
-- predicate it is (__RFC Compliance__, __Best Practice__, __Optional__).
--
-- RFCs distinguish between the force of requirements (e.g. __MUST__ vs.
-- __SHOULD__). __RFC Compliance__ includes any absolute requirements present
-- in RFCs. The __Best Practices__ includes, in addition to RFC
-- recommendations, recommendations found elsewhere or generally accepted.
, not500
, onlyJsonObjects
, notAllowedContainsAllowHeader
, unauthorizedContainsWWWAuthenticate
, getsHaveCacheControlHeader
, headsHaveCacheControlHeader
-- *** Predicate utilities and types
, (<%>)
, Predicates
, ResponsePredicate(..)
, RequestPredicate(..)
-- * Equality testing -- * Equality testing
, serversEqual , serversEqual
@ -28,19 +51,10 @@ module Servant.QuickCheck
-- ** Response equality type -- ** Response equality type
, ResponseEquality(..) , ResponseEquality(..)
-- * Property testing -- * Test setup helpers
, serverSatisfies -- | Helpers to setup and teardown @servant@ servers during tests.
-- ** Predicates , withServantServer
-- *** Useful predicates , withServantServerAndContext
, not500
, onlyJsonObjects
, notAllowedContainsAllowHeader
, unauthorizedContainsWWWAuthenticate
-- *** Predicate utilities and types
, (<%>)
, Predicates
, ResponsePredicate(..)
, RequestPredicate(..)
-- ** Re-exports -- ** Re-exports
, BaseUrl(..) , BaseUrl(..)

View File

@ -1,22 +1,28 @@
{-# LANGUAGE MultiWayIf #-}
module Servant.QuickCheck.Internal.Predicates where module Servant.QuickCheck.Internal.Predicates where
import Control.Monad import Control.Monad
import Data.Aeson (Object, decode) import Data.Aeson (Object, decode)
import Data.Bifunctor (Bifunctor (..)) import Data.Bifunctor (Bifunctor (..))
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString as SBS
import qualified Data.ByteString as SBS
import qualified Data.ByteString.Char8 as SBSC import qualified Data.ByteString.Char8 as SBSC
import Data.CaseInsensitive (mk) import qualified Data.ByteString.Lazy as LBS
import Data.Either (isRight) import Data.CaseInsensitive (mk)
import Data.List.Split (wordsBy) import Data.Either (isRight)
import Data.Monoid ((<>)) import Data.List.Split (wordsBy)
import Data.Text (Text) import Data.Maybe (isJust)
import GHC.Generics (Generic) import Data.Monoid ((<>))
import Network.HTTP.Client (Manager, Request, Response, httpLbs, import Data.Text (Text)
responseBody, responseStatus, responseHeaders) import GHC.Generics (Generic)
import Network.HTTP.Types (status500, status405, status401, parseMethod) import Network.HTTP.Client (Manager, Request, Response, httpLbs,
method, responseBody, responseHeaders,
responseStatus)
import Network.HTTP.Types (methodGet, methodHead, parseMethod,
status401, renderStdMethod, status405, status500)
-- | @500 Internal Server Error@ should be avoided - it may represent some -- | [__Best Practice__]
--
-- @500 Internal Server Error@ should be avoided - it may represent some
-- issue with the application code, and it moreover gives the client little -- issue with the application code, and it moreover gives the client little
-- indication of how to proceed or what went wrong. -- indication of how to proceed or what went wrong.
-- --
@ -24,7 +30,9 @@ import Network.HTTP.Types (status500, status405, status401, parseMet
not500 :: ResponsePredicate Text Bool not500 :: ResponsePredicate Text Bool
not500 = ResponsePredicate "not500" (\resp -> not $ responseStatus resp == status500) not500 = ResponsePredicate "not500" (\resp -> not $ responseStatus resp == status500)
-- | Returning anything other than an object when returning JSON is considered -- | [__Best Practice__]
--
-- Returning anything other than an object when returning JSON is considered
-- bad practice, as: -- bad practice, as:
-- --
-- (1) it is hard to modify the returned value while maintaining backwards -- (1) it is hard to modify the returned value while maintaining backwards
@ -66,8 +74,11 @@ getsHaveLastModifiedHeader
-} -}
-- | When an HTTP request has a method that is not allowed, a 405 response -- | [__RFC Compliance__]
-- should be returned. Additionally, it is good practice to return an @Allow@ --
-- When an HTTP request has a method that is not allowed,
-- a 405 response should be returned. Additionally, it is good practice to
-- return an @Allow@
-- header with the list of allowed methods. -- header with the list of allowed methods.
-- --
-- This function checks that every @405 Method Not Allowed@ response contains -- This function checks that every @405 Method Not Allowed@ response contains
@ -163,7 +174,9 @@ linkHeadersAreValid
= ResponsePredicate "linkHeadersAreValid" _ = ResponsePredicate "linkHeadersAreValid" _
-} -}
-- | Any @401 Unauthorized@ response must include a @WWW-Authenticate@ header. -- | [__RFC Compliance__]
--
-- Any @401 Unauthorized@ response must include a @WWW-Authenticate@ header.
-- --
-- This function checks that, if a response has status code 401, it contains a -- This function checks that, if a response has status code 401, it contains a
-- @WWW-Authenticate@ header. -- @WWW-Authenticate@ header.

View File

@ -1,4 +1,3 @@
-- | This module contains wrappers around lower-level functionality.
module Servant.QuickCheck.Internal.QuickCheck where module Servant.QuickCheck.Internal.QuickCheck where
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy as LBS
@ -8,13 +7,14 @@ import Network.HTTP.Client (Manager, Request, checkStatus,
defaultManagerSettings, httpLbs, defaultManagerSettings, httpLbs,
newManager) newManager)
import Network.Wai.Handler.Warp (withApplication) import Network.Wai.Handler.Warp (withApplication)
import Servant (HasServer, Server, serve) import Servant (Context (EmptyContext), HasServer,
Server, serveWithContext)
import Servant.Client (BaseUrl (..), Scheme (..)) import Servant.Client (BaseUrl (..), Scheme (..))
import System.IO.Unsafe (unsafePerformIO) import System.IO.Unsafe (unsafePerformIO)
import Test.Hspec (Expectation, expectationFailure) import Test.Hspec (Expectation, expectationFailure)
import Test.QuickCheck (Args (..), Result (..), import Test.QuickCheck (Args (..), Result (..),
quickCheckWithResult) quickCheckWithResult)
import Test.QuickCheck.Monadic import Test.QuickCheck.Monadic (assert, forAllM, monadicIO, run)
import Servant.QuickCheck.Internal.HasGenRequest import Servant.QuickCheck.Internal.HasGenRequest
import Servant.QuickCheck.Internal.Predicates import Servant.QuickCheck.Internal.Predicates