on master help sign in
Initial code
commit13683e424875e2c6d6886a1cef6d34f059059efc authorMichael Snoyman <michael@snoyman.com> dateWed 22 Dec 2010, 22:51 (16 years ago) parente48954d
4 files changed+154
LICENSE+25 Network/Wai/Test.hs+91 Setup.lhs+8 wai-test.cabal+30
LICENSEnew file+25
@@ -0,0 +1,25 @@
1+The following license covers this documentation, and the source code, except
2+where otherwise indicated.
3+
4+Copyright 2010, Michael Snoyman. All rights reserved.
5+
6+Redistribution and use in source and binary forms, with or without
7+modification, are permitted provided that the following conditions are met:
8+
9+* Redistributions of source code must retain the above copyright notice, this
10+ list of conditions and the following disclaimer.
11+
12+* Redistributions in binary form must reproduce the above copyright notice,
13+ this list of conditions and the following disclaimer in the documentation
14+ and/or other materials provided with the distribution.
15+
16+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR
17+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
20+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
24+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Network/Wai/Test.hsnew file+91
@@ -0,0 +1,91 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Network.Wai.Test
3+ ( -- * Session
4+ Session
5+ , runSession
6+ -- * Requests
7+ , request
8+ , SResponse (..)
9+ -- * Assertions
10+ , assertStatus
11+ , assertContentType
12+ ) where
13+import Network.Wai
14+import qualified Test.HUnit.Base as H
15+import Control.Monad.IO.Class (liftIO)
16+import Control.Monad.Trans.State (StateT, evalStateT, get, put)
17+import Control.Monad.Trans.Reader (ReaderT, runReaderT, ask)
18+import Data.Map (Map)
19+import qualified Data.Map as Map
20+import Data.ByteString (ByteString)
21+import qualified Data.ByteString as S
22+import qualified Data.ByteString.Char8 as S8
23+import Data.Enumerator (joinI, consume, ($$))
24+import Blaze.ByteString.Builder.Enumerator (builderToByteString)
25+import qualified Data.ByteString.Lazy as L
26+
27+type Session = ReaderT Application (StateT ClientState IO)
28+
29+data ClientState = ClientState
30+ { clientCookies :: Map ByteString ByteString
31+ }
32+
33+initState :: ClientState
34+initState = ClientState Map.empty
35+
36+runSession :: Session a -> Application -> IO a
37+runSession session app = evalStateT (runReaderT session app) initState
38+
39+data SResponse = SResponse
40+ { simpleStatus :: Status
41+ , simpleHeaders :: [(CIByteString, ByteString)]
42+ , simpleBody :: L.ByteString
43+ }
44+ deriving (Show, Eq)
45+request :: Request -> Session SResponse
46+request req = do
47+ app <- ask
48+ sres <- liftIO $ app req >>= runResponse
49+ -- FIXME cookie processing
50+ return sres
51+
52+runResponse :: Response -> IO SResponse
53+runResponse res =
54+ responseEnumerator res go
55+ where
56+ go s h = do
57+ bss <- joinI $ builderToByteString $$ consume
58+ return $ SResponse s h $ L.fromChunks bss
59+
60+assertBool :: String -> Bool -> Session ()
61+assertBool s b = liftIO $ H.assertBool s b
62+
63+assertString :: String -> Session ()
64+assertString s = liftIO $ H.assertString s
65+
66+assertContentType :: ByteString -> SResponse -> Session ()
67+assertContentType ct SResponse{simpleHeaders = h} =
68+ case lookup "content-type" h of
69+ Nothing -> assertString $ concat
70+ [ "Expected content type "
71+ , show ct
72+ , ", but no content type provided"
73+ ]
74+ Just ct' -> assertBool (concat
75+ [ "Expected content type "
76+ , show ct
77+ , ", but received "
78+ , show ct'
79+ ]) (go ct == go ct')
80+ where
81+ go = S8.takeWhile (/= ';')
82+
83+assertStatus :: Int -> SResponse -> Session ()
84+assertStatus i SResponse{simpleStatus = s} = assertBool (concat
85+ [ "Expected status code "
86+ , show i
87+ , ", but received "
88+ , show sc
89+ ]) $ i == sc
90+ where
91+ sc = statusCode s
Setup.lhsnew file+8
@@ -0,0 +1,8 @@
1+#!/usr/bin/env runhaskell
2+
3+> module Main where
4+> import Distribution.Simple
5+> import System.Cmd (system)
6+
7+> main :: IO ()
8+> main = defaultMain
wai-test.cabalnew file+30
@@ -0,0 +1,30 @@
1+name: wai-test
2+version: 0.0.0
3+license: BSD3
4+license-file: LICENSE
5+author: Michael Snoyman <michael@snoyman.com>
6+maintainer: Michael Snoyman <michael@snoyman.com>
7+synopsis: Unit test framework (built on HUnit) for WAI applications.
8+category: Testing, Web, Yesod
9+stability: Stable
10+cabal-version: >= 1.6
11+build-type: Simple
12+homepage: http://github.com/snoyberg/wai-test/
13+
14+library
15+ build-depends: base >= 4 && < 5
16+ , wai >= 0.3 && < 0.4
17+ , bytestring >= 0.9.1.4 && < 0.10
18+ , blaze-builder >= 0.2.1 && < 0.3
19+ , transformers >= 0.2 && < 0.3
20+ , containers >= 0.2 && < 0.5
21+ , enumerator >= 0.4 && < 0.5
22+ , cookie >= 0.0 && < 0.1
23+ , blaze-builder-enumerator >= 0.2 && < 0.3
24+ , HUnit >= 1.2 && < 1.3
25+ exposed-modules: Network.Wai.Test
26+ ghc-options: -Wall
27+
28+source-repository head
29+ type: git
30+ location: git://github.com/snoyberg/wai-test.git