{-# 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 as L (readFile) import qualified Data.ByteString.Lazy.Char8 as LB (unpack) import Data.ByteString.Lazy.Char8 (ByteString) import Data.Either (either) import Data.Morpheus.Core (parseFullGQLDocument, validateSchema) import Data.Morpheus.Types.Internal.AST ( GQLErrors, Schema, ) import Data.Morpheus.Types.Internal.Resolving ( Eventless, Result (..), ) import Data.Semigroup ((<>)) import Data.Text (pack) import GHC.Generics (Generic) import Lib ( CaseTree (..), FileUrl (..), scanSchemaTests, toString, ) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (assertFailure, testCase) readSource :: String -> IO ByteString readSource = L.readFile readSchema :: String -> IO (Eventless Schema) readSchema = fmap (validateSchema <=< parseFullGQLDocument) . readSource . (<> "/schema.gql") readResponse :: String -> IO Response readResponse = fmap (either AesonError id . eitherDecode) . readSource . (<> "/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) toTests :: CaseTree -> TestTree toTests CaseTree {caseUrl, children = Left {}} = schemaCase caseUrl toTests CaseTree {caseUrl = FileUrl {fileName}, children = Right children} = testGroup fileName (map toTests children) testSchema :: IO TestTree testSchema = toTests <$> scanSchemaTests "test/schema" schemaCase :: FileUrl -> TestTree schemaCase url = testCase (fileName url) $ do schema <- readSchema (toString url) expected <- readResponse (toString url) 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))