{-# LANGUAGE OverloadedStrings #-}
module Test.Unit.Migration (testMigrations) where
import Control.Monad.Reader (runReaderT)
import qualified Data.Text as Text
import Database.Persist.Migration.Internal
import Database.Persist.Sql (SqlType(..))
import Test.Tasty (TestName, TestTree, testGroup)
import Test.Unit.Utils.Backends
(MockDatabase(..), defaultDatabase, setDatabase, withTestBackend)
import Test.Utils.Goldens (goldenVsText)
-- | Build a test suite for the given MigrateBackend.
testMigrations :: FilePath -> MigrateBackend -> TestTree
testMigrations dir backend = testGroup "migrations"
[ goldenMigration' "Basic migration" defaultDatabase
[ Operation (0 ~> 1) $
CreateTable
{ ctName = "person"
, ctSchema =
[ Column "id" SqlInt32 []
, Column "name" SqlString [NotNull]
, Column "age" SqlInt32 [NotNull]
, Column "alive" SqlBool [NotNull]
, Column "hometown" SqlInt64 [References ("cities", "id")]
]
, ctConstraints =
[ PrimaryKey ["id"]
, Unique "unique_name" ["name"]
]
}
, Operation (1 ~> 2) $ AddColumn "person" (Column "gender" SqlString []) Nothing
, Operation (2 ~> 3) $ DropColumn ("person", "alive")
, Operation (3 ~> 4) $ DropTable "person"
]
, goldenMigration' "Partial migration" (withVersion 1)
[ Operation (0 ~> 1) $ CreateTable "person" [] []
, Operation (1 ~> 2) $ DropTable "person"
]
, goldenMigration' "Complete migration" (withVersion 2)
[ Operation (0 ~> 1) $ CreateTable "person" [] []
, Operation (1 ~> 2) $ DropTable "person"
]
, goldenMigration' "Migration with shorter path" defaultDatabase
[ Operation (0 ~> 1) $ CreateTable "person" [] []
, Operation (1 ~> 2) $ AddColumn "person" (Column "gender" SqlString []) Nothing
, Operation (0 ~> 2) $ CreateTable "person" [Column "gender" SqlString []] []
]
, goldenMigration' "Partial migration avoids shorter path" (withVersion 1)
[ Operation (0 ~> 1) $ CreateTable "person" [] []
, Operation (1 ~> 2) $ AddColumn "person" (Column "gender" SqlString []) Nothing
, Operation (0 ~> 2) $ CreateTable "person" [Column "gender" SqlString []] []
]
]
where
goldenMigration' = goldenMigration dir backend
{- Helpers -}
-- | Run a goldens test for a migration.
goldenMigration
:: FilePath -> MigrateBackend -> TestName -> MockDatabase -> Migration -> TestTree
goldenMigration dir backend name testBackend migration = goldenVsText dir name $ do
setDatabase testBackend
Text.unlines <$> getMigration' migration
where
getMigration' = withTestBackend . runReaderT . getMigration backend defaultSettings
-- | Set the version in the MockDatabase.
withVersion :: Version -> MockDatabase
withVersion v = defaultDatabase{version = Just v}