{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans -O0 #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
module EmbedTest (specsWith, cleanDB, embedMigrate) where
import Control.Exception (Exception, throw)
import Data.List.NonEmpty hiding (insert, length)
import qualified Data.Map as M
import qualified Data.Text as T
import qualified Data.Set as S
import EntityEmbedTest
import Init
data TestException = TestException
deriving (Show, Eq)
instance Exception TestException
instance PersistFieldSql a => PersistFieldSql (NonEmpty a) where
sqlType _ = SqlString
instance PersistField a => PersistField (NonEmpty a) where
toPersistValue = toPersistValue . toList
fromPersistValue pv = do
xs <- fromPersistValue pv
case xs of
[] -> Left "PersistField: NonEmpty found unexpected Empty List"
(l:ls) -> Right (l:|ls)
share [mkPersist sqlSettings { mpsGeneric = True }, mkMigrate "embedMigrate"] [persistUpperCase|
OnlyName
name Text
deriving Show Eq Read Ord
HasEmbed
name Text
embed OnlyName
deriving Show Eq Read Ord
HasEmbeds
name Text
embed OnlyName
double HasEmbed
deriving Show Eq Read Ord
HasListEmbed
name Text
list [HasEmbed]
deriving Show Eq Read Ord
HasSetEmbed
name Text
set (S.Set HasEmbed)
deriving Show Eq Read Ord
HasMap
name Text
map (M.Map T.Text T.Text)
deriving Show Eq Read Ord
HasList
list [HasListId]
deriving Show Eq Read Ord
EmbedsHasMap
name Text Maybe
embed HasMap
deriving Show Eq Read Ord
InList
one Int
two Int
deriving Show Eq
ListEmbed
nested [InList]
one Int
two Int
deriving Show Eq
User
ident Text
password Text Maybe
profile Profile
deriving Show Eq Read Ord
Profile
firstName Text
lastName Text
contact Contact Maybe
deriving Show Eq Read Ord
Contact
phone Int
email T.Text
deriving Show Eq Read Ord
Account
userIds (NonEmpty (Key User))
name Text Maybe
customDomains [Text] -- we may want to allow multiple cust domains. use [] instead of maybe
deriving Show Eq Read Ord
HasNestedList
list [IntList]
deriving Show Eq
IntList
ints [Int]
deriving Show Eq
-- We would like to be able to use OnlyNameId
-- But (Key OnlyName) works
MapIdValue
map (M.Map T.Text (Key OnlyName))
deriving Show Eq Read Ord
HasArrayWithEntities
hasEntity (Entity ARecord)
arrayWithEntities [AnEntity]
deriving Show Eq Read Ord
-- Self refrences are only allowed as a nullable type:
-- a Maybe or a List
SelfList
reference [SelfList]
SelfMaybe
reference SelfMaybe Maybe
-- This failes
-- SelfDirect
-- reference SelfDirect
|]
cleanDB :: (PersistQuery backend, PersistEntityBackend HasMap ~ backend, MonadIO m) => ReaderT backend m ()
cleanDB = do
deleteWhere ([] :: [Filter (HasEmbedGeneric backend)])
deleteWhere ([] :: [Filter (HasEmbedsGeneric backend)])
deleteWhere ([] :: [Filter (HasListEmbedGeneric backend)])
deleteWhere ([] :: [Filter (HasSetEmbedGeneric backend)])
deleteWhere ([] :: [Filter (UserGeneric backend)])
deleteWhere ([] :: [Filter (HasMapGeneric backend)])
deleteWhere ([] :: [Filter (HasListGeneric backend)])
deleteWhere ([] :: [Filter (EmbedsHasMapGeneric backend)])
deleteWhere ([] :: [Filter (ListEmbedGeneric backend)])
deleteWhere ([] :: [Filter (ARecordGeneric backend)])
deleteWhere ([] :: [Filter (AccountGeneric backend)])
deleteWhere ([] :: [Filter (HasNestedListGeneric backend)])
_unlessM :: MonadIO m => IO Bool -> m () -> m ()
_unlessM predicate body = do
b <- liftIO predicate
unless b body
specsWith :: Runner SqlBackend m => RunDb SqlBackend m -> Spec
specsWith runDb = describe "embedded entities" $ do
it "simple entities" $ runDb $ do
let container = HasEmbeds "container" (OnlyName "2")
(HasEmbed "embed" (OnlyName "1"))
contK <- insert container
Just res <- selectFirst [HasEmbedsName ==. "container"] []
res @== Entity contK container
it "query for equality of embeded entity" $ runDb $ do
let container = HasEmbed "container" (OnlyName "2")
contK <- insert container
Just res <- selectFirst [HasEmbedEmbed ==. OnlyName "2"] []
res @== Entity contK container
it "Set" $ runDb $ do
let container = HasSetEmbed "set" $ S.fromList
[ HasEmbed "embed" (OnlyName "1")
, HasEmbed "embed" (OnlyName "2")
]
contK <- insert container
Just res <- selectFirst [HasSetEmbedName ==. "set"] []
res @== Entity contK container
it "Set empty" $ runDb $ do
let container = HasSetEmbed "set empty" $ S.fromList []
contK <- insert container
Just res <- selectFirst [HasSetEmbedName ==. "set empty"] []
res @== Entity contK container
it "exception" $ flip shouldThrow (== TestException) $ runDb $ do
let container = HasSetEmbed "set" $ S.fromList
[ HasEmbed "embed" (OnlyName "1")
, HasEmbed "embed" (OnlyName "2")
]
contK <- insert container
Just res <- selectFirst [HasSetEmbedName ==. throw TestException] []
res @== Entity contK container
it "ListEmbed" $ runDb $ do
let container = HasListEmbed "list"
[ HasEmbed "embed" (OnlyName "1")
, HasEmbed "embed" (OnlyName "2")
]
contK <- insert container
Just res <- selectFirst [HasListEmbedName ==. "list"] []
res @== Entity contK container
it "ListEmbed empty" $ runDb $ do
let container = HasListEmbed "list empty" []
contK <- insert container
Just res <- selectFirst [HasListEmbedName ==. "list empty"] []
res @== Entity contK container
it "List empty" $ runDb $ do
let container = HasList []
contK <- insert container
Just res <- selectFirst [] []
res @== Entity contK container
it "NonEmpty List wrapper" $ runDb $ do
let con = Contact 123456 "foo@bar.com"
let prof = Profile "fstN" "lstN" (Just con)
uid <- insert $ User "foo" (Just "pswd") prof
let container = Account (uid:|[]) (Just "Account") []
contK <- insert container
Just res <- selectFirst [AccountUserIds ==. (uid:|[])] []
res @== Entity contK container
it "Map" $ runDb $ do
let container = HasMap "2 items" $ M.fromList [
("k1","v1")
, ("k2","v2")
]
contK <- insert container
Just res <- selectFirst [HasMapName ==. "2 items"] []
res @== Entity contK container
it "Map empty" $ runDb $ do
let container = HasMap "empty" $ M.fromList []
contK <- insert container
Just res <- selectFirst [HasMapName ==. "empty"] []
res @== Entity contK container
it "Embeds a Map" $ runDb $ do
let container = EmbedsHasMap (Just "non-empty map") $ HasMap "2 items" $ M.fromList [
("k1","v1")
, ("k2","v2")
]
contK <- insert container
Just res <- selectFirst [EmbedsHasMapName ==. Just "non-empty map"] []
res @== Entity contK container
it "Embeds a Map empty" $ runDb $ do
let container = EmbedsHasMap (Just "empty map") $ HasMap "empty" $ M.fromList []
contK <- insert container
Just res <- selectFirst [EmbedsHasMapName ==. Just "empty map"] []
res @== Entity contK container
it "Embeds a Map with ids as values" $ runDb $ do
onId <- insert $ OnlyName "nombre"
onId2 <- insert $ OnlyName "nombre2"
let midValue = MapIdValue $ M.fromList [("foo", onId),("bar",onId2)]
mK <- insert midValue
Just mv <- get mK
mv @== midValue