pg-store-0.1.0: tests/Test/Database/PostgreSQL/Store/Table.hs
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes #-}
module Test.Database.PostgreSQL.Store.Table (
allTableSpecs
) where
import Test.Hspec
import Data.Proxy
import Database.PostgreSQL.Store.Table
import Database.PostgreSQL.Store.Query
import Database.PostgreSQL.Store.Errand
import qualified Database.PostgreSQL.LibPQ as P
data OnlyEvens = OnlyEvens {
value :: Int
} deriving (Show, Eq)
mkTable ''OnlyEvens
[Unique ['value],
Check [pgss| value % 2 = 0 |]]
allTableSpecs :: Maybe P.Connection -> Spec
allTableSpecs mbCon = do
maybe (pure ()) liveSpecs mbCon
dropTable :: P.Connection -> IO ()
dropTable con =
() <$ runErrand con (query_ [pgsq| DROP TABLE @OnlyEvens |])
clearTable :: P.Connection -> IO ()
clearTable con =
() <$ runErrand con (query_ [pgsq| DELETE FROM @OnlyEvens |])
liveSpecs :: P.Connection -> Spec
liveSpecs con =
describe "Database.PostgreSQL.Store.Table (live)" $
afterAll_ (dropTable con) $ describe "auto-generated instance Table" $
after_ (clearTable con) $ do
it "creates tables" $ do
res1 <- runErrand con $
query_ $(mkCreateQuery ''OnlyEvens)
shouldBe res1 (Right ())
-- Table exists now
let table = tableName (Proxy :: Proxy OnlyEvens)
res2 <- runErrand con $
query [pgsq| SELECT COUNT(*) FROM pg_tables WHERE tablename = $table |]
shouldBe res2 (Right [Single (1 :: Int)])
it "inserts a rows" $ do
res1 <- runErrand con (insert (OnlyEvens 2))
shouldSatisfy res1 $ \ r ->
case r of
Right (Reference _) -> True
_ -> False
-- Has been inserted correctly
res2 <- runErrand con $
query [pgsq| SELECT #OnlyEvens FROM @OnlyEvens |]
shouldBe res2 (Right [OnlyEvens 2])
it "respects constraints while inserting" $ do
-- Violate UNIQUE
res3 <- runErrand con $ do
insert (OnlyEvens 2)
insert (OnlyEvens 2)
shouldSatisfy res3 $ \ r ->
case r of
Left (ExecError _ UniqueViolation _ _ _) -> True
_ -> False
-- Violate CHECK
res4 <- runErrand con (insert (OnlyEvens 1))
shouldSatisfy res4 $ \ r ->
case r of
Left (ExecError _ CheckViolation _ _ _) -> True
_ -> False
it "inserts many rows" $ do
res1 <- runErrand con (insertMany (map OnlyEvens [2, 4 .. 100]))
shouldSatisfy res1 $ \ r ->
case r of
Right xs -> length xs == 50
_ -> False
-- Verify that there are actually 50 present
res2 <- runErrand con $
query [pgsq| SELECT COUNT(*) FROM @OnlyEvens |]
shouldBe res2 (Right [Single (50 :: Int)])
it "finds a row" $ do
res1 <- runErrand con $ do
ref <- insert (OnlyEvens 4)
find ref
shouldBe res1 (Right (OnlyEvens 4))
it "finds many rows" $
pendingWith "Not yet implemented"
it "updates a row" $ do
res1 <- runErrand con $ do
ref <- insert (OnlyEvens 4)
update ref (OnlyEvens 6)
find ref
shouldBe res1 (Right (OnlyEvens 6))
it "respects constraints while updating" $ do
-- Violate UNIQUE
res1 <- runErrand con $ do
insert (OnlyEvens 2)
ref <- insert (OnlyEvens 4)
update ref (OnlyEvens 2)
shouldSatisfy res1 $ \ r ->
case r of
Left (ExecError _ UniqueViolation _ _ _) -> True
_ -> False
-- Vioate CHECK
res2 <- runErrand con $ do
ref <- insert (OnlyEvens 6)
update ref (OnlyEvens 7)
shouldSatisfy res2 $ \ r ->
case r of
Left (ExecError _ CheckViolation _ _ _) -> True
_ -> False
it "updates many rows" $
pendingWith "Not yet implemented"
it "deletes a row" $ do
res1 <- runErrand con $ do
ref <- insert (OnlyEvens 2)
delete ref
shouldBe res1 (Right ())
it "deletes many rows" $
pendingWith "Not yet implemented"