@@ -15,8 +15,10 @@ import Data.Monoid ((<>))
1515import Data.Proxy (Proxy (Proxy))
1616import Data.String (fromString)
1717import Data.String.Conversions (cs)
18+import qualified Data.Text as T
1819import GHC.Generics (Generic)
19−import Network.HTTP.Types (hContentType, methodDelete,
20+import Network.HTTP.Types (hAccept, hContentType,
21+ methodDelete, methodGet,
2022 methodPatch, methodPost, methodPut,
2123 ok200, parseQuery, status409)
2224import Network.Wai (Application, Request, pathInfo,
@@ -31,8 +33,9 @@ import Test.Hspec.Wai (get, liftIO, matchStatus, post,
3133import Servant.API ((:<|>) (..), (:>), Capture, Delete,
3234 Get, Header, JSON, MatrixFlag,
3335 MatrixParam, MatrixParams, Patch,
34− Post, Put, QueryFlag, QueryParam,
35− QueryParams, Raw, ReqBody)
36+ PlainText, Post, Put, QueryFlag,
37+ QueryParam, QueryParams, Raw,
38+ ReqBody)
3639import Servant.Server (Server, serve)
3740import Servant.Server.Internal (RouteMismatch (..))
3841
@@ -41,7 +44,7 @@ import Servant.Server.Internal (RouteMismatch (..))
4144
4245data Person = Person {
4346 name :: String,
44− age :: Integer
47+ age :: Integer
4548 }
4649 deriving (Eq, Show, Generic)
4750
@@ -52,7 +55,7 @@ alice :: Person
5255alice = Person "Alice" 42
5356
5457data Animal = Animal {
55− species :: String,
58+ species :: String,
5659 numberOfLegs :: Integer
5760 }
5861 deriving (Eq, Show, Generic)
@@ -97,10 +100,13 @@ captureSpec :: Spec
97100captureSpec = do
98101 describe "Servant.API.Capture" $ do
99102 with (return (serve captureApi captureServer)) $ do
103+
100104 it "can capture parts of the 'pathInfo'" $ do
101105 response <- get "/2"
102− liftIO $ do
103− decode' (simpleBody response) `shouldBe` Just tweety
106+ liftIO $ decode' (simpleBody response) `shouldBe` Just tweety
107+
108+ it "returns 404 if the decoding fails" $ do
109+ get "/notAnInt" `shouldRespondWith` 404
104110
105111 with (return (serve
106112 (Proxy :: Proxy (Capture "captured" String :> Raw))
@@ -120,18 +126,23 @@ getSpec = do
120126 describe "Servant.API.Get" $ do
121127 let server = return alice :<|> return ()
122128 with (return $ serve getApi server) $ do
129+
123130 it "allows to GET a Person" $ do
124131 response <- get "/"
125132 return response `shouldRespondWith` 200
126− liftIO $ do
127− decode' (simpleBody response) `shouldBe` Just alice
133+ liftIO $ decode' (simpleBody response) `shouldBe` Just alice
128134
129135 it "throws 405 (wrong method) on POSTs" $ do
130136 post "/" "" `shouldRespondWith` 405
137+ post "/empty" "" `shouldRespondWith` 405
131138
132139 it "returns 204 if the type is '()'" $ do
133140 get "empty" `shouldRespondWith` ""{ matchStatus = 204 }
134141
142+ it "returns 415 if the Accept header is not supported" $ do
143+ Test.Hspec.Wai.request methodGet "" [(hAccept, "crazy/mime")] ""
144+ `shouldRespondWith` 415
145+
135146
136147
137148type QueryParamApi = QueryParam "name" String :> Get '[JSON] Person
@@ -483,6 +494,10 @@ rawSpec = do
483494type AlternativeApi =
484495 "foo" :> Get '[JSON] Person
485496 :<|> "bar" :> Get '[JSON] Animal
497+ :<|> "foo" :> Get '[PlainText] T.Text
498+ :<|> "bar" :> Post '[JSON] Animal
499+ :<|> "bar" :> Put '[JSON] Animal
500+ :<|> "bar" :> Delete
486501unionApi :: Proxy AlternativeApi
487502unionApi = Proxy
488503
@@ -490,11 +505,16 @@ unionServer :: Server AlternativeApi
490505unionServer =
491506 return alice
492507 :<|> return jerry
508+ :<|> return "a string"
509+ :<|> return jerry
510+ :<|> return jerry
511+ :<|> return ()
493512
494513unionSpec :: Spec
495514unionSpec = do
496515 describe "Servant.API.Alternative" $ do
497516 with (return $ serve unionApi unionServer) $ do
517+
498518 it "unions endpoints" $ do
499519 response <- get "/foo"
500520 liftIO $ do
@@ -505,6 +525,12 @@ unionSpec = do
505525 decode' (simpleBody response_) `shouldBe`
506526 Just jerry
507527
528+ it "checks all endpoints before returning 415" $ do
529+ get "/foo" `shouldRespondWith` 200
530+
531+ it "returns 404 if the path does not exist" $ do
532+ get "/nonexistent" `shouldRespondWith` 404
533+
508534-- | Test server error functionality.
509535errorsSpec :: Spec
510536errorsSpec = do