Some tests for provided content-types.
This commit is contained in:
parent
d299bd3397
commit
0453cc3d2a
3 changed files with 87 additions and 9 deletions
|
@ -86,6 +86,7 @@ test-suite spec
|
||||||
main-is: Spec.hs
|
main-is: Spec.hs
|
||||||
build-depends:
|
build-depends:
|
||||||
base == 4.*
|
base == 4.*
|
||||||
|
, aeson
|
||||||
, hspec == 2.*
|
, hspec == 2.*
|
||||||
, QuickCheck
|
, QuickCheck
|
||||||
, parsec
|
, parsec
|
||||||
|
|
|
@ -15,10 +15,12 @@ import Control.Arrow (left)
|
||||||
import Data.Aeson (FromJSON, ToJSON, eitherDecode,
|
import Data.Aeson (FromJSON, ToJSON, eitherDecode,
|
||||||
encode)
|
encode)
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.ByteString.Lazy (ByteString)
|
import Data.ByteString.Lazy (ByteString, fromStrict, toStrict)
|
||||||
import Data.String.Conversions (cs)
|
import Data.String.Conversions (cs)
|
||||||
import qualified Data.Text.Lazy as Text
|
import qualified Data.Text.Lazy as TextL
|
||||||
import qualified Data.Text.Lazy.Encoding as Text
|
import qualified Data.Text.Lazy.Encoding as TextL
|
||||||
|
import qualified Data.Text as TextS
|
||||||
|
import qualified Data.Text.Encoding as TextS
|
||||||
import Data.Typeable
|
import Data.Typeable
|
||||||
import GHC.Exts (Constraint)
|
import GHC.Exts (Constraint)
|
||||||
import qualified Network.HTTP.Media as M
|
import qualified Network.HTTP.Media as M
|
||||||
|
@ -73,6 +75,7 @@ newtype AcceptHeader = AcceptHeader BS.ByteString
|
||||||
-- > toByteString _ val = pack ("This is MINE! " ++ show val)
|
-- > toByteString _ val = pack ("This is MINE! " ++ show val)
|
||||||
-- >
|
-- >
|
||||||
-- > type MyAPI = "path" :> Get '[MyContentType] Int
|
-- > type MyAPI = "path" :> Get '[MyContentType] Int
|
||||||
|
--
|
||||||
class Accept ctype => MimeRender ctype a where
|
class Accept ctype => MimeRender ctype a where
|
||||||
toByteString :: Proxy ctype -> a -> ByteString
|
toByteString :: Proxy ctype -> a -> ByteString
|
||||||
|
|
||||||
|
@ -92,6 +95,20 @@ instance ( AllMimeRender ctyps a, IsNonEmpty ctyps
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
-- * Unrender
|
-- * Unrender
|
||||||
|
|
||||||
|
-- | Instantiate this class to register a way of deserializing a type based
|
||||||
|
-- on the request's @Content-Type@ header.
|
||||||
|
--
|
||||||
|
-- > data MyContentType = MyContentType String
|
||||||
|
-- >
|
||||||
|
-- > instance Accept MyContentType where
|
||||||
|
-- > contentType _ = "example" // "prs.me.mine" /: ("charset", "utf-8")
|
||||||
|
-- >
|
||||||
|
-- > instance Show a => MimeRender MyContentType where
|
||||||
|
-- > fromByteString _ bs = MyContentType $ unpack bs
|
||||||
|
-- >
|
||||||
|
-- > type MyAPI = "path" :> ReqBody '[MyContentType] :> Get '[JSON] Int
|
||||||
|
--
|
||||||
class Accept ctype => MimeUnrender ctype a where
|
class Accept ctype => MimeUnrender ctype a where
|
||||||
fromByteString :: Proxy ctype -> ByteString -> Either String a
|
fromByteString :: Proxy ctype -> ByteString -> Either String a
|
||||||
|
|
||||||
|
@ -162,9 +179,13 @@ type family IsNonEmpty (ls::[*]) :: Constraint where
|
||||||
instance ToJSON a => MimeRender JSON a where
|
instance ToJSON a => MimeRender JSON a where
|
||||||
toByteString _ = encode
|
toByteString _ = encode
|
||||||
|
|
||||||
-- | `Text.encodeUtf8`
|
-- | `TextL.encodeUtf8`
|
||||||
instance MimeRender PlainText Text.Text where
|
instance MimeRender PlainText TextL.Text where
|
||||||
toByteString _ = Text.encodeUtf8
|
toByteString _ = TextL.encodeUtf8
|
||||||
|
|
||||||
|
-- | `fromStrict . TextS.encodeUtf8`
|
||||||
|
instance MimeRender PlainText TextS.Text where
|
||||||
|
toByteString _ = fromStrict . TextS.encodeUtf8
|
||||||
|
|
||||||
-- | `id`
|
-- | `id`
|
||||||
instance MimeRender OctetStream ByteString where
|
instance MimeRender OctetStream ByteString where
|
||||||
|
@ -177,9 +198,13 @@ instance MimeRender OctetStream ByteString where
|
||||||
instance FromJSON a => MimeUnrender JSON a where
|
instance FromJSON a => MimeUnrender JSON a where
|
||||||
fromByteString _ = eitherDecode
|
fromByteString _ = eitherDecode
|
||||||
|
|
||||||
-- | `left show . Text.decodeUtf8'`
|
-- | `left show . TextL.decodeUtf8'`
|
||||||
instance MimeUnrender PlainText Text.Text where
|
instance MimeUnrender PlainText TextL.Text where
|
||||||
fromByteString _ = left show . Text.decodeUtf8'
|
fromByteString _ = left show . TextL.decodeUtf8'
|
||||||
|
|
||||||
|
-- | `left show . TextS.decodeUtf8' . toStrict`
|
||||||
|
instance MimeUnrender PlainText TextS.Text where
|
||||||
|
fromByteString _ = left show . TextS.decodeUtf8' . toStrict
|
||||||
|
|
||||||
-- | `Right . id`
|
-- | `Right . id`
|
||||||
instance MimeUnrender OctetStream ByteString where
|
instance MimeUnrender OctetStream ByteString where
|
||||||
|
|
52
test/Servant/API/ContentTypesSpec.hs
Normal file
52
test/Servant/API/ContentTypesSpec.hs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
|
module Servant.API.ContentTypesSpec where
|
||||||
|
|
||||||
|
import Control.Applicative
|
||||||
|
import Data.Aeson
|
||||||
|
import Data.Proxy
|
||||||
|
import qualified Data.Text as TextS
|
||||||
|
import qualified Data.Text.Lazy as TextL
|
||||||
|
import GHC.Generics
|
||||||
|
import Test.Hspec
|
||||||
|
import Test.QuickCheck
|
||||||
|
|
||||||
|
import Servant.API.ContentTypes
|
||||||
|
|
||||||
|
spec :: Spec
|
||||||
|
spec = describe "Servant.API.ContentTypes" $ do
|
||||||
|
|
||||||
|
describe "The JSON Content-Type type" $ do
|
||||||
|
|
||||||
|
it "has fromByteString reverse toByteString for valid top-level json ([Int]) " $ do
|
||||||
|
let p = Proxy :: Proxy JSON
|
||||||
|
property $ \x -> fromByteString p (toByteString p x) == Right (x::[Int])
|
||||||
|
|
||||||
|
it "has fromByteString reverse toByteString for valid top-level json " $ do
|
||||||
|
let p = Proxy :: Proxy JSON
|
||||||
|
property $ \x -> fromByteString p (toByteString p x) == Right (x::SomeData)
|
||||||
|
|
||||||
|
describe "The PlainText Content-Type type" $ do
|
||||||
|
|
||||||
|
it "has fromByteString reverse toByteString (lazy Text)" $ do
|
||||||
|
let p = Proxy :: Proxy PlainText
|
||||||
|
property $ \x -> fromByteString p (toByteString p x) == Right (x::TextL.Text)
|
||||||
|
|
||||||
|
it "has fromByteString reverse toByteString (strict Text)" $ do
|
||||||
|
let p = Proxy :: Proxy PlainText
|
||||||
|
property $ \x -> fromByteString p (toByteString p x) == Right (x::TextS.Text)
|
||||||
|
|
||||||
|
|
||||||
|
data SomeData = SomeData { record1 :: String, record2 :: Int }
|
||||||
|
deriving (Generic, Eq, Show)
|
||||||
|
|
||||||
|
instance FromJSON SomeData
|
||||||
|
instance ToJSON SomeData
|
||||||
|
instance Arbitrary SomeData where
|
||||||
|
arbitrary = SomeData <$> arbitrary <*> arbitrary
|
||||||
|
|
||||||
|
instance Arbitrary TextL.Text where
|
||||||
|
arbitrary = TextL.pack <$> arbitrary
|
||||||
|
|
||||||
|
instance Arbitrary TextS.Text where
|
||||||
|
arbitrary = TextS.pack <$> arbitrary
|
Loading…
Reference in a new issue