module Main where
import Data.ByteString.Lazy (LazyByteString)
import Data.Kind (Type)
import Effectful
import Effectful.Hspec
import Effectful.HttpClient hiding (Proxy)
import Effectful.Servant
import Effectful.Servant.Server.Generic (AsServer)
import Effectful.Wai (Application)
import Effectful.Wai.Handler.Warp (Port, withApplication)
import GHC.Generics (Generic)
import Network.HTTP.Types qualified as HTTP
import Prelude
type API = NamedRoutes NamedAPI
data NamedAPI (mode :: Type) = NamedAPI
{ hello :: mode :- Get '[PlainText] String
, helloNamed :: mode :- Capture "name" String :/ Get '[PlainText] String
}
deriving stock (Generic)
server :: NamedAPI (AsServer es)
server = NamedAPI{..}
where
hello :: Handler es String
hello = pure "Hello!"
helloNamed :: String -> Handler es String
helloNamed "teapot" = throwError err418
helloNamed name = pure $ "Hello, " <> name <> "!"
app :: (IOE :> es) => Application es
app = serve @API Proxy server
get :: (HttpClient :> es) => String -> Port -> Eff es (Response LazyByteString)
get path port = do
req <- parseRequest $ "http://127.0.0.1:" <> show port <> path
httpLbs req{requestHeaders = [("Connection", "close")]}
main :: IO ()
main = runEff . runHttpClient . runHspec . describe "Servant" $ do
it "says hello" do
resp <- withApplication (pure app) (get "/")
responseBody resp `shouldBe` "Hello!"
it "says hello to Ueli" do
resp <- withApplication (pure app) (get "/Ueli")
responseBody resp `shouldBe` "Hello, Ueli!"
it "is a teapot" do
resp <- withApplication (pure app) (get "/teapot")
responseStatus resp `shouldBe` HTTP.status418