snap-predicates-0.3.0: test/Tests/Snap/Route.hs
{-# LANGUAGE OverloadedStrings, TypeOperators #-}
module Tests.Snap.Route (tests) where
import Control.Applicative hiding (Const)
import Control.Monad.IO.Class
import Test.Framework
import Test.Framework.Providers.HUnit
import Test.HUnit hiding (Test)
import Data.ByteString (ByteString)
import Data.Predicate
import Data.String
import Snap.Core
import Snap.Predicate hiding (Text)
import Snap.Predicate.Types
import Snap.Route
import qualified Snap.Test as T
import qualified Data.Map.Strict as M
import qualified Data.Text as Text
tests :: [Test]
tests =
[ testSitemap
, testMedia
]
testSitemap :: Test
testSitemap = testCase "Sitemap" $ do
let routes = expandRoutes sitemap
let handler = route routes
assertEqual "Endpoints" ["/a", "/b", "/c", "/d", "/e", "/f", "/z"] (map fst routes)
testEndpointA handler
testEndpointB handler
testEndpointC handler
testEndpointD handler
testEndpointE handler
testEndpointF handler
sitemap :: Routes Snap ()
sitemap = do
get "/a" handlerA
(Accept Application Json :&: (Param "name" :|: Param "nick") :&: Param "foo")
get "/b" handlerB
(Param "baz")
get "/c" handlerC
(ParamOpt "foo")
get "/d" handlerD
(ParamDef "foo" 0)
get "/e" handlerE
(HdrDef "foo" 0)
get "/f" handlerF
(Param "foo")
get "/z" handlerZ
(Fail (err 410 "Gone."))
handlerA :: MediaType Application Json :*: Int :*: ByteString -> Snap ()
handlerA (_ :*: i :*: _) = writeText (fromString . show $ i)
handlerB :: Int -> Snap ()
handlerB baz = writeText (Text.pack . show $ baz)
handlerC :: Maybe Int -> Snap ()
handlerC foo = writeText (Text.pack . show $ foo)
handlerD :: Int -> Snap ()
handlerD foo = writeText (Text.pack . show $ foo)
handlerE :: Int -> Snap ()
handlerE foo = writeText (Text.pack . show $ foo)
handlerF :: CSV Int -> Snap ()
handlerF foo = writeText (Text.pack . show . sum . list $ foo)
handlerZ :: MediaType Application Json -> Snap ()
handlerZ _ = do
rq <- getRequest
with (Param "bar" :&: Param "baz") rq $ \(bar :*: baz) -> do
writeBS bar
writeBS baz
testEndpointA :: Snap () -> Assertion
testEndpointA m = do
let rq0 = T.get "/a" M.empty >> T.addHeader "Accept" "foo/bar"
st0 <- rspStatus <$> T.runHandler rq0 m
assertEqual "Accept fails" 406 st0
let rq1 = rq0 >> T.addHeader "Accept" "application/json"
st1 <- rspStatus <$> T.runHandler rq1 m
assertEqual "Param fails" 400 st1
let rq2 = T.get "/a" (M.fromList [("name", ["x"])]) >>
T.addHeader "Accept" "application/json"
st2 <- rspStatus <$> T.runHandler rq2 m
assertEqual "Param fails" 400 st2
let rq3 = T.get "/a" (M.fromList [("name", ["123"]), ("foo", ["\"y\""])]) >>
T.addHeader "Accept" "application/json"
T.runHandler rq3 m >>= T.assertSuccess
testEndpointB :: Snap () -> Assertion
testEndpointB m = do
rs0 <- T.runHandler (T.get "/b" M.empty) m
bd0 <- T.getResponseBody rs0
assertEqual "b. baz 1" 400 (rspStatus rs0)
assertEqual "b. baz 2" "Missing parameter 'baz'." bd0
rs1 <- T.runHandler (T.get "/b" $ M.fromList [("baz", ["abc"])]) m
bd1 <- T.getResponseBody rs1
assertEqual "b. baz 3" 400 (rspStatus rs1)
assertEqual "b. baz 4" "no read" bd1
rs2 <- T.runHandler (T.get "/b" $ M.fromList [("baz", ["abc", "123"])]) m
bd2 <- T.getResponseBody rs2
assertEqual "b. baz 5" 200 (rspStatus rs2)
assertEqual "b. baz 6" "123" bd2
testEndpointC :: Snap () -> Assertion
testEndpointC m = do
rs0 <- T.runHandler (T.get "/c" M.empty) m
bd0 <- T.getResponseBody rs0
assertEqual "c. foo 1" 200 (rspStatus rs0)
assertEqual "c. foo 2" "Nothing" bd0
rs1 <- T.runHandler (T.get "/c" $ M.fromList [("foo", ["abc", "123"])]) m
bd1 <- T.getResponseBody rs1
assertEqual "c. foo 3" 200 (rspStatus rs1)
assertEqual "c. foo 4" "Just 123" bd1
rs2 <- T.runHandler (T.get "/c" $ M.fromList [("foo", ["abc"])]) m
bd2 <- T.getResponseBody rs2
assertEqual "c. foo 5" 400 (rspStatus rs2)
assertEqual "c. foo 6" "no read" bd2
testEndpointD :: Snap () -> Assertion
testEndpointD m = do
rs0 <- T.runHandler (T.get "/d" M.empty) m
bd0 <- T.getResponseBody rs0
assertEqual "d. foo 1" 200 (rspStatus rs0)
assertEqual "d. foo 2" "0" bd0
rs1 <- T.runHandler (T.get "/d" $ M.fromList [("foo", ["xxx", "42"])]) m
bd1 <- T.getResponseBody rs1
assertEqual "d. foo 3" 200 (rspStatus rs1)
assertEqual "d. foo 4" "42" bd1
rs2 <- T.runHandler (T.get "/d" $ M.fromList [("foo", ["yyy"])]) m
bd2 <- T.getResponseBody rs2
assertEqual "d. foo 5" 400 (rspStatus rs2)
assertEqual "d. foo 6" "no read" bd2
testEndpointE :: Snap () -> Assertion
testEndpointE m = do
rs0 <- T.runHandler (T.get "/e" M.empty) m
bd0 <- T.getResponseBody rs0
assertEqual "e. foo 1" 200 (rspStatus rs0)
assertEqual "e. foo 2" "0" bd0
rs1 <- T.runHandler (T.get "/e" M.empty >> T.addHeader "foo" "42") m
bd1 <- T.getResponseBody rs1
assertEqual "e. foo 3" 200 (rspStatus rs1)
assertEqual "e. foo 4" "42" bd1
rs2 <- T.runHandler (T.get "/e" M.empty >> T.addHeader "foo" "abc") m
bd2 <- T.getResponseBody rs2
assertEqual "e. foo 5" 400 (rspStatus rs2)
assertEqual "e. foo 6" "no read" bd2
testEndpointF :: Snap () -> Assertion
testEndpointF m = do
rs0 <- T.runHandler (T.get "/f" $ M.fromList [("foo", ["1,2,3,4"])]) m
bd0 <- T.getResponseBody rs0
assertEqual "e. foo 1" 200 (rspStatus rs0)
assertEqual "e. foo 2" "10" bd0
-- Media Selection Tests:
testMedia :: Test
testMedia = testCase "Media Selection" $ do
let [(_, h)] = expandRoutes sitemapMedia
expectMedia "application/json;q=0.3, application/x-thrift;q=0.7" "application/x-thrift" h
expectMedia "application/json;q=0.7, application/x-thrift;q=0.3" "application/json" h
sitemapMedia :: Routes Snap ()
sitemapMedia = do
get "/media" handlerJson $ Accept Application Json
get "/media" handlerThrift $ Accept Application Thrift
handlerJson :: MediaType Application Json -> Snap ()
handlerJson _ = writeBS "application/json"
handlerThrift :: MediaType Application Thrift -> Snap ()
handlerThrift _ = writeBS "application/x-thrift"
expectMedia :: ByteString -> ByteString -> Snap () -> Assertion
expectMedia hdr res m = do
let rq0 = T.get "/media" M.empty >>
T.addHeader "Accept" hdr
txt0 <- T.runHandler rq0 m >>= liftIO . T.getResponseBody
assertEqual "media type" res txt0