graphql-engine/server/tests-hspec/Harness/Test/Introspection.hs
Philip Lykke Carlsen 12c3eddef7 Amendments to the hspec testsuite
This PR proposes some changes to the hspec testsuite:

* It amends the framework to make it easier to test from the ghci REPL
* It introduces a new module `Fixture`, distinguished from `Context` by:
   * using a new concept of `SetupAction`s which bundle setup and teardown actions into one abstraction, making test system state setup more concise, modularized and safe (because the fixture know knows about the ordering of setup actions and can do partial rollbacks)
   * somewhat opinionated, elides the `Options` of `Context`, preferring instead that tests that care about stringification of json numbers manage that themselves.

(Note that this PR builds on #4390, so contains some spurious commits which will become irrelevant once that PR is merged)

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4630
GitOrigin-RevId: 619c8d985aed0aa42de31d6f16891d0782f4b4b5
2022-06-08 16:36:50 +00:00

89 lines
2.7 KiB
Haskell

{-# LANGUAGE QuasiQuotes #-}
-- | This module contains functions that help defining tests in terms the
-- results of GraphQL introspection queries.
module Harness.Test.Introspection
( introspectTypes,
introspectEnums,
)
where
import Data.Aeson.Types (Parser, Value, listParser, parseEither, withObject, (.:), (.:?))
import Data.Text
import Data.Text.Encoding (encodeUtf8)
import Harness.GraphqlEngine qualified as GraphqlEngine
import Harness.Quoter.Graphql
import Harness.TestEnvironment (TestEnvironment)
import Hasura.Prelude
----------------------------------
-- Test helpers
-- | Query the names of all known types by a GraphQL introspection query against
-- a 'TestEnvironment' under a specific role.
introspectTypes :: TestEnvironment -> Text -> IO [Text]
introspectTypes env role = do
res <-
GraphqlEngine.postGraphqlWithHeaders
env
[("X-Hasura-Role", encodeUtf8 role)]
[graphql|
query IntrospectTypes { __schema {
types { name }
}}
|]
onLeft (parseEither getTypes res) fail
where
getTypes :: Value -> Parser [Text]
getTypes = withObject "introspection top-level" $ \top -> do
d <- top .: "data"
sch <- d .: "__schema"
types <- sch .: "types"
listParser parseType types
parseType :: Value -> Parser Text
parseType = withObject "a 'types' element" $ \types -> types .: "name"
-- | Query all known enum types by a GraphQL introspection query against
-- a 'TestEnvironment' under a specific role.
--
-- Returns the names and enum values '(enumName :: Text, enumValues :: [Text])'
-- of all known enums.
introspectEnums :: TestEnvironment -> Text -> IO [(Text, [Text])]
introspectEnums env role = do
res <-
GraphqlEngine.postGraphqlWithHeaders
env
[("X-Hasura-Role", encodeUtf8 role)]
[graphql|
query IntrospectEnums {
__schema {
types {
enumValues {
name
}
name
}
}
}
|]
onLeft (parseEither getEnums res) fail
where
getEnums :: Value -> Parser [(Text, [Text])]
getEnums = withObject "introspection top-level" $ \top -> do
d <- top .: "data"
sch <- d .: "__schema"
types <- sch .: "types"
catMaybes <$> listParser parseEnum types
parseEnum :: Value -> Parser (Maybe (Text, [Text]))
parseEnum = withObject "a 'types' element" $ \types -> do
name <- types .: "name"
maybeVals <- types .:? "enumValues"
case maybeVals of
Nothing -> return Nothing
Just vals -> Just . (name,) <$> listParser parseEnumValue vals
parseEnumValue :: Value -> Parser Text
parseEnumValue = withObject "enumValue" (.: "name")