packages feed

servant-avro-0.1.0.0: test/Servant/API/ContentTypes/AvroSpec.hs

{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators     #-}

module Servant.API.ContentTypes.AvroSpec (spec) where

import           Control.Concurrent            (forkIO)
import           Control.Monad                 (void)
import           Control.Monad.IO.Class        (liftIO)
import           Data.Proxy                    (Proxy (..))
import           Data.Text                     (Text, pack)
import           Network.HTTP.Client           (defaultManagerSettings,
                                                newManager)
import qualified Network.Wai.Handler.Warp      as Warp
import           Servant.API
import           Servant.API.ContentTypes.Avro
import           Servant.Client
import           Servant.Server

import           Test.Hspec
import           Test.QuickCheck
import           Test.QuickCheck.Monadic



newtype ArbitraryText = ArbitraryText Text deriving Show

instance Arbitrary ArbitraryText where
  arbitrary = ArbitraryText . pack <$> arbitrary



type TestAPI =
  "put" :> ReqBody '[Avro, JSON] Text :> Put '[JSON] Text
  :<|>
  "get" :> Get '[Avro] (Maybe Text)

testApp :: Application
testApp = serve (Proxy :: Proxy TestAPI) handlers
  where
    handlers = handlePut :<|> handleGet

    handlePut :: Text -> Handler Text
    handlePut input = return $ input <> "x"

    handleGet :: Handler (Maybe Text)
    handleGet = return (Just "weewoo")

-- The app is stateless so we don't need a fresh server each time we run a test.
startTestApp :: IO ()
startTestApp = void . liftIO . forkIO $ Warp.run 8888 testApp

testPut :: Text -> ClientM Text
testGet :: ClientM (Maybe Text)
testPut :<|> testGet = client (Proxy :: Proxy TestAPI)


spec :: Spec
spec = do
  runIO startTestApp

  clientEnv <- runIO (mkClientEnv
                      <$> newManager defaultManagerSettings
                      <*> parseBaseUrl "http://localhost:8888")

  describe "GET /get" $
    it "produces the expected result" $ do
      result <- runClientM testGet clientEnv
      result `shouldBe` Right (Just "weewoo")

  describe "PUT /put" $
    it "appends 'x' to the request body and returns it" $ property $
      \(ArbitraryText str) -> monadicIO $ do
        result <- run $ runClientM (testPut str) clientEnv
        return $ result === Right (str <> "x")

  it "compiles" $
    True `shouldBe` True