module Test.Entities.Foo ( Foo (..) , FooId , FooName , table , generate , generateFooWithName , generateFooWithId , generateFooId , generateFooName , generateList , generateListUsing , generateNonEmpty , withTable , fooIdField , fooNameField , fooAgeField , hasName , averageFooAge ) where import Control.Monad.IO.Class (MonadIO (liftIO)) import Data.Function (on) import Data.Int (Int32) import qualified Data.List as List import qualified Data.List.NonEmpty as NEL import qualified Data.Text as T import qualified Hedgehog as HH import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range import qualified Orville.PostgreSQL as Orville import qualified Orville.PostgreSQL.Raw.Connection as Conn import qualified Test.PgGen as PgGen import qualified Test.TestTable as TestTable type FooId = Int32 type FooName = T.Text type FooAge = Int32 data Foo = Foo { fooId :: FooId , fooName :: FooName , fooAge :: FooAge } deriving (Eq, Show) table :: Orville.TableDefinition (Orville.HasKey FooId) Foo Foo table = Orville.mkTableDefinition "foo" (Orville.primaryKey fooIdField) fooMarshaller fooMarshaller :: Orville.SqlMarshaller Foo Foo fooMarshaller = Foo <$> Orville.marshallField fooId fooIdField <*> Orville.marshallField fooName fooNameField <*> Orville.marshallField fooAge fooAgeField fooIdField :: Orville.FieldDefinition Orville.NotNull FooId fooIdField = Orville.integerField "id" fooNameField :: Orville.FieldDefinition Orville.NotNull FooName fooNameField = Orville.unboundedTextField "name" fooAgeField :: Orville.FieldDefinition Orville.NotNull FooAge fooAgeField = Orville.integerField "age" generate :: HH.Gen Foo generate = Foo <$> generateFooId <*> generateFooName <*> generateFooAge generateFooWithId :: FooId -> HH.Gen Foo generateFooWithId knownId = Foo knownId <$> generateFooName <*> generateFooAge generateFooWithName :: FooName -> HH.Gen Foo generateFooWithName name = Foo <$> generateFooId <*> pure name <*> generateFooAge generateFooId :: HH.Gen FooId generateFooId = PgGen.pgInt32 generateFooName :: HH.Gen FooName generateFooName = PgGen.pgText (Range.constant 0 10) generateFooAge :: HH.Gen FooAge generateFooAge = Gen.integral (Range.constant minFooAge maxFooAge) minFooAge :: FooAge minFooAge = 0 maxFooAge :: FooAge maxFooAge = 50 averageFooAge :: FooAge averageFooAge = div (minFooAge + maxFooAge) 2 hasName :: FooName -> Foo -> Bool hasName name foo = fooName foo == name generateList :: HH.Range Int -> HH.Gen [Foo] generateList = flip generateListUsing generate generateListUsing :: HH.Range Int -> HH.Gen Foo -> HH.Gen [Foo] generateListUsing range generator = fmap (List.nubBy ((==) `on` fooId)) (Gen.list range generator) generateNonEmpty :: HH.Range Int -> HH.Gen (NEL.NonEmpty Foo) generateNonEmpty range = fmap (NEL.nubBy ((==) `on` fooId)) (Gen.nonEmpty range generate) withTable :: MonadIO m => Orville.ConnectionPool -> Orville.Orville a -> m a withTable pool operation = liftIO $ do Conn.withPoolConnection pool $ \connection -> TestTable.dropAndRecreateTableDef connection table Orville.runOrville pool operation