servant-matrix-param-0.3.2: test/Servant/MatrixParam/ServerSpec.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
module Servant.MatrixParam.ServerSpec where
import Control.Monad.IO.Class
import Data.ByteString.Lazy
import Data.Map.Strict
import Data.Proxy
import Data.Text
import Network.HTTP.Types (ok200)
import Network.Wai
import Network.Wai.Test
import Servant.API
import Servant.Server
import Test.Hspec
import Servant.MatrixParam
import Servant.MatrixParam.Server ()
import Servant.MatrixParam.Server.Internal
type Api =
WithMatrixParams "a" '[MatrixParam "name" String] :> Get '[PlainText] String
:<|> WithMatrixParams "b" '[MatrixParam "foo" Int, MatrixParam "bar" Int]
:> Get '[PlainText] String
:<|> WithMatrixParams "c" '[MatrixParam "foo" Int, MatrixFlag "baz", MatrixParam "bar" Int]
:> Get '[PlainText] String
:<|> CaptureWithMatrixParams "d" Int '[MatrixParam "foo" Int, MatrixFlag "baz"]
:> Get '[PlainText] String
api :: Proxy Api
api = Proxy
server :: Server Api
server = a :<|> b :<|> c :<|> d
where
a :: Maybe String -> Handler String
a p = return $ show p
b :: Maybe Int -> Maybe Int -> Handler String
b foo bar = return $ show (foo, bar)
c :: Maybe Int -> Bool -> Maybe Int -> Handler String
c foo baz bar | baz = return $ show (foo, bar)
| otherwise = return ""
d :: Int -> Maybe Int -> Bool -> Handler String
d capture foo baz | baz = return $ show capture
| otherwise = return $ show foo
testWithPath :: [Text] -> ByteString -> IO ()
testWithPath segments expected = do
(flip runSession) (serve api server) $ do
response <- Network.Wai.Test.request defaultRequest{
pathInfo = segments
}
liftIO $ do
simpleStatus response `shouldBe` ok200
simpleBody response `shouldBe` expected
spec :: Spec
spec = do
describe "Servant.API.MatrixParam" $ do
it "allows to retrieve simple matrix parameters" $ do
testWithPath ["a;name=bob"] "Just \"bob\""
it "retrieves matrix flags" $ do
testWithPath ["c;baz"] "(Nothing,Nothing)"
testWithPath ["c;foo=1;baz"] "(Just 1,Nothing)"
testWithPath ["c;bar=1;baz"] "(Nothing,Just 1)"
testWithPath ["c;bar=1;baz;foo=2"] "(Just 2,Just 1)"
testWithPath ["c;foo=1"] ""
it "treats 'true' as a flag that's present" $ do
testWithPath ["c;baz=true"] "(Nothing,Nothing)"
it "treats '1' as a flag that's present" $ do
testWithPath ["c;baz=1"] "(Nothing,Nothing)"
it "allows to omit matrix parameters" $ do
testWithPath ["a"] "Nothing"
it "allows multiple keys per segment" $ do
testWithPath ["b;foo=23;bar=42"] "(Just 23,Just 42)"
it "allows to overwrite matrix params" $ do
testWithPath ["a;name=alice;name=bob"] "Just \"bob\""
context "with capture" $
it "parses the capture " $ do
testWithPath ["5;baz"] "5"
testWithPath ["5;foo=3"] "Just 3"
describe "parsePathSegment" $ do
it "parses a path segment with a matrix param" $ do
parsePathSegment "foo;bar=baz" `shouldBe`
Just (MatrixSegment "foo" (Just (fromList [("bar", Just "baz")])))
it "parses a bare segment" $ do
parsePathSegment "foo" `shouldBe`
Just (MatrixSegment "foo" mempty)
it "parses a segment with multiple matrix params" $ do
parsePathSegment "foo;bar=baz;huhu=baba" `shouldBe`
Just (MatrixSegment "foo" (Just (fromList [("bar", Just "baz"),
("huhu", Just "baba")])))
it "parses a segment with multiple values for the same matrix param" $ do
parsePathSegment "foo;bar=baz;bar=huhu" `shouldBe`
Just (MatrixSegment "foo" (Just (fromList [("bar", Just "huhu")])))
it "parses a segment with semicolon but without params" $ do
parsePathSegment "foo;" `shouldBe`
Just (MatrixSegment "foo" mempty)
it "succeeds for invalid matrix parameters strings" $ do
parsePathSegment "foo;bar==" `shouldBe`
Just (MatrixSegment "foo" mempty)
it "can parse the empty string as value" $ do
parsePathSegment "foo;bar=" `shouldBe`
Just (MatrixSegment "foo" (Just (fromList [("bar", Just "")])))