{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
module Freckle.App.Test.Yesod
(
MonadYesodExample (..)
, request
, RequestBuilder
, setMethod
, setUrl
, setRequestBody
, addGetParam
, addPostParam
, addRequestHeader
, addJsonHeaders
, setLanguage
, addAcceptLanguage
, addFile
, get
, post
, followRedirect
, getRawBody
, getCsvBody
, getJsonBody
, getResponse
, withResponse
, SResponse (..)
, statusIs
, assertHeader
, assertHeaderContains
, assertHeaderSatisfies
, bodyContains
, getRequestCookies
, testSetCookie
, testDeleteCookie
, testClearCookies
, SIO
, TestApp
, YesodExample
, YesodExampleData (..)
, getTestYesod
)
where
import Freckle.App.Prelude
import Blammo.Logging (LoggingT)
import Control.Monad.Except (ExceptT)
import Control.Monad.State (StateT)
import Control.Monad.Trans.Maybe (MaybeT)
import Control.Monad.Trans.Resource (ResourceT)
import Control.Monad.Validate (ValidateT)
import Data.Aeson (FromJSON, eitherDecode)
import Data.BCP47 (BCP47)
import qualified Data.BCP47 as BCP47
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
import Data.CaseInsensitive (CI)
import Data.Csv (FromNamedRecord, decodeByName)
import qualified Data.Text as T
import qualified Data.Vector as V
import Network.HTTP.Types.Header (hAccept, hAcceptLanguage, hContentType)
import Network.Wai.Test (SResponse (..))
import Test.Hspec.Expectations.Lifted (expectationFailure)
import Web.Cookie (SetCookie)
import Yesod.Core (RedirectUrl, Yesod)
import Yesod.Test
( RequestBuilder
, SIO
, TestApp
, YesodExample
, YesodExampleData (..)
, addFile
, addGetParam
, addPostParam
, addRequestHeader
, getRequestCookies
, setMethod
, setRequestBody
, setUrl
, withResponse
)
import qualified Yesod.Test
class (MonadIO m, Yesod site) => MonadYesodExample site m | m -> site where
liftYesodExample :: YesodExample site a -> m a
instance Yesod site => MonadYesodExample site (YesodExample site) where
liftYesodExample :: forall a. YesodExample site a -> YesodExample site a
liftYesodExample = YesodExample site a -> YesodExample site a
forall a. a -> a
id
instance MonadYesodExample site m => MonadYesodExample site (StateT s m) where
liftYesodExample :: forall a. YesodExample site a -> StateT s m a
liftYesodExample = m a -> StateT s m a
forall (m :: * -> *) a. Monad m => m a -> StateT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> StateT s m a)
-> (YesodExample site a -> m a)
-> YesodExample site a
-> StateT s m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YesodExample site a -> m a
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample
instance MonadYesodExample site m => MonadYesodExample site (ReaderT r m) where
liftYesodExample :: forall a. YesodExample site a -> ReaderT r m a
liftYesodExample = m a -> ReaderT r m a
forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ReaderT r m a)
-> (YesodExample site a -> m a)
-> YesodExample site a
-> ReaderT r m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YesodExample site a -> m a
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample
instance MonadYesodExample site m => MonadYesodExample site (ValidateT e m) where
liftYesodExample :: forall a. YesodExample site a -> ValidateT e m a
liftYesodExample = m a -> ValidateT e m a
forall (m :: * -> *) a. Monad m => m a -> ValidateT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ValidateT e m a)
-> (YesodExample site a -> m a)
-> YesodExample site a
-> ValidateT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YesodExample site a -> m a
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample
instance MonadYesodExample site m => MonadYesodExample site (MaybeT m) where
liftYesodExample :: forall a. YesodExample site a -> MaybeT m a
liftYesodExample = m a -> MaybeT m a
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> MaybeT m a)
-> (YesodExample site a -> m a)
-> YesodExample site a
-> MaybeT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YesodExample site a -> m a
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample
instance MonadYesodExample site m => MonadYesodExample site (ExceptT e m) where
liftYesodExample :: forall a. YesodExample site a -> ExceptT e m a
liftYesodExample = m a -> ExceptT e m a
forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ExceptT e m a)
-> (YesodExample site a -> m a)
-> YesodExample site a
-> ExceptT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YesodExample site a -> m a
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample
instance MonadYesodExample site m => MonadYesodExample site (ResourceT m) where
liftYesodExample :: forall a. YesodExample site a -> ResourceT m a
liftYesodExample = m a -> ResourceT m a
forall (m :: * -> *) a. Monad m => m a -> ResourceT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ResourceT m a)
-> (YesodExample site a -> m a)
-> YesodExample site a
-> ResourceT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YesodExample site a -> m a
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample
instance MonadYesodExample site m => MonadYesodExample site (LoggingT m) where
liftYesodExample :: forall a. YesodExample site a -> LoggingT m a
liftYesodExample = m a -> LoggingT m a
forall (m :: * -> *) a. Monad m => m a -> LoggingT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> LoggingT m a)
-> (YesodExample site a -> m a)
-> YesodExample site a
-> LoggingT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YesodExample site a -> m a
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample
bodyContains :: forall m site. MonadYesodExample site m => String -> m ()
bodyContains :: forall (m :: * -> *) site.
MonadYesodExample site m =>
String -> m ()
bodyContains = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ())
-> (String -> YesodExample site ()) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> YesodExample site ()
forall site. HasCallStack => String -> YesodExample site ()
Yesod.Test.bodyContains
testClearCookies :: forall m site. MonadYesodExample site m => m ()
testClearCookies :: forall (m :: * -> *) site. MonadYesodExample site m => m ()
testClearCookies = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample YesodExample site ()
forall site. YesodExample site ()
Yesod.Test.testClearCookies
testDeleteCookie
:: forall m site. MonadYesodExample site m => ByteString -> m ()
testDeleteCookie :: forall (m :: * -> *) site.
MonadYesodExample site m =>
ByteString -> m ()
testDeleteCookie = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ())
-> (ByteString -> YesodExample site ()) -> ByteString -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> YesodExample site ()
forall site. ByteString -> YesodExample site ()
Yesod.Test.testDeleteCookie
testSetCookie :: forall m site. MonadYesodExample site m => SetCookie -> m ()
testSetCookie :: forall (m :: * -> *) site.
MonadYesodExample site m =>
SetCookie -> m ()
testSetCookie = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ())
-> (SetCookie -> YesodExample site ()) -> SetCookie -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SetCookie -> YesodExample site ()
forall site. SetCookie -> YesodExample site ()
Yesod.Test.testSetCookie
getJsonBody :: forall a m site. (MonadYesodExample site m, FromJSON a) => m a
getJsonBody :: forall a (m :: * -> *) site.
(MonadYesodExample site m, FromJSON a) =>
m a
getJsonBody = (String -> m a) -> (a -> m a) -> Either String a -> m a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> m a
forall {m :: * -> *} {a}. MonadIO m => String -> m a
err a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String a -> m a)
-> (ByteString -> Either String a) -> ByteString -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String a
forall a. FromJSON a => ByteString -> Either String a
eitherDecode (ByteString -> m a) -> m ByteString -> m a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m ByteString
forall (m :: * -> *) site. MonadYesodExample site m => m ByteString
getRawBody
where
err :: String -> m a
err String
e = String -> m a
forall (m :: * -> *) a. (MonadIO m, HasCallStack) => String -> m a
throwString (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ String
"Error decoding JSON response body: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
e
getCsvBody
:: forall a m site. (MonadYesodExample site m, FromNamedRecord a) => m [a]
getCsvBody :: forall a (m :: * -> *) site.
(MonadYesodExample site m, FromNamedRecord a) =>
m [a]
getCsvBody = (String -> m [a])
-> ((Header, Vector a) -> m [a])
-> Either String (Header, Vector a)
-> m [a]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> m [a]
forall {m :: * -> *} {a}. MonadIO m => String -> m a
err ([a] -> m [a]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([a] -> m [a])
-> ((Header, Vector a) -> [a]) -> (Header, Vector a) -> m [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector a -> [a]
forall a. Vector a -> [a]
V.toList (Vector a -> [a])
-> ((Header, Vector a) -> Vector a) -> (Header, Vector a) -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Header, Vector a) -> Vector a
forall a b. (a, b) -> b
snd) (Either String (Header, Vector a) -> m [a])
-> (ByteString -> Either String (Header, Vector a))
-> ByteString
-> m [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String (Header, Vector a)
forall a.
FromNamedRecord a =>
ByteString -> Either String (Header, Vector a)
decodeByName (ByteString -> m [a]) -> m ByteString -> m [a]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m ByteString
forall (m :: * -> *) site. MonadYesodExample site m => m ByteString
getRawBody
where
err :: String -> m a
err String
e = String -> m a
forall (m :: * -> *) a. (MonadIO m, HasCallStack) => String -> m a
throwString (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ String
"Error decoding CSV response body: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
e
getRawBody :: forall m site. MonadYesodExample site m => m BSL.ByteString
getRawBody :: forall (m :: * -> *) site. MonadYesodExample site m => m ByteString
getRawBody =
(SResponse -> ByteString) -> m SResponse -> m ByteString
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SResponse -> ByteString
simpleBody (m SResponse -> m ByteString)
-> (Maybe SResponse -> m SResponse)
-> Maybe SResponse
-> m ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m SResponse
-> (SResponse -> m SResponse) -> Maybe SResponse -> m SResponse
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> m SResponse
forall (m :: * -> *) a. (MonadIO m, HasCallStack) => String -> m a
throwString String
"Test response had no body") SResponse -> m SResponse
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
(Maybe SResponse -> m ByteString)
-> m (Maybe SResponse) -> m ByteString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m (Maybe SResponse)
forall (m :: * -> *) site.
MonadYesodExample site m =>
m (Maybe SResponse)
getResponse
getResponse :: forall m site. MonadYesodExample site m => m (Maybe SResponse)
getResponse :: forall (m :: * -> *) site.
MonadYesodExample site m =>
m (Maybe SResponse)
getResponse = YesodExample site (Maybe SResponse) -> m (Maybe SResponse)
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample YesodExample site (Maybe SResponse)
forall site. YesodExample site (Maybe SResponse)
Yesod.Test.getResponse
request
:: forall m site. MonadYesodExample site m => RequestBuilder site () -> m ()
request :: forall (m :: * -> *) site.
MonadYesodExample site m =>
RequestBuilder site () -> m ()
request = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ())
-> (RequestBuilder site () -> YesodExample site ())
-> RequestBuilder site ()
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RequestBuilder site () -> YesodExample site ()
forall site. RequestBuilder site () -> YesodExample site ()
Yesod.Test.request
setLanguage :: BCP47 -> RequestBuilder site ()
setLanguage :: forall site. BCP47 -> RequestBuilder site ()
setLanguage = Text -> Text -> RequestBuilder site ()
forall site. Text -> Text -> RequestBuilder site ()
addGetParam Text
"_LANG" (Text -> RequestBuilder site ())
-> (BCP47 -> Text) -> BCP47 -> RequestBuilder site ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BCP47 -> Text
BCP47.toText
addAcceptLanguage :: [Text] -> RequestBuilder site ()
addAcceptLanguage :: forall site. [Text] -> RequestBuilder site ()
addAcceptLanguage [Text]
values =
Header -> RequestBuilder site ()
forall site. Header -> RequestBuilder site ()
addRequestHeader (HeaderName
hAcceptLanguage, Text -> ByteString
encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
T.intercalate Text
"," [Text]
values)
addJsonHeaders :: RequestBuilder site ()
= do
Header -> RequestBuilder site ()
forall site. Header -> RequestBuilder site ()
addRequestHeader (HeaderName
hContentType, ByteString
"application/json")
Header -> RequestBuilder site ()
forall site. Header -> RequestBuilder site ()
addRequestHeader (HeaderName
hAccept, ByteString
"application/json")
statusIs
:: forall m site. (MonadYesodExample site m, HasCallStack) => Int -> m ()
statusIs :: forall (m :: * -> *) site.
(MonadYesodExample site m, HasCallStack) =>
Int -> m ()
statusIs = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ())
-> (Int -> YesodExample site ()) -> Int -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> YesodExample site ()
forall site. HasCallStack => Int -> YesodExample site ()
Yesod.Test.statusIs
assertHeaderSatisfies
:: forall m site
. MonadYesodExample site m
=> CI ByteString
-> String
-> (ByteString -> Bool)
-> m ()
HeaderName
header String
predicateDesc ByteString -> Bool
predicate = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ()) -> YesodExample site () -> m ()
forall a b. (a -> b) -> a -> b
$ (SResponse -> YesodExample site ()) -> YesodExample site ()
forall site a.
HasCallStack =>
(SResponse -> YesodExample site a) -> YesodExample site a
withResponse ((SResponse -> YesodExample site ()) -> YesodExample site ())
-> (SResponse -> YesodExample site ()) -> YesodExample site ()
forall a b. (a -> b) -> a -> b
$ \SResponse
res ->
case HeaderName -> [Header] -> Maybe ByteString
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup HeaderName
header ([Header] -> Maybe ByteString) -> [Header] -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ SResponse -> [Header]
simpleHeaders SResponse
res of
Just ByteString
value | ByteString -> Bool
predicate ByteString
value -> () -> YesodExample site ()
forall a. a -> SIO (YesodExampleData site) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just ByteString
value ->
String -> YesodExample site ()
forall (m :: * -> *). (HasCallStack, MonadIO m) => String -> m ()
expectationFailure (String -> YesodExample site ()) -> String -> YesodExample site ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ String
"Expected header "
, HeaderName -> String
forall a. Show a => a -> String
show HeaderName
header
, String
" "
, String
predicateDesc
, String
", but received "
, ByteString -> String
forall a. Show a => a -> String
show ByteString
value
]
Maybe ByteString
Nothing ->
String -> YesodExample site ()
forall (m :: * -> *). (HasCallStack, MonadIO m) => String -> m ()
expectationFailure (String -> YesodExample site ()) -> String -> YesodExample site ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ String
"Expected header "
, HeaderName -> String
forall a. Show a => a -> String
show HeaderName
header
, String
predicateDesc
, String
", but it was not present"
]
assertHeaderContains
:: MonadYesodExample site m
=> CI ByteString
-> ByteString
-> m ()
HeaderName
header ByteString
substring =
HeaderName -> String -> (ByteString -> Bool) -> m ()
forall (m :: * -> *) site.
MonadYesodExample site m =>
HeaderName -> String -> (ByteString -> Bool) -> m ()
assertHeaderSatisfies
HeaderName
header
(String
"to contain " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> ByteString -> String
forall a. Show a => a -> String
show ByteString
substring)
(ByteString
substring ByteString -> ByteString -> Bool
`BS.isInfixOf`)
assertHeader
:: forall m site
. MonadYesodExample site m
=> CI ByteString
-> ByteString
-> m ()
HeaderName
k ByteString
v = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ()) -> YesodExample site () -> m ()
forall a b. (a -> b) -> a -> b
$ HeaderName -> ByteString -> YesodExample site ()
forall site.
HasCallStack =>
HeaderName -> ByteString -> YesodExample site ()
Yesod.Test.assertHeader HeaderName
k ByteString
v
followRedirect
:: forall m site
. MonadYesodExample site m
=> m (Either Text Text)
followRedirect :: forall (m :: * -> *) site.
MonadYesodExample site m =>
m (Either Text Text)
followRedirect = YesodExample site (Either Text Text) -> m (Either Text Text)
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample YesodExample site (Either Text Text)
forall site. Yesod site => YesodExample site (Either Text Text)
Yesod.Test.followRedirect
get
:: forall url m site
. (MonadYesodExample site m, RedirectUrl site url)
=> url
-> m ()
get :: forall url (m :: * -> *) site.
(MonadYesodExample site m, RedirectUrl site url) =>
url -> m ()
get = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ())
-> (url -> YesodExample site ()) -> url -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. url -> YesodExample site ()
forall site url.
(Yesod site, RedirectUrl site url) =>
url -> YesodExample site ()
Yesod.Test.get
post
:: forall url m site
. (MonadYesodExample site m, RedirectUrl site url)
=> url
-> m ()
post :: forall url (m :: * -> *) site.
(MonadYesodExample site m, RedirectUrl site url) =>
url -> m ()
post = YesodExample site () -> m ()
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample (YesodExample site () -> m ())
-> (url -> YesodExample site ()) -> url -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. url -> YesodExample site ()
forall site url.
(Yesod site, RedirectUrl site url) =>
url -> YesodExample site ()
Yesod.Test.post
getTestYesod :: forall m site. MonadYesodExample site m => m site
getTestYesod :: forall (m :: * -> *) site. MonadYesodExample site m => m site
getTestYesod = YesodExample site site -> m site
forall a. YesodExample site a -> m a
forall site (m :: * -> *) a.
MonadYesodExample site m =>
YesodExample site a -> m a
liftYesodExample YesodExample site site
forall site. YesodExample site site
Yesod.Test.getTestYesod