sydtest-yesod-0.3.0.1: blog-example/Example/BlogSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Example.BlogSpec (spec) where
import Control.Monad.Reader
import qualified Data.Text as T
import Database.Persist (selectList)
import Database.Persist.Sql (Entity (..), SqlPersistT)
import Example.Blog
import Network.HTTP.Client as HTTP
import Path
import Path.IO
import Test.QuickCheck
import Test.Syd
import Test.Syd.Path
import Test.Syd.Persistent.Sqlite
import Test.Syd.Wai (managerSpec)
import Test.Syd.Yesod
appSetupFunc :: HTTP.Manager -> SetupFunc App
appSetupFunc _ = do
tdir <- tempDirSetupFunc "sydtest-yesod"
sessionKeyFile <- resolveFile tdir "client_session_key.aes"
pool <- connectionPoolSetupFunc migrateThoughts
pure $
App
{ appSessionKeyFile = fromAbsFile sessionKeyFile,
appConnectionPool = pool
}
testDB :: SqlPersistT IO a -> YesodClientM App a
testDB func = do
pool <- asks $ appConnectionPool . yesodClientSite
liftIO $ runSqlPool func pool
spec :: Spec
spec = managerSpec . modifyMaxSuccess (`div` 20) . yesodSpecWithSiteSetupFunc appSetupFunc $ do
-- A simple read-only test: We can request the home page succesfully.
it "can GET the home page" $ do
get HomeR
statusIs 200
-- A simple test that shows a post request, and shows that empty forms will not be accepted.
it "cannot post if the form data is missing" $ do
get NewThoughtR
statusIs 200
request $ do
setMethod "POST"
setUrl NewThoughtR
addToken -- For the CSRF protection
statusIs 400
-- A simple form POST request test.
-- Each part of the form needs to be added using 'addPostParam'
-- Don't forget the 'addToken' piece to make sure you don't run into CSRF errors.
it "can post this example blogpost" $ do
get NewThoughtR
statusIs 200
request $ do
setMethod "POST"
setUrl NewThoughtR
addToken
addPostParam "title" "example title"
addPostParam "contents" "example contents"
statusIs 200
-- A property test that does the same as the simple POST request test above,
-- Note that ut for _any_ title and contents instead of specific above.
-- Note that we need to use nonempty title and contents so they don't look missing to the server.
it "can post any blogpost" $ \yc ->
forAll (arbitrary `suchThat` (not . null)) $ \title ->
forAll (arbitrary `suchThat` (not . null)) $ \contents ->
runYesodClientM yc $ do
get NewThoughtR
statusIs 200
request $ do
setMethod "POST"
setUrl NewThoughtR
addToken
addPostParam "title" (T.pack title)
addPostParam "contents" (T.pack contents)
statusIs 200
-- A proprety test that does the above, but also goes and finds the thought that was posted,
-- both on the page and in the database.
-- We generate alphanumeric titles and contents just so that we don't have to depend on `genvalidity` here and figure out encodings correctly.
it "can post any blogpost and then look it up" $ \yc ->
forAll (listOf (choose ('a', 'z')) `suchThat` (not . null)) $ \title ->
forAll (listOf (choose ('a', 'z')) `suchThat` (not . null)) $ \contents ->
runYesodClientM yc $ do
let titleText = T.pack title
let contentsText = T.pack contents
get NewThoughtR
statusIs 200
request $ do
setMethod "POST"
setUrl NewThoughtR
addToken
addPostParam "title" titleText
addPostParam "contents" contentsText
statusIs 200
thoughts <- testDB $ selectList [] []
Entity thoughtId thought <- case thoughts of
[] -> liftIO $ expectationFailure "Expected to find at least one thought, found none."
[e] -> pure e
_ -> liftIO $ expectationFailure "Found more than one thought."
liftIO $ do
thoughtTitle thought `shouldBe` titleText
thoughtContents thought `shouldBe` contentsText
get $ ThoughtR thoughtId
bodyContains $ T.unpack titleText
bodyContains $ T.unpack contentsText
statusIs 200