@@ -8,6 +8,8 @@
8{-# OPTIONS_GHC -fcontext-stack=25 #-}
8{-# OPTIONS_GHC -fcontext-stack=25 #-}
9module Servant.ClientSpec where
9module Servant.ClientSpec where
11+import Control.Applicative
12+import qualified Control.Arrow as Arrow
11import Control.Concurrent
13import Control.Concurrent
12import Control.Exception
14import Control.Exception
13import Control.Monad.Trans.Either
15import Control.Monad.Trans.Either
@@ -29,7 +31,6 @@ import Test.Hspec.QuickCheck
29import Test.QuickCheck
31import Test.QuickCheck
31import Servant.API
33import Servant.API
32−import Servant.API.ContentTypes
33import Servant.Client
34import Servant.Client
34import Servant.Server
35import Servant.Server
@@ -110,21 +111,21 @@ server = serve api (
110withServer :: (BaseUrl -> IO a) -> IO a
111withServer :: (BaseUrl -> IO a) -> IO a
111withServer action = withWaiDaemon (return server) action
112withServer action = withWaiDaemon (return server) action
113−getGet :: BaseUrl -> EitherT String IO Person
114+getGet :: BaseUrl -> EitherT ServantError IO Person
114−getDelete :: BaseUrl -> EitherT String IO ()
115+getDelete :: BaseUrl -> EitherT ServantError IO ()
115−getCapture :: String -> BaseUrl -> EitherT String IO Person
116+getCapture :: String -> BaseUrl -> EitherT ServantError IO Person
116−getBody :: Person -> BaseUrl -> EitherT String IO Person
117+getBody :: Person -> BaseUrl -> EitherT ServantError IO Person
117−getQueryParam :: Maybe String -> BaseUrl -> EitherT String IO Person
118+getQueryParam :: Maybe String -> BaseUrl -> EitherT ServantError IO Person
118−getQueryParams :: [String] -> BaseUrl -> EitherT String IO [Person]
119+getQueryParams :: [String] -> BaseUrl -> EitherT ServantError IO [Person]
119−getQueryFlag :: Bool -> BaseUrl -> EitherT String IO Bool
120+getQueryFlag :: Bool -> BaseUrl -> EitherT ServantError IO Bool
120−getMatrixParam :: Maybe String -> BaseUrl -> EitherT String IO Person
121+getMatrixParam :: Maybe String -> BaseUrl -> EitherT ServantError IO Person
121−getMatrixParams :: [String] -> BaseUrl -> EitherT String IO [Person]
122+getMatrixParams :: [String] -> BaseUrl -> EitherT ServantError IO [Person]
122−getMatrixFlag :: Bool -> BaseUrl -> EitherT String IO Bool
123+getMatrixFlag :: Bool -> BaseUrl -> EitherT ServantError IO Bool
123−getRawSuccess :: Method -> BaseUrl -> EitherT String IO (Int, ByteString, MediaType)
124+getRawSuccess :: Method -> BaseUrl -> EitherT ServantError IO (Int, ByteString, MediaType)
124−getRawFailure :: Method -> BaseUrl -> EitherT String IO (Int, ByteString, MediaType)
125+getRawFailure :: Method -> BaseUrl -> EitherT ServantError IO (Int, ByteString, MediaType)
125getMultiple :: String -> Maybe Int -> Bool -> [(String, [Rational])]
126getMultiple :: String -> Maybe Int -> Bool -> [(String, [Rational])]
126 -> BaseUrl
127 -> BaseUrl
127− -> EitherT String IO (String, Maybe Int, Bool, [(String, [Rational])])
128+ -> EitherT ServantError IO (String, Maybe Int, Bool, [(String, [Rational])])
129 :<|> getDelete
130 :<|> getDelete
130 :<|> getCapture
131 :<|> getCapture
@@ -143,32 +144,32 @@ getMultiple :: String -> Maybe Int -> Bool -> [(String, [Rational])]
143spec :: Spec
144spec :: Spec
145 it "Servant.API.Get" $ withServer $ \ host -> do
146 it "Servant.API.Get" $ withServer $ \ host -> do
146− runEitherT (getGet host) `shouldReturn` Right alice
147+ (Arrow.left show <$> runEitherT (getGet host)) `shouldReturn` Right alice
148 it "Servant.API.Delete" $ withServer $ \ host -> do
149 it "Servant.API.Delete" $ withServer $ \ host -> do
149− runEitherT (getDelete host) `shouldReturn` Right ()
150+ (Arrow.left show <$> runEitherT (getDelete host)) `shouldReturn` Right ()
151 it "Servant.API.Capture" $ withServer $ \ host -> do
152 it "Servant.API.Capture" $ withServer $ \ host -> do
152− runEitherT (getCapture "Paula" host) `shouldReturn` Right (Person "Paula" 0)
153+ (Arrow.left show <$> runEitherT (getCapture "Paula" host)) `shouldReturn` Right (Person "Paula" 0)
154 it "Servant.API.ReqBody" $ withServer $ \ host -> do
155 it "Servant.API.ReqBody" $ withServer $ \ host -> do
155 let p = Person "Clara" 42
156 let p = Person "Clara" 42
156− runEitherT (getBody p host) `shouldReturn` Right p
157+ (Arrow.left show <$> runEitherT (getBody p host)) `shouldReturn` Right p
158 it "Servant.API.QueryParam" $ withServer $ \ host -> do
159 it "Servant.API.QueryParam" $ withServer $ \ host -> do
159− runEitherT (getQueryParam (Just "alice") host) `shouldReturn` Right alice
160+ (Arrow.left show <$> runEitherT (getQueryParam (Just "alice") host)) `shouldReturn` Right alice
160− Left result <- runEitherT (getQueryParam (Just "bob") host)
161+ Left (FailureResponse s _ _) <- runEitherT (getQueryParam (Just "bob") host)
161− result `shouldContain` "bob not found"
162+ statusCode s `shouldBe` 400
163 it "Servant.API.QueryParam.QueryParams" $ withServer $ \ host -> do
164 it "Servant.API.QueryParam.QueryParams" $ withServer $ \ host -> do
164− runEitherT (getQueryParams [] host) `shouldReturn` Right []
165+ (Arrow.left show <$> runEitherT (getQueryParams [] host)) `shouldReturn` Right []
165− runEitherT (getQueryParams ["alice", "bob"] host)
166+ (Arrow.left show <$> runEitherT (getQueryParams ["alice", "bob"] host))
166 `shouldReturn` Right [Person "alice" 0, Person "bob" 1]
167 `shouldReturn` Right [Person "alice" 0, Person "bob" 1]
168 context "Servant.API.QueryParam.QueryFlag" $
169 context "Servant.API.QueryParam.QueryFlag" $
169 forM_ [False, True] $ \ flag ->
170 forM_ [False, True] $ \ flag ->
170 it (show flag) $ withServer $ \ host -> do
171 it (show flag) $ withServer $ \ host -> do
171− runEitherT (getQueryFlag flag host) `shouldReturn` Right flag
172+ (Arrow.left show <$> runEitherT (getQueryFlag flag host)) `shouldReturn` Right flag
174 it "Servant.API.MatrixParam" $ withServer $ \ host -> do
175 it "Servant.API.MatrixParam" $ withServer $ \ host -> do
@@ -188,17 +189,19 @@ spec = do
190 it "Servant.API.Raw on success" $ withServer $ \ host -> do
191 it "Servant.API.Raw on success" $ withServer $ \ host -> do
192+ (Arrow.left show <$> runEitherT (getRawSuccess methodGet host))
191− runEitherT (getRawSuccess methodGet host) `shouldReturn` Right (200, "rawSuccess", "application"//"octet-stream")
193+ `shouldReturn` Right (200, "rawSuccess", "application"//"octet-stream")
193 it "Servant.API.Raw on failure" $ withServer $ \ host -> do
195 it "Servant.API.Raw on failure" $ withServer $ \ host -> do
196+ (Arrow.left show <$> runEitherT (getRawFailure methodGet host))
194− runEitherT (getRawFailure methodGet host) `shouldReturn` Right (400, "rawFailure", "application"//"octet-stream")
197+ `shouldReturn` Right (400, "rawFailure", "application"//"octet-stream")
196 modifyMaxSuccess (const 20) $ do
199 modifyMaxSuccess (const 20) $ do
197 it "works for a combination of Capture, QueryParam, QueryFlag and ReqBody" $
200 it "works for a combination of Capture, QueryParam, QueryFlag and ReqBody" $
198 property $ forAllShrink pathGen shrink $ \(NonEmpty cap) num flag body ->
201 property $ forAllShrink pathGen shrink $ \(NonEmpty cap) num flag body ->
199 ioProperty $ do
202 ioProperty $ do
200 withServer $ \ host -> do
203 withServer $ \ host -> do
201− result <- runEitherT (getMultiple cap num flag body host)
204+ result <- Arrow.left show <$> runEitherT (getMultiple cap num flag body host)
203 result === Right (cap, num, flag, body)
206 result === Right (cap, num, flag, body)
@@ -209,10 +212,10 @@ spec = do
209 it desc $
212 it desc $
210 withWaiDaemon (return (serve api (left (500, "error message")))) $
213 withWaiDaemon (return (serve api (left (500, "error message")))) $
211 \ host -> do
214 \ host -> do
212− let getResponse :: BaseUrl -> EitherT String IO ()
215+ let getResponse :: BaseUrl -> EitherT ServantError IO ()
213 getResponse = client api
216 getResponse = client api
214− Left result <- runEitherT (getResponse host)
217+ Left (FailureResponse status _ _) <- runEitherT (getResponse host)
215− result `shouldContain` "error message"
218+ status `shouldBe` (Status 500 "error message")
216 mapM_ test $
219 mapM_ test $
217 (WrappedApi (Proxy :: Proxy Delete), "Delete") :
220 (WrappedApi (Proxy :: Proxy Delete), "Delete") :
218 (WrappedApi (Proxy :: Proxy (Get '[JSON] ())), "Delete") :
221 (WrappedApi (Proxy :: Proxy (Get '[JSON] ())), "Delete") :
@@ -222,7 +225,7 @@ spec = do
223data WrappedApi where
226data WrappedApi where
224 WrappedApi :: (HasServer api, Server api ~ EitherT (Int, String) IO a,
227 WrappedApi :: (HasServer api, Server api ~ EitherT (Int, String) IO a,
225− HasClient api, Client api ~ (BaseUrl -> EitherT String IO ())) =>
228+ HasClient api, Client api ~ (BaseUrl -> EitherT ServantError IO ())) =>
226 Proxy api -> WrappedApi
229 Proxy api -> WrappedApi