diff options
Diffstat (limited to 'tests/Test/StarWars')
| -rw-r--r-- | tests/Test/StarWars/Data.hs | 13 | ||||
| -rw-r--r-- | tests/Test/StarWars/QuerySpec.hs | 182 | ||||
| -rw-r--r-- | tests/Test/StarWars/Schema.hs | 55 |
3 files changed, 132 insertions, 118 deletions
diff --git a/tests/Test/StarWars/Data.hs b/tests/Test/StarWars/Data.hs index 4854f8f..9466991 100644 --- a/tests/Test/StarWars/Data.hs +++ b/tests/Test/StarWars/Data.hs @@ -8,7 +8,6 @@ module Test.StarWars.Data , getEpisode , getFriends , getHero - , getHeroIO , getHuman , id_ , homePlanet @@ -17,11 +16,8 @@ module Test.StarWars.Data , typeName ) where -import Data.Monoid (mempty) -import Control.Applicative ( Alternative(..) - , liftA2 - ) -import Control.Monad.IO.Class (MonadIO(..)) +import Data.Functor.Identity (Identity) +import Control.Applicative (Alternative(..), liftA2) import Control.Monad.Trans.Except (throwE) import Data.Maybe (catMaybes) import Data.Text (Text) @@ -71,7 +67,7 @@ appearsIn :: Character -> [Int] appearsIn (Left x) = _appearsIn . _droidChar $ x appearsIn (Right x) = _appearsIn . _humanChar $ x -secretBackstory :: MonadIO m => Character -> ActionT m Text +secretBackstory :: Character -> ActionT Identity Text secretBackstory = const $ ActionT $ throwE "secretBackstory is secret." typeName :: Character -> Text @@ -166,9 +162,6 @@ getHero :: Int -> Character getHero 5 = luke getHero _ = artoo -getHeroIO :: Int -> IO Character -getHeroIO = pure . getHero - getHuman :: Alternative f => ID -> f Character getHuman = fmap Right . getHuman' diff --git a/tests/Test/StarWars/QuerySpec.hs b/tests/Test/StarWars/QuerySpec.hs index 0f6a2ef..45fcf42 100644 --- a/tests/Test/StarWars/QuerySpec.hs +++ b/tests/Test/StarWars/QuerySpec.hs @@ -5,20 +5,15 @@ module Test.StarWars.QuerySpec ) where import qualified Data.Aeson as Aeson -import Data.Aeson ( object - , (.=) - ) +import Data.Aeson ((.=)) +import Data.Functor.Identity (Identity(..)) +import qualified Data.HashMap.Strict as HashMap import Data.Text (Text) import Language.GraphQL import Language.GraphQL.Schema (Subs) import Text.RawString.QQ (r) -import Test.Hspec.Expectations ( Expectation - , shouldBe - ) -import Test.Hspec ( Spec - , describe - , it - ) +import Test.Hspec.Expectations (Expectation, shouldBe) +import Test.Hspec (Spec, describe, it) import Test.StarWars.Schema -- * Test @@ -34,7 +29,11 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object [ "data" .= object ["hero" .= object ["id" .= ("2001" :: Text)]]] + $ Aeson.object + [ "data" .= Aeson.object + [ "hero" .= Aeson.object ["id" .= ("2001" :: Text)] + ] + ] it "R2-D2 ID and friends" $ testQuery [r| query HeroNameAndFriendsQuery { hero { @@ -46,14 +45,14 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object [ "data" .= object [ - "hero" .= object + $ Aeson.object [ "data" .= Aeson.object [ + "hero" .= Aeson.object [ "id" .= ("2001" :: Text) , r2d2Name , "friends" .= - [ object [lukeName] - , object [hanName] - , object [leiaName] + [ Aeson.object [lukeName] + , Aeson.object [hanName] + , Aeson.object [leiaName] ] ] ]] @@ -73,37 +72,37 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object [ "data" .= object [ - "hero" .= object [ + $ Aeson.object [ "data" .= Aeson.object [ + "hero" .= Aeson.object [ "name" .= ("R2-D2" :: Text) , "friends" .= [ - object [ + Aeson.object [ "name" .= ("Luke Skywalker" :: Text) , "appearsIn" .= ["NEWHOPE","EMPIRE","JEDI" :: Text] , "friends" .= [ - object [hanName] - , object [leiaName] - , object [c3poName] - , object [r2d2Name] + Aeson.object [hanName] + , Aeson.object [leiaName] + , Aeson.object [c3poName] + , Aeson.object [r2d2Name] ] ] - , object [ + , Aeson.object [ hanName , "appearsIn" .= [ "NEWHOPE","EMPIRE","JEDI" :: Text] - , "friends" .= [ - object [lukeName] - , object [leiaName] - , object [r2d2Name] + , "friends" .= + [ Aeson.object [lukeName] + , Aeson.object [leiaName] + , Aeson.object [r2d2Name] ] ] - , object [ + , Aeson.object [ leiaName , "appearsIn" .= [ "NEWHOPE","EMPIRE","JEDI" :: Text] - , "friends" .= [ - object [lukeName] - , object [hanName] - , object [c3poName] - , object [r2d2Name] + , "friends" .= + [ Aeson.object [lukeName] + , Aeson.object [hanName] + , Aeson.object [c3poName] + , Aeson.object [r2d2Name] ] ] ] @@ -116,40 +115,40 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object [ "data" .= object [ - "human" .= object [lukeName] - ]] + $ Aeson.object [ "data" .= Aeson.object + [ "human" .= Aeson.object [lukeName] + ]] it "Luke ID with variable" $ testQueryParams - (\v -> if v == "someId" then Just "1000" else Nothing) + (HashMap.singleton "someId" "1000") [r| query FetchSomeIDQuery($someId: String!) { human(id: $someId) { name } } |] - $ object [ "data" .= object [ - "human" .= object [lukeName] + $ Aeson.object [ "data" .= Aeson.object [ + "human" .= Aeson.object [lukeName] ]] it "Han ID with variable" $ testQueryParams - (\v -> if v == "someId" then Just "1002" else Nothing) + (HashMap.singleton "someId" "1002") [r| query FetchSomeIDQuery($someId: String!) { human(id: $someId) { name } } |] - $ object [ "data" .= object [ - "human" .= object [hanName] + $ Aeson.object [ "data" .= Aeson.object [ + "human" .= Aeson.object [hanName] ]] it "Invalid ID" $ testQueryParams - (\v -> if v == "id" then Just "Not a valid ID" else Nothing) + (HashMap.singleton "id" "Not a valid ID") [r| query humanQuery($id: String!) { human(id: $id) { name } } - |] $ object ["data" .= object ["human" .= Aeson.Null]] + |] $ Aeson.object ["data" .= Aeson.object ["human" .= Aeson.Null]] it "Luke aliased" $ testQuery [r| query FetchLukeAliased { luke: human(id: "1000") { @@ -157,8 +156,8 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object [ "data" .= object [ - "luke" .= object [lukeName] + $ Aeson.object [ "data" .= Aeson.object [ + "luke" .= Aeson.object [lukeName] ]] it "R2-D2 ID and friends aliased" $ testQuery [r| query HeroNameAndFriendsQuery { @@ -171,14 +170,14 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object [ "data" .= object [ - "hero" .= object [ + $ Aeson.object [ "data" .= Aeson.object [ + "hero" .= Aeson.object [ "id" .= ("2001" :: Text) , r2d2Name - , "friends" .= [ - object ["friendName" .= ("Luke Skywalker" :: Text)] - , object ["friendName" .= ("Han Solo" :: Text)] - , object ["friendName" .= ("Leia Organa" :: Text)] + , "friends" .= + [ Aeson.object ["friendName" .= ("Luke Skywalker" :: Text)] + , Aeson.object ["friendName" .= ("Han Solo" :: Text)] + , Aeson.object ["friendName" .= ("Leia Organa" :: Text)] ] ] ]] @@ -192,9 +191,9 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object [ "data" .= object [ - "luke" .= object [lukeName] - , "leia" .= object [leiaName] + $ Aeson.object [ "data" .= Aeson.object + [ "luke" .= Aeson.object [lukeName] + , "leia" .= Aeson.object [leiaName] ]] describe "Fragments for complex queries" $ do @@ -210,9 +209,9 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object [ "data" .= object [ - "luke" .= object [lukeName, tatooine] - , "leia" .= object [leiaName, alderaan] + $ Aeson.object [ "data" .= Aeson.object [ + "luke" .= Aeson.object [lukeName, tatooine] + , "leia" .= Aeson.object [leiaName, alderaan] ]] it "Fragment for duplicate content" $ testQuery [r| query UseFragment { @@ -228,9 +227,9 @@ spec = describe "Star Wars Query Tests" $ do homePlanet } |] - $ object [ "data" .= object [ - "luke" .= object [lukeName, tatooine] - , "leia" .= object [leiaName, alderaan] + $ Aeson.object [ "data" .= Aeson.object [ + "luke" .= Aeson.object [lukeName, tatooine] + , "leia" .= Aeson.object [leiaName, alderaan] ]] describe "__typename" $ do @@ -242,8 +241,11 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object ["data" .= object [ - "hero" .= object ["__typename" .= ("Droid" :: Text), r2d2Name] + $ Aeson.object ["data" .= Aeson.object [ + "hero" .= Aeson.object + [ "__typename" .= ("Droid" :: Text) + , r2d2Name + ] ]] it "Luke is a human" $ testQuery [r| query CheckTypeOfLuke { @@ -253,8 +255,11 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object ["data" .= object [ - "hero" .= object ["__typename" .= ("Human" :: Text), lukeName] + $ Aeson.object ["data" .= Aeson.object [ + "hero" .= Aeson.object + [ "__typename" .= ("Human" :: Text) + , lukeName + ] ]] describe "Errors in resolvers" $ do @@ -267,15 +272,15 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object - [ "data" .= object - [ "hero" .= object + $ Aeson.object + [ "data" .= Aeson.object + [ "hero" .= Aeson.object [ "name" .= ("R2-D2" :: Text) , "secretBackstory" .= Aeson.Null ] ] , "errors" .= - [ object + [ Aeson.object ["message" .= ("secretBackstory is secret." :: Text)] ] ] @@ -290,19 +295,19 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object ["data" .= object - [ "hero" .= object + $ Aeson.object ["data" .= Aeson.object + [ "hero" .= Aeson.object [ "name" .= ("R2-D2" :: Text) , "friends" .= - [ object + [ Aeson.object [ "name" .= ("Luke Skywalker" :: Text) , "secretBackstory" .= Aeson.Null ] - , object + , Aeson.object [ "name" .= ("Han Solo" :: Text) , "secretBackstory" .= Aeson.Null ] - , object + , Aeson.object [ "name" .= ("Leia Organa" :: Text) , "secretBackstory" .= Aeson.Null ] @@ -310,9 +315,15 @@ spec = describe "Star Wars Query Tests" $ do ] ] , "errors" .= - [ object ["message" .= ("secretBackstory is secret." :: Text)] - , object ["message" .= ("secretBackstory is secret." :: Text)] - , object ["message" .= ("secretBackstory is secret." :: Text)] + [ Aeson.object + [ "message" .= ("secretBackstory is secret." :: Text) + ] + , Aeson.object + [ "message" .= ("secretBackstory is secret." :: Text) + ] + , Aeson.object + [ "message" .= ("secretBackstory is secret." :: Text) + ] ] ] it "error on secretBackstory with alias" $ testQuery @@ -323,15 +334,17 @@ spec = describe "Star Wars Query Tests" $ do } } |] - $ object - [ "data" .= object - [ "mainHero" .= object + $ Aeson.object + [ "data" .= Aeson.object + [ "mainHero" .= Aeson.object [ "name" .= ("R2-D2" :: Text) , "story" .= Aeson.Null ] ] , "errors" .= - [ object ["message" .= ("secretBackstory is secret." :: Text)] + [ Aeson.object + [ "message" .= ("secretBackstory is secret." :: Text) + ] ] ] @@ -345,7 +358,8 @@ spec = describe "Star Wars Query Tests" $ do alderaan = "homePlanet" .= ("Alderaan" :: Text) testQuery :: Text -> Aeson.Value -> Expectation -testQuery q expected = graphql schema q >>= flip shouldBe expected +testQuery q expected = runIdentity (graphql schema q) `shouldBe` expected testQueryParams :: Subs -> Text -> Aeson.Value -> Expectation -testQueryParams f q expected = graphqlSubs schema f q >>= flip shouldBe expected +testQueryParams f q expected = + runIdentity (graphqlSubs schema f q) `shouldBe` expected diff --git a/tests/Test/StarWars/Schema.hs b/tests/Test/StarWars/Schema.hs index 7b98747..cd25599 100644 --- a/tests/Test/StarWars/Schema.hs +++ b/tests/Test/StarWars/Schema.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} module Test.StarWars.Schema ( character @@ -10,9 +9,12 @@ module Test.StarWars.Schema import Control.Monad.Trans.Except (throwE) import Control.Monad.Trans.Class (lift) -import Control.Monad.IO.Class (MonadIO(..)) +import Data.Functor.Identity (Identity) +import Data.HashMap.Strict (HashMap) +import qualified Data.HashMap.Strict as HashMap import Data.List.NonEmpty (NonEmpty(..)) import Data.Maybe (catMaybes) +import Data.Text (Text) import qualified Language.GraphQL.Schema as Schema import Language.GraphQL.Trans import qualified Language.GraphQL.Type as Type @@ -20,32 +22,37 @@ import Test.StarWars.Data -- See https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsSchema.js -schema :: MonadIO m => NonEmpty (Schema.Resolver m) -schema = hero :| [human, droid] +schema :: HashMap Text (NonEmpty (Schema.Resolver Identity)) +schema = HashMap.singleton "Query" $ hero :| [human, droid] -hero :: MonadIO m => Schema.Resolver m -hero = Schema.objectA "hero" $ \case - [] -> character artoo - [Schema.Argument "episode" (Schema.Enum "NEWHOPE")] -> character $ getHero 4 - [Schema.Argument "episode" (Schema.Enum "EMPIRE" )] -> character $ getHero 5 - [Schema.Argument "episode" (Schema.Enum "JEDI" )] -> character $ getHero 6 - _ -> ActionT $ throwE "Invalid arguments." +hero :: Schema.Resolver Identity +hero = Schema.object "hero" $ do + episode <- argument "episode" + character $ case episode of + Schema.Enum "NEWHOPE" -> getHero 4 + Schema.Enum "EMPIRE" -> getHero 5 + Schema.Enum "JEDI" -> getHero 6 + _ -> artoo -human :: MonadIO m => Schema.Resolver m -human = Schema.wrappedObjectA "human" $ \case - [Schema.Argument "id" (Schema.String i)] -> do - humanCharacter <- lift $ return $ getHuman i >>= Just - case humanCharacter of - Nothing -> return Type.Null - Just e -> Type.Named <$> character e - _ -> ActionT $ throwE "Invalid arguments." +human :: Schema.Resolver Identity +human = Schema.wrappedObject "human" $ do + id' <- argument "id" + case id' of + Schema.String i -> do + humanCharacter <- lift $ return $ getHuman i >>= Just + case humanCharacter of + Nothing -> return Type.Null + Just e -> Type.Named <$> character e + _ -> ActionT $ throwE "Invalid arguments." -droid :: MonadIO m => Schema.Resolver m -droid = Schema.objectA "droid" $ \case - [Schema.Argument "id" (Schema.String i)] -> character =<< liftIO (getDroid i) - _ -> ActionT $ throwE "Invalid arguments." +droid :: Schema.Resolver Identity +droid = Schema.object "droid" $ do + id' <- argument "id" + case id' of + Schema.String i -> character =<< getDroid i + _ -> ActionT $ throwE "Invalid arguments." -character :: MonadIO m => Character -> ActionT m [Schema.Resolver m] +character :: Character -> ActionT Identity [Schema.Resolver Identity] character char = return [ Schema.scalar "id" $ return $ id_ char , Schema.scalar "name" $ return $ name char |
