wai-routes-0.9.2: test/HelloSpec.hs
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes, TypeFamilies, ViewPatterns, MultiParamTypeClasses, FlexibleInstances #-}
{-
Test simple routes
-}
module HelloSpec (spec) where
import Data.Maybe (fromMaybe)
import Network.Wai (Application)
import Network.Wai.Middleware.Routes
import Data.Aeson (Value(Number), (.=), object)
import Data.Text (Text)
import qualified Data.Text as T
import Test.Hspec
import Test.Hspec.Wai
import qualified Test.Hspec.Wai.JSON as H (json)
---- A SMALL SUBSITE ----
data SubRoute = SubRoute
class MasterContract master where
getMasterName :: master -> Text
mkRouteSub "SubRoute" "MasterContract" [parseRoutes|
/ SubHomeR GET
|]
getSubHomeR :: MasterContract master => HandlerS SubRoute master
getSubHomeR = runHandlerM $ do
m <- master
plain $ T.concat ["subsite-", getMasterName m]
getSubRoute :: master -> SubRoute
getSubRoute = const SubRoute
---- THE APPLICATION TO BE TESTED ----
data MyRoute = MyRoute
instance MasterContract MyRoute where
getMasterName MyRoute = "MyRoute"
mkRoute "MyRoute" [parseRoutes|
/ HomeR GET
/some-json FooR GET
/post PostR POST
/subsite SubR SubRoute getSubRoute
/nested NestedR:
/ NRootR GET
/abcd AbcdR GET
|]
getHomeR :: Handler MyRoute
getHomeR = runHandlerM $ plain "hello"
getFooR :: Handler MyRoute
getFooR = runHandlerM $ json $ object ["foo" .= Number 23, "bar" .= Number 42]
-- Post parameters (getParam can also be used for query params)
postPostR :: Handler MyRoute
postPostR = runHandlerM $ do
name <- getParam "name"
plain $ fromMaybe "unnamed" name
-- Nested routes
getNRootR, getAbcdR :: Handler MyRoute
getNRootR = runHandlerM $ plain "Nested ROOT"
getAbcdR = runHandlerM $ plain "Nested ABCD"
-- An example of an unrouted handler
handleInfoRequest :: Handler DefaultMaster
handleInfoRequest = runHandlerM $ do
Just (DefaultRoute (_,query)) <- maybeRoute
case lookup "info" query of
-- If an override param "info" was supplied then display info
Just _ -> plain "Info was requested - You are running wai-routes tests"
-- Else, move on to the next handler (i.e. do nothing special)
Nothing -> next
application :: IO Application
application = return $ waiApp $ do
handler handleInfoRequest
route MyRoute
catchall $ staticApp $ defaultFileServerSettings "test/static"
---- THE TESTS ----
spec :: Spec
spec = with application $ do
describe "GET /" $
it "responds with 'hello' and has 'Content-Type: text/plain; charset=utf-8'" $
get "/" `shouldRespondWith` "hello" {matchStatus = 200, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]}
describe "GET /some-json" $
it "responds with correct json and has 'Content-Type: application/json; charset=utf-8'" $
get "/some-json" `shouldRespondWith` [H.json|{foo: 23, bar: 42}|] {matchStatus = 200, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"]}
describe "GET /?info" $
it "responds with info when requested" $
get "/?info" `shouldRespondWith` "Info was requested - You are running wai-routes tests" {matchStatus = 200, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]}
describe "POST /post?name=foobar" $
it "can read query parameters" $
postHtmlForm "/post?name=foobar" [("name","ignored")] `shouldRespondWith` "foobar" {matchStatus = 200, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]}
describe "POST /post" $
it "can read post body parameters" $
postHtmlForm "/post" [("name","foobar")] `shouldRespondWith` "foobar" {matchStatus = 200, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]}
describe "GET /subsite" $
it "can access the subsite correctly" $
get "/subsite" `shouldRespondWith` "subsite-MyRoute" {matchStatus = 200, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]}
describe "GET /nested" $
it "can access nested routes root correctly" $
get "/nested" `shouldRespondWith` "Nested ROOT" {matchStatus = 200, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]}
describe "GET /nested/abcd" $
it "can access nested routes correctly" $
get "/nested/abcd" `shouldRespondWith` "Nested ABCD" {matchStatus = 200, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]}
describe "GET /lambda.png" $
it "returns a file correctly" $
get "/lambda.png" `shouldRespondWith` 200 {matchHeaders = ["Content-Type" <:> "image/png"]}