-- allows automatic derivation from Entity type class {-# LANGUAGE DeriveAnyClass #-} module ExceptionsSpec ( test, spec, ) where import Database.GP.GenericPersistenceSafe import Database.HDBC.Sqlite3 import GHC.Generics import Test.Hspec -- `test` is here so that this module can be run from GHCi on its own. It is -- not needed for automatic spec discovery. -- (start up stack repl --test to bring up ghci and have access to all the test functions) test :: IO () test = hspec spec prepareDB :: IO Conn prepareDB = do conn <- connect SQLite <$> connectSqlite3 ":memory:" setupTableFor @Article conn return conn data Article = Article { articleID :: Int, title :: String, year :: Int } deriving (Generic, Entity, Show, Eq) yearField :: Field yearField = field "year" article :: Article article = Article 1 "The Hitchhiker's Guide to the Galaxy" 1979 expectationSuccess :: IO () expectationSuccess = return () spec :: Spec spec = do describe "Exception Handling" $ do it "detects duplicate inserts" $ do conn <- prepareDB _ <- insert conn article eitherExRes <- insert conn article :: IO (Either PersistenceException ()) case eitherExRes of Left (DuplicateInsert _) -> expectationSuccess _ -> expectationFailure "Expected DuplicateInsert exception" it "detects duplicate inserts in insertMany" $ do conn <- prepareDB _ <- insert conn article eitherExRes <- insertMany conn [article,article] :: IO (Either PersistenceException ()) case eitherExRes of Left (DuplicateInsert _) -> expectationSuccess _ -> expectationFailure "Expected DuplicateInsert exception" it "detects missing entities in selectById" $ do conn <- prepareDB eitherExRes <- selectById conn "1" :: IO (Either PersistenceException Article) case eitherExRes of Left (EntityNotFound _) -> expectationSuccess _ -> expectationFailure "Expected EntityNotFound exception" it "detects missing entities in update" $ do conn <- prepareDB eitherExRes <- update conn article :: IO (Either PersistenceException ()) case eitherExRes of Left (EntityNotFound _) -> expectationSuccess _ -> expectationFailure "Expected EntityNotFound exception" it "detects missing entities in delete" $ do conn <- prepareDB eitherExRes <- delete conn article :: IO (Either PersistenceException ()) case eitherExRes of Left (EntityNotFound _) -> expectationSuccess _ -> expectationFailure "Right: Expected EntityNotFound exception" it "detects general backend issues" $ do conn <- connect SQLite <$> connectSqlite3 ":memory:" eitherExRes <- update conn article :: IO (Either PersistenceException ()) case eitherExRes of Left (DatabaseError _) -> expectationSuccess _ -> expectationFailure "Expected DatabaseError exception" it "has no leaking backend exceptions" $ do conn <- connect SQLite <$> connectSqlite3 ":memory:" _ <- update conn article :: IO (Either PersistenceException ()) _ <- insert conn article :: IO (Either PersistenceException ()) _ <- persist conn article :: IO (Either PersistenceException ()) _ <- delete conn article :: IO (Either PersistenceException ()) _ <- selectById conn "1" :: IO (Either PersistenceException Article) _ <- select conn allEntries :: IO (Either PersistenceException [Article]) _ <- select conn (yearField =. "2023") :: IO (Either PersistenceException [Article]) _ <- insertMany conn [article] :: IO (Either PersistenceException ()) _ <- updateMany conn [article] :: IO (Either PersistenceException ()) _ <- deleteMany conn [article] :: IO (Either PersistenceException ()) expectationSuccess