aboutsummaryrefslogtreecommitdiff
path: root/tests/Language/GraphQL/ExecuteSpec.hs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Language/GraphQL/ExecuteSpec.hs')
-rw-r--r--tests/Language/GraphQL/ExecuteSpec.hs87
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