{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} module TestImport ( module TestImport , module X ) where import Application (makeFoundation, makeLogWare) import ClassyPrelude as X hiding (delete, deleteBy, Handler) import Database.Persist as X hiding (get) import Database.Persist.Sql (SqlPersistM, SqlBackend, runSqlPersistMPool, rawExecute, rawSql, unSingle, connEscapeName) import Foundation as X import Model as X import Test.Hspec as X import Yesod.Default.Config2 (useEnv, loadYamlSettings) import Yesod.Auth as X import Yesod.Test as X import Yesod.Core.Unsafe (fakeHandlerGetLogger) runDB :: SqlPersistM a -> YesodExample App a runDB query = do app <- getTestYesod liftIO $ runDBWithApp app query runDBWithApp :: App -> SqlPersistM a -> IO a runDBWithApp app query = runSqlPersistMPool query (appConnPool app) runHandler :: Handler a -> YesodExample App a runHandler handler = do app <- getTestYesod fakeHandlerGetLogger appLogger app handler withApp :: SpecWith (TestApp App) -> Spec withApp = before $ do settings <- loadYamlSettings ["config/test-settings.yml", "config/settings.yml"] [] useEnv foundation <- makeFoundation settings wipeDB foundation logWare <- liftIO $ makeLogWare foundation return (foundation, logWare) -- This function will truncate all of the tables in your database. -- 'withApp' calls it before each test, creating a clean environment for each -- spec to run in. wipeDB :: App -> IO () wipeDB app = runDBWithApp app $ do tables <- getTables sqlBackend <- ask let queries = map (\t -> "TRUNCATE TABLE " ++ connEscapeName sqlBackend (DBName t)) tables -- In MySQL, a table cannot be truncated if another table references it via foreign key. -- Since we're wiping both the parent and child tables, though, it's safe -- to temporarily disable this check. rawExecute "SET foreign_key_checks = 0;" [] forM_ queries (\q -> rawExecute q []) rawExecute "SET foreign_key_checks = 1;" [] getTables :: MonadIO m => ReaderT SqlBackend m [Text] getTables = do tables <- rawSql "SHOW TABLES;" [] return $ map unSingle tables -- | Authenticate as a user. This relies on the `auth-dummy-login: true` flag -- being set in test-settings.yaml, which enables dummy authentication in -- Foundation.hs authenticateAs :: Entity User -> YesodExample App () authenticateAs (Entity _ u) = do request $ do setMethod "POST" addPostParam "ident" $ userIdent u setUrl $ AuthR $ PluginR "dummy" [] -- | Create a user. The dummy email entry helps to confirm that foreign-key -- checking is switched off in wipeDB for those database backends which need it. createUser :: Text -> YesodExample App (Entity User) createUser ident = runDB $ do user <- insertEntity User { userIdent = ident , userPassword = Nothing } _ <- insert Email { emailEmail = ident , emailUserId = Just $ entityKey user , emailVerkey = Nothing } return user