Files
postgrest/test/Feature/InsertSpec.hs
T

90 lines
2.8 KiB
Haskell

{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}
module Feature.InsertSpec where
-- {{{ Imports
import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Network.Wai.Test (SResponse(simpleBody,simpleHeaders,simpleStatus))
import SpecHelper
import qualified Data.Aeson as JSON
import Data.Aeson ((.:))
import Data.Maybe (fromJust)
import Control.Applicative ((<$>), (<*>))
import Control.Monad (mzero)
import qualified Data.HashMap.Strict as Hash
import qualified Data.ByteString.Char8 as BS
import Data.CaseInsensitive
import Text.Regex.TDFA ((=~))
import Network.HTTP.Types.Header
import Network.HTTP.Types.Status
-- }}}
data IncPK = IncPK {
incId :: Int
, incNullableStr :: Maybe String
, incStr :: String
, incInsert :: String
} deriving (Show)
instance JSON.FromJSON IncPK where
parseJSON (JSON.Object r) = IncPK <$>
r .: "id" <*>
r .: "nullable_string" <*>
r .: "non_nullable_string" <*>
r .: "inserted_at"
parseJSON _ = mzero
getHeader :: CI BS.ByteString -> [Header] -> Maybe BS.ByteString
getHeader name headers =
Hash.lookup name $ Hash.fromList headers
matchHeader :: CI BS.ByteString -> String -> [Header] -> Bool
matchHeader name valRegex headers =
maybe False (=~ valRegex) $ getHeader name headers
spec :: Spec
spec = around appWithFixture $
describe "Posting new record" $ do
it "accepts disparate json types" $
post "/menagerie"
[json| {
"integer": 13, "double": 3.14159, "varchar": "testing!"
, "boolean": false, "date": "01/01/1900", "money": "$3.99"
} |]
`shouldRespondWith` 201
context "with no pk supplied" $ do
context "into a table with auto-incrementing pk" $
it "succeeds with 201 and link" $ do
p <- post "/auto_incrementing_pk" [json| { "non_nullable_string":"not null"} |]
liftIO $ do
simpleBody p `shouldBe` ""
simpleHeaders p `shouldSatisfy` matchHeader hLocation "/auto_incrementing_pk\\?id=eq\\.[0-9]+"
simpleStatus p `shouldBe` created201
let Just location = getHeader hLocation $ simpleHeaders p
r <- get location
let [record] = fromJust (JSON.decode $ simpleBody r :: Maybe [IncPK])
liftIO $ do
incStr record `shouldBe` "not null"
incNullableStr record `shouldBe` Nothing
context "into a table with simple pk" $
it "fails with 400 and error" $
post "/simple_pk" [json| { "extra":"foo"} |]
`shouldRespondWith` 400
context "with compound pk supplied" $
it "builds response location header appropriately" $
post "/compound_pk" [json| { "k1":12, "k2":42 } |]
`shouldRespondWith` ResponseMatcher {
matchBody = Nothing,
matchStatus = 201,
matchHeaders = [("Location", "/compound_pk?k1=eq.12&k2=eq.42")]
}