on master help sign in
Added test cases for matrix parameters. Added some missing cases in the IsElem type family (QueryParams and QueryFlag)
commit409a10442d4d9e845f69336b480329a954feb92e authorDaniel Larsson <daniel.j.larsson@gmail.com> dateSun 4 Jan 2015, 18:14 (12 years ago) parent80b82fd
4 files changed+64−16
src/Servant/QQ.hs+30−16 src/Servant/Utils/Links.hs+6 test/Servant/QQSpec.hs+22 test/Servant/Utils/LinksSpec.hs+6
src/Servant/QQ.hs+30−16
@@ -40,6 +40,7 @@ import Servant.API.Post
4040import Servant.API.Put
4141import Servant.API.Delete
4242import Servant.API.QueryParam
43+import Servant.API.MatrixParam
4344import Servant.API.ReqBody
4445import Servant.API.Sub
4546import Servant.API.Alternative
@@ -50,15 +51,16 @@ import Servant.API.Alternative
5051-- only one of 'get', 'post', 'put', and 'delete' in a value), but
5152-- sometimes requires a little more work.
5253class ExpSYM repr' repr | repr -> repr', repr' -> repr where
53− lit :: String -> repr' -> repr
54− capture :: String -> String -> repr -> repr
55− reqBody :: String -> repr -> repr
56− queryParam :: String -> String -> repr -> repr
57− conj :: repr' -> repr -> repr
58− get :: String -> repr
59− post :: String -> repr
60− put :: String -> repr
61− delete :: String -> repr
54+ lit :: String -> repr' -> repr
55+ capture :: String -> String -> repr -> repr
56+ reqBody :: String -> repr -> repr
57+ queryParam :: String -> String -> repr -> repr
58+ matrixParam :: String -> String -> repr -> repr
59+ conj :: repr' -> repr -> repr
60+ get :: String -> repr
61+ post :: String -> repr
62+ put :: String -> repr
63+ delete :: String -> repr
6264
6365
6466infixr 6 >:
@@ -72,7 +74,9 @@ instance ExpSYM Type Type where
7274 capture name typ r = AppT (AppT (ConT ''Capture) (LitT (StrTyLit name)))
7375 (ConT $ mkName typ) >: r
7476 reqBody typ r = AppT (ConT ''ReqBody) (ConT $ mkName typ) >: r
75− queryParam name typ r = AppT (AppT (ConT ''QueryParam) (LitT (StrTyLit name)))
77+ queryParam name typ r = AppT (AppT (ConT ''QueryParam) (LitT (StrTyLit name)))
78+ (ConT $ mkName typ) >: r
79+ matrixParam name typ r = AppT (AppT (ConT ''MatrixParam) (LitT (StrTyLit name)))
7680 (ConT $ mkName typ) >: r
7781 conj x = AppT (AppT (ConT ''(:>)) x)
7882 get typ = AppT (ConT ''Get) (ConT $ mkName typ)
@@ -93,17 +97,27 @@ parseUrlSegment = try parseCapture
9397 <|> try parseLit
9498 where
9599 parseCapture = do
96− cname <- many (noneOf " ?/:")
100+ cname <- many (noneOf " ?/:;")
97101 char ':'
98− ctyp <- many (noneOf " ?/:")
99− return $ capture cname ctyp
102+ ctyp <- many (noneOf " ?/:;")
103+ mx <- many parseMatrixParam
104+ return $ capture cname ctyp . foldr (.) id mx
100105 parseQueryParam = do
101106 char '?'
102− cname <- many (noneOf " ?/:")
107+ cname <- many (noneOf " ?/:;")
103108 char ':'
104− ctyp <- many (noneOf " ?/:")
109+ ctyp <- many (noneOf " ?/:;")
105110 return $ queryParam cname ctyp
106− parseLit = lit <$> many (noneOf " ?/:")
111+ parseLit = do
112+ lt <- many (noneOf " ?/:;")
113+ mx <- many parseMatrixParam
114+ return $ lit lt . foldr (.) id mx
115+ parseMatrixParam = do
116+ char ';'
117+ cname <- many (noneOf " ?/:;")
118+ char ':'
119+ ctyp <- many (noneOf " ?/:;")
120+ return $ matrixParam cname ctyp
107121
108122parseUrl :: ExpSYM repr repr => Parser (repr -> repr)
109123parseUrl = do
src/Servant/Utils/Links.hs+6
@@ -54,6 +54,7 @@ import GHC.TypeLits
5454import Servant.API.Capture
5555import Servant.API.ReqBody
5656import Servant.API.QueryParam
57+import Servant.API.MatrixParam
5758import Servant.API.Get
5859import Servant.API.Post
5960import Servant.API.Put
@@ -78,6 +79,11 @@ type family IsElem a s where
7879 IsElem (e :> sa) (Capture x y :> sb) = IsElem sa sb
7980 IsElem sa (ReqBody x :> sb) = IsElem sa sb
8081 IsElem sa (QueryParam x y :> sb) = IsElem sa sb
82+ IsElem sa (QueryParams x y :> sb) = IsElem sa sb
83+ IsElem sa (QueryFlag x :> sb) = IsElem sa sb
84+ IsElem sa (MatrixParam x y :> sb) = IsElem sa sb
85+ IsElem sa (MatrixParams x y :> sb) = IsElem sa sb
86+ IsElem sa (MatrixFlag x :> sb) = IsElem sa sb
8187 IsElem e e = 'True
8288 IsElem e a = 'False
8389
test/Servant/QQSpec.hs+22
@@ -76,6 +76,20 @@ type SimpleQueryParam' = "hello" :> QueryParam "p" Int :> Post Bool
7676type SimpleQueryParam'' = "hello" :> QueryParam "r" Int :> Post Bool
7777type SimpleQueryParam''' = "hello" :> QueryParam "p" Bool :> Post Bool
7878
79+type SimpleMatrixParam = [sitemap|
80+POST hello;p:Int Bool
81+|]
82+type SimpleMatrixParam' = "hello" :> MatrixParam "p" Int :> Post Bool
83+type SimpleMatrixParam'' = "hello" :> MatrixParam "r" Int :> Post Bool
84+type SimpleMatrixParam''' = "hello" :> MatrixParam "p" Bool :> Post Bool
85+
86+type ComplexMatrixParam = [sitemap|
87+POST hello;p:Int;q:String/world;r:Int Bool
88+|]
89+type ComplexMatrixParam' = "hello" :> MatrixParam "p" Int :> MatrixParam "q" String :> "world" :> MatrixParam "r" Int :> Post Bool
90+type ComplexMatrixParam'' = "hello" :> MatrixParam "p" Int :> MatrixParam "q" String :> "world" :> MatrixParam "s" Int :> Post Bool
91+type ComplexMatrixParam''' = "hello" :> MatrixParam "p" Int :> MatrixParam "q" String :> "world" :> MatrixParam "r" Bool :> Post Bool
92+
7993-- Combinations ----------------------------------------------------------
8094
8195type TwoPaths = [sitemap|
@@ -144,6 +158,14 @@ spec = do
144158 (u::SimpleQueryParam) ~= (u::SimpleQueryParam' ) ~> True
145159 (u::SimpleQueryParam) ~= (u::SimpleQueryParam'') ~> False
146160 (u::SimpleQueryParam) ~= (u::SimpleQueryParam''') ~> False
161+ it "Handles simple matrix parameters" $ do
162+ (u::SimpleMatrixParam) ~= (u::SimpleMatrixParam' ) ~> True
163+ (u::SimpleMatrixParam) ~= (u::SimpleMatrixParam'') ~> False
164+ (u::SimpleMatrixParam) ~= (u::SimpleMatrixParam''') ~> False
165+ it "Handles more complex matrix parameters" $ do
166+ (u::ComplexMatrixParam) ~= (u::ComplexMatrixParam' ) ~> True
167+ (u::ComplexMatrixParam) ~= (u::ComplexMatrixParam'') ~> False
168+ (u::ComplexMatrixParam) ~= (u::ComplexMatrixParam''') ~> False
147169 it "Handles multiples paths" $ do
148170 (u::TwoPaths) ~= (u::TwoPaths') ~> True
149171 it "Ignores inline comments" $ do
test/Servant/Utils/LinksSpec.hs+6
@@ -12,12 +12,15 @@ import Servant.Utils.Links (IsElem, IsLink)
1212type TestApi =
1313 "hello" :> Capture "name" String :> QueryParam "capital" Bool :> Get Bool
1414 :<|> "greet" :> ReqBody 'True :> Post Bool
15+ :<|> "parent" :> MatrixParams "name" String :> "child" :> MatrixParam "gender" String :> Get String
1516
1617type TestLink = "hello" :> "hi" :> Get Bool
1718type TestLink2 = "greet" :> Post Bool
19+type TestLink3 = "parent" :> "child" :> Get String
1820
1921type BadTestLink = "hallo" :> "hi" :> Get Bool
2022type BadTestLink2 = "greet" :> Get Bool
23+type BadTestLink3 = "parent" :> "child" :> MatrixFlag "male" :> Get String
2124
2225type NotALink = "hello" :> Capture "x" Bool :> Get Bool
2326type NotALink2 = "hello" :> ReqBody 'True :> Get Bool
@@ -37,15 +40,18 @@ isElem = describe "IsElem" $ do
3740 it "is True when the first argument is an url within the second" $ do
3841 reflected (Proxy::Proxy (IsElem TestLink TestApi)) ~> True
3942 reflected (Proxy::Proxy (IsElem TestLink2 TestApi)) ~> True
43+ reflected (Proxy::Proxy (IsElem TestLink3 TestApi)) ~> True
4044 it "is False when the first argument is not an url within the second" $ do
4145 reflected (Proxy::Proxy (IsElem BadTestLink TestApi)) ~> False
4246 reflected (Proxy::Proxy (IsElem BadTestLink2 TestApi)) ~> False
47+ reflected (Proxy::Proxy (IsElem BadTestLink3 TestApi)) ~> False
4348
4449isLink :: Spec
4550isLink = describe "IsLink" $ do
4651 it "is True when all Subs are paths and the last is a method" $ do
4752 reflected (Proxy::Proxy (IsLink TestLink)) ~> True
4853 reflected (Proxy::Proxy (IsLink TestLink2)) ~> True
54+ reflected (Proxy::Proxy (IsLink TestLink3)) ~> True
4955 it "is False of anything with captures" $ do
5056 reflected (Proxy::Proxy (IsLink NotALink)) ~> False
5157 reflected (Proxy::Proxy (IsLink NotALink2)) ~> False