diff options
Diffstat (limited to 'tests/Language/GraphQL/ExecuteSpec.hs')
| -rw-r--r-- | tests/Language/GraphQL/ExecuteSpec.hs | 87 |
1 files changed, 59 insertions, 28 deletions
diff --git a/tests/Language/GraphQL/ExecuteSpec.hs b/tests/Language/GraphQL/ExecuteSpec.hs index d14eb9d..6723524 100644 --- a/tests/Language/GraphQL/ExecuteSpec.hs +++ b/tests/Language/GraphQL/ExecuteSpec.hs @@ -21,6 +21,7 @@ import Language.GraphQL.AST (Document, Location(..), Name) import Language.GraphQL.AST.Parser (document) import Language.GraphQL.Error import Language.GraphQL.Execute (execute) +import Language.GraphQL.TH import qualified Language.GraphQL.Type.Schema as Schema import Language.GraphQL.Type import qualified Language.GraphQL.Type.In as In @@ -28,7 +29,6 @@ import qualified Language.GraphQL.Type.Out as Out import Prelude hiding (id) import Test.Hspec (Spec, context, describe, it, shouldBe) import Text.Megaparsec (parse) -import Text.RawString.QQ (r) data PhilosopherException = PhilosopherException deriving Show @@ -54,18 +54,23 @@ queryType = Out.ObjectType "Query" Nothing [] $ HashMap.fromList [ ("philosopher", ValueResolver philosopherField philosopherResolver) , ("genres", ValueResolver genresField genresResolver) + , ("count", ValueResolver countField countResolver) ] where philosopherField = - Out.Field Nothing (Out.NonNullObjectType philosopherType) + Out.Field Nothing (Out.NamedObjectType philosopherType) $ HashMap.singleton "id" $ In.Argument Nothing (In.NamedScalarType id) Nothing philosopherResolver = pure $ Object mempty genresField = - let fieldType = Out.ListType $ Out.NonNullScalarType string - in Out.Field Nothing fieldType HashMap.empty + let fieldType = Out.ListType $ Out.NonNullScalarType string + in Out.Field Nothing fieldType HashMap.empty genresResolver :: Resolve (Either SomeException) genresResolver = throwM PhilosopherException + countField = + let fieldType = Out.NonNullScalarType int + in Out.Field Nothing fieldType HashMap.empty + countResolver = pure "" musicType :: Out.ObjectType (Either SomeException) musicType = Out.ObjectType "Music" Nothing [] @@ -101,6 +106,7 @@ philosopherType = Out.ObjectType "Philosopher" Nothing [] , ("interest", ValueResolver interestField interestResolver) , ("majorWork", ValueResolver majorWorkField majorWorkResolver) , ("century", ValueResolver centuryField centuryResolver) + , ("firstLanguage", ValueResolver firstLanguageField firstLanguageResolver) ] firstNameField = Out.Field Nothing (Out.NonNullScalarType string) HashMap.empty @@ -126,6 +132,9 @@ philosopherType = Out.ObjectType "Philosopher" Nothing [] centuryField = Out.Field Nothing (Out.NonNullScalarType int) HashMap.empty centuryResolver = pure $ Float 18.5 + firstLanguageField + = Out.Field Nothing (Out.NonNullScalarType string) HashMap.empty + firstLanguageResolver = pure Null workType :: Out.InterfaceType (Either SomeException) workType = Out.InterfaceType "Work" Nothing [] @@ -191,7 +200,7 @@ spec :: Spec spec = describe "execute" $ do it "rejects recursive fragments" $ - let sourceQuery = [r| + let sourceQuery = [gql| { ...cyclicFragment } @@ -230,14 +239,13 @@ spec = it "errors on invalid output enum values" $ let data'' = Aeson.object - [ "philosopher" .= Aeson.object - [ "school" .= Aeson.Null - ] + [ "philosopher" .= Aeson.Null ] executionErrors = pure $ Error - { message = "Enum value completion failed." + { message = + "Value completion error. Expected type !School, found: EXISTENTIALISM." , locations = [Location 1 17] - , path = [] + , path = [Segment "philosopher", Segment "school"] } expected = Response data'' executionErrors Right (Right actual) = either (pure . parseError) execute' @@ -246,14 +254,13 @@ spec = it "gives location information for non-null unions" $ let data'' = Aeson.object - [ "philosopher" .= Aeson.object - [ "interest" .= Aeson.Null - ] + [ "philosopher" .= Aeson.Null ] executionErrors = pure $ Error - { message = "Union value completion failed." + { message = + "Value completion error. Expected type !Interest, found: { instrument: \"piano\" }." , locations = [Location 1 17] - , path = [] + , path = [Segment "philosopher", Segment "interest"] } expected = Response data'' executionErrors Right (Right actual) = either (pure . parseError) execute' @@ -262,14 +269,14 @@ spec = it "gives location information for invalid interfaces" $ let data'' = Aeson.object - [ "philosopher" .= Aeson.object - [ "majorWork" .= Aeson.Null - ] + [ "philosopher" .= Aeson.Null ] executionErrors = pure $ Error - { message = "Interface value completion failed." + { message + = "Value completion error. Expected type !Work, found:\ + \ { title: \"Also sprach Zarathustra: Ein Buch f\252r Alle und Keinen\" }." , locations = [Location 1 17] - , path = [] + , path = [Segment "philosopher", Segment "majorWork"] } expected = Response data'' executionErrors Right (Right actual) = either (pure . parseError) execute' @@ -281,9 +288,10 @@ spec = [ "philosopher" .= Aeson.Null ] executionErrors = pure $ Error - { message = "Argument coercing failed." + { message = + "Argument \"id\" has invalid type. Expected type ID, found: True." , locations = [Location 1 15] - , path = [] + , path = [Segment "philosopher"] } expected = Response data'' executionErrors Right (Right actual) = either (pure . parseError) execute' @@ -292,14 +300,12 @@ spec = it "gives location information for failed result coercion" $ let data'' = Aeson.object - [ "philosopher" .= Aeson.object - [ "century" .= Aeson.Null - ] + [ "philosopher" .= Aeson.Null ] executionErrors = pure $ Error - { message = "Result coercion failed." + { message = "Unable to coerce result to !Int." , locations = [Location 1 26] - , path = [] + , path = [Segment "philosopher", Segment "century"] } expected = Response data'' executionErrors Right (Right actual) = either (pure . parseError) execute' @@ -313,13 +319,38 @@ spec = executionErrors = pure $ Error { message = "PhilosopherException" , locations = [Location 1 3] - , path = [] + , path = [Segment "genres"] } expected = Response data'' executionErrors Right (Right actual) = either (pure . parseError) execute' $ parse document "" "{ genres }" in actual `shouldBe` expected + it "sets data to null if a root field isn't nullable" $ + let executionErrors = pure $ Error + { message = "Unable to coerce result to !Int." + , locations = [Location 1 3] + , path = [Segment "count"] + } + expected = Response Aeson.Null executionErrors + Right (Right actual) = either (pure . parseError) execute' + $ parse document "" "{ count }" + in actual `shouldBe` expected + + it "detects nullability errors" $ + let data'' = Aeson.object + [ "philosopher" .= Aeson.Null + ] + executionErrors = pure $ Error + { message = "Value completion error. Expected type !String, found: null." + , locations = [Location 1 26] + , path = [Segment "philosopher", Segment "firstLanguage"] + } + expected = Response data'' executionErrors + Right (Right actual) = either (pure . parseError) execute' + $ parse document "" "{ philosopher(id: \"1\") { firstLanguage } }" + in actual `shouldBe` expected + context "Subscription" $ it "subscribes" $ let data'' = Aeson.object |
