content: {-# LANGUAGE QuasiQuotes #-}
  {-# LANGUAGE NoImplicitPrelude #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE FlexibleContexts #-}
  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, runSqlPersistMPool, rawExecute, rawSql, unSingle)
  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)
  
  -- Wiping the database
  import Database.Persist.Sqlite              (sqlDatabase, mkSqliteConnectionInfo, fkEnabled, createSqlitePoolFromInfo)
  import Control.Monad.Logger                 (runLoggingT)
  import Lens.Micro                           (set)
  import Settings (appDatabaseConf)
  import Yesod.Core (messageLoggerSource)
  import Types
  
  runDB :: SqlPersistM a -> YesodExample App a
  runDB query = do
      pool <- fmap appConnPool getTestYesod
      liftIO $ runSqlPersistMPool query pool
  
  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 = do
      let logFunc = messageLoggerSource app (appLogger app)
  
      let dbName = sqlDatabase $ appDatabaseConf $ appSettings app
          connInfo = set fkEnabled False $ mkSqliteConnectionInfo dbName
  
      pool <- runLoggingT (createSqlitePoolFromInfo connInfo 1) logFunc
  
      flip runSqlPersistMPool pool $ do
          tables <- getTables
          -- sqlBackend <- ask
          -- let queries = map (\t -> "DELETE FROM " ++ (connEscapeName sqlBackend $ DBName t)) tables
          let queries = map (\t -> "DELETE FROM " ++ t) tables
          forM_ queries (\q -> rawExecute q [])
  
  getTables :: DB [Text]
  getTables = do
      tables <- rawSql "SELECT name FROM sqlite_master WHERE type = 'table';" []
      return (fmap unSingle tables)
  