@@ -17,57 +17,62 @@
1717
1818module Servant.ServerSpec where
1919
20−import Control.Monad (forM_, when, unless)
21−import Control.Monad.Error.Class (MonadError (..))
22−import Data.Aeson (FromJSON, ToJSON, decode', encode)
23−import qualified Data.ByteString.Base64 as Base64
24−import Data.Char (toUpper)
20+import Control.Monad
21+ (forM_, unless, when)
22+import Control.Monad.Error.Class
23+ (MonadError (..))
24+import Data.Aeson
25+ (FromJSON, ToJSON, decode', encode)
26+import qualified Data.ByteString as BS
27+import qualified Data.ByteString.Base64 as Base64
28+import Data.Char
29+ (toUpper)
2530import Data.Monoid
26−import Data.Proxy (Proxy (Proxy))
27−import Data.String (fromString)
28−import Data.String.Conversions (cs)
29−import qualified Data.Text as T
30−import GHC.Generics (Generic)
31−import Network.HTTP.Types (Status (..), hAccept, hContentType,
32− methodDelete, methodGet,
33− methodHead, methodPatch,
34− methodPost, methodPut, ok200,
35− imATeapot418,
36− parseQuery)
37−import Network.Wai (Application, Request, requestHeaders, pathInfo,
38− queryString, rawQueryString,
39− responseLBS)
40−import Network.Wai.Test (defaultRequest, request,
41− runSession, simpleBody,
42− simpleHeaders, simpleStatus)
43−import Servant.API ((:<|>) (..), (:>), AuthProtect,
44− BasicAuth, BasicAuthData(BasicAuthData),
45− Capture, CaptureAll, Delete, Get, Header,
46− Headers, HttpVersion,
47− IsSecure (..), JSON,
48− NoContent (..), Patch, PlainText,
49− Post, Put, EmptyAPI,
50− QueryFlag, QueryParam, QueryParams,
51− Raw, RemoteHost, ReqBody,
52− StdMethod (..), Verb, addHeader)
31+import Data.Proxy
32+ (Proxy (Proxy))
33+import Data.String
34+ (fromString)
35+import Data.String.Conversions
36+ (cs)
37+import qualified Data.Text as T
38+import GHC.Generics
39+ (Generic)
40+import Network.HTTP.Types
41+ (Status (..), hAccept, hContentType, imATeapot418,
42+ methodDelete, methodGet, methodHead, methodPatch, methodPost,
43+ methodPut, ok200, parseQuery)
44+import Network.Wai
45+ (Application, Request, pathInfo, queryString, rawQueryString,
46+ requestHeaders, responseLBS)
47+import Network.Wai.Test
48+ (defaultRequest, request, runSession, simpleBody,
49+ simpleHeaders, simpleStatus)
50+import Servant.API
51+ ((:<|>) (..), (:>), AuthProtect, BasicAuth,
52+ BasicAuthData (BasicAuthData), Capture, CaptureAll, Delete,
53+ EmptyAPI, Get, Header, Headers, HttpVersion, IsSecure (..),
54+ JSON, NoContent (..), NoFraming, OctetStream, Patch,
55+ PlainText, Post, Put, QueryFlag, QueryParam, QueryParams, Raw,
56+ RemoteHost, ReqBody, StdMethod (..), Stream,
57+ StreamGenerator (..), Verb, addHeader)
5358import Servant.API.Internal.Test.ComprehensiveAPI
54−import Servant.Server (Server, Handler, Tagged (..), err401, err403,
55− err404, serve, serveWithContext,
56− Context((:.), EmptyContext), emptyServer)
57−import Test.Hspec (Spec, context, describe, it,
58− shouldBe, shouldContain)
59−import qualified Test.Hspec.Wai as THW
60−import Test.Hspec.Wai (get, liftIO, matchHeaders,
61− matchStatus, shouldRespondWith,
62− with, (<:>))
63−
64−import Servant.Server.Internal.BasicAuth (BasicAuthCheck(BasicAuthCheck),
65− BasicAuthResult(Authorized,Unauthorized))
59+import Servant.Server
60+ (Context ((:.), EmptyContext), Handler, Server, Tagged (..),
61+ emptyServer, err401, err403, err404, serve, serveWithContext)
62+import Test.Hspec
63+ (Spec, context, describe, it, shouldBe, shouldContain)
64+import Test.Hspec.Wai
65+ (get, liftIO, matchHeaders, matchStatus, shouldRespondWith,
66+ with, (<:>))
67+import qualified Test.Hspec.Wai as THW
68+
6669import Servant.Server.Experimental.Auth
67− (AuthHandler, AuthServerData,
68− mkAuthHandler)
70+ (AuthHandler, AuthServerData, mkAuthHandler)
71+import Servant.Server.Internal.BasicAuth
72+ (BasicAuthCheck (BasicAuthCheck),
73+ BasicAuthResult (Authorized, Unauthorized))
6974import Servant.Server.Internal.Context
70− (NamedContext(..))
75+ (NamedContext (..))
7176
7277-- * comprehensive api test
7378
@@ -105,6 +110,7 @@ type VerbApi method status
105110 :<|> "accept" :> ( Verb method status '[JSON] Person
106111 :<|> Verb method status '[PlainText] String
107112 )
113+ :<|> "stream" :> Stream method status NoFraming OctetStream (StreamGenerator BS.ByteString)
108114
109115verbSpec :: Spec
110116verbSpec = describe "Servant.API.Verb" $ do
@@ -114,6 +120,8 @@ verbSpec = describe "Servant.API.Verb" $ do
114120 :<|> return (addHeader 5 alice)
115121 :<|> return (addHeader 10 NoContent)
116122 :<|> (return alice :<|> return "B")
123+ :<|> return (StreamGenerator $ \f _ -> f "bytestring")
124+
117125 get200 = Proxy :: Proxy (VerbApi 'GET 200)
118126 post210 = Proxy :: Proxy (VerbApi 'POST 210)
119127 put203 = Proxy :: Proxy (VerbApi 'PUT 203)
@@ -179,6 +187,11 @@ verbSpec = describe "Servant.API.Verb" $ do
179187 liftIO $ simpleHeaders response `shouldContain`
180188 [("Content-Type", "application/json;charset=utf-8")]
181189
190+ it "works for Stream as for Result" $ do
191+ response <- THW.request method "/stream" [] ""
192+ liftIO $ statusCode (simpleStatus response) `shouldBe` status
193+ liftIO $ simpleBody response `shouldBe` "bytestring"
194+
182195 test "GET 200" get200 methodGet 200
183196 test "POST 210" post210 methodPost 210
184197 test "PUT 203" put203 methodPut 203