{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Utils.MergeSchema
( test,
)
where
import Control.Applicative (pure)
import Control.Monad ((>>=))
import Control.Monad.Fail (fail)
import Data.Aeson (decode, encode)
import qualified Data.Aeson as A
import qualified Data.ByteString.Lazy as L (readFile)
import qualified Data.ByteString.Lazy.Char8 as LB (unpack)
import Data.Functor ((<$>), fmap)
import Data.Functor.Identity (Identity (..))
import Data.Morpheus.Core
( App (..),
AppData (..),
mkApp,
mkApp,
parseGQLDocument,
render,
runAppStream,
)
import Data.Morpheus.Types.IO
import Data.Morpheus.Types.Internal.AST
( FieldName (..),
Schema,
VALID,
Value,
)
import Data.Morpheus.Types.Internal.Resolving
( ResponseStream,
ResultT (..),
resultOr,
)
import Data.Semigroup ((<>))
import Data.Text (unpack)
import Data.Traversable (traverse)
import Test.Tasty
( TestTree,
testGroup,
)
import Test.Tasty.HUnit
( assertFailure,
testCase,
)
import Utils.Utils
( expectedResponse,
getRequest,
getResolver,
)
import Prelude
( ($),
(.),
Eq (..),
IO,
Maybe (..),
otherwise,
show,
)
readSchema :: FieldName -> IO (Schema VALID)
readSchema (FieldName p) = L.readFile (unpack p) >>= (resultOr (fail . show) pure . parseGQLDocument)
loadApi :: FieldName -> IO (App () Identity)
loadApi url = do
schema <- readSchema ("test/" <> url <> ".gql")
resolvers <- getResolver ("test/" <> url <> ".json")
pure $ mkApp schema resolvers
schemaAssertion :: App () Identity -> Schema VALID -> IO ()
schemaAssertion (App AppData {appSchema}) expectedSchema
| render expectedSchema == render appSchema = pure ()
| otherwise =
assertFailure
$ unpack
$ "expected: \n " <> render expectedSchema <> " \n but got: \n " <> render appSchema
schemaAssertion (FailApp gqlerror) _ = assertFailure $ " error: " <> show gqlerror
schemaCase :: (FieldName, [FieldName]) -> IO TestTree
schemaCase (url, files) = do
schema <- loadApi (url <> "/api/app")
extension <- loadApi (url <> "/api/ext")
let api = schema <> extension
pure $
testGroup
(show url)
[ testCase
"Schema"
(readSchema ("test/" <> url <> "/expected/ok.gql") >>= schemaAssertion api),
testGroup
"Requests"
(fmap (testApiRequest api url) files)
]
test :: IO TestTree
test =
testGroup
"merge schema"
<$> traverse
schemaCase
[ ("merge/schema/simple-query", ["query"]),
("merge/schema/query-subscription-mutation", ["query", "mutation"])
]
assertion :: A.Value -> ResponseStream e Identity (Value VALID) -> IO ()
assertion expected (ResultT (Identity actual))
| Just expected == decode actualValue = pure ()
| otherwise =
assertFailure $
LB.unpack
("expected: \n\n " <> encode expected <> " \n\n but got: \n\n " <> actualValue)
where
actualValue = encode (renderResponse actual)
testApiRequest ::
App () Identity ->
FieldName ->
FieldName ->
TestTree
testApiRequest api base path = testCase (unpack $ readName path) $ do
let fullPath = base <> "/request/" <> path
actual <- runAppStream api <$> getRequest fullPath
expected <- expectedResponse fullPath
assertion expected actual