{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Migration (testMigrations) where import Control.Monad.Reader (runReaderT) import qualified Data.Text as Text import Database.Persist.Migration import Database.Persist.Migration.Core (getMigration) import Test.Tasty (TestName, TestTree, testGroup) import Utils.Backends (MockDatabase(..), defaultDatabase, setDatabase, withTestBackend) import Utils.Goldens (goldenVsText) -- | Build a test suite for the given MigrateBackend. testMigrations :: FilePath -> MigrateBackend -> TestTree testMigrations dir backend = testGroup "goldens" [ goldenMigration' "Basic migration" defaultDatabase [ 0 ~> 1 := [ CreateTable { name = "person" , schema = [ Column "id" SqlInt32 [] , Column "name" SqlString [NotNull] , Column "age" SqlInt32 [NotNull] , Column "alive" SqlBool [NotNull] , Column "hometown" SqlInt64 [References ("cities", "id")] ] , constraints = [ PrimaryKey ["id"] , Unique "unique_name" ["name"] ] } ] , 1 ~> 2 := [ AddColumn "person" (Column "gender" SqlString []) Nothing , DropColumn ("person", "alive") ] , 2 ~> 3 := [ DropTable "person" ] ] , goldenMigration' "Partial migration" (withVersion 1) [ 0 ~> 1 := [createTablePerson []] , 1 ~> 2 := [DropTable "person"] ] , goldenMigration' "Complete migration" (withVersion 2) [ 0 ~> 1 := [createTablePerson []] , 1 ~> 2 := [DropTable "person"] ] , goldenMigration' "Migration with shorter path" defaultDatabase [ 0 ~> 1 := [createTablePerson []] , 1 ~> 2 := [AddColumn "person" (Column "gender" SqlString []) Nothing] , 0 ~> 2 := [createTablePerson [Column "gender" SqlString []]] ] , goldenMigration' "Partial migration avoids shorter path" (withVersion 1) [ 0 ~> 1 := [createTablePerson []] , 1 ~> 2 := [AddColumn "person" (Column "gender" SqlString []) Nothing] , 0 ~> 2 := [createTablePerson [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 testName testBackend migration = goldenVsText dir testName $ do setDatabase testBackend MigrateSql{..} <- concatSql Text.unlines <$> getMigration' migration return $ Text.unlines [sqlText, Text.pack $ show sqlVals] where getMigration' = withTestBackend . runReaderT . getMigration backend defaultSettings -- | Set the version in the MockDatabase. withVersion :: Version -> MockDatabase withVersion v = defaultDatabase{version = Just v} -- | Create a basic 'person' table. createTablePerson :: [Column] -> Operation createTablePerson cols = CreateTable { name = "person" , schema = Column "id" SqlInt64 [NotNull, AutoIncrement] : cols , constraints = [PrimaryKey ["id"]] }