Fail on cyclic fragments, fix #22

This commit is contained in:
Eugen Wissner 2019-11-13 20:40:09 +01:00
parent 31c516927d
commit 115aa02672
2 changed files with 36 additions and 10 deletions

View File

@ -94,17 +94,21 @@ collectFragments = do
_ <- fragmentDefinition nextValue
collectFragments
fragmentDefinition :: Full.FragmentDefinition -> TransformT (NonEmpty Core.Selection)
fragmentDefinition ::
Full.FragmentDefinition ->
TransformT (NonEmpty Core.Selection)
fragmentDefinition (Full.FragmentDefinition name _tc _dirs sels) = do
modify deleteFragmentDefinition
selections <- traverse selection sels
let newValue = either id pure =<< selections
modify $ moveFragment newValue
modify $ insertFragment newValue
liftJust newValue
where
moveFragment newValue (Replacement fullFragments emptyFragDefs) =
let newFragments = HashMap.insert name newValue fullFragments
newDefinitions = HashMap.delete name emptyFragDefs
in Replacement newFragments newDefinitions
deleteFragmentDefinition (Replacement fragments' fragmentDefinitions') =
Replacement fragments' $ HashMap.delete name fragmentDefinitions'
insertFragment newValue (Replacement fragments' fragmentDefinitions') =
let newFragments = HashMap.insert name newValue fragments'
in Replacement newFragments fragmentDefinitions'
field :: Full.Field -> TransformT Core.Field
field (Full.Field a n args _dirs sels) = do

View File

@ -10,7 +10,13 @@ import Data.List.NonEmpty (NonEmpty(..))
import Data.Text (Text)
import Language.GraphQL
import qualified Language.GraphQL.Schema as Schema
import Test.Hspec (Spec, describe, it, shouldBe, shouldNotSatisfy)
import Test.Hspec ( Spec
, describe
, it
, shouldBe
, shouldSatisfy
, shouldNotSatisfy
)
import Text.RawString.QQ (r)
size :: Schema.Resolver IO
@ -37,6 +43,10 @@ inlineQuery = [r|{
}
}|]
hasErrors :: Value -> Bool
hasErrors (Object object') = HashMap.member "errors" object'
hasErrors _ = True
spec :: Spec
spec = describe "Inline fragment executor" $ do
it "chooses the first selection if the type matches" $ do
@ -91,9 +101,7 @@ spec = describe "Inline fragment executor" $ do
}|]
actual <- graphql (size :| []) query
let hasErrors (Object object') = HashMap.member "errors" object'
hasErrors _ = True
in actual `shouldNotSatisfy` hasErrors
actual `shouldNotSatisfy` hasErrors
it "evaluates nested fragments" $ do
let query = [r|
@ -140,3 +148,17 @@ spec = describe "Inline fragment executor" $ do
]
]
in actual `shouldBe` expected
it "rejects recursive" $ do
let query = [r|
{
...circumferenceFragment
}
fragment circumferenceFragment on Hat {
...circumferenceFragment
}
|]
actual <- graphql (circumference :| []) query
actual `shouldSatisfy` hasErrors