packages feed

servant-db-postgresql-0.2.0.0: test/Servant/PostgreSQLSpec.hs

module Servant.PostgreSQLSpec(spec) where

import           Data.Proxy
import           DB
import           Fixture
import           Test.Hspec                    hiding (Arg)
import           Test.HUnit
import           Test.QuickCheck

import           Servant.API.DB
import           Servant.DB.PostgreSQL
import           Servant.DB.PostgreSQL.Default

square :: Int -> PostgresM (Only Int)
square = deriveDB (Proxy :: Proxy SquareAPI) (Proxy :: Proxy PostgresM)

squareSchema :: Int -> PostgresM (Only Int)
squareSchema = deriveDB (Proxy :: Proxy SquareSchemaAPI) (Proxy :: Proxy PostgresM)

succAndPred :: Int -> PostgresM (Int, Int)
succAndPred = deriveDB (Proxy :: Proxy SuccAndPredAPI) (Proxy :: Proxy PostgresM)

postUser :: Composite UserCreate -> PostgresM (Only Int)
getUser :: Int -> PostgresM (Maybe User)
deleteUser :: Int -> PostgresM ()
getUsers :: PostgresM [User]
(      postUser
  :<|> getUser
  :<|> deleteUser
  :<|> getUsers) = deriveDB (Proxy :: Proxy UserAPI) (Proxy :: Proxy PostgresM)

ordered1 :: Int -> Int -> Int -> PostgresM (Only Int)
ordered1 = deriveDB (Proxy :: Proxy OrderedAPI1) (Proxy :: Proxy PostgresM)

ordered2 :: Int -> Int -> Int -> PostgresM (Only Int)
ordered2 = deriveDB (Proxy :: Proxy OrderedAPI2) (Proxy :: Proxy PostgresM)

voidProc :: PostgresM ()
voidProc = deriveDB (Proxy :: Proxy VoidAPI) (Proxy :: Proxy PostgresM)

variadicProc :: Variadic Int -> PostgresM (Maybe (Only Int))
variadicProc = deriveDB (Proxy :: Proxy VariadicAPI) (Proxy :: Proxy PostgresM)

arrayProc :: PGArray Int -> PostgresM (Maybe (Only Int))
arrayProc = deriveDB (Proxy :: Proxy ArrayAPI) (Proxy :: Proxy PostgresM)

defaultProc :: Default Int -> Default Int -> PostgresM (Only Int)
defaultProc = deriveDB (Proxy :: Proxy DefaultAPI) (Proxy :: Proxy PostgresM)

spec :: Spec
spec = describe "Servant.DB.PostgreSQL" $ do
  it "can call simple stored functions" $ withSquareFunc $ do
    Only b <- runDB $ square 4
    assertEqual "4^2 = 16" 16 b
  it "can call stored functions in schema" $ withTestSchema $ withSquareSchema $ do
    Only b <- runDB $ squareSchema 4
    assertEqual "4^2 = 16" 16 b
  it "supports row return" $ withSuccAndPred $ do
    b <- runDB $ succAndPred 4
    assertEqual "4+1 and 4-1 = (5, 3)" (5,3) b
  it "supports table return" $ withUserFuncs $ do
    user <- generate arbitrary
    Only i <- runDB $ postUser $ Composite user
    users <- runDB getUsers
    let user' = userCreateToUser user i
    assertEqual "wrote == read list" [user'] users
    muser1 <- runDB $ getUser i
    assertEqual "wrote == read single" (Just user') muser1
    runDB $ deleteUser i
    muser2 <- runDB $ getUser i
    assertEqual "deleted cannot be read" Nothing muser2
  it "handles ordered arguments" $ withOrderedFuncs $ do
    Only b <- runDB $ ordered1 1 2 3
    assertEqual "1+2*2+3*3 = 14" 14 b
  it "handles mixed argument style" $ withOrderedFuncs $ do
    Only b <- runDB $ ordered2 1 2 3
    assertEqual "1+3*2+2*3 = 13" 13 b
  it "handles void return type" $ withVoid $ runDB voidProc
  it "handles variadic type" $ withVariadic $ do
    res1 <- runDB $ variadicProc (Variadic $ PGArray [10, -1, 5, 4])
    assertEqual "mleast [10, -1, 5, 4] = -1" (Just $ Only (-1)) res1
    res2 <- runDB $ variadicProc (Variadic $ PGArray [])
    assertEqual "mleast [] = NULL" Nothing res2
  it "handles array type" $ withArrayFuncs $ do
    res1 <- runDB $ arrayProc (PGArray [10, -1, 5, 4])
    assertEqual "mleast [10, -1, 5, 4] = -1" (Just $ Only (-1)) res1
    res2 <- runDB $ arrayProc (PGArray [])
    assertEqual "mleast [] = NULL" Nothing res2
  it "handles default values" $ withDefaultFuncs $ do
    Only res1 <- runDB $ defaultProc (Default $ Just 1) (Default $ Just 1)
    assertEqual "1+1 = 2" 2 res1
    Only res2 <- runDB $ defaultProc (Default $ Just 1) (Default Nothing)
    assertEqual "1+0 = 1" 1 res2
    Only res3 <- runDB $ defaultProc (Default Nothing) (Default $ Just 2)
    assertEqual "0+2 = 2" 2 res3
    Only res4 <- runDB $ defaultProc (Default Nothing) (Default Nothing)
    assertEqual "0+0 = 0" 0 res4