@@ -1,258 +0,0 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE DeriveGeneric #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE QuasiQuotes #-}
5−{-# LANGUAGE ScopedTypeVariables #-}
6−{-# LANGUAGE TypeOperators #-}
8−module Servant.ServerSpec where
11−import Control.Monad.Trans.Either
16−import Data.String.Conversions
18−import Network.HTTP.Types
20−import Network.Wai.Test
24−import Servant.API.Capture
25−import Servant.API.Get
26−import Servant.API.ReqBody
27−import Servant.API.Post
28−import Servant.API.QueryParam
29−import Servant.API.Raw
30−import Servant.API.Sub
31−import Servant.API.Alternative
37−data Person = Person {
41− deriving (Eq, Show, Generic)
43−instance ToJSON Person
44−instance FromJSON Person
47−alice = Person "Alice" 42
49−data Animal = Animal {
51− numberOfLegs :: Integer
53− deriving (Eq, Show, Generic)
55−instance ToJSON Animal
56−instance FromJSON Animal
59−jerry = Animal "Mouse" 4
62−tweety = Animal "Bird" 2
77−type CaptureApi = Capture "legs" Integer :> Get Animal
78−captureApi :: Proxy CaptureApi
80−captureServer :: Integer -> EitherT (Int, String) IO Animal
81−captureServer legs = case legs of
84− _ -> left (404, "not found")
88− describe "Servant.API.Capture" $ do
89− with (return (serve captureApi captureServer)) $ do
90− it "can capture parts of the 'pathInfo'" $ do
93− decode' (simpleBody response) `shouldBe` Just tweety
96− (Proxy :: Proxy (Capture "captured" String :> Raw))
97− (\ "captured" request respond ->
98− respond $ responseLBS ok200 [] (cs $ show $ pathInfo request)))) $ do
99− it "strips the captured path snippet from pathInfo" $ do
100− get "/captured/foo" `shouldRespondWith` (fromString (show ["foo" :: String]))
103−type GetApi = Get Person
104−getApi :: Proxy GetApi
109− describe "Servant.API.Get" $ do
110− with (return (serve getApi (return alice))) $ do
111− it "allows to GET a Person" $ do
113− return response `shouldRespondWith` 200
115− decode' (simpleBody response) `shouldBe` Just alice
117− it "throws 405 (wrong method) on POSTs" $ do
118− post "/" "" `shouldRespondWith` 405
121−type QueryParamApi = QueryParam "name" String :> Get Person
122− :<|> "a" :> QueryParams "names" String :> Get Person
123− :<|> "b" :> QueryFlag "capitalize" :> Get Person
125−queryParamApi :: Proxy QueryParamApi
126−queryParamApi = Proxy
128−qpServer :: Server QueryParamApi
129−qpServer = queryParamServer :<|> qpNames :<|> qpCapitalize
131− where qpNames (_:name2:_) = return alice { name = name2 }
132− qpNames _ = return alice
134− qpCapitalize False = return alice
135− qpCapitalize True = return alice { name = map toUpper (name alice) }
137− queryParamServer (Just name) = return alice{name = name}
138− queryParamServer Nothing = return alice
140−queryParamSpec :: Spec
142− describe "Servant.API.QueryParam" $ do
143− it "allows to retrieve simple GET parameters" $
144− (flip runSession) (serve queryParamApi qpServer) $ do
145− let params1 = "?name=bob"
146− response1 <- Network.Wai.Test.request defaultRequest{
147− rawQueryString = params1,
148− queryString = parseQuery params1
151− decode' (simpleBody response1) `shouldBe` Just alice{
155− it "allows to retrieve lists in GET parameters" $
156− (flip runSession) (serve queryParamApi qpServer) $ do
157− let params2 = "?names[]=bob&names[]=john"
158− response2 <- Network.Wai.Test.request defaultRequest{
159− rawQueryString = params2,
160− queryString = parseQuery params2,
164− decode' (simpleBody response2) `shouldBe` Just alice{
168− it "allows to retrieve value-less GET parameters" $
169− (flip runSession) (serve queryParamApi qpServer) $ do
170− let params3 = "?capitalize"
171− response3 <- Network.Wai.Test.request defaultRequest{
172− rawQueryString = params3,
173− queryString = parseQuery params3,
177− decode' (simpleBody response3) `shouldBe` Just alice{
181− let params3' = "?capitalize="
182− response3' <- Network.Wai.Test.request defaultRequest{
183− rawQueryString = params3',
184− queryString = parseQuery params3',
188− decode' (simpleBody response3') `shouldBe` Just alice{
192−type PostApi = ReqBody Person :> Post Integer
193−postApi :: Proxy PostApi
198− describe "Servant.API.Post and .ReqBody" $ do
199− with (return (serve postApi (return . age))) $ do
200− it "allows to POST a Person" $ do
201− post "/" (encode alice) `shouldRespondWith` "42"{
205− it "correctly rejects invalid request bodies with status 400" $ do
206− post "/" "some invalid body" `shouldRespondWith` 400
209−type RawApi = "foo" :> Raw
210−rawApi :: Proxy RawApi
212−rawApplication :: Show a => (Request -> a) -> Application
213−rawApplication f request respond = respond $ responseLBS ok200 [] (cs $ show $ f request)
217− describe "Servant.API.Raw" $ do
218− it "runs applications" $ do
219− (flip runSession) (serve rawApi (rawApplication (const (42 :: Integer)))) $ do
220− response <- Network.Wai.Test.request defaultRequest{
224− simpleBody response `shouldBe` "42"
226− it "gets the pathInfo modified" $ do
227− (flip runSession) (serve rawApi (rawApplication pathInfo)) $ do
228− response <- Network.Wai.Test.request defaultRequest{
229− pathInfo = ["foo", "bar"]
232− simpleBody response `shouldBe` cs (show ["bar" :: String])
235−type AlternativeApi =
237− :<|> "bar" :> Get Animal
238−unionApi :: Proxy AlternativeApi
241−unionServer :: Server AlternativeApi
248− describe "Servant.API.Alternative" $ do
249− with (return $ serve unionApi unionServer) $ do
250− it "unions endpoints" $ do
251− response <- get "/foo"
253− decode' (simpleBody response) `shouldBe`
255− response <- get "/bar"
257− decode' (simpleBody response) `shouldBe`