@@ -9,6 +9,7 @@ import Blaze.ByteString.Builder (toByteString)
99import Network.Wai
1010import Network.Wai.Test
1111import Network.Wai.Parse
12+import Network.Wai.UrlMap
1213import qualified Data.ByteString as S
1314import qualified Data.ByteString.Char8 as S8
1415import qualified Data.ByteString.Lazy.Char8 as L8
@@ -17,6 +18,7 @@ import qualified Data.Text.Lazy as T
1718import qualified Data.Text as TS
1819import qualified Data.Text.Encoding as TE
1920import Control.Arrow
21+import Control.Applicative
2022import Control.Monad.Trans.Resource (getInternalState, withInternalState, runResourceT)
2123
2224import Network.Wai.Middleware.Jsonp
@@ -42,6 +44,9 @@ import qualified Data.IORef as I
4244
4345specs :: Spec
4446specs = do
47+ describe "Network.Wai.UrlMap" $ do
48+ mapM_ (uncurry it) casesUrlMap
49+
4550 describe "Network.Wai.Parse" $ do
4651 describe "parseContentType" $ do
4752 let go (x, y, z) = it (TS.unpack $ TE.decodeUtf8 x) $ parseContentType x `shouldBe` (y, z)
@@ -561,3 +566,63 @@ caseDebugRequestBody = do
561566
562567 {-debugApp = debug $ \req -> do-}
563568 {-return $ responseLBS status200 [ ] ""-}
569+
570+urlMapTestApp :: Application
571+urlMapTestApp = mapUrls $
572+ mount "bugs" bugsApp
573+ <|> mount "helpdesk" helpdeskApp
574+ <|> mount "api"
575+ ( mount "v1" apiV1
576+ <|> mount "v2" apiV2
577+ )
578+ <|> mountRoot mainApp
579+
580+ where
581+ trivialApp :: S.ByteString -> Application
582+ trivialApp name req =
583+ return $
584+ responseLBS
585+ status200
586+ [ ("content-type", "text/plain")
587+ , ("X-pathInfo", S8.pack . show . pathInfo $ req)
588+ , ("X-rawPathInfo", rawPathInfo req)
589+ , ("X-appName", name)
590+ ]
591+ ""
592+
593+ bugsApp = trivialApp "bugs"
594+ helpdeskApp = trivialApp "helpdesk"
595+ apiV1 = trivialApp "apiv1"
596+ apiV2 = trivialApp "apiv2"
597+ mainApp = trivialApp "main"
598+
599+casesUrlMap :: [(String, Assertion)]
600+casesUrlMap = [pair1, pair2, pair3, pair4]
601+ where
602+ makePair name session = (name, runSession session urlMapTestApp)
603+ get reqPath = request $ setPath defaultRequest reqPath
604+ s = S8.pack . show :: [TS.Text] -> S.ByteString
605+
606+ pair1 = makePair "should mount root" $ do
607+ res1 <- get "/"
608+ assertStatus 200 res1
609+ assertHeader "X-rawPathInfo" "/" res1
610+ assertHeader "X-pathInfo" (s []) res1
611+ assertHeader "X-appName" "main" res1
612+
613+ pair2 = makePair "should mount apps" $ do
614+ res2 <- get "/bugs"
615+ assertStatus 200 res2
616+ assertHeader "X-rawPathInfo" "/" res2
617+ assertHeader "X-pathInfo" (s []) res2
618+ assertHeader "X-appName" "bugs" res2
619+
620+ pair3 = makePair "should preserve extra path info" $ do
621+ res3 <- get "/helpdesk/issues/11"
622+ assertStatus 200 res3
623+ assertHeader "X-rawPathInfo" "/issues/11" res3
624+ assertHeader "X-pathInfo" (s ["issues", "11"]) res3
625+
626+ pair4 = makePair "should 404 if none match" $ do
627+ res4 <- get "/api/v3"
628+ assertStatus 404 res4