graphql-engine/server/src-test/Hasura/Metadata/DTO/MetadataDTOSpec.hs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

135 lines
4.8 KiB
Haskell
Raw Normal View History

{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Hasura.Metadata.DTO.MetadataDTOSpec (spec) where
import Data.Aeson
( FromJSON (parseJSON),
ToJSON (toJSON),
Value,
eitherDecode,
eitherDecodeFileStrict',
)
import Data.Aeson.QQ.Simple (aesonQQ)
import Data.Aeson.Types (parseEither)
import Data.Either (isLeft, isRight)
import Data.FileEmbed (makeRelativeToProject, strToExp)
import Hasura.Metadata.DTO.Metadata (MetadataDTO (..))
import Hasura.Metadata.DTO.MetadataV1 (MetadataV1 (..))
import Hasura.Metadata.DTO.MetadataV2 (MetadataV2 (..))
import Hasura.Metadata.DTO.MetadataV3 (MetadataV3 (..))
import Hasura.Metadata.DTO.Placeholder (PlaceholderArray (PlaceholderArray))
import Hasura.Prelude
import Hasura.RQL.Types.Metadata (Metadata, metadataToDTO)
import Test.Hspec
spec :: Spec
spec = describe "MetadataDTO" $ do
describe "distinguishing metadata revisions" $ do
it "serializes v1" $ do
let output = V1 $ emptyMetadataV1
let expected = [aesonQQ|{ "version": 1, "tables": [] }|]
toJSON output `shouldBe` expected
it "serializes v2" $ do
let output = V2 $ emptyMetadataV2
let expected = [aesonQQ|{ "version": 2, "tables": [] }|]
toJSON output `shouldBe` expected
it "serializes v3" $ do
let output = V3 $ emptyMetadataV3
let expected = [aesonQQ|{ "version": 3, "sources": [] }|]
toJSON output `shouldBe` expected
it "parses v2" $ do
let input = "{ \"version\": 2, \"tables\": [] }"
let expected = V2 $ emptyMetadataV2
let actual = eitherDecode input :: Either String MetadataDTO
actual `shouldBe` Right expected
it "parses v3" $ do
let input = "{\"version\": 3, \"sources\": [] }"
let expected = V3 $ emptyMetadataV3
let actual = eitherDecode input :: Either String MetadataDTO
actual `shouldBe` Right expected
it "fails parsing v3 on version mismatch" $ do
let input = "{\"version\": 3, \"tables\": [] }"
let actual = eitherDecode input :: Either String MetadataDTO
actual `shouldSatisfy` isLeft
it "assumes v1 if version field is absent" $ do
let input = "{\"tables\": [] }"
let expected = V1 $ emptyMetadataV1
let actual = eitherDecode input :: Either String MetadataDTO
actual `shouldBe` Right expected
it "fails parsing if input is not v1-compatible, and version is absent" $ do
let input = "{\"sources\": [] }"
let actual = eitherDecode input :: Either String MetadataDTO
actual `shouldSatisfy` isLeft
beforeAll getMetadataFixture $ do
describe "v3" $ do
it "deserializes and re-serializes equivalently to Metadata" $ \metadataFixture -> do
let dto = parseEither parseJSON =<< metadataFixture :: Either String MetadataDTO
let fromDto = toJSON <$> dto
fromDto `shouldSatisfy` isRight
fromDto `shouldBe` metadataFixture
it "converts metadata to DTO to JSON to metadata" $ \metadataFixture -> do
let origMetadata = parseEither (parseJSON @Metadata) =<< metadataFixture
let dto = metadataToDTO <$> origMetadata
let json = toJSON <$> dto
let metadata = parseEither (parseJSON @Metadata) =<< json
metadata `shouldSatisfy` isRight
metadata `shouldBe` origMetadata
emptyMetadataV3 :: MetadataV3
emptyMetadataV3 =
MetadataV3
{ metaV3Sources = PlaceholderArray mempty,
metaV3RemoteSchemas = Nothing,
metaV3QueryCollections = Nothing,
metaV3Allowlist = Nothing,
metaV3Actions = Nothing,
metaV3CustomTypes = Nothing,
metaV3CronTriggers = Nothing,
metaV3RestEndpoints = Nothing,
metaV3ApiLimits = Nothing,
metaV3MetricsConfig = Nothing,
metaV3InheritedRoles = Nothing,
metaV3GraphqlSchemaIntrospection = Nothing,
metaV3Network = Nothing,
metaV3BackendConfigs = Nothing
}
emptyMetadataV2 :: MetadataV2
emptyMetadataV2 =
MetadataV2
{ metaV2Actions = Nothing,
metaV2Allowlist = Nothing,
metaV2CronTriggers = Nothing,
metaV2CustomTypes = Nothing,
metaV2Functions = Nothing,
metaV2QueryCollections = Nothing,
metaV2RemoteSchemas = Nothing,
metaV2Tables = PlaceholderArray mempty
}
emptyMetadataV1 :: MetadataV1
emptyMetadataV1 =
MetadataV1
{ metaV1Functions = Nothing,
metaV1RemoteSchemas = Nothing,
metaV1Tables = PlaceholderArray mempty
}
getMetadataFixture :: IO (Either String Value)
getMetadataFixture = do
let filePath = $(strToExp =<< makeRelativeToProject "../cli/internal/metadatautil/testdata/json/t2/metadata.json")
-- Round-trip fixture data through the server's old serialization so that we
-- will get consistent results on the next round-trip.
metadata <- eitherDecodeFileStrict' filePath :: IO (Either String Metadata)
return $ toJSON <$> metadata