mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
e0c0043e76
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9284 GitOrigin-RevId: 2f2cf2ad01900a54e4bdb970205ac0ef313c7e00
170 lines
6.6 KiB
Haskell
170 lines
6.6 KiB
Haskell
module Hasura.RQL.WebhookTransformsSpec
|
|
( spec,
|
|
)
|
|
where
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
import Data.Aeson (FromJSON, ToJSON, eitherDecode, encode, fromJSON, toJSON)
|
|
import Data.CaseInsensitive qualified as CI
|
|
import Data.List (nubBy)
|
|
import Data.Set qualified as S
|
|
import Hasura.Prelude
|
|
import Hasura.RQL.DDL.Webhook.Transform (RequestFields (..), RequestTransformFns, WithOptional (..), withOptional)
|
|
import Hasura.RQL.DDL.Webhook.Transform.Body (BodyTransformFn)
|
|
import Hasura.RQL.DDL.Webhook.Transform.Body qualified as Body
|
|
import Hasura.RQL.DDL.Webhook.Transform.Class (Template (..), TemplatingEngine (..), UnescapedTemplate (..))
|
|
import Hasura.RQL.DDL.Webhook.Transform.Headers (HeadersTransformFn, TransformFn (..))
|
|
import Hasura.RQL.DDL.Webhook.Transform.Headers qualified as Headers
|
|
import Hasura.RQL.DDL.Webhook.Transform.Method (Method (..), MethodTransformFn)
|
|
import Hasura.RQL.DDL.Webhook.Transform.Method qualified as Method
|
|
import Hasura.RQL.DDL.Webhook.Transform.QueryParams (QueryParamsTransformFn, TransformFn (..))
|
|
import Hasura.RQL.DDL.Webhook.Transform.QueryParams qualified as QueryParams
|
|
import Hasura.RQL.DDL.Webhook.Transform.Url (UrlTransformFn)
|
|
import Hasura.RQL.DDL.Webhook.Transform.Url qualified as Url
|
|
import Hedgehog (Gen, MonadTest, forAll, tripping, (===))
|
|
import Hedgehog.Gen qualified as Gen
|
|
import Hedgehog.Range qualified as Range
|
|
import Test.Hspec (Spec, describe, it)
|
|
import Test.Hspec.Hedgehog (hedgehog)
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
spec :: Spec
|
|
spec = describe "WebhookTransform" do
|
|
it "Method RoundTrip"
|
|
. hedgehog
|
|
$ forAll genMethod
|
|
>>= trippingJSON
|
|
|
|
it "StringTemplateText RoundTrip"
|
|
. hedgehog
|
|
$ forAll genUnescapedTemplate
|
|
>>= trippingJSON
|
|
|
|
it "Url RoundTrip"
|
|
. hedgehog
|
|
$ forAll genUrl
|
|
>>= trippingJSON
|
|
|
|
it "Template RoundTrip"
|
|
. hedgehog
|
|
$ forAll genTemplate
|
|
>>= trippingJSON
|
|
|
|
it "TemplateEngine RoundTrip"
|
|
. hedgehog
|
|
$ forAll genTemplatingEngine
|
|
>>= trippingJSON
|
|
|
|
it "TransformHeaders" . hedgehog $ do
|
|
headers <- forAll genTransformHeaders
|
|
let sortH (Headers.AddReplaceOrRemoveFields {..}) =
|
|
Headers.AddReplaceOrRemoveFields (sort addOrReplaceHeaders) (sort removeHeaders)
|
|
let headersMaybe = eitherDecode $ encode headers
|
|
Right (sortH headers) === fmap sortH headersMaybe
|
|
|
|
it "MetadataRequestTransform RoundTrip" . hedgehog $ do
|
|
reqFields <- forAll genRequestTransformDefunc
|
|
let sortH (WithOptional Nothing) = WithOptional Nothing
|
|
sortH
|
|
(WithOptional (Just (HeadersTransformFn_ (Headers.AddReplaceOrRemove (Headers.AddReplaceOrRemoveFields {..}))))) =
|
|
WithOptional
|
|
. Just
|
|
. HeadersTransformFn_
|
|
. Headers.AddReplaceOrRemove
|
|
$ Headers.AddReplaceOrRemoveFields (sort addOrReplaceHeaders) (sort removeHeaders)
|
|
|
|
let sortQ (WithOptional Nothing) = WithOptional Nothing
|
|
sortQ
|
|
(WithOptional (Just (QueryParamsTransformFn_ (QueryParams.AddOrReplace qs)))) =
|
|
WithOptional
|
|
. Just
|
|
. QueryParamsTransformFn_
|
|
. QueryParams.AddOrReplace
|
|
$ sortOn fst qs
|
|
sortQ
|
|
(WithOptional (Just (QueryParamsTransformFn_ (QueryParams.ParamTemplate qs)))) =
|
|
WithOptional . Just . QueryParamsTransformFn_ . QueryParams.ParamTemplate $ qs
|
|
let sortRF rf@RequestFields {requestHeaders, queryParams} =
|
|
rf {requestHeaders = sortH requestHeaders, queryParams = sortQ queryParams}
|
|
let reqFieldsMaybe = eitherDecode $ encode reqFields
|
|
Right (sortRF reqFields) === fmap sortRF reqFieldsMaybe
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Generators
|
|
|
|
genMethod :: Gen Method
|
|
genMethod = (Method . CI.mk) <$> Gen.text (Range.constant 3 20) Gen.alphaNum
|
|
|
|
genTemplatingEngine :: Gen TemplatingEngine
|
|
genTemplatingEngine = Gen.enumBounded
|
|
|
|
-- NOTE: This generator is strictly useful for roundtrip aeson testing
|
|
-- and does not produce valid template snippets.
|
|
genTemplate :: Gen Template
|
|
genTemplate = Template . wrap <$> Gen.text (Range.constant 3 20) Gen.alphaNum
|
|
where
|
|
wrap txt = "\"" <> txt <> "\""
|
|
|
|
genUnescapedTemplate :: Gen UnescapedTemplate
|
|
genUnescapedTemplate = UnescapedTemplate <$> Gen.text (Range.constant 3 20) Gen.alphaNum
|
|
|
|
genTransformHeaders :: Gen Headers.AddReplaceOrRemoveFields
|
|
genTransformHeaders = do
|
|
numHeaders <- Gen.integral $ Range.constant 1 20
|
|
|
|
let genHeaderKey = CI.mk <$> Gen.text (Range.constant 1 20) Gen.alphaNum
|
|
genHeaderValue = genUnescapedTemplate
|
|
|
|
genKeys = S.toList <$> Gen.set (Range.singleton numHeaders) genHeaderKey
|
|
genValues = S.toList <$> Gen.set (Range.singleton numHeaders) genHeaderValue
|
|
|
|
removeHeaders <- Gen.list (Range.constant 1 10) genHeaderKey
|
|
addOrReplaceHeaders <- liftA2 zip genKeys genValues
|
|
pure $ Headers.AddReplaceOrRemoveFields {addOrReplaceHeaders, removeHeaders}
|
|
|
|
genQueryParams :: Gen [(UnescapedTemplate, Maybe UnescapedTemplate)]
|
|
genQueryParams = do
|
|
numParams <- Gen.integral $ Range.constant 1 20
|
|
let keyGen = genUnescapedTemplate
|
|
valueGen = Gen.maybe $ genUnescapedTemplate
|
|
keys <- Gen.list (Range.singleton numParams) keyGen
|
|
values <- Gen.list (Range.singleton numParams) valueGen
|
|
pure $ nubBy (\a b -> fst a == fst b) $ zip keys values
|
|
|
|
genUrl :: Gen UnescapedTemplate
|
|
genUrl = do
|
|
host <- Gen.text (Range.constant 3 20) Gen.alphaNum
|
|
|
|
pure $ UnescapedTemplate $ "http://www." <> host <> ".com"
|
|
|
|
genRequestTransformDefunc :: Gen RequestTransformFns
|
|
genRequestTransformDefunc = do
|
|
method <- Gen.maybe genMethod
|
|
-- NOTE: At the moment no need to generate valid urls or templates
|
|
-- but such instances maybe useful in the future.
|
|
url <- Gen.maybe genUrl
|
|
body <- Gen.maybe genTemplate
|
|
queryParams <- Gen.maybe genQueryParams
|
|
headers <- Gen.maybe genTransformHeaders
|
|
pure
|
|
RequestFields
|
|
{ method = withOptional @MethodTransformFn (fmap Method.Replace method),
|
|
url = withOptional @UrlTransformFn (fmap Url.Modify url),
|
|
body = withOptional @BodyTransformFn (fmap Body.ModifyAsJSON body),
|
|
queryParams = withOptional @QueryParamsTransformFn (fmap QueryParams.AddOrReplace queryParams),
|
|
requestHeaders = withOptional @HeadersTransformFn (fmap Headers.AddReplaceOrRemove headers)
|
|
}
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Helpers
|
|
|
|
-- | TODO: Move this out to a common module!
|
|
trippingJSON ::
|
|
forall a m.
|
|
(Show a, Eq a, ToJSON a, FromJSON a, MonadTest m) =>
|
|
a ->
|
|
m ()
|
|
trippingJSON val = tripping val toJSON fromJSON
|