feat: sql handlers for custom media types

* test text/html and drop HtmlRawOutputSpec.hs
* all tests passing, removed all pendingWith
* make functions compatible with pg <= 12
* move custom media types tests to own spec
* anyelement aggregate
* apply aggregates without a final function
* overriding works
* overriding anyelement with particular agg
* cannot override vendored media types
* plan spec works with custom aggregate
* renamed media types to make clear which ones are overridable
* correct content negotiation with same weight
* text/tab-separated-values media type
* text/csv with BOM plus content-disposition header
This commit is contained in:
steve-chavez
2023-10-26 09:04:02 -05:00
committed by Steve Chavez
parent 4a90e9fbd9
commit 82b38341bf
28 changed files with 755 additions and 384 deletions
+224
View File
@@ -0,0 +1,224 @@
module Feature.Query.CustomMediaSpec where
import Network.Wai (Application)
import Network.HTTP.Types
import Network.Wai.Test (SResponse (simpleBody, simpleHeaders, simpleStatus))
import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Text.Heredoc (str)
import Protolude hiding (get)
import SpecHelper
spec :: SpecWith ((), Application)
spec = describe "custom media types" $ do
context "for tables with aggregate" $ do
it "can query if there's an aggregate defined for the table" $ do
r <- request methodGet "/lines" (acceptHdrs "application/vnd.twkb") ""
liftIO $ do
simpleBody r `shouldBe` readFixtureFile "lines.twkb"
simpleHeaders r `shouldContain` [("Content-Type", "application/vnd.twkb")]
it "can query by id if there's an aggregate defined for the table" $ do
r <- request methodGet "/lines?id=eq.1" (acceptHdrs "application/vnd.twkb") ""
liftIO $ do
simpleBody r `shouldBe` readFixtureFile "1.twkb"
simpleHeaders r `shouldContain` [("Content-Type", "application/vnd.twkb")]
it "will fail if there's no aggregate defined for the table" $ do
request methodGet "/lines" (acceptHdrs "text/plain") ""
`shouldRespondWith`
[json| {"code":"PGRST107","details":null,"hint":null,"message":"None of these media types are available: text/plain"} |]
{ matchStatus = 415
, matchHeaders = [matchContentTypeJson]
}
it "can get raw xml output with Accept: text/xml if there's an aggregate defined" $ do
request methodGet "/xmltest" (acceptHdrs "text/xml") ""
`shouldRespondWith`
"<myxml>foo</myxml>bar<foobar><baz/></foobar>"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/xml; charset=utf-8"]
}
-- TODO SOH (start of heading) is being added to results
context "for tables with anyelement aggregate" $ do
it "will use the application/vnd.geo2+json media type for any table" $
request methodGet "/lines" (acceptHdrs "application/vnd.geo2+json") ""
`shouldRespondWith`
"\SOH{\"type\": \"FeatureCollection\", \"hello\": \"world\"}"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/vnd.geo2+json"]
}
it "will use the more specific application/vnd.geo2 handler for this table" $ do
request methodGet "/shop_bles" (acceptHdrs "application/vnd.geo2+json") ""
`shouldRespondWith`
"\SOH\"anyelement overridden\""
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/vnd.geo2+json"]
}
request methodGet "/rpc/get_shop_bles" (acceptHdrs "application/vnd.geo2+json") ""
`shouldRespondWith`
"\SOH\"anyelement overridden\""
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/vnd.geo2+json"]
}
context "Proc that returns scalar" $ do
it "can get raw output with Accept: text/html" $ do
request methodGet "/rpc/welcome.html" (acceptHdrs "text/html") ""
`shouldRespondWith`
[str|
|<html>
| <head>
| <title>PostgREST</title>
| </head>
| <body>
| <h1>Welcome to PostgREST</h1>
| </body>
|</html>
|]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/html"]
}
it "can get raw output with Accept: text/plain" $ do
request methodGet "/rpc/welcome" (acceptHdrs "text/plain") ""
`shouldRespondWith` "Welcome to PostgREST"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]
}
it "can get raw xml output with Accept: text/xml" $ do
request methodGet "/rpc/return_scalar_xml" (acceptHdrs "text/xml") ""
`shouldRespondWith`
"<my-xml-tag/>"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/xml; charset=utf-8"]
}
it "can get raw xml output with Accept: text/xml" $ do
request methodGet "/rpc/welcome.xml" (acceptHdrs "text/xml") ""
`shouldRespondWith`
"<html>\n <head>\n <title>PostgREST</title>\n </head>\n <body>\n <h1>Welcome to PostgREST</h1>\n </body>\n</html>"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/xml; charset=utf-8"]
}
it "should fail with function returning text and Accept: text/xml" $ do
request methodGet "/rpc/welcome" (acceptHdrs "text/xml") ""
`shouldRespondWith`
[json|
{"code":"PGRST107","details":null,"hint":null,"message":"None of these media types are available: text/xml"}
|]
{ matchStatus = 415
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"]
}
context "Proc that returns scalar based on a table" $ do
it "can get an image with Accept: image/png" $ do
r <- request methodGet "/rpc/ret_image" (acceptHdrs "image/png") ""
liftIO $ do
simpleBody r `shouldBe` readFixtureFile "A.png"
simpleHeaders r `shouldContain` [("Content-Type", "image/png")]
context "Proc that returns set of scalars and Accept: text/plain" $
it "will err because only scalars work with media type domains" $ do
request methodGet "/rpc/welcome_twice"
(acceptHdrs "text/plain")
""
`shouldRespondWith`
[json|{"code":"PGRST107","details":null,"hint":null,"message":"None of these media types are available: text/plain"}|]
{ matchStatus = 415
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"]
}
context "Proc that returns rows and accepts custom media type" $ do
it "works if it has an aggregate defined" $ do
r <- request methodGet "/rpc/get_lines" [("Accept", "application/vnd.twkb")] ""
liftIO $ do
simpleBody r `shouldBe` readFixtureFile "lines.twkb"
simpleHeaders r `shouldContain` [("Content-Type", "application/vnd.twkb")]
it "fails if doesn't have an aggregate defined" $ do
request methodGet "/rpc/get_lines"
(acceptHdrs "application/octet-stream") ""
`shouldRespondWith`
[json| {"code":"PGRST107","details":null,"hint":null,"message":"None of these media types are available: application/octet-stream"} |]
{ matchStatus = 415 }
-- TODO SOH (start of heading) is being added to results
it "works if there's an anyelement aggregate defined" $ do
request methodGet "/rpc/get_lines" (acceptHdrs "application/vnd.geo2+json") ""
`shouldRespondWith`
"\SOH{\"type\": \"FeatureCollection\", \"hello\": \"world\"}"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/vnd.geo2+json"]
}
context "overriding" $ do
it "will override the application/json handler for a single table" $
request methodGet "/ov_json" (acceptHdrs "application/json") ""
`shouldRespondWith`
[json| {"overridden": "true"} |]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"]
}
-- TODO SOH (start of heading) is being added to results
it "will override the application/geo+json handler for a single table" $
request methodGet "/lines?id=eq.1" (acceptHdrs "application/geo+json") ""
`shouldRespondWith`
"\SOH{\"crs\": {\"type\": \"name\", \"properties\": {\"name\": \"EPSG:4326\"}}, \"type\": \"FeatureCollection\", \"features\": [{\"type\": \"Feature\", \"geometry\": {\"type\": \"LineString\", \"coordinates\": [[1, 1], [5, 5]]}, \"properties\": {\"id\": 1, \"name\": \"line-1\"}}]}"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/geo+json; charset=utf-8"]
}
it "will not override vendored media types like application/vnd.pgrst.object" $
request methodGet "/projects?id=eq.1" (acceptHdrs "application/vnd.pgrst.object") ""
`shouldRespondWith`
[json|{"id":1,"name":"Windows 7","client_id":1}|]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/vnd.pgrst.object+json; charset=utf-8"]
}
context "matches requested media type correctly" $ do
-- https://github.com/PostgREST/postgrest/issues/1462
it "will match image/png according to q values" $ do
r1 <- request methodGet "/rpc/ret_image" (acceptHdrs "image/png, */*") ""
liftIO $ do
simpleBody r1 `shouldBe` readFixtureFile "A.png"
simpleHeaders r1 `shouldContain` [("Content-Type", "image/png")]
r2 <- request methodGet "/rpc/ret_image" (acceptHdrs "text/html,application/xhtml+xml,application/xml;q=0.9,image/png,*/*;q=0.8") ""
liftIO $ do
simpleBody r2 `shouldBe` readFixtureFile "A.png"
simpleHeaders r2 `shouldContain` [("Content-Type", "image/png")]
-- https://github.com/PostgREST/postgrest/issues/2170
it "will match json in presence of text/plain" $ do
r <- request methodGet "/projects?id=eq.1" (acceptHdrs "text/plain, application/json") ""
liftIO $ do
simpleStatus r `shouldBe` status200
simpleHeaders r `shouldContain` [("Content-Type", "application/json; charset=utf-8")]
-- https://github.com/PostgREST/postgrest/issues/1102
it "will match a custom text/tab-separated-values" $ do
request methodGet "/projects?id=in.(1,2)" (acceptHdrs "text/tab-separated-values") ""
`shouldRespondWith`
"id\tname\tclient_id\n1\tWindows 7\t1\n2\tWindows 10\t1\n"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/tab-separated-values"]
}
-- https://github.com/PostgREST/postgrest/issues/1371#issuecomment-519248984
it "will match a custom text/csv with BOM" $ do
r <- request methodGet "/lines" (acceptHdrs "text/csv") ""
liftIO $ do
simpleBody r `shouldBe` readFixtureFile "lines.csv"
simpleHeaders r `shouldContain` [("Content-Type", "text/csv; charset=utf-8")]
simpleHeaders r `shouldContain` [("Content-Disposition", "attachment; filename=\"lines.csv\"")]
@@ -1,31 +0,0 @@
module Feature.Query.HtmlRawOutputSpec where
import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai
import Text.Heredoc
import Protolude hiding (get)
import SpecHelper (acceptHdrs)
spec :: SpecWith ((), Application)
spec = describe "When raw-media-types is set to \"text/html\"" $
it "can get raw output with Accept: text/html" $ do
pendingWith "TBD"
request methodGet "/rpc/welcome.html" (acceptHdrs "text/html") ""
`shouldRespondWith`
[str|
|<html>
| <head>
| <title>PostgREST</title>
| </head>
| <body>
| <h1>Welcome to PostgREST</h1>
| </body>
|</html>
|]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/html"]
}
+28 -12
View File
@@ -275,18 +275,6 @@ spec actualPgVersion = do
resStatus `shouldBe` Status { statusCode = 200, statusMessage="OK" }
totalCost `shouldBe` 68.56
it "outputs the plan for text/xml" $ do
pendingWith "TBD"
r <- request methodGet "/rpc/return_scalar_xml"
(acceptHdrs "application/vnd.pgrst.plan+json; for=\"text/xml\"; options=verbose") ""
let aggCol = simpleBody r ^? nth 0 . key "Plan" . key "Output" . nth 2
resHeaders = simpleHeaders r
liftIO $ do
resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"text/xml\"; options=verbose; charset=utf-8")
aggCol `shouldBe` Just [aesonQQ| "COALESCE(xmlagg(return_scalar_xml.pgrst_scalar), ''::xml)" |]
describe "text format" $ do
it "outputs the total cost for a function call" $ do
r <- request methodGet "/projects?id=in.(1,2,3)"
@@ -442,6 +430,34 @@ spec actualPgVersion = do
liftIO $ do
resBody `shouldSatisfy` (\t -> T.isInfixOf "Index" (decodeUtf8 $ LBS.toStrict t))
describe "custom media types" $ do
it "outputs the plan for a scalar function text/xml" $ do
r <- request methodGet "/rpc/return_scalar_xml"
(acceptHdrs "application/vnd.pgrst.plan+json; for=\"text/xml\"; options=verbose") ""
let aggCol = simpleBody r ^? nth 0 . key "Plan" . key "Output" . nth 2
resHeaders = simpleHeaders r
liftIO $ do
resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"text/xml\"; options=verbose; charset=utf-8")
aggCol `shouldBe` Just [aesonQQ| "return_scalar_xml.pgrst_scalar" |]
it "outputs the plan for an aggregate application/vnd.twkb" $ do
r <- request methodGet "/lines"
(acceptHdrs "application/vnd.pgrst.plan+json; for=\"application/vnd.twkb\"; options=verbose") ""
let aggCol = simpleBody r ^? nth 0 . key "Plan" . key "Output" . nth 2
resHeaders = simpleHeaders r
liftIO $ do
resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"application/vnd.twkb\"; options=verbose; charset=utf-8")
aggCol `shouldBe`
(
if actualPgVersion >= pgVersion120
then Just [aesonQQ| "twkb_agg(ROW(lines.id, lines.name, lines.geom)::lines)" |]
else Just [aesonQQ| "twkb_agg(ROW(pgrst_source.id, pgrst_source.name, pgrst_source.geom)::lines)" |]
)
disabledSpec :: SpecWith ((), Application)
disabledSpec =
it "doesn't work if db-plan-enabled=false(the default)" $ do
-55
View File
@@ -1042,61 +1042,6 @@ spec actualPgVersion = do
[json|[{"a$num$":100}]|]
{ matchHeaders = [matchContentTypeJson] }
context "binary output" $ do
it "can query if a single column is selected" $ do
pendingWith "TBD"
request methodGet "/images_base64?select=img&name=eq.A.png" (acceptHdrs "application/octet-stream") ""
`shouldRespondWith` "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEUAAAD/AAAb/40iAAAAP0lEQVQI12NgwAbYG2AE/wEYwQMiZB4ACQkQYZEAIgqAhAGIKLCAEQ8kgMT/P1CCEUwc4IMSzA3sUIIdCHECAGSQEkeOTUyCAAAAAElFTkSuQmCC"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/octet-stream"]
}
it "can get raw output with Accept: text/plain" $ do
pendingWith "TBD"
request methodGet "/projects?select=name&id=eq.1" (acceptHdrs "text/plain") ""
`shouldRespondWith` "Windows 7"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]
}
it "can get raw xml output with Accept: text/xml" $ do
pendingWith "TBD"
request methodGet "/xmltest?select=xml" (acceptHdrs "text/xml") ""
`shouldRespondWith`
"<myxml>foo</myxml>bar<foobar><baz/></foobar>"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/xml; charset=utf-8"]
}
it "fails if a single column is not selected" $ do
pendingWith "TBD"
request methodGet "/images?select=img,name&name=eq.A.png" (acceptHdrs "application/octet-stream") ""
`shouldRespondWith`
[json| {"message":"application/octet-stream requested but more than one column was selected","code":"PGRST113","details":null,"hint":null} |]
{ matchStatus = 406 }
request methodGet "/images?select=*&name=eq.A.png"
(acceptHdrs "application/octet-stream")
""
`shouldRespondWith`
[json| {"message":"application/octet-stream requested but more than one column was selected","code":"PGRST113","details":null,"hint":null} |]
{ matchStatus = 406 }
request methodGet "/images?name=eq.A.png"
(acceptHdrs "application/octet-stream")
""
`shouldRespondWith`
[json| {"message":"application/octet-stream requested but more than one column was selected","code":"PGRST113","details":null,"hint":null} |]
{ matchStatus = 406 }
it "concatenates results if more than one row is returned" $ do
pendingWith "TBD"
request methodGet "/images_base64?select=img&name=in.(A.png,B.png)" (acceptHdrs "application/octet-stream") ""
`shouldRespondWith` "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEUAAAD/AAAb/40iAAAAP0lEQVQI12NgwAbYG2AE/wEYwQMiZB4ACQkQYZEAIgqAhAGIKLCAEQ8kgMT/P1CCEUwc4IMSzA3sUIIdCHECAGSQEkeOTUyCAAAAAElFTkSuQmCCiVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEX///8AAP94wDzzAAAAL0lEQVQIW2NgwAb+HwARH0DEDyDxwAZEyGAhLODqHmBRzAcn5GAS///A1IF14AAA5/Adbiiz/0gAAAAASUVORK5CYII="
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/octet-stream"]
}
describe "values with quotes in IN and NOT IN" $ do
it "succeeds when only quoted values are present" $ do
get "/w_or_wo_comma_names?name=in.(\"Hebdon, John\")" `shouldRespondWith`
+4 -92
View File
@@ -1,12 +1,11 @@
module Feature.Query.RpcSpec where
import qualified Data.ByteString.Lazy as BL (empty, readFile)
import qualified Data.ByteString.Lazy as BL (empty)
import Network.Wai (Application)
import Network.Wai.Test (SResponse (simpleBody, simpleHeaders, simpleStatus))
import Network.HTTP.Types
import System.IO.Unsafe (unsafePerformIO)
import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
@@ -1077,87 +1076,6 @@ spec actualPgVersion =
, matchHeaders = []
}
context "binary output" $ do
context "Proc that returns scalar" $ do
it "can query without selecting column" $ do
pendingWith "TBD"
request methodPost "/rpc/ret_base64_bin" (acceptHdrs "application/octet-stream") ""
`shouldRespondWith` "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEUAAAD/AAAb/40iAAAAP0lEQVQI12NgwAbYG2AE/wEYwQMiZB4ACQkQYZEAIgqAhAGIKLCAEQ8kgMT/P1CCEUwc4IMSzA3sUIIdCHECAGSQEkeOTUyCAAAAAElFTkSuQmCC"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/octet-stream"]
}
it "can get raw output with Accept: text/plain" $ do
pendingWith "TBD"
request methodGet "/rpc/welcome" (acceptHdrs "text/plain") ""
`shouldRespondWith` "Welcome to PostgREST"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]
}
it "can get raw xml output with Accept: text/xml" $ do
pendingWith "TBD"
request methodGet "/rpc/return_scalar_xml" (acceptHdrs "text/xml") ""
`shouldRespondWith`
"<my-xml-tag/>"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/xml; charset=utf-8"]
}
it "can get raw xml output with Accept: text/xml" $ do
pendingWith "TBD"
request methodGet "/rpc/welcome.xml" (acceptHdrs "text/xml") ""
`shouldRespondWith`
"<html>\n <head>\n <title>PostgREST</title>\n </head>\n <body>\n <h1>Welcome to PostgREST</h1>\n </body>\n</html>"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/xml; charset=utf-8"]
}
it "should fail with function returning text and Accept: text/xml" $ do
pendingWith "TBD"
request methodGet "/rpc/welcome" (acceptHdrs "text/xml") ""
`shouldRespondWith`
[json|
{
"hint":"No function matches the given name and argument types. You might need to add explicit type casts.",
"details":null,
"code":"42883",
"message":"function xmlagg(text) does not exist"
}
|]
{ matchStatus = 406
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"]
}
context "Proc that returns set of scalars" $
it "can query without selecting column" $ do
pendingWith "TBD"
request methodGet "/rpc/welcome_twice"
(acceptHdrs "text/plain")
""
`shouldRespondWith`
"Welcome to PostgRESTWelcome to PostgREST"
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "text/plain; charset=utf-8"]
}
context "Proc that returns rows" $ do
it "can query if a single column is selected" $ do
pendingWith "TBD"
request methodPost "/rpc/ret_rows_with_base64_bin?select=img" (acceptHdrs "application/octet-stream") ""
`shouldRespondWith` "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEUAAAD/AAAb/40iAAAAP0lEQVQI12NgwAbYG2AE/wEYwQMiZB4ACQkQYZEAIgqAhAGIKLCAEQ8kgMT/P1CCEUwc4IMSzA3sUIIdCHECAGSQEkeOTUyCAAAAAElFTkSuQmCCiVBORw0KGgoAAAANSUhEUgAAAB4AAAAeAQMAAAAB/jzhAAAABlBMVEX///8AAP94wDzzAAAAL0lEQVQIW2NgwAb+HwARH0DEDyDxwAZEyGAhLODqHmBRzAcn5GAS///A1IF14AAA5/Adbiiz/0gAAAAASUVORK5CYII="
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/octet-stream"]
}
it "fails if a single column is not selected" $ do
pendingWith "TBD"
request methodPost "/rpc/ret_rows_with_base64_bin"
(acceptHdrs "application/octet-stream") ""
`shouldRespondWith`
[json| {"message":"application/octet-stream requested but more than one column was selected","code":"PGRST113","details":null,"hint":null} |]
{ matchStatus = 406 }
context "only for GET rpc" $ do
it "should fail on mutating procs" $ do
get "/rpc/callcounter" `shouldRespondWith` 405
@@ -1327,7 +1245,6 @@ spec actualPgVersion =
[json|{"A": 1, "B": 2, "C": 3}|]
it "can insert text directly" $ do
pendingWith "TBD"
request methodPost "/rpc/unnamed_text_param"
[("Content-Type", "text/plain"), ("Accept", "text/plain")]
[str|unnamed text arg|]
@@ -1335,7 +1252,6 @@ spec actualPgVersion =
[str|unnamed text arg|]
it "can insert xml directly" $ do
pendingWith "TBD"
request methodPost "/rpc/unnamed_xml_param"
[("Content-Type", "text/xml"), ("Accept", "text/xml")]
[str|<note><from>John</from><to>Jane</to><message>Remember me</message></note>|]
@@ -1343,8 +1259,7 @@ spec actualPgVersion =
[str|<note><from>John</from><to>Jane</to><message>Remember me</message></note>|]
it "can insert bytea directly" $ do
pendingWith "TBD"
let file = unsafePerformIO $ BL.readFile "test/spec/fixtures/image.png"
let file = readFixtureFile "image.png"
r <- request methodPost "/rpc/unnamed_bytea_param"
[("Content-Type", "application/octet-stream"), ("Accept", "application/octet-stream")]
file
@@ -1397,10 +1312,9 @@ spec actualPgVersion =
}
it "will err when no function with single unnamed bytea parameter exists and application/octet-stream is specified" $
let file = unsafePerformIO $ BL.readFile "test/spec/fixtures/image.png" in
request methodPost "/rpc/unnamed_int_param"
[("Content-Type", "application/octet-stream")]
file
(readFixtureFile "image.png")
`shouldRespondWith`
[json|{
"hint": null,
@@ -1429,7 +1343,6 @@ spec actualPgVersion =
}
it "should be able to fallback to the single unnamed parameter function when other overloaded functions are not found" $ do
pendingWith "TBD"
request methodPost "/rpc/overloaded_unnamed_param"
[("Content-Type", "application/json")]
[json|{"A": 1, "B": 2, "C": 3}|]
@@ -1440,7 +1353,7 @@ spec actualPgVersion =
[str|unnamed text arg|]
`shouldRespondWith`
[str|unnamed text arg|]
let file = unsafePerformIO $ BL.readFile "test/spec/fixtures/image.png"
let file = readFixtureFile "image.png"
r <- request methodPost "/rpc/overloaded_unnamed_param"
[("Content-Type", "application/octet-stream"), ("Accept", "application/octet-stream")]
file
@@ -1488,7 +1401,6 @@ spec actualPgVersion =
}
it "should fail on /rpc/unnamed_xml_param when posting invalid xml" $ do
pendingWith "TBD"
request methodPost "/rpc/unnamed_xml_param"
[("Content-Type", "text/xml"), ("Accept", "text/xml")]
[str|<|]