serversession/examples/serversession-example-yesod-persistent/test/TestImport.hs
Felipe Lessa 23584a9c47 Add new Yesod+Persistent example, currently just "yesod init".
Separating "yesod init" commit from others in order to be clearer what
changes were made to the scaffold.

[ci skip]
2015-06-01 13:01:23 -03:00

75 lines
2.9 KiB
Haskell

module TestImport
( module TestImport
, module X
) where
import Application (makeFoundation)
import ClassyPrelude as X
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 Text.Shakespeare.Text (st)
import Yesod.Default.Config2 (ignoreEnv, loadAppSettings)
import Yesod.Test as X
-- Wiping the database
import Database.Persist.Sqlite (sqlDatabase, wrapConnection, createSqlPool)
import qualified Database.Sqlite as Sqlite
import Control.Monad.Logger (runLoggingT)
import Settings (appDatabaseConf)
import Yesod.Core (messageLoggerSource)
runDB :: SqlPersistM a -> YesodExample App a
runDB query = do
pool <- fmap appConnPool getTestYesod
liftIO $ runSqlPersistMPool query pool
withApp :: SpecWith App -> Spec
withApp = before $ do
settings <- loadAppSettings
["config/test-settings.yml", "config/settings.yml"]
[]
ignoreEnv
foundation <- makeFoundation settings
wipeDB foundation
return foundation
-- 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 = do
-- In order to wipe the database, we need to temporarily disable foreign key checks.
-- Unfortunately, disabling FK checks in a transaction is a noop in SQLite.
-- Normal Persistent functions will wrap your SQL in a transaction,
-- so we create a raw SQLite connection to disable foreign keys.
-- Foreign key checks are per-connection, so this won't effect queries outside this function.
-- Aside: SQLite by default *does not enable foreign key checks*
-- (disabling foreign keys is only necessary for those who specifically enable them).
let settings = appSettings app
sqliteConn <- rawConnection (sqlDatabase $ appDatabaseConf settings)
disableForeignKeys sqliteConn
let logFunc = messageLoggerSource app (appLogger app)
pool <- runLoggingT (createSqlPool (wrapConnection sqliteConn) 1) logFunc
flip runSqlPersistMPool pool $ do
tables <- getTables
sqlBackend <- ask
let queries = map (\t -> "DELETE FROM " ++ (connEscapeName sqlBackend $ DBName t)) tables
forM_ queries (\q -> rawExecute q [])
rawConnection :: Text -> IO Sqlite.Connection
rawConnection t = Sqlite.open t
disableForeignKeys :: Sqlite.Connection -> IO ()
disableForeignKeys conn = Sqlite.prepare conn "PRAGMA foreign_keys = OFF;" >>= void . Sqlite.step
getTables :: MonadIO m => ReaderT SqlBackend m [Text]
getTables = do
tables <- rawSql "SELECT name FROM sqlite_master WHERE type = 'table';" []
return (fmap unSingle tables)