{- ColtraneTests.hs Sean Welleck | Yuanfeng Peng | 2013 Contains tests, and examples of usage. An application used for testing (testApp) is created below, with various routes. Uses HUnit to run the test cases. A test case consists of making a request made to one of testApp's routes, and checking the response contents. The requests are made using the Network.HTTP library. In order to run the tests, the testApp must be running. Run the main function to start the testApp. Then, run the runTests function to run the tests. testApp2 defines various routes and handlers that are equivalent to those defined by testApp, but with different syntax. -} {-# LANGUAGE OverloadedStrings #-} import Coltrane import ColtraneTypes import Test.HUnit hiding (Path, State, path) import Network.HTTP.Types hiding (Header) import Network.HTTP hiding (GET, POST, PUT, DELETE, HeaderName) import qualified Control.Monad.State as MS import qualified Data.ByteString.Char8 as BS hiding (putStrLn) import Network.Wai.Parse import Network.Stream import Text.Regex import Network.Wai hiding (Response) -- appends a path to the base url make_url :: String -> String make_url path = "http://localhost:9000/" ++ path -- sends a GET or POST request to the given URL -- returns the response and the response body make_request :: StdMethod -> String -> IO (Result (Response String)) make_request GET url = simpleHTTP $ getRequest url make_request POST url = let (u:qs)= BS.split '?' (BS.pack url) in case qs of x:_ -> simpleHTTP $ postRequestWithBody (BS.unpack u) "application/x-www-form-urlencoded" (BS.unpack x) _ -> simpleHTTP $ postRequest url make_request _ _ = error "Unsupported request method." -- make a request and return the response's body and code response_data :: StdMethod -> String -> IO (String, ResponseCode) response_data m url = do resp <- make_request m url body <- getResponseBody resp code <- getResponseCode resp return (body, code) response_all :: StdMethod -> String -> IO (String) response_all m url = do resp <- make_request m url case resp of Right r -> return $ show r Left r -> return $ show r -- test whether a request to the given path returns -- the expected body and code test_response :: (StdMethod ,String ,(String, ResponseCode)) -> IO Test test_response (m ,path, expected) = do actual <- response_data m (make_url path) return $ "request body " ++ path ~: expected ~=? actual -- check whether the response contains the header test_header :: (StdMethod, String, BS.ByteString) -> IO Test test_header (m, path, expected) = do headers <- response_all m (make_url path) putStrLn headers return $ "response header " ++ path ~: (BS.isInfixOf expected (BS.pack headers)) ~=? True -- a test case is a 3-tuple containing: -- HTTP method -- path -- expected output, as a pair: -- (expected ResponseBody, expected ResponseCode) testCases = [ (POST, "post?name=John+Coltrane&famous=true", (show testPostParams1, (2,0,0))), (POST, "regex/upenn?dpt=cis", (show testPostParams2,(2,0,0))), (POST, "regex/upenn/seas?dpt=cis", (show testPostParams3,(2,0,0))), (POST, "regex/upenn/1seas?dpt=cis", ("404 : Page not Found.",(4,0,4))), (GET, "hello", ("Hello World!", (2,0,0))), (GET, "fj92i", ("404 : Page not Found.", (4,0,4))), (GET, "raise" , ("An error has occurred!", (5,0,0))), (GET, "status", ("Status Change", (2,0,3))), (GET, "status2", ("Status Change", (2,0,0))), (GET, "param/John/Coltrane", ("Hi John Coltrane!", (2,0,0))), (GET, "paramErr/John", ("Error: Param :name not found.", (5,0,0))), (GET, "regex/1234", ("'{'r1': '/1234'}'",(2,0,0))), (POST, "post/employee/company/august/sth", (show testPostParams4,(2,0,0))), (POST, "post/employee/company/august", ("404 : Page not Found.", (4,0,4)) ), (POST, "post", ("[]", (2,0,0))), (GET, "catchErr", ("Caught the error.", (2,0,0))), (GET, "field?album=Soultrane", ("Soultrane", (2,0,0))), (GET, "", ("