{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, OverloadedStrings, DataKinds, TypeOperators, TypeSynonymInstances, FlexibleInstances #-} module WebApi.RouteSpec (spec) where import WebApi import Data.Text (Text) import Test.Hspec import Test.Hspec.Wai import qualified Network.Wai as Wai withApp :: SpecWith Wai.Application -> Spec withApp = with (return routingSpecApp) routingSpecApp :: Wai.Application routingSpecApp = serverApp serverSettings RoutingSpecImpl data RoutingSpec data RoutingSpecImpl = RoutingSpecImpl type StaticRoute1 = "this":/"is":/"a":/"static":/"route" type StaticRoute2 = Static "static_route" type RouteWithParam = "param":/Int type RouteWithParamAtBegin = Bool:/"param" type RouteWithParams = Text:/"param1":/Int:/"param2" type OverlappingRoute = "foo":/"param1":/Int:/"param2" instance WebApi RoutingSpec where type Version RoutingSpec = MajorMinor '(0, 1) type Apis RoutingSpec = '[ Route '[GET] StaticRoute1 , Route '[GET] StaticRoute2 , Route '[GET] RouteWithParam , Route '[GET] RouteWithParamAtBegin , Route '[GET] OverlappingRoute , Route '[GET] RouteWithParams ] instance ApiContract RoutingSpec GET StaticRoute1 where type ApiOut GET StaticRoute1 = () instance ApiContract RoutingSpec GET StaticRoute2 where type ApiOut GET StaticRoute2 = () instance ApiContract RoutingSpec GET RouteWithParam where type ApiOut GET RouteWithParam = () instance ApiContract RoutingSpec GET RouteWithParamAtBegin where type ApiOut GET RouteWithParamAtBegin = Text instance ApiContract RoutingSpec GET RouteWithParams where type ApiOut GET RouteWithParams = Text instance ApiContract RoutingSpec GET OverlappingRoute where type ApiOut GET OverlappingRoute = Text instance WebApiImplementation RoutingSpecImpl where type HandlerM RoutingSpecImpl = IO type ApiInterface RoutingSpecImpl = RoutingSpec instance ApiHandler RoutingSpecImpl GET StaticRoute1 where handler _ _ = respond () instance ApiHandler RoutingSpecImpl GET StaticRoute2 where handler _ _ = respond () instance ApiHandler RoutingSpecImpl GET RouteWithParam where handler _ _ = respond () instance ApiHandler RoutingSpecImpl GET RouteWithParamAtBegin where handler _ _ = respond "RouteWithParamAtBegin" instance ApiHandler RoutingSpecImpl GET RouteWithParams where handler _ _ = respond "RouteWithParams" instance ApiHandler RoutingSpecImpl GET OverlappingRoute where handler _ _ = respond "OverlappingRoute" spec :: Spec spec = withApp $ describe "WebApi routing" $ do context "static route with only one piece" $ do it "should be 200 ok" $ do get "static_route" `shouldRespondWith` 200 context "static route with many pieces" $ do it "should be 200 ok" $ do get "this/is/a/static/route" `shouldRespondWith` 200 context "route with param" $ do it "should be 200 ok" $ do get "param/5" `shouldRespondWith` 200 context "route with param at beginning" $ do it "should be 200 ok returning RouteWithParamAtBegin" $ do get "True/param" `shouldRespondWith` "\"RouteWithParamAtBegin\"" { matchStatus = 200 } context "route with multiple params" $ do it "should be 200 ok returning RouteWithParams" $ do get "bar/param1/5/param2" `shouldRespondWith` "\"RouteWithParams\"" { matchStatus = 200 } context "overlapping route selected by order" $ do it "should be 200 ok returning OverlappingRoute" $ do get "foo/param1/5/param2" `shouldRespondWith` "\"OverlappingRoute\"" { matchStatus = 200 } context "non existing route" $ do it "should be 404 ok" $ do get "foo/param1/5/param3" `shouldRespondWith` 404