make yesod-test work with mongo
depends on resource-pool branch of persistent
This commit is contained in:
parent
d739955944
commit
fa291bf9fe
@ -1,5 +1,6 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-|
|
{-|
|
||||||
Yesod.Test is a pragmatic framework for testing web applications built
|
Yesod.Test is a pragmatic framework for testing web applications built
|
||||||
using wai and persistent.
|
using wai and persistent.
|
||||||
@ -16,7 +17,7 @@ This is very useful for testing web applications built in yesod for example,
|
|||||||
were your forms may have field names generated by the framework or a randomly
|
were your forms may have field names generated by the framework or a randomly
|
||||||
generated '_nonce' field.
|
generated '_nonce' field.
|
||||||
|
|
||||||
Your database is also directly available so you can use runDB to set up
|
Your database is also directly available so you can use runDBRunner to set up
|
||||||
backend pre-conditions, or to assert that your session is having the desired effect.
|
backend pre-conditions, or to assert that your session is having the desired effect.
|
||||||
|
|
||||||
-}
|
-}
|
||||||
@ -47,7 +48,7 @@ module Yesod.Test (
|
|||||||
addNonce, addNonce_,
|
addNonce, addNonce_,
|
||||||
|
|
||||||
-- * Running database queries
|
-- * Running database queries
|
||||||
runDB,
|
runDBRunner,
|
||||||
|
|
||||||
-- * Assertions
|
-- * Assertions
|
||||||
assertEqual, assertHeader, assertNoHeader, statusIs, bodyEquals, bodyContains,
|
assertEqual, assertHeader, assertNoHeader, statusIs, bodyEquals, bodyContains,
|
||||||
@ -84,25 +85,26 @@ import qualified Control.Monad.Trans.State as ST
|
|||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
import System.IO
|
import System.IO
|
||||||
import Yesod.Test.TransversingCSS
|
import Yesod.Test.TransversingCSS
|
||||||
import Database.Persist.GenericSql
|
|
||||||
import Data.Monoid (mappend)
|
import Data.Monoid (mappend)
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
import Data.Text.Lazy.Encoding (encodeUtf8, decodeUtf8)
|
import Data.Text.Lazy.Encoding (encodeUtf8, decodeUtf8)
|
||||||
import Text.XML.Cursor hiding (element)
|
import Text.XML.Cursor hiding (element)
|
||||||
import qualified Text.XML.Cursor as C
|
import qualified Text.XML.Cursor as C
|
||||||
import qualified Text.HTML.DOM as HD
|
import qualified Text.HTML.DOM as HD
|
||||||
|
import Data.Conduit.Pool (Pool)
|
||||||
|
import Control.Monad.Trans.Control (MonadBaseControl)
|
||||||
|
|
||||||
-- | The state used in 'describe' to build a list of specs
|
-- | The state used in 'describe' to build a list of specs
|
||||||
data SpecsData = SpecsData Application ConnectionPool [Core.Spec]
|
data SpecsData conn = SpecsData Application (Pool conn) [Core.Spec]
|
||||||
|
|
||||||
-- | The specs state monad is where 'describe' runs.
|
-- | The specs state monad is where 'describe' runs.
|
||||||
type Specs = ST.StateT SpecsData IO ()
|
type Specs conn = ST.StateT (SpecsData conn) IO ()
|
||||||
|
|
||||||
-- | The state used in a single test case defined using 'it'
|
-- | The state used in a single test case defined using 'it'
|
||||||
data OneSpecData = OneSpecData Application ConnectionPool CookieValue (Maybe SResponse)
|
data OneSpecData conn = OneSpecData Application (Pool conn) CookieValue (Maybe SResponse)
|
||||||
|
|
||||||
-- | The OneSpec state monad is where 'it' runs.
|
-- | The OneSpec state monad is where 'it' runs.
|
||||||
type OneSpec = ST.StateT OneSpecData IO
|
type OneSpec conn = ST.StateT (OneSpecData conn) IO
|
||||||
|
|
||||||
data RequestBuilderData = RequestBuilderData [RequestPart] (Maybe SResponse)
|
data RequestBuilderData = RequestBuilderData [RequestPart] (Maybe SResponse)
|
||||||
|
|
||||||
@ -121,7 +123,7 @@ type RequestBuilder = ST.StateT RequestBuilderData IO
|
|||||||
-- the last received response.
|
-- the last received response.
|
||||||
class HoldsResponse a where
|
class HoldsResponse a where
|
||||||
readResponse :: a -> Maybe SResponse
|
readResponse :: a -> Maybe SResponse
|
||||||
instance HoldsResponse OneSpecData where
|
instance HoldsResponse (OneSpecData conn) where
|
||||||
readResponse (OneSpecData _ _ _ x) = x
|
readResponse (OneSpecData _ _ _ x) = x
|
||||||
instance HoldsResponse RequestBuilderData where
|
instance HoldsResponse RequestBuilderData where
|
||||||
readResponse (RequestBuilderData _ x) = x
|
readResponse (RequestBuilderData _ x) = x
|
||||||
@ -136,21 +138,21 @@ type CookieValue = ByteString
|
|||||||
--
|
--
|
||||||
-- Look at the examples directory on this package to get an idea of the (small) amount of
|
-- Look at the examples directory on this package to get an idea of the (small) amount of
|
||||||
-- boilerplate code you'll need to write before calling this.
|
-- boilerplate code you'll need to write before calling this.
|
||||||
runTests :: Application -> ConnectionPool -> Specs -> IO ()
|
runTests :: Application -> Pool conn -> Specs conn -> IO ()
|
||||||
runTests app connection specsDef = do
|
runTests app connection specsDef = do
|
||||||
(SpecsData _ _ specs) <- ST.execStateT specsDef (SpecsData app connection [])
|
(SpecsData _ _ specs) <- ST.execStateT specsDef (SpecsData app connection [])
|
||||||
Runner.hspec specs
|
Runner.hspec specs
|
||||||
|
|
||||||
-- | Start describing a Tests suite keeping cookies and a reference to the tested 'Application'
|
-- | Start describing a Tests suite keeping cookies and a reference to the tested 'Application'
|
||||||
-- and 'ConnectionPool'
|
-- and 'ConnectionPool'
|
||||||
describe :: String -> Specs -> Specs
|
describe :: String -> Specs conn -> Specs conn
|
||||||
describe label action = do
|
describe label action = do
|
||||||
sData <- ST.get
|
sData <- ST.get
|
||||||
SpecsData app conn specs <- liftIO $ ST.execStateT action sData
|
SpecsData app conn specs <- liftIO $ ST.execStateT action sData
|
||||||
ST.put $ SpecsData app conn [Core.describe label specs]
|
ST.put $ SpecsData app conn [Core.describe label specs]
|
||||||
|
|
||||||
-- | Describe a single test that keeps cookies, and a reference to the last response.
|
-- | Describe a single test that keeps cookies, and a reference to the last response.
|
||||||
it :: String -> OneSpec () -> Specs
|
it :: String -> OneSpec conn () -> Specs conn
|
||||||
it label action = do
|
it label action = do
|
||||||
SpecsData app conn specs <- ST.get
|
SpecsData app conn specs <- ST.get
|
||||||
let spec = Core.it label $ do
|
let spec = Core.it label $ do
|
||||||
@ -177,7 +179,7 @@ htmlQuery query = withResponse $ \ res ->
|
|||||||
Right matches -> return $ map (encodeUtf8 . TL.pack) matches
|
Right matches -> return $ map (encodeUtf8 . TL.pack) matches
|
||||||
|
|
||||||
-- | Asserts that the two given values are equal.
|
-- | Asserts that the two given values are equal.
|
||||||
assertEqual :: (Eq a) => String -> a -> a -> OneSpec ()
|
assertEqual :: (Eq a) => String -> a -> a -> OneSpec conn ()
|
||||||
assertEqual msg a b = liftIO $ HUnit.assertBool msg (a == b)
|
assertEqual msg a b = liftIO $ HUnit.assertBool msg (a == b)
|
||||||
|
|
||||||
-- | Assert the last response status is as expected.
|
-- | Assert the last response status is as expected.
|
||||||
@ -341,24 +343,24 @@ addNonce :: RequestBuilder ()
|
|||||||
addNonce = addNonce_ ""
|
addNonce = addNonce_ ""
|
||||||
|
|
||||||
-- | Perform a POST request to url, using params
|
-- | Perform a POST request to url, using params
|
||||||
post :: BS8.ByteString -> RequestBuilder () -> OneSpec ()
|
post :: BS8.ByteString -> RequestBuilder () -> OneSpec conn ()
|
||||||
post url paramsBuild = do
|
post url paramsBuild = do
|
||||||
doRequest "POST" url paramsBuild
|
doRequest "POST" url paramsBuild
|
||||||
|
|
||||||
-- | Perform a POST request without params
|
-- | Perform a POST request without params
|
||||||
post_ :: BS8.ByteString -> OneSpec ()
|
post_ :: BS8.ByteString -> OneSpec conn ()
|
||||||
post_ = flip post $ return ()
|
post_ = flip post $ return ()
|
||||||
|
|
||||||
-- | Perform a GET request to url, using params
|
-- | Perform a GET request to url, using params
|
||||||
get :: BS8.ByteString -> RequestBuilder () -> OneSpec ()
|
get :: BS8.ByteString -> RequestBuilder () -> OneSpec conn ()
|
||||||
get url paramsBuild = doRequest "GET" url paramsBuild
|
get url paramsBuild = doRequest "GET" url paramsBuild
|
||||||
|
|
||||||
-- | Perform a GET request without params
|
-- | Perform a GET request without params
|
||||||
get_ :: BS8.ByteString -> OneSpec ()
|
get_ :: BS8.ByteString -> OneSpec conn ()
|
||||||
get_ = flip get $ return ()
|
get_ = flip get $ return ()
|
||||||
|
|
||||||
-- | General interface to performing requests, letting you specify the request method and extra headers.
|
-- | General interface to performing requests, letting you specify the request method and extra headers.
|
||||||
doRequest :: H.Method -> BS8.ByteString -> RequestBuilder a -> OneSpec ()
|
doRequest :: H.Method -> BS8.ByteString -> RequestBuilder a -> OneSpec conn ()
|
||||||
doRequest method url paramsBuild = do
|
doRequest method url paramsBuild = do
|
||||||
OneSpecData app conn cookie mRes <- ST.get
|
OneSpecData app conn cookie mRes <- ST.get
|
||||||
RequestBuilderData parts _ <- liftIO $ ST.execStateT paramsBuild $ RequestBuilderData [] mRes
|
RequestBuilderData parts _ <- liftIO $ ST.execStateT paramsBuild $ RequestBuilderData [] mRes
|
||||||
@ -413,10 +415,13 @@ doRequest method url paramsBuild = do
|
|||||||
|
|
||||||
-- | Run a persistent db query. For asserting on the results of performed actions
|
-- | Run a persistent db query. For asserting on the results of performed actions
|
||||||
-- or setting up pre-conditions. At the moment this part is still very raw.
|
-- or setting up pre-conditions. At the moment this part is still very raw.
|
||||||
runDB :: SqlPersist IO a -> OneSpec a
|
--
|
||||||
runDB query = do
|
-- It is intended that you parametize the first argument of this function for your backend
|
||||||
|
-- runDB = runDBRunnder SqlPersist
|
||||||
|
runDBRunner :: (MonadBaseControl IO m, MonadIO m) => (poolrunner m a -> Pool conn -> IO a) -> poolrunner m a -> OneSpec conn a
|
||||||
|
runDBRunner poolRunner query = do
|
||||||
OneSpecData _ pool _ _ <- ST.get
|
OneSpecData _ pool _ _ <- ST.get
|
||||||
liftIO $ runSqlPool query pool
|
liftIO $ poolRunner query pool
|
||||||
|
|
||||||
-- Yes, just a shortcut
|
-- Yes, just a shortcut
|
||||||
failure :: (MonadIO a) => T.Text -> a b
|
failure :: (MonadIO a) => T.Text -> a b
|
||||||
|
|||||||
@ -33,6 +33,8 @@ library
|
|||||||
, html-conduit >= 0.1 && < 0.2
|
, html-conduit >= 0.1 && < 0.2
|
||||||
, blaze-html >= 0.5 && < 0.6
|
, blaze-html >= 0.5 && < 0.6
|
||||||
, blaze-markup >= 0.5.1 && < 0.6
|
, blaze-markup >= 0.5.1 && < 0.6
|
||||||
|
, pool-conduit
|
||||||
|
, monad-control
|
||||||
|
|
||||||
exposed-modules: Yesod.Test
|
exposed-modules: Yesod.Test
|
||||||
Yesod.Test.CssQuery
|
Yesod.Test.CssQuery
|
||||||
|
|||||||
@ -2,9 +2,8 @@ Default: &defaults
|
|||||||
user: ~project~
|
user: ~project~
|
||||||
password: ~project~
|
password: ~project~
|
||||||
host: localhost
|
host: localhost
|
||||||
port: 27017
|
|
||||||
database: ~project~
|
database: ~project~
|
||||||
poolsize: 10
|
connections: 10
|
||||||
|
|
||||||
Development:
|
Development:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
@ -15,10 +14,11 @@ Testing:
|
|||||||
|
|
||||||
Staging:
|
Staging:
|
||||||
database: ~project~_staging
|
database: ~project~_staging
|
||||||
poolsize: 100
|
connections: 100
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
|
||||||
Production:
|
Production:
|
||||||
database: ~project~_production
|
database: ~project~_production
|
||||||
poolsize: 100
|
connections: 100
|
||||||
|
host: localhost
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user