{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Test.Morpheus
( FileUrl,
mkUrl,
cd,
file,
deepScan,
scan,
getAppsBy,
testApi,
testSchema,
testQueryRendering,
renderingAssertion,
testQuery,
testQueryValidation,
mainTest,
)
where
import Data.Aeson
( FromJSON (..),
ToJSON (..),
encode,
)
import Data.ByteString.Lazy.Char8 (ByteString)
import Relude hiding (ByteString)
import Test.Morpheus.File
import Test.Morpheus.Response
import Test.Morpheus.Utils
import Test.Tasty
( TestTree,
defaultMain,
testGroup,
)
import Test.Tasty.HUnit
( assertFailure,
testCase,
)
mainTest :: String -> [IO TestTree] -> IO ()
mainTest :: String -> [IO TestTree] -> IO ()
mainTest String
name [IO TestTree]
xs = do
[TestTree]
tests <- forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [IO TestTree]
xs
TestTree -> IO ()
defaultMain forall a b. (a -> b) -> a -> b
$
String -> [TestTree] -> TestTree
testGroup
String
name
[TestTree]
tests
testApi ::
(FromJSON req, ToJSON res) =>
(req -> IO res) ->
FileUrl ->
TestTree
testApi :: forall req res.
(FromJSON req, ToJSON res) =>
(req -> IO res) -> FileUrl -> TestTree
testApi req -> IO res
api =
forall a.
(FromJSON a, Eq a, ToJSON a) =>
(FileUrl -> IO (CaseAssertion a)) -> FileUrl -> TestTree
assertResponse
(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. ToJSON a => a -> CaseAssertion Value
expects forall b c a. (b -> c) -> (a -> b) -> a -> c
. req -> IO res
api forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< forall req. FromJSON req => FileUrl -> IO req
getQuery)
testQuery ::
(FromJSON req, ToJSON err, Eq err, FromJSON err) =>
(req -> Either err a) ->
FileUrl ->
TestTree
testQuery :: forall req err a.
(FromJSON req, ToJSON err, Eq err, FromJSON err) =>
(req -> Either err a) -> FileUrl -> TestTree
testQuery req -> Either err a
f =
forall a.
(FromJSON a, Eq a, ToJSON a) =>
(FileUrl -> IO (CaseAssertion a)) -> FileUrl -> TestTree
assertResponse
(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall err a. ToJSON err => Either err a -> CaseAssertion err
fromEither forall b c a. (b -> c) -> (a -> b) -> a -> c
. req -> Either err a
f) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall req. FromJSON req => FileUrl -> IO req
getQuery)
testSchema ::
(ToJSON err, Eq err, FromJSON err) =>
(ByteString -> Either err a) ->
FileUrl ->
TestTree
testSchema :: forall err a.
(ToJSON err, Eq err, FromJSON err) =>
(ByteString -> Either err a) -> FileUrl -> TestTree
testSchema ByteString -> Either err a
f =
forall a.
(FromJSON a, Eq a, ToJSON a) =>
(FileUrl -> IO (CaseAssertion a)) -> FileUrl -> TestTree
assertResponse
(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall err a. ToJSON err => Either err a -> CaseAssertion err
fromEither forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either err a
f) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. ReadSource t => FileUrl -> IO t
readSchemaFile)
renderingAssertion ::
(ToJSON e) =>
(FileUrl -> IO (Either e ByteString)) ->
FileUrl ->
TestTree
renderingAssertion :: forall e.
ToJSON e =>
(FileUrl -> IO (Either e ByteString)) -> FileUrl -> TestTree
renderingAssertion FileUrl -> IO (Either e ByteString)
api FileUrl
url = String -> IO () -> TestTree
testCase (FileUrl -> String
fileName FileUrl
url) forall a b. (a -> b) -> a -> b
$ do
Either e ByteString
actual <- FileUrl -> IO (Either e ByteString)
api FileUrl
url
ByteString
expected <- forall t. ReadSource t => String -> FileUrl -> IO t
readGQL String
"rendering" FileUrl
url
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
(forall a. HasCallStack => String -> IO a
assertFailure forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
" error: " forall a. Semigroup a => a -> a -> a
<>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. (Show a, IsString b) => a -> b
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => a -> ByteString
encode)
(forall t. Eq t => (t -> ByteString) -> t -> t -> IO ()
requireEq forall a. a -> a
id ByteString
expected)
Either e ByteString
actual
getAppBy ::
(Show err, FromJSON resolvers) =>
( ByteString -> Either err schema,
schema -> resolvers -> app
) ->
FileUrl ->
IO app
getAppBy :: forall err resolvers schema app.
(Show err, FromJSON resolvers) =>
(ByteString -> Either err schema, schema -> resolvers -> app)
-> FileUrl -> IO app
getAppBy (ByteString -> Either err schema
parseSchema, schema -> resolvers -> app
mkApp) FileUrl
url =
schema -> resolvers -> app
mkApp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a err b.
(ReadSource a, Show err) =>
(a -> Either err b) -> FileUrl -> IO b
getSchema ByteString -> Either err schema
parseSchema FileUrl
url
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall req. FromJSON req => FileUrl -> IO req
getResolver FileUrl
url
testQueryValidation ::
( ToJSON errors,
Show errors,
FromJSON request,
FromJSON errors,
Eq errors
) =>
( schema -> request -> Either errors a,
ByteString -> Either errors schema
) ->
FileUrl ->
FileUrl ->
TestTree
testQueryValidation :: forall errors request schema a.
(ToJSON errors, Show errors, FromJSON request, FromJSON errors,
Eq errors) =>
(schema -> request -> Either errors a,
ByteString -> Either errors schema)
-> FileUrl -> FileUrl -> TestTree
testQueryValidation (schema -> request -> Either errors a
parseRequest, ByteString -> Either errors schema
parseSchema) FileUrl
schemaUrl =
forall a.
(FromJSON a, Eq a, ToJSON a) =>
(FileUrl -> IO (CaseAssertion a)) -> FileUrl -> TestTree
assertResponse
( \FileUrl
url -> do
schema
schema <- forall a err b.
(ReadSource a, Show err) =>
(a -> Either err b) -> FileUrl -> IO b
getSchema ByteString -> Either errors schema
parseSchema FileUrl
schemaUrl
request
query <- forall req. FromJSON req => FileUrl -> IO req
getQuery FileUrl
url
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall err a. ToJSON err => Either err a -> CaseAssertion err
fromEither (schema -> request -> Either errors a
parseRequest schema
schema request
query)
)
testQueryRendering ::
( ToJSON errors,
Show errors,
FromJSON request
) =>
( schema -> request -> Either errors ByteString,
ByteString -> Either errors schema
) ->
FileUrl ->
FileUrl ->
TestTree
testQueryRendering :: forall errors request schema.
(ToJSON errors, Show errors, FromJSON request) =>
(schema -> request -> Either errors ByteString,
ByteString -> Either errors schema)
-> FileUrl -> FileUrl -> TestTree
testQueryRendering (schema -> request -> Either errors ByteString
parseRequest, ByteString -> Either errors schema
parseSchema) FileUrl
schemaUrl =
forall e.
ToJSON e =>
(FileUrl -> IO (Either e ByteString)) -> FileUrl -> TestTree
renderingAssertion
( \FileUrl
requestUrl -> do
request
request <- forall req. FromJSON req => FileUrl -> IO req
getQuery FileUrl
requestUrl
schema
schema <- forall a err b.
(ReadSource a, Show err) =>
(a -> Either err b) -> FileUrl -> IO b
getSchema ByteString -> Either errors schema
parseSchema FileUrl
schemaUrl
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ schema -> request -> Either errors ByteString
parseRequest schema
schema request
request
)
getAppsWIth ::
(Semigroup b, Show err, FromJSON resolvers) =>
( ByteString -> Either err schema,
schema -> resolvers -> b
) ->
FileUrl ->
[FilePath] ->
IO b
getAppsWIth :: forall b err resolvers schema.
(Semigroup b, Show err, FromJSON resolvers) =>
(ByteString -> Either err schema, schema -> resolvers -> b)
-> FileUrl -> [String] -> IO b
getAppsWIth (ByteString -> Either err schema, schema -> resolvers -> b)
f FileUrl
url [] = forall err resolvers schema app.
(Show err, FromJSON resolvers) =>
(ByteString -> Either err schema, schema -> resolvers -> app)
-> FileUrl -> IO app
getAppBy (ByteString -> Either err schema, schema -> resolvers -> b)
f FileUrl
url
getAppsWIth (ByteString -> Either err schema, schema -> resolvers -> b)
f FileUrl
url (String
x : [String]
xs) = forall a. Semigroup a => NonEmpty a -> a
sconcat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall err resolvers schema app.
(Show err, FromJSON resolvers) =>
(ByteString -> Either err schema, schema -> resolvers -> app)
-> FileUrl -> IO app
getAppBy (ByteString -> Either err schema, schema -> resolvers -> b)
f) (FileUrl -> String -> FileUrl
file FileUrl
url forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String
x forall a. a -> [a] -> NonEmpty a
:| [String]
xs))
getAppsBy ::
(Semigroup b, Show err, FromJSON resolvers) =>
( ByteString -> Either err schema,
schema -> resolvers -> b
) ->
FileUrl ->
IO b
getAppsBy :: forall b err resolvers schema.
(Semigroup b, Show err, FromJSON resolvers) =>
(ByteString -> Either err schema, schema -> resolvers -> b)
-> FileUrl -> IO b
getAppsBy (ByteString -> Either err schema, schema -> resolvers -> b)
f FileUrl
url = do
[String]
files <- FileUrl -> IO [String]
searchAppFiles FileUrl
url
forall b err resolvers schema.
(Semigroup b, Show err, FromJSON resolvers) =>
(ByteString -> Either err schema, schema -> resolvers -> b)
-> FileUrl -> [String] -> IO b
getAppsWIth (ByteString -> Either err schema, schema -> resolvers -> b)
f FileUrl
url (forall a. Ord a => [a] -> [a]
sort [String]
files)