@@ -12,23 +12,33 @@ import Data.Maybe (fromJust)
12import Network.HTTP.Client (path, queryString)
12import Network.HTTP.Client (path, queryString)
13import Prelude.Compat
13import Prelude.Compat
14import Servant
14import Servant
15−import Servant.HTML.Blaze (HTML)
16−import qualified Text.Blaze.Html as Blaze
17−import qualified Text.Blaze.Html5 as Blaze5
18import Test.Hspec (Spec, context, describe, it, shouldBe,
15import Test.Hspec (Spec, context, describe, it, shouldBe,
19 shouldContain)
16 shouldContain)
20−import Test.Hspec.Core.Spec (Arg, Example, Result (..), ResultStatus (..),
17+import Test.Hspec.Core.Spec (Arg, Example, Result (..),
21− defaultParams, safeEvaluateExample)
18+ defaultParams)
22import Test.QuickCheck.Gen (generate, unGen)
19import Test.QuickCheck.Gen (generate, unGen)
23import Test.QuickCheck.Random (mkQCGen)
20import Test.QuickCheck.Random (mkQCGen)
23+#if MIN_VERSION_servant(0,8,0)
26−import Servant.Test.ComprehensiveAPI (comprehensiveAPIWithoutStreamingOrRaw)
24+import Servant.API.Internal.Test.ComprehensiveAPI (comprehensiveAPIWithoutRaw)
26+import Servant.API.Internal.Test.ComprehensiveAPI (ComprehensiveAPI,
30+#if MIN_VERSION_hspec(2,4,0)
31+import Test.Hspec.Core.Spec (safeEvaluateExample)
33+import Control.Exception (try)
34+import Test.Hspec.Core.Spec (evaluateExample)
28import Servant.QuickCheck
37import Servant.QuickCheck
29import Servant.QuickCheck.Internal (genRequest, runGenRequest,
38import Servant.QuickCheck.Internal (genRequest, runGenRequest,
30 serverDoesntSatisfy)
39 serverDoesntSatisfy)
32spec :: Spec
42spec :: Spec
34 serversEqualSpec
44 serversEqualSpec
@@ -39,7 +49,6 @@ spec = do
39 queryParamsSpec
49 queryParamsSpec
40 queryFlagsSpec
50 queryFlagsSpec
41 deepPathSpec
51 deepPathSpec
43 unbiasedGenerationSpec
52 unbiasedGenerationSpec
45serversEqualSpec :: Spec
54serversEqualSpec :: Spec
@@ -63,9 +72,9 @@ serversEqualSpec = describe "serversEqual" $ do
63 context "when JSON is equal but looks a bit different as a ByteString" $ do
72 context "when JSON is equal but looks a bit different as a ByteString" $ do
65 it "sanity check: different whitespace same JSON objects bodyEquality fails" $ do
74 it "sanity check: different whitespace same JSON objects bodyEquality fails" $ do
66− FailedWith err <- withServantServer jsonApi jsonServer1 $ \burl1 ->
75+ Right (Failure _ err) <- withServantServer jsonApi jsonServer1 $ \burl1 ->
67 withServantServer jsonApi jsonServer2 $ \burl2 -> do
76 withServantServer jsonApi jsonServer2 $ \burl2 -> do
68− evalExample $ serversEqual jsonApi burl1 burl2 args bodyEquality
77+ safeEvalExample $ serversEqual jsonApi burl1 burl2 args bodyEquality
69 show err `shouldContain` "Server equality failed"
78 show err `shouldContain` "Server equality failed"
71 it "jsonEquality considers equal JSON apis equal regardless of key ordering or whitespace" $ do
80 it "jsonEquality considers equal JSON apis equal regardless of key ordering or whitespace" $ do
@@ -74,16 +83,16 @@ serversEqualSpec = describe "serversEqual" $ do
74 serversEqual jsonApi burl1 burl2 args jsonEquality
83 serversEqual jsonApi burl1 burl2 args jsonEquality
76 it "sees when JSON apis are not equal because any value is different" $ do
85 it "sees when JSON apis are not equal because any value is different" $ do
77− FailedWith err <- withServantServer jsonApi jsonServer2 $ \burl1 ->
86+ Right (Failure _ err) <- withServantServer jsonApi jsonServer2 $ \burl1 ->
78 withServantServer jsonApi jsonServer3 $ \burl2 -> do
87 withServantServer jsonApi jsonServer3 $ \burl2 -> do
79− evalExample $ serversEqual jsonApi burl1 burl2 args jsonEquality
88+ safeEvalExample $ serversEqual jsonApi burl1 burl2 args jsonEquality
80 show err `shouldContain` "Server equality failed"
89 show err `shouldContain` "Server equality failed"
81 show err `shouldContain` "Path: /jsonComparison"
90 show err `shouldContain` "Path: /jsonComparison"
83 it "sees when JSON apis are not equal due to different keys but same values" $ do
92 it "sees when JSON apis are not equal due to different keys but same values" $ do
84− FailedWith err <- withServantServer jsonApi jsonServer2 $ \burl1 ->
93+ Right (Failure _ err) <- withServantServer jsonApi jsonServer2 $ \burl1 ->
85 withServantServer jsonApi jsonServer4 $ \burl2 -> do
94 withServantServer jsonApi jsonServer4 $ \burl2 -> do
86− evalExample $ serversEqual jsonApi burl1 burl2 args jsonEquality
95+ safeEvalExample $ serversEqual jsonApi burl1 burl2 args jsonEquality
87 show err `shouldContain` "Server equality failed"
96 show err `shouldContain` "Server equality failed"
88 show err `shouldContain` "Path: /jsonComparison"
97 show err `shouldContain` "Path: /jsonComparison"
@@ -128,10 +137,6 @@ onlyJsonObjectSpec = describe "onlyJsonObjects" $ do
128 withServantServerAndContext octetAPI ctx serverOctetAPI $ \burl ->
137 withServantServerAndContext octetAPI ctx serverOctetAPI $ \burl ->
129 serverSatisfies octetAPI burl args (onlyJsonObjects <%> mempty)
138 serverSatisfies octetAPI burl args (onlyJsonObjects <%> mempty)
131− it "does not fail when there is no content-type" $ do
132− withServantServerAndContext api2 ctx serverFailing $ \burl ->
133− serverSatisfies api2 burl args (onlyJsonObjects <%> mempty)
135notLongerThanSpec :: Spec
140notLongerThanSpec :: Spec
136notLongerThanSpec = describe "notLongerThan" $ do
141notLongerThanSpec = describe "notLongerThan" $ do
@@ -149,7 +154,7 @@ isComprehensiveSpec :: Spec
149isComprehensiveSpec = describe "HasGenRequest" $ do
154isComprehensiveSpec = describe "HasGenRequest" $ do
151 it "has instances for all 'servant' combinators" $ do
156 it "has instances for all 'servant' combinators" $ do
152− let _g = genRequest comprehensiveAPIWithoutStreamingOrRaw
157+ let _g = genRequest comprehensiveAPIWithoutRaw
153 True `shouldBe` True -- This is a type-level check
158 True `shouldBe` True -- This is a type-level check
155deepPathSpec :: Spec
160deepPathSpec :: Spec
@@ -185,25 +190,6 @@ queryFlagsSpec = describe "QueryFlags" $ do
185 qs = C.unpack $ queryString req
190 qs = C.unpack $ queryString req
186 qs `shouldBe` "one&two"
191 qs `shouldBe` "one&two"
188−htmlDocTypesSpec :: Spec
189−htmlDocTypesSpec = describe "HtmlDocTypes" $ do
191− it "fails HTML without doctype correctly" $ do
192− err <- withServantServerAndContext docTypeApi ctx noDocTypeServer $ \burl -> do
193− evalExample $ serverSatisfies docTypeApi burl args
194− (htmlIncludesDoctype <%> mempty)
195− show err `shouldContain` "htmlIncludesDoctype"
197− it "passes HTML with a doctype at start" $ do
198− withServantServerAndContext docTypeApi ctx docTypeServer $ \burl ->
199− serverSatisfies docTypeApi burl args (htmlIncludesDoctype <%> mempty)
201− it "accepts json endpoints and passes over them in silence" $ do
202− withServantServerAndContext api ctx server $ \burl -> do
203− serverSatisfies (Proxy :: Proxy (Get '[JSON] Int)) burl args
204− (htmlIncludesDoctype <%> mempty)
207makeRandomRequest :: Proxy LargeAPI -> BaseUrl -> IO Integer
193makeRandomRequest :: Proxy LargeAPI -> BaseUrl -> IO Integer
208makeRandomRequest large burl = do
194makeRandomRequest large burl = do
209 req <- generate $ runGenRequest large
195 req <- generate $ runGenRequest large
@@ -273,23 +259,7 @@ server2 = return $ return 1
273server3 :: IO (Server API2)
259server3 :: IO (Server API2)
274server3 = return $ return 2
260server3 = return $ return 2
276−serverFailing :: IO (Server API2)
277−serverFailing = return . throwError $ err405
280−type HtmlDoctype = Get '[HTML] Blaze.Html
282−docTypeApi :: Proxy HtmlDoctype
285−docTypeServer :: IO (Server HtmlDoctype)
286−docTypeServer = pure $ pure $ Blaze5.docTypeHtml $ Blaze5.span "Hello Test!"
288−noDocTypeServer :: IO (Server HtmlDoctype)
289−noDocTypeServer = pure $ pure $ Blaze.text "Hello Test!"
292−-- Api for unbiased generation of requests tests
293largeApi :: Proxy LargeAPI
263largeApi :: Proxy LargeAPI
294largeApi = Proxy
264largeApi = Proxy
@@ -344,14 +314,27 @@ ctx = BasicAuthCheck (const . return $ NoSuchUser) :. EmptyContext
345------------------------------------------------------------------------------
315------------------------------------------------------------------------------
346evalExample :: (Example e, Arg e ~ ()) => e -> IO EvalResult
316evalExample :: (Example e, Arg e ~ ()) => e -> IO EvalResult
317+#if MIN_VERSION_hspec(2,4,0)
347evalExample e = do
318evalExample e = do
348 r <- safeEvaluateExample e defaultParams ($ ()) progCallback
319 r <- safeEvaluateExample e defaultParams ($ ()) progCallback
349− case resultStatus r of
320+ case r of
321+ Left err -> return $ AnException err
350− Success -> return $ AllGood
322+ Right Success -> return $ AllGood
351− Failure _ reason -> return $ FailedWith $ show reason
323+ Right (Failure _ reason) -> return $ FailedWith $ show reason
324+ Right (Pending _) -> error "should not happen"
326+ progCallback _ = return ()
329+ r <- try $ evaluateExample e defaultParams ($ ()) progCallback
331+ Left err -> return $ AnException err
332+ Right Success -> return $ AllGood
333+ Right (Fail _ reason) -> return $ FailedWith reason
352− Pending {} -> error "should not happen"
334+ Right (Pending _) -> error "should not happen"
354 progCallback _ = return ()
336 progCallback _ = return ()
356data EvalResult
339data EvalResult
357 = AnException SomeException
340 = AnException SomeException
@@ -369,3 +352,8 @@ noOfTestCases = 20000
370noOfTestCases = 1000
353noOfTestCases = 1000
356+#if !MIN_VERSION_servant(0,8,0)
357+comprehensiveAPIWithoutRaw :: Proxy ComprehensiveAPI
358+comprehensiveAPIWithoutRaw = comprehensiveAPI