Skip to content

Commit 377408b

Browse files
committed
Tests for querying union
1 parent bed8382 commit 377408b

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

tests/EndToEndTests.hs

+59-5
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import Protolude
1313
import Data.Aeson (Value(Null), toJSON, object, (.=))
1414
import qualified Data.Map as Map
1515
import GraphQL (makeSchema, compileQuery, executeQuery, interpretAnonymousQuery, interpretQuery)
16-
import GraphQL.API (Object, Field, Argument, (:>), Defaultable(..), HasAnnotatedInputType(..))
16+
import GraphQL.API (Object, Field, List, Argument, (:>), Defaultable(..), HasAnnotatedInputType(..))
1717
import GraphQL.Internal.Syntax.AST (Variable(..))
18-
import GraphQL.Resolver ((:<>)(..), Handler)
18+
import GraphQL.Resolver ((:<>)(..), Handler, unionValue)
1919
import GraphQL.Value (ToValue(..), FromValue(..), makeName)
2020
import Test.Tasty (TestTree)
2121
import Test.Tasty.Hspec (testSpec, describe, it, shouldBe)
@@ -36,6 +36,8 @@ import ExampleSchema
3636
type QueryRoot = Object "QueryRoot" '[]
3737
'[ Field "dog" Dog
3838
, Argument "dog" DogStuff :> Field "describeDog" Text
39+
, Field "catOrDog" CatOrDog
40+
, Field "catOrDogList" (List CatOrDog)
3941
]
4042

4143
-- | An object that is passed as an argument. i.e. an input object.
@@ -49,6 +51,25 @@ instance Defaultable DogStuff where
4951
defaultFor "dog" = pure DogStuff { toy = "shoe", likesTreats = False }
5052
defaultFor _ = empty
5153

54+
catOrDog :: Handler IO CatOrDog
55+
catOrDog = do
56+
name <- pure "MonadicFelix" -- we can do monadic actions
57+
unionValue @Cat (catHandler name Nothing 15)
58+
59+
catOrDogList :: Handler IO (List CatOrDog)
60+
catOrDogList =
61+
pure [ unionValue @Cat (catHandler "Felix the Cat" (Just "felix") 42)
62+
, unionValue @Cat (catHandler "Henry" Nothing 10)
63+
, unionValue @Dog (viewServerDog mortgage)
64+
]
65+
66+
catHandler :: Text -> Maybe Text -> Int32 -> Handler IO Cat
67+
catHandler name nickName meowVolume = pure $
68+
pure name :<>
69+
pure (pure <$> nickName) :<>
70+
pure . const False :<> -- doesn't know any commands
71+
pure meowVolume
72+
5273
-- | Our server's internal representation of a 'Dog'.
5374
data ServerDog
5475
= ServerDog
@@ -87,7 +108,7 @@ describeDog (DogStuff toy likesTreats)
87108
| otherwise = pure $ "their favorite toy is a " <> toy
88109

89110
rootHandler :: ServerDog -> Handler IO QueryRoot
90-
rootHandler dog = pure $ viewServerDog dog :<> describeDog
111+
rootHandler dog = pure $ viewServerDog dog :<> describeDog :<> catOrDog :<> catOrDogList
91112

92113
-- | jml has a stuffed black dog called "Mortgage".
93114
mortgage :: ServerDog
@@ -243,8 +264,6 @@ tests = testSpec "End-to-end tests" $ do
243264
]
244265
toJSON (toValue response) `shouldBe` expected
245266
it "Handles fairly complex queries" $ do
246-
-- TODO: jml would like to put some union checks in here, but we don't
247-
-- have any unions reachable from Dog!
248267
let query = [r|{
249268
dog {
250269
callsign: name
@@ -276,6 +295,41 @@ tests = testSpec "End-to-end tests" $ do
276295
]
277296
]
278297
toJSON (toValue response) `shouldBe` expected
298+
it "Lets you query union types" $ do
299+
let query = "{ catOrDog { ... on Cat { name meowVolume } ... on Dog { barkVolume } } }"
300+
response <- interpretAnonymousQuery @QueryRoot (rootHandler mortgage) query
301+
let expected =
302+
object
303+
[ "data" .= object
304+
[ "catOrDog" .= object
305+
[ "name" .= ("MonadicFelix" :: Text)
306+
, "meowVolume" .= (15 :: Float)
307+
]
308+
]
309+
]
310+
toJSON (toValue response) `shouldBe` expected
311+
it "Lets you query lists of union types" $ do
312+
let query = "{ catOrDogList { ... on Cat { name meowVolume } ... on Dog { barkVolume } } }"
313+
response <- interpretAnonymousQuery @QueryRoot (rootHandler mortgage) query
314+
let expected =
315+
object
316+
[ "data" .= object
317+
[ "catOrDogList" .=
318+
[ object
319+
[ "name" .= ("Felix the Cat" :: Text)
320+
, "meowVolume" .= (42 :: Float)
321+
]
322+
, object
323+
[ "name" .= ("Henry" :: Text)
324+
, "meowVolume" .= (10 :: Float)
325+
]
326+
, object
327+
[ "barkVolume" .= (0 :: Float)
328+
]
329+
]
330+
]
331+
]
332+
toJSON (toValue response) `shouldBe` expected
279333
describe "interpretQuery" $ do
280334
it "Handles the simplest named query" $ do
281335
let query = [r|query myQuery {

tests/ExampleSchema.hs

+3
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ type Human = Object "Human" '[Sentient]
249249
-- @
250250
data CatCommand = Jump deriving Generic
251251

252+
instance Defaultable CatCommand where
253+
defaultFor _ = empty
254+
252255
instance GraphQLEnum CatCommand
253256

254257
-- | A cat.

0 commit comments

Comments
 (0)