wai-test (empty) → 0.0.0
raw patch · 4 files changed
+207/−0 lines, 4 filesdep +HUnitdep +basedep +blaze-buildersetup-changed
Dependencies added: HUnit, base, blaze-builder, blaze-builder-enumerator, bytestring, containers, cookie, enumerator, transformers, wai
Files
- LICENSE +25/−0
- Network/Wai/Test.hs +144/−0
- Setup.lhs +8/−0
- wai-test.cabal +30/−0
+ LICENSE view
@@ -0,0 +1,25 @@+The following license covers this documentation, and the source code, except+where otherwise indicated.++Copyright 2010, Michael Snoyman. All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++* Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Network/Wai/Test.hs view
@@ -0,0 +1,144 @@+{-# LANGUAGE OverloadedStrings #-}+module Network.Wai.Test+ ( -- * Session+ Session+ , runSession+ -- * Requests+ , request+ , srequest+ , SRequest (..)+ , SResponse (..)+ -- * Assertions+ , assertStatus+ , assertContentType+ , assertBody+ , assertHeader+ , assertNoHeader+ ) where+import Network.Wai+import qualified Test.HUnit.Base as H+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.State (StateT, evalStateT, get, put)+import Control.Monad.Trans.Reader (ReaderT, runReaderT, ask)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.ByteString (ByteString)+import qualified Data.ByteString as S+import qualified Data.ByteString.Char8 as S8+import Data.Enumerator (joinI, consume, ($$), run_, enumList)+import Blaze.ByteString.Builder.Enumerator (builderToByteString)+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8++type Session = ReaderT Application (StateT ClientState IO)++data ClientState = ClientState+ { clientCookies :: Map ByteString ByteString+ }++initState :: ClientState+initState = ClientState Map.empty++runSession :: Session a -> Application -> IO a+runSession session app = evalStateT (runReaderT session app) initState++data SRequest = SRequest+ { simpleRequest :: Request+ , simpleRequestBody :: L.ByteString+ }+data SResponse = SResponse+ { simpleStatus :: Status+ , simpleHeaders :: [(CIByteString, ByteString)]+ , simpleBody :: L.ByteString+ }+ deriving (Show, Eq)+request :: Request -> Session SResponse+request = srequest . flip SRequest L.empty++srequest :: SRequest -> Session SResponse+srequest (SRequest req bod) = do+ app <- ask+ res <- liftIO $ run_ $ enumList 4 (L.toChunks bod) $$ app req+ sres <- liftIO $ runResponse res+ -- FIXME cookie processing+ return sres++runResponse :: Response -> IO SResponse+runResponse res =+ responseEnumerator res go+ where+ go s h = do+ bss <- joinI $ builderToByteString $$ consume+ return $ SResponse s h $ L.fromChunks bss++assertBool :: String -> Bool -> Session ()+assertBool s b = liftIO $ H.assertBool s b++assertString :: String -> Session ()+assertString s = liftIO $ H.assertString s++assertContentType :: ByteString -> SResponse -> Session ()+assertContentType ct SResponse{simpleHeaders = h} =+ case lookup "content-type" h of+ Nothing -> assertString $ concat+ [ "Expected content type "+ , show ct+ , ", but no content type provided"+ ]+ Just ct' -> assertBool (concat+ [ "Expected content type "+ , show ct+ , ", but received "+ , show ct'+ ]) (go ct == go ct')+ where+ go = S8.takeWhile (/= ';')++assertStatus :: Int -> SResponse -> Session ()+assertStatus i SResponse{simpleStatus = s} = assertBool (concat+ [ "Expected status code "+ , show i+ , ", but received "+ , show sc+ ]) $ i == sc+ where+ sc = statusCode s++assertBody :: L.ByteString -> SResponse -> Session ()+assertBody lbs SResponse{simpleBody = lbs'} = assertBool (concat+ [ "Expected response body "+ , show $ L8.unpack lbs+ , ", but received "+ , show $ L8.unpack lbs'+ ]) $ lbs == lbs'++assertHeader :: CIByteString -> S.ByteString -> SResponse -> Session ()+assertHeader header value SResponse{simpleHeaders = h} =+ case lookup header h of+ Nothing -> assertString $ concat+ [ "Expected header "+ , show header+ , " to be "+ , show value+ , ", but it was not present"+ ]+ Just value' -> assertBool (concat+ [ "Expected header "+ , show header+ , " to be "+ , show value+ , ", but received "+ , show value'+ ]) (value == value')++assertNoHeader :: CIByteString -> SResponse -> Session ()+assertNoHeader header SResponse{simpleHeaders = h} =+ case lookup header h of+ Nothing -> return ()+ Just s -> assertString $ concat+ [ "Unexpected header "+ , show header+ , " containing "+ , show s+ ]
+ Setup.lhs view
@@ -0,0 +1,8 @@+#!/usr/bin/env runhaskell++> module Main where+> import Distribution.Simple+> import System.Cmd (system)++> main :: IO ()+> main = defaultMain
+ wai-test.cabal view
@@ -0,0 +1,30 @@+name: wai-test+version: 0.0.0+license: BSD3+license-file: LICENSE+author: Michael Snoyman <michael@snoyman.com>+maintainer: Michael Snoyman <michael@snoyman.com>+synopsis: Unit test framework (built on HUnit) for WAI applications.+category: Testing, Web, Yesod+stability: Stable+cabal-version: >= 1.6+build-type: Simple+homepage: http://github.com/snoyberg/wai-test/++library+ build-depends: base >= 4 && < 5+ , wai >= 0.3 && < 0.4+ , bytestring >= 0.9.1.4 && < 0.10+ , blaze-builder >= 0.2.1 && < 0.3+ , transformers >= 0.2 && < 0.3+ , containers >= 0.2 && < 0.5+ , enumerator >= 0.4 && < 0.5+ , cookie >= 0.0 && < 0.1+ , blaze-builder-enumerator >= 0.2 && < 0.3+ , HUnit >= 1.2 && < 1.3+ exposed-modules: Network.Wai.Test+ ghc-options: -Wall++source-repository head+ type: git+ location: git://github.com/snoyberg/wai-test.git