packages feed

orville-postgresql-1.1.0.0: test/Test/Expr/TableDefinition.hs

module Test.Expr.TableDefinition
  ( tableDefinitionTests
  )
where

import qualified Control.Monad.IO.Class as MIO
import Data.List.NonEmpty (NonEmpty ((:|)))

import qualified Orville.PostgreSQL as Orville
import qualified Orville.PostgreSQL.Expr as Expr

import qualified Test.PgAssert as PgAssert
import qualified Test.Property as Property

tableDefinitionTests :: Orville.ConnectionPool -> Property.Group
tableDefinitionTests pool =
  Property.group
    "Expr - TableDefinition"
    [ prop_createWithOneColumn pool
    , prop_createWithMultipleColumns pool
    , prop_renameTable pool
    , prop_addOneColumn pool
    , prop_addMultipleColumns pool
    ]

prop_createWithOneColumn :: Property.NamedDBProperty
prop_createWithOneColumn =
  Property.singletonNamedDBProperty "Create table creates a table with one column" $ \pool -> do
    MIO.liftIO $
      Orville.runOrville pool $ do
        Orville.executeVoid Orville.DDLQuery $ Expr.dropTableExpr (Just Expr.ifExists) exprTableName
        Orville.executeVoid Orville.DDLQuery $ Expr.createTableExpr exprTableName [column1Definition] Nothing []

    tableDesc <- PgAssert.assertTableExists pool tableNameString
    PgAssert.assertColumnNamesEqual tableDesc [column1NameString]

prop_createWithMultipleColumns :: Property.NamedDBProperty
prop_createWithMultipleColumns =
  Property.singletonNamedDBProperty "Create table creates a table with multiple columns" $ \pool -> do
    MIO.liftIO $
      Orville.runOrville pool $ do
        Orville.executeVoid Orville.DDLQuery $ Expr.dropTableExpr (Just Expr.ifExists) exprTableName
        Orville.executeVoid Orville.DDLQuery $ Expr.createTableExpr exprTableName [column1Definition, column2Definition, column1DefinitionGenAlways, column1DefinitionGenByDefault] Nothing []

    tableDesc <- PgAssert.assertTableExists pool tableNameString
    PgAssert.assertColumnNamesEqual tableDesc [column1NameString, column1AlwaysNameString, column1ByDefaultNameString, column2NameString]

prop_renameTable :: Property.NamedDBProperty
prop_renameTable =
  Property.singletonNamedDBProperty "Rename table results in the new name existing and the old name not" $ \pool -> do
    let
      newTableNameString = "renamed_" <> tableNameString
      newTableName = Expr.unqualified $ Expr.tableName newTableNameString
    MIO.liftIO $
      Orville.runOrville pool $ do
        Orville.executeVoid Orville.DDLQuery $ Expr.dropTableExpr (Just Expr.ifExists) exprTableName
        Orville.executeVoid Orville.DDLQuery $ Expr.dropTableExpr (Just Expr.ifExists) newTableName
        Orville.executeVoid Orville.DDLQuery $ Expr.createTableExpr exprTableName [column1Definition] Nothing []
        Orville.executeVoid Orville.DDLQuery $ Expr.renameTableExpr exprTableName newTableName

    PgAssert.assertTableDoesNotExist pool tableNameString
    tableDesc <- PgAssert.assertTableExists pool newTableNameString
    PgAssert.assertColumnNamesEqual tableDesc [column1NameString]

prop_addOneColumn :: Property.NamedDBProperty
prop_addOneColumn =
  Property.singletonNamedDBProperty "Alter table adds one column" $ \pool -> do
    MIO.liftIO $
      Orville.runOrville pool $ do
        Orville.executeVoid Orville.DDLQuery $ Expr.dropTableExpr (Just Expr.ifExists) exprTableName
        Orville.executeVoid Orville.DDLQuery $ Expr.createTableExpr exprTableName [] Nothing []
        Orville.executeVoid Orville.DDLQuery $ Expr.alterTableExpr exprTableName (Expr.addColumn column1Definition :| [])

    tableDesc <- PgAssert.assertTableExists pool tableNameString
    PgAssert.assertColumnNamesEqual tableDesc [column1NameString]

prop_addMultipleColumns :: Property.NamedDBProperty
prop_addMultipleColumns =
  Property.singletonNamedDBProperty "Alter table adds multiple columns" $ \pool -> do
    MIO.liftIO $
      Orville.runOrville pool $ do
        Orville.executeVoid Orville.DDLQuery $ Expr.dropTableExpr (Just Expr.ifExists) exprTableName
        Orville.executeVoid Orville.DDLQuery $ Expr.createTableExpr exprTableName [] Nothing []
        Orville.executeVoid Orville.DDLQuery $ Expr.alterTableExpr exprTableName (Expr.addColumn column1Definition :| [Expr.addColumn column1DefinitionGenAlways, Expr.addColumn column1DefinitionGenByDefault, Expr.addColumn column2Definition])

    tableDesc <- PgAssert.assertTableExists pool tableNameString
    PgAssert.assertColumnNamesEqual tableDesc [column1NameString, column2NameString, column1AlwaysNameString, column1ByDefaultNameString]

exprTableName :: Expr.QualifiedOrUnqualified Expr.TableName
exprTableName =
  Expr.unqualified (Expr.tableName tableNameString)

tableNameString :: String
tableNameString =
  "table_definition_test"

column1Definition :: Expr.ColumnDefinition
column1Definition =
  Expr.columnDefinition
    (Expr.columnName column1NameString)
    Expr.text
    mempty
    Nothing

column1DefinitionGenByDefault :: Expr.ColumnDefinition
column1DefinitionGenByDefault =
  Expr.columnDefinition
    (Expr.columnName column1ByDefaultNameString)
    Expr.int
    [Expr.notNullConstraint, Expr.identityColumnConstraint Expr.byDefaultColumnIdentityGeneration]
    Nothing

column1DefinitionGenAlways :: Expr.ColumnDefinition
column1DefinitionGenAlways =
  Expr.columnDefinition
    (Expr.columnName column1AlwaysNameString)
    Expr.int
    [Expr.notNullConstraint, Expr.identityColumnConstraint Expr.alwaysColumnIdentityGeneration]
    Nothing

column1NameString :: String
column1NameString =
  "column1"

column1AlwaysNameString :: String
column1AlwaysNameString =
  "column1_always"

column1ByDefaultNameString :: String
column1ByDefaultNameString =
  "column1_by_default"

column2Definition :: Expr.ColumnDefinition
column2Definition =
  Expr.columnDefinition
    (Expr.columnName column2NameString)
    Expr.text
    mempty
    Nothing

column2NameString :: String
column2NameString =
  "column2"