{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module Main
( main,
)
where
import qualified Data.Aeson as A
import Data.Aeson (decode, encode)
import Data.Functor.Identity (Identity (..))
import Data.Morpheus.Core (runApi)
import Data.Morpheus.Internal.Utils
( fromElems,
)
import Data.Morpheus.QuasiQuoter (dsl)
import Data.Morpheus.Types.IO
( GQLRequest (..),
)
import Data.Morpheus.Types.Internal.AST
( FieldName,
Schema,
VALID,
Value (..),
msg,
)
import Data.Morpheus.Types.Internal.Resolving
( ResModel,
Resolver,
ResponseStream,
Result (..),
ResultT (..),
RootResModel (..),
WithOperation,
mkList,
mkNull,
mkObject,
mkString,
)
import Data.Semigroup ((<>))
import qualified Data.Text.Lazy as LT (toStrict)
import Data.Text.Lazy.Encoding (decodeUtf8)
import Lib
( getGQLBody,
getResponseBody,
maybeVariables,
)
import Schema
( testSchema,
)
import Test.Tasty
( TestTree,
defaultMain,
testGroup,
)
import Test.Tasty.HUnit
( assertFailure,
testCase,
)
getSchema :: Monad m => ResponseStream e m Schema
getSchema =
fromElems
[dsl|
type Query {
deity(name: String): Deity!
}
interface Character {
name : String
}
interface Supernatural {
power: [String!]!
}
type Hero implements Character {
name: String
}
type Deity implements Character Supernatural {
name: String!
power: [String!]!
}
|]
resolver :: Monad m => RootResModel e m
resolver =
RootResModel
{ query =
pure $
mkObject
"Query"
[("deity", resolveDeity)],
mutation = pure mkNull,
subscription = pure mkNull
}
resolveDeity :: (WithOperation o, Monad m) => Resolver o e m (ResModel o e m)
resolveDeity =
pure $
mkObject
"Deity"
[ ("name", pure $ mkString "Morpheus"),
("power", pure $ mkList [mkString "Shapeshifting"])
]
main :: IO ()
main = do
schema <- testSchema
defaultMain
$ testGroup
"core tests"
$ map
(uncurry basicTest)
[ ("basic Test", "api/simple"),
("test interface", "api/interface")
]
<> [schema]
basicTest :: String -> FieldName -> TestTree
basicTest description path = testCase description $ do
actual <- simpleTest <$> getRequest path
expected <- expectedResponse path
assertion expected actual
simpleTest :: GQLRequest -> ResponseStream e Identity (Value VALID)
simpleTest request = do
schema <- getSchema
runApi schema resolver request
expectedResponse :: FieldName -> IO A.Value
expectedResponse = getResponseBody
assertion :: A.Value -> ResponseStream e Identity (Value VALID) -> IO ()
assertion expected (ResultT (Identity Success {result}))
| Just expected == decode (encode result) = return ()
| otherwise =
assertFailure $ show ("expected: \n " <> msg expected <> " \n but got: \n " <> msg result)
assertion _ (ResultT (Identity Failure {errors})) = assertFailure (show errors)
getRequest :: FieldName -> IO GQLRequest
getRequest path = do
queryBS <- LT.toStrict . decodeUtf8 <$> getGQLBody path
variables <- maybeVariables path
pure $
GQLRequest
{ operationName = Nothing,
query = queryBS,
variables
}