on master help sign in
Fix tests (URI -> Link)
2b12436Oleg Grenrus
servant/CHANGELOG.md+1−1
@@ -5,7 +5,7 @@
5 ([#616](https://github.com/haskell-servant/servant/issues/616))
5 ([#616](https://github.com/haskell-servant/servant/issues/616))
6
6
7* Change to `MkLink (Verb ...) = Link` (previously `URI`). To consume `Link`
7* Change to `MkLink (Verb ...) = Link` (previously `URI`). To consume `Link`
8− use its `ToHttpApiData` instance.
8+ use its `ToHttpApiData` instance or `linkURI`.
9 ([#527](https://github.com/haskell-servant/servant/issues/527))
9 ([#527](https://github.com/haskell-servant/servant/issues/527))
10
10
110.9.1
110.9.1
servant/src/Servant/API.hs+1−1
@@ -101,7 +101,7 @@ import Servant.API.Verbs (PostCreated, Delete, DeleteAccepte
101 ReflectMethod (reflectMethod),
101 ReflectMethod (reflectMethod),
102 Verb, StdMethod(..))
102 Verb, StdMethod(..))
103import Servant.API.WithNamedContext (WithNamedContext)
103import Servant.API.WithNamedContext (WithNamedContext)
104−import Servant.Utils.Links (HasLink (..), IsElem, IsElem',
104+import Servant.Utils.Links (HasLink (..), Link, IsElem, IsElem',
105 URI (..), safeLink)
105 URI (..), safeLink)
106import Web.HttpApiData (FromHttpApiData (..),
106import Web.HttpApiData (FromHttpApiData (..),
107 ToHttpApiData (..))
107 ToHttpApiData (..))
servant/src/Servant/Utils/Links.hs+14−12
@@ -30,7 +30,7 @@
30-- you would like to restrict links to. The second argument is the destination
30-- you would like to restrict links to. The second argument is the destination
31-- endpoint you would like the link to point to, this will need to end with a
31-- endpoint you would like the link to point to, this will need to end with a
32-- verb like GET or POST. Further arguments may be required depending on the
32-- verb like GET or POST. Further arguments may be required depending on the
33−-- type of the endpoint. If everything lines up you will get a 'URI' out the
33+-- type of the endpoint. If everything lines up you will get a 'Link' out the
34-- other end.
34-- other end.
35--
35--
36-- You may omit 'QueryParam's and the like should you not want to provide them,
36-- You may omit 'QueryParam's and the like should you not want to provide them,
@@ -41,19 +41,19 @@
41-- with an example. Here, a link is generated with no parameters:
41-- with an example. Here, a link is generated with no parameters:
42--
42--
43-- >>> let hello = Proxy :: Proxy ("hello" :> Get '[JSON] Int)
43-- >>> let hello = Proxy :: Proxy ("hello" :> Get '[JSON] Int)
44−-- >>> print (safeLink api hello :: URI)
44+-- >>> toUrlPiece (safeLink api hello :: Link)
45−-- hello
45+-- "hello"
46--
46--
47-- If the API has an endpoint with parameters then we can generate links with
47-- If the API has an endpoint with parameters then we can generate links with
48-- or without those:
48-- or without those:
49--
49--
50-- >>> let with = Proxy :: Proxy ("bye" :> QueryParam "name" String :> Delete '[JSON] NoContent)
50-- >>> let with = Proxy :: Proxy ("bye" :> QueryParam "name" String :> Delete '[JSON] NoContent)
51−-- >>> print $ safeLink api with (Just "Hubert")
51+-- >>> toUrlPiece $ safeLink api with (Just "Hubert")
52−-- bye?name=Hubert
52+-- "bye?name=Hubert"
53--
53--
54-- >>> let without = Proxy :: Proxy ("bye" :> Delete '[JSON] NoContent)
54-- >>> let without = Proxy :: Proxy ("bye" :> Delete '[JSON] NoContent)
55−-- >>> print $ safeLink api without
55+-- >>> toUrlPiece $ safeLink api without
56−-- bye
56+-- "bye"
57--
57--
58-- If you would like create a helper for generating links only within that API,
58-- If you would like create a helper for generating links only within that API,
59-- you can partially apply safeLink if you specify a correct type signature
59-- you can partially apply safeLink if you specify a correct type signature
@@ -94,11 +94,11 @@ module Servant.Utils.Links (
94 , Or
94 , Or
95) where
95) where
96
96
97−import qualified Data.ByteString.Char8 as BSC
98import Data.List
97import Data.List
99import Data.Monoid.Compat ( (<>) )
98import Data.Monoid.Compat ( (<>) )
100import Data.Proxy ( Proxy(..) )
99import Data.Proxy ( Proxy(..) )
101import qualified Data.Text as Text
100import qualified Data.Text as Text
101+import qualified Data.Text.Encoding as TE
102import GHC.Exts (Constraint)
102import GHC.Exts (Constraint)
103import GHC.TypeLits ( KnownSymbol, symbolVal )
103import GHC.TypeLits ( KnownSymbol, symbolVal )
104import Network.URI ( URI(..), escapeURIString, isUnreserved )
104import Network.URI ( URI(..), escapeURIString, isUnreserved )
@@ -126,8 +126,10 @@ data Link = Link
126 } deriving Show
126 } deriving Show
127
127
128instance ToHttpApiData Link where
128instance ToHttpApiData Link where
129− toUrlPiece = Text.pack . show
129+ toHeader = TE.encodeUtf8 . toUrlPiece
130− toHeader = BSC.pack . show
130+ toUrlPiece l =
131+ let uri = linkURI l
132+ in Text.pack $ uriPath uri ++ uriQuery uri
131
133
132-- | If either a or b produce an empty constraint, produce an empty constraint.
134-- | If either a or b produce an empty constraint, produce an empty constraint.
133type family Or (a :: Constraint) (b :: Constraint) :: Constraint where
135type family Or (a :: Constraint) (b :: Constraint) :: Constraint where
@@ -311,5 +313,5 @@ instance HasLink (Verb m s ct a) where
311 toLink _ = id
313 toLink _ = id
312
314
313instance HasLink Raw where
315instance HasLink Raw where
314− type MkLink Raw = URI
316+ type MkLink Raw = Link
315− toLink _ = linkURI
317+ toLink _ = id
servant/test/Servant/Utils/LinksSpec.hs+16−15
@@ -7,6 +7,7 @@ module Servant.Utils.LinksSpec where
7import Data.Proxy (Proxy (..))
7import Data.Proxy (Proxy (..))
8import Test.Hspec (Expectation, Spec, describe, it,
8import Test.Hspec (Expectation, Spec, describe, it,
9 shouldBe)
9 shouldBe)
10+import Data.String (fromString)
10
11
11import Servant.API
12import Servant.API
12
13
@@ -32,38 +33,38 @@ apiLink = safeLink (Proxy :: Proxy TestApi)
32
33
33-- | Convert a link to a URI and ensure that this maps to the given string
34-- | Convert a link to a URI and ensure that this maps to the given string
34-- given string
35-- given string
35−shouldBeURI :: URI -> String -> Expectation
36+shouldBeLink :: Link -> String -> Expectation
36−shouldBeURI link expected =
37+shouldBeLink link expected =
37− show link `shouldBe` expected
38+ toUrlPiece link `shouldBe` fromString expected
38
39
39spec :: Spec
40spec :: Spec
40spec = describe "Servant.Utils.Links" $ do
41spec = describe "Servant.Utils.Links" $ do
41 it "generates correct links for capture query params" $ do
42 it "generates correct links for capture query params" $ do
42 let l1 = Proxy :: Proxy ("hello" :> Capture "name" String :> Delete '[JSON] NoContent)
43 let l1 = Proxy :: Proxy ("hello" :> Capture "name" String :> Delete '[JSON] NoContent)
43− apiLink l1 "hi" `shouldBeURI` "hello/hi"
44+ apiLink l1 "hi" `shouldBeLink` "hello/hi"
44
45
45 let l2 = Proxy :: Proxy ("hello" :> Capture "name" String
46 let l2 = Proxy :: Proxy ("hello" :> Capture "name" String
46 :> QueryParam "capital" Bool
47 :> QueryParam "capital" Bool
47 :> Delete '[JSON] NoContent)
48 :> Delete '[JSON] NoContent)
48− apiLink l2 "bye" (Just True) `shouldBeURI` "hello/bye?capital=true"
49+ apiLink l2 "bye" (Just True) `shouldBeLink` "hello/bye?capital=true"
49
50
50 it "generates correct links for CaptureAll" $ do
51 it "generates correct links for CaptureAll" $ do
51 apiLink (Proxy :: Proxy ("all" :> CaptureAll "names" String :> Get '[JSON] NoContent))
52 apiLink (Proxy :: Proxy ("all" :> CaptureAll "names" String :> Get '[JSON] NoContent))
52 ["roads", "lead", "to", "rome"]
53 ["roads", "lead", "to", "rome"]
53− `shouldBeURI` "all/roads/lead/to/rome"
54+ `shouldBeLink` "all/roads/lead/to/rome"
54
55
55 it "generates correct links for query flags" $ do
56 it "generates correct links for query flags" $ do
56 let l1 = Proxy :: Proxy ("balls" :> QueryFlag "bouncy"
57 let l1 = Proxy :: Proxy ("balls" :> QueryFlag "bouncy"
57 :> QueryFlag "fast" :> Delete '[JSON] NoContent)
58 :> QueryFlag "fast" :> Delete '[JSON] NoContent)
58− apiLink l1 True True `shouldBeURI` "balls?bouncy&fast"
59+ apiLink l1 True True `shouldBeLink` "balls?bouncy&fast"
59− apiLink l1 False True `shouldBeURI` "balls?fast"
60+ apiLink l1 False True `shouldBeLink` "balls?fast"
60
61
61 it "generates correct links for all of the verbs" $ do
62 it "generates correct links for all of the verbs" $ do
62− apiLink (Proxy :: Proxy ("get" :> Get '[JSON] NoContent)) `shouldBeURI` "get"
63+ apiLink (Proxy :: Proxy ("get" :> Get '[JSON] NoContent)) `shouldBeLink` "get"
63− apiLink (Proxy :: Proxy ("put" :> Put '[JSON] NoContent)) `shouldBeURI` "put"
64+ apiLink (Proxy :: Proxy ("put" :> Put '[JSON] NoContent)) `shouldBeLink` "put"
64− apiLink (Proxy :: Proxy ("post" :> Post '[JSON] NoContent)) `shouldBeURI` "post"
65+ apiLink (Proxy :: Proxy ("post" :> Post '[JSON] NoContent)) `shouldBeLink` "post"
65− apiLink (Proxy :: Proxy ("delete" :> Delete '[JSON] NoContent)) `shouldBeURI` "delete"
66+ apiLink (Proxy :: Proxy ("delete" :> Delete '[JSON] NoContent)) `shouldBeLink` "delete"
66− apiLink (Proxy :: Proxy ("raw" :> Raw)) `shouldBeURI` "raw"
67+ apiLink (Proxy :: Proxy ("raw" :> Raw)) `shouldBeLink` "raw"
67
68
68
69
69-- |
70-- |
@@ -96,8 +97,8 @@ spec = describe "Servant.Utils.Links" $ do
96-- ...
97-- ...
97--
98--
98-- sanity check
99-- sanity check
99−-- >>> apiLink (Proxy :: Proxy AllGood)
100+-- >>> toUrlPiece $ apiLink (Proxy :: Proxy AllGood)
100−-- get
101+-- "get"
101type WrongPath = "getTypo" :> Get '[JSON] NoContent
102type WrongPath = "getTypo" :> Get '[JSON] NoContent
102type WrongReturnType = "get" :> Get '[JSON] Bool
103type WrongReturnType = "get" :> Get '[JSON] Bool
103type WrongContentType = "get" :> Get '[OctetStream] NoContent
104type WrongContentType = "get" :> Get '[OctetStream] NoContent