{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} module Schema ( testSchema, ) where import Control.Monad ((<=<)) import Data.Aeson ((.:), (.=), FromJSON (..), ToJSON (..), Value (..), eitherDecode, encode, object) import qualified Data.ByteString.Lazy.Char8 as LB (unpack) import Data.Either (either) import Data.Morpheus.Core (parseFullGQLDocument, validateSchema) import Data.Morpheus.Types.Internal.AST ( FieldName, GQLErrors, Schema, ) import Data.Morpheus.Types.Internal.Resolving ( Eventless, Result (..), ) import Data.Semigroup ((<>)) import Data.Text (pack) import GHC.Generics (Generic) import Lib (readSource) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (assertFailure, testCase) readSchema :: FieldName -> IO (Eventless Schema) readSchema = fmap (validateSchema <=< parseFullGQLDocument) . readSource . ("schema/" <>) . (<> "/schema.gql") readResponse :: FieldName -> IO Response readResponse = fmap (either AesonError id . eitherDecode) . readSource . ("schema/" <>) . (<> "/response.json") data Response = OK | Errors {errors :: GQLErrors} | AesonError String deriving (Generic) instance FromJSON Response where parseJSON (Object v) = Errors <$> v .: "errors" parseJSON (String "OK") = pure OK parseJSON v = pure $ AesonError (show v) instance ToJSON Response where toJSON OK = String "OK" toJSON (Errors err) = object ["errors" .= toJSON err] toJSON (AesonError err) = String (pack err) testSchema :: TestTree testSchema = testGroup "Test Schema" [ testGroup "Validation" $ map (uncurry schemaCase) [ ("validation/interface/ok", "interface validation success"), ("validation/interface/fail", "interface validation fails") ] ] schemaCase :: FieldName -> String -> TestTree schemaCase path description = testCase description $ do schema <- readSchema path expected <- readResponse path assertion expected schema assertion :: Response -> Eventless Schema -> IO () assertion OK Success {} = return () assertion Errors {errors = err} Failure {errors} | err == errors = pure () assertion expected Success {} = assertFailure $ LB.unpack ("expected: \n " <> encode expected <> " \n but got: \n OK") assertion expected Failure {errors} = assertFailure $ LB.unpack ("expected: \n " <> encode expected <> " \n but got: \n " <> encode (Errors errors))