Compare commits
No commits in common. "v1.5.0.0" and "v1.4.0.0" have entirely different histories.
@ -6,14 +6,6 @@ The format is based on
|
|||||||
and this project adheres to
|
and this project adheres to
|
||||||
[Haskell Package Versioning Policy](https://pvp.haskell.org/).
|
[Haskell Package Versioning Policy](https://pvp.haskell.org/).
|
||||||
|
|
||||||
## [1.5.0.0] - 2024-12-03
|
|
||||||
### Removed
|
|
||||||
- Remove deprecated 'gql' quasi quoter.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Validate the subscription root not to be an introspection field
|
|
||||||
(`singleFieldSubscriptionsRule`).
|
|
||||||
|
|
||||||
## [1.4.0.0] - 2024-10-26
|
## [1.4.0.0] - 2024-10-26
|
||||||
### Changed
|
### Changed
|
||||||
- `Schema.Directive` is extended to contain a boolean argument, representing
|
- `Schema.Directive` is extended to contain a boolean argument, representing
|
||||||
@ -546,7 +538,6 @@ and this project adheres to
|
|||||||
### Added
|
### Added
|
||||||
- Data types for the GraphQL language.
|
- Data types for the GraphQL language.
|
||||||
|
|
||||||
[1.5.0.0]: https://git.caraus.tech/OSS/graphql/compare/v1.4.0.0...v1.5.0.0
|
|
||||||
[1.4.0.0]: https://git.caraus.tech/OSS/graphql/compare/v1.3.0.0...v1.4.0.0
|
[1.4.0.0]: https://git.caraus.tech/OSS/graphql/compare/v1.3.0.0...v1.4.0.0
|
||||||
[1.3.0.0]: https://git.caraus.tech/OSS/graphql/compare/v1.2.0.3...v1.3.0.0
|
[1.3.0.0]: https://git.caraus.tech/OSS/graphql/compare/v1.2.0.3...v1.3.0.0
|
||||||
[1.2.0.3]: https://git.caraus.tech/OSS/graphql/compare/v1.2.0.2...v1.2.0.3
|
[1.2.0.3]: https://git.caraus.tech/OSS/graphql/compare/v1.2.0.2...v1.2.0.3
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
cabal-version: 3.0
|
cabal-version: 3.0
|
||||||
|
|
||||||
name: graphql
|
name: graphql
|
||||||
version: 1.5.0.0
|
version: 1.4.0.0
|
||||||
synopsis: Haskell GraphQL implementation
|
synopsis: Haskell GraphQL implementation
|
||||||
description: Haskell <https://spec.graphql.org/June2018/ GraphQL> implementation.
|
description: Haskell <https://spec.graphql.org/June2018/ GraphQL> implementation.
|
||||||
category: Language
|
category: Language
|
||||||
@ -40,6 +40,7 @@ library
|
|||||||
Language.GraphQL.Execute
|
Language.GraphQL.Execute
|
||||||
Language.GraphQL.Execute.Coerce
|
Language.GraphQL.Execute.Coerce
|
||||||
Language.GraphQL.Execute.OrderedMap
|
Language.GraphQL.Execute.OrderedMap
|
||||||
|
Language.GraphQL.TH
|
||||||
Language.GraphQL.Type
|
Language.GraphQL.Type
|
||||||
Language.GraphQL.Type.In
|
Language.GraphQL.Type.In
|
||||||
Language.GraphQL.Type.Out
|
Language.GraphQL.Type.Out
|
||||||
@ -62,6 +63,7 @@ library
|
|||||||
exceptions ^>= 0.10.4,
|
exceptions ^>= 0.10.4,
|
||||||
megaparsec >= 9.0 && < 10,
|
megaparsec >= 9.0 && < 10,
|
||||||
parser-combinators >= 1.3 && < 2,
|
parser-combinators >= 1.3 && < 2,
|
||||||
|
template-haskell >= 2.16 && < 3,
|
||||||
text >= 1.2 && < 3,
|
text >= 1.2 && < 3,
|
||||||
transformers >= 0.5.6 && < 0.7,
|
transformers >= 0.5.6 && < 0.7,
|
||||||
unordered-containers ^>= 0.2.14,
|
unordered-containers ^>= 0.2.14,
|
||||||
@ -82,6 +84,7 @@ test-suite graphql-test
|
|||||||
Language.GraphQL.Execute.CoerceSpec
|
Language.GraphQL.Execute.CoerceSpec
|
||||||
Language.GraphQL.Execute.OrderedMapSpec
|
Language.GraphQL.Execute.OrderedMapSpec
|
||||||
Language.GraphQL.ExecuteSpec
|
Language.GraphQL.ExecuteSpec
|
||||||
|
Language.GraphQL.THSpec
|
||||||
Language.GraphQL.Type.OutSpec
|
Language.GraphQL.Type.OutSpec
|
||||||
Language.GraphQL.Validate.RulesSpec
|
Language.GraphQL.Validate.RulesSpec
|
||||||
Schemas.HeroSchema
|
Schemas.HeroSchema
|
||||||
|
@ -482,9 +482,12 @@ instance Monoid Description
|
|||||||
data TypeDefinition
|
data TypeDefinition
|
||||||
= ScalarTypeDefinition Description Name [Directive]
|
= ScalarTypeDefinition Description Name [Directive]
|
||||||
| ObjectTypeDefinition
|
| ObjectTypeDefinition
|
||||||
Description Name (ImplementsInterfaces []) [Directive] [FieldDefinition]
|
Description
|
||||||
| InterfaceTypeDefinition
|
Name
|
||||||
Description Name (ImplementsInterfaces []) [Directive] [FieldDefinition]
|
(ImplementsInterfaces [])
|
||||||
|
[Directive]
|
||||||
|
[FieldDefinition]
|
||||||
|
| InterfaceTypeDefinition Description Name [Directive] [FieldDefinition]
|
||||||
| UnionTypeDefinition Description Name [Directive] (UnionMemberTypes [])
|
| UnionTypeDefinition Description Name [Directive] (UnionMemberTypes [])
|
||||||
| EnumTypeDefinition Description Name [Directive] [EnumValueDefinition]
|
| EnumTypeDefinition Description Name [Directive] [EnumValueDefinition]
|
||||||
| InputObjectTypeDefinition
|
| InputObjectTypeDefinition
|
||||||
|
@ -226,11 +226,10 @@ typeDefinition formatter = \case
|
|||||||
<> optempty (directives formatter) directives'
|
<> optempty (directives formatter) directives'
|
||||||
<> eitherFormat formatter " " ""
|
<> eitherFormat formatter " " ""
|
||||||
<> bracesList formatter (fieldDefinition nextFormatter) fields'
|
<> bracesList formatter (fieldDefinition nextFormatter) fields'
|
||||||
Full.InterfaceTypeDefinition description' name' ifaces' directives' fields'
|
Full.InterfaceTypeDefinition description' name' directives' fields'
|
||||||
-> optempty (description formatter) description'
|
-> optempty (description formatter) description'
|
||||||
<> "interface "
|
<> "interface "
|
||||||
<> Lazy.Text.fromStrict name'
|
<> Lazy.Text.fromStrict name'
|
||||||
<> optempty (" " <>) (implementsInterfaces ifaces')
|
|
||||||
<> optempty (directives formatter) directives'
|
<> optempty (directives formatter) directives'
|
||||||
<> eitherFormat formatter " " ""
|
<> eitherFormat formatter " " ""
|
||||||
<> bracesList formatter (fieldDefinition nextFormatter) fields'
|
<> bracesList formatter (fieldDefinition nextFormatter) fields'
|
||||||
|
@ -214,7 +214,6 @@ interfaceTypeDefinition :: Full.Description -> Parser Full.TypeDefinition
|
|||||||
interfaceTypeDefinition description' = Full.InterfaceTypeDefinition description'
|
interfaceTypeDefinition description' = Full.InterfaceTypeDefinition description'
|
||||||
<$ symbol "interface"
|
<$ symbol "interface"
|
||||||
<*> name
|
<*> name
|
||||||
<*> option (Full.ImplementsInterfaces []) (implementsInterfaces sepBy1)
|
|
||||||
<*> directives
|
<*> directives
|
||||||
<*> braces (many fieldDefinition)
|
<*> braces (many fieldDefinition)
|
||||||
<?> "InterfaceTypeDefinition"
|
<?> "InterfaceTypeDefinition"
|
||||||
|
48
src/Language/GraphQL/TH.hs
Normal file
48
src/Language/GraphQL/TH.hs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||||
|
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||||
|
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||||
|
|
||||||
|
-- | Template Haskell helpers.
|
||||||
|
module Language.GraphQL.TH
|
||||||
|
( gql
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Language.Haskell.TH.Quote (QuasiQuoter(..))
|
||||||
|
import Language.Haskell.TH (Exp(..), Lit(..))
|
||||||
|
|
||||||
|
stripIndentation :: String -> String
|
||||||
|
stripIndentation code = reverse
|
||||||
|
$ dropWhile isLineBreak
|
||||||
|
$ reverse
|
||||||
|
$ unlines
|
||||||
|
$ indent spaces <$> lines' withoutLeadingNewlines
|
||||||
|
where
|
||||||
|
indent 0 xs = xs
|
||||||
|
indent count (' ' : xs) = indent (count - 1) xs
|
||||||
|
indent _ xs = xs
|
||||||
|
withoutLeadingNewlines = dropWhile isLineBreak code
|
||||||
|
spaces = length $ takeWhile (== ' ') withoutLeadingNewlines
|
||||||
|
lines' "" = []
|
||||||
|
lines' string =
|
||||||
|
let (line, rest) = break isLineBreak string
|
||||||
|
reminder =
|
||||||
|
case rest of
|
||||||
|
[] -> []
|
||||||
|
'\r' : '\n' : strippedString -> lines' strippedString
|
||||||
|
_ : strippedString -> lines' strippedString
|
||||||
|
in line : reminder
|
||||||
|
isLineBreak = flip any ['\n', '\r'] . (==)
|
||||||
|
|
||||||
|
-- | Removes leading and trailing newlines. Indentation of the first line is
|
||||||
|
-- removed from each line of the string.
|
||||||
|
{-# DEPRECATED gql "Use Language.GraphQL.Class.gql from graphql-spice instead" #-}
|
||||||
|
gql :: QuasiQuoter
|
||||||
|
gql = QuasiQuoter
|
||||||
|
{ quoteExp = pure . LitE . StringL . stripIndentation
|
||||||
|
, quotePat = const
|
||||||
|
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a pattern)"
|
||||||
|
, quoteType = const
|
||||||
|
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a type)"
|
||||||
|
, quoteDec = const
|
||||||
|
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a declaration)"
|
||||||
|
}
|
@ -210,7 +210,7 @@ typeDefinition context rule = \case
|
|||||||
Full.ObjectTypeDefinition _ _ _ directives' fields
|
Full.ObjectTypeDefinition _ _ _ directives' fields
|
||||||
-> directives context rule objectLocation directives'
|
-> directives context rule objectLocation directives'
|
||||||
>< foldMap (fieldDefinition context rule) fields
|
>< foldMap (fieldDefinition context rule) fields
|
||||||
Full.InterfaceTypeDefinition _ _ _ directives' fields
|
Full.InterfaceTypeDefinition _ _ directives' fields
|
||||||
-> directives context rule interfaceLocation directives'
|
-> directives context rule interfaceLocation directives'
|
||||||
>< foldMap (fieldDefinition context rule) fields
|
>< foldMap (fieldDefinition context rule) fields
|
||||||
Full.UnionTypeDefinition _ _ directives' _ ->
|
Full.UnionTypeDefinition _ _ directives' _ ->
|
||||||
|
@ -137,28 +137,25 @@ singleFieldSubscriptionsRule :: forall m. Rule m
|
|||||||
singleFieldSubscriptionsRule = OperationDefinitionRule $ \case
|
singleFieldSubscriptionsRule = OperationDefinitionRule $ \case
|
||||||
Full.OperationDefinition Full.Subscription name' _ _ rootFields location' -> do
|
Full.OperationDefinition Full.Subscription name' _ _ rootFields location' -> do
|
||||||
groupedFieldSet <- evalStateT (collectFields rootFields) HashSet.empty
|
groupedFieldSet <- evalStateT (collectFields rootFields) HashSet.empty
|
||||||
case HashSet.toList groupedFieldSet of
|
case HashSet.size groupedFieldSet of
|
||||||
[rootName]
|
1 -> lift mempty
|
||||||
| Text.isPrefixOf "__" rootName -> makeError location' name'
|
_
|
||||||
"exactly one top level field, which must not be an introspection field."
|
| Just name <- name' -> pure $ Error
|
||||||
| otherwise -> lift mempty
|
{ message = concat
|
||||||
[] -> makeError location' name' "exactly one top level field."
|
[ "Subscription \""
|
||||||
_ -> makeError location' name' "only one top level field."
|
, Text.unpack name
|
||||||
|
, "\" must select only one top level field."
|
||||||
|
]
|
||||||
|
, locations = [location']
|
||||||
|
}
|
||||||
|
| otherwise -> pure $ Error
|
||||||
|
{ message = errorMessage
|
||||||
|
, locations = [location']
|
||||||
|
}
|
||||||
_ -> lift mempty
|
_ -> lift mempty
|
||||||
where
|
where
|
||||||
makeError location' (Just operationName) errorLine = pure $ Error
|
errorMessage =
|
||||||
{ message = concat
|
"Anonymous Subscription must select only one top level field."
|
||||||
[ "Subscription \""
|
|
||||||
, Text.unpack operationName
|
|
||||||
, "\" must select "
|
|
||||||
, errorLine
|
|
||||||
]
|
|
||||||
, locations = [location']
|
|
||||||
}
|
|
||||||
makeError location' Nothing errorLine = pure $ Error
|
|
||||||
{ message = "Anonymous Subscription must select " <> errorLine
|
|
||||||
, locations = [location']
|
|
||||||
}
|
|
||||||
collectFields = foldM forEach HashSet.empty
|
collectFields = foldM forEach HashSet.empty
|
||||||
forEach accumulator = \case
|
forEach accumulator = \case
|
||||||
Full.FieldSelection fieldSelection -> forField accumulator fieldSelection
|
Full.FieldSelection fieldSelection -> forField accumulator fieldSelection
|
||||||
@ -859,8 +856,8 @@ knownArgumentNamesRule = ArgumentsRule fieldRule directiveRule
|
|||||||
, "\"."
|
, "\"."
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | GraphQL services define what directives they support. For each usage of a
|
-- | GraphQL servers define what directives they support. For each usage of a
|
||||||
-- directive, the directive must be available on that service.
|
-- directive, the directive must be available on that server.
|
||||||
knownDirectiveNamesRule :: Rule m
|
knownDirectiveNamesRule :: Rule m
|
||||||
knownDirectiveNamesRule = DirectivesRule $ const $ \directives' -> do
|
knownDirectiveNamesRule = DirectivesRule $ const $ \directives' -> do
|
||||||
definitions' <- asks $ Schema.directives . schema
|
definitions' <- asks $ Schema.directives . schema
|
||||||
@ -912,9 +909,9 @@ knownInputFieldNamesRule = ValueRule go constGo
|
|||||||
, "\"."
|
, "\"."
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | GraphQL services define what directives they support and where they support
|
-- | GraphQL servers define what directives they support and where they support
|
||||||
-- them. For each usage of a directive, the directive must be used in a location
|
-- them. For each usage of a directive, the directive must be used in a location
|
||||||
-- that the service has declared support for.
|
-- that the server has declared support for.
|
||||||
directivesInValidLocationsRule :: Rule m
|
directivesInValidLocationsRule :: Rule m
|
||||||
directivesInValidLocationsRule = DirectivesRule directivesRule
|
directivesInValidLocationsRule = DirectivesRule directivesRule
|
||||||
where
|
where
|
||||||
|
@ -181,7 +181,7 @@ spec = do
|
|||||||
argument = Full.InputValueDefinition mempty "arg" someType Nothing mempty
|
argument = Full.InputValueDefinition mempty "arg" someType Nothing mempty
|
||||||
arguments = Full.ArgumentsDefinition [argument]
|
arguments = Full.ArgumentsDefinition [argument]
|
||||||
definition' = Full.TypeDefinition
|
definition' = Full.TypeDefinition
|
||||||
$ Full.InterfaceTypeDefinition mempty "UUID" (Full.ImplementsInterfaces []) mempty
|
$ Full.InterfaceTypeDefinition mempty "UUID" mempty
|
||||||
$ pure
|
$ pure
|
||||||
$ Full.FieldDefinition mempty "value" arguments someType mempty
|
$ Full.FieldDefinition mempty "value" arguments someType mempty
|
||||||
expected = "interface UUID {\n\
|
expected = "interface UUID {\n\
|
||||||
|
@ -103,12 +103,6 @@ spec = describe "Parser" $ do
|
|||||||
\ name: String\n\
|
\ name: String\n\
|
||||||
\}"
|
\}"
|
||||||
|
|
||||||
it "parses ImplementsInterfaces on interfaces" $
|
|
||||||
parse document "" `shouldSucceedOn`
|
|
||||||
"interface Person implements NamedEntity & ValuedEntity {\n\
|
|
||||||
\ name: String\n\
|
|
||||||
\}"
|
|
||||||
|
|
||||||
it "parses minimal enum type definition" $
|
it "parses minimal enum type definition" $
|
||||||
parse document "" `shouldSucceedOn`
|
parse document "" `shouldSucceedOn`
|
||||||
"enum Direction {\n\
|
"enum Direction {\n\
|
||||||
|
24
tests/Language/GraphQL/THSpec.hs
Normal file
24
tests/Language/GraphQL/THSpec.hs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||||
|
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||||
|
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||||
|
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
|
||||||
|
module Language.GraphQL.THSpec
|
||||||
|
( spec
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Language.GraphQL.TH (gql)
|
||||||
|
import Test.Hspec (Spec, describe, it, shouldBe)
|
||||||
|
|
||||||
|
spec :: Spec
|
||||||
|
spec =
|
||||||
|
describe "gql" $
|
||||||
|
it "replaces CRNL with NL" $
|
||||||
|
let expected = "line1\nline2\nline3"
|
||||||
|
actual = [gql|
|
||||||
|
line1
|
||||||
|
line2
|
||||||
|
line3
|
||||||
|
|]
|
||||||
|
in actual `shouldBe` expected
|
@ -94,7 +94,7 @@ dogType = ObjectType "Dog" Nothing [petType] $ HashMap.fromList
|
|||||||
, ("nickname", nicknameResolver)
|
, ("nickname", nicknameResolver)
|
||||||
, ("barkVolume", barkVolumeResolver)
|
, ("barkVolume", barkVolumeResolver)
|
||||||
, ("doesKnowCommand", doesKnowCommandResolver)
|
, ("doesKnowCommand", doesKnowCommandResolver)
|
||||||
, ("isHouseTrained", isHouseTrainedResolver)
|
, ("isHousetrained", isHousetrainedResolver)
|
||||||
, ("owner", ownerResolver)
|
, ("owner", ownerResolver)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
@ -105,10 +105,10 @@ dogType = ObjectType "Dog" Nothing [petType] $ HashMap.fromList
|
|||||||
$ In.Argument Nothing (In.NonNullEnumType dogCommandType) Nothing
|
$ In.Argument Nothing (In.NonNullEnumType dogCommandType) Nothing
|
||||||
doesKnowCommandResolver = ValueResolver doesKnowCommandField
|
doesKnowCommandResolver = ValueResolver doesKnowCommandField
|
||||||
$ pure $ Boolean True
|
$ pure $ Boolean True
|
||||||
isHouseTrainedField = Field Nothing (Out.NonNullScalarType boolean)
|
isHousetrainedField = Field Nothing (Out.NonNullScalarType boolean)
|
||||||
$ HashMap.singleton "atOtherHomes"
|
$ HashMap.singleton "atOtherHomes"
|
||||||
$ In.Argument Nothing (In.NamedScalarType boolean) Nothing
|
$ In.Argument Nothing (In.NamedScalarType boolean) Nothing
|
||||||
isHouseTrainedResolver = ValueResolver isHouseTrainedField
|
isHousetrainedResolver = ValueResolver isHousetrainedField
|
||||||
$ pure $ Boolean True
|
$ pure $ Boolean True
|
||||||
ownerField = Field Nothing (Out.NamedObjectType humanType) mempty
|
ownerField = Field Nothing (Out.NamedObjectType humanType) mempty
|
||||||
ownerResolver = ValueResolver ownerField $ pure Null
|
ownerResolver = ValueResolver ownerField $ pure Null
|
||||||
@ -206,18 +206,6 @@ spec =
|
|||||||
}
|
}
|
||||||
in validate queryString `shouldContain` [expected]
|
in validate queryString `shouldContain` [expected]
|
||||||
|
|
||||||
it "rejects an introspection field as the subscription root" $
|
|
||||||
let queryString = "subscription sub {\n\
|
|
||||||
\ __typename\n\
|
|
||||||
\}"
|
|
||||||
expected = Error
|
|
||||||
{ message =
|
|
||||||
"Subscription \"sub\" must select exactly one top \
|
|
||||||
\level field, which must not be an introspection field."
|
|
||||||
, locations = [AST.Location 1 1]
|
|
||||||
}
|
|
||||||
in validate queryString `shouldContain` [expected]
|
|
||||||
|
|
||||||
it "rejects multiple subscription root fields coming from a fragment" $
|
it "rejects multiple subscription root fields coming from a fragment" $
|
||||||
let queryString = "subscription sub {\n\
|
let queryString = "subscription sub {\n\
|
||||||
\ ...multipleSubscriptions\n\
|
\ ...multipleSubscriptions\n\
|
||||||
@ -467,7 +455,7 @@ spec =
|
|||||||
it "rejects duplicate field arguments" $
|
it "rejects duplicate field arguments" $
|
||||||
let queryString = "{\n\
|
let queryString = "{\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ isHouseTrained(atOtherHomes: true, atOtherHomes: true)\n\
|
\ isHousetrained(atOtherHomes: true, atOtherHomes: true)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
@ -504,7 +492,7 @@ spec =
|
|||||||
it "rejects duplicate variables" $
|
it "rejects duplicate variables" $
|
||||||
let queryString = "query houseTrainedQuery($atOtherHomes: Boolean, $atOtherHomes: Boolean) {\n\
|
let queryString = "query houseTrainedQuery($atOtherHomes: Boolean, $atOtherHomes: Boolean) {\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ isHouseTrained(atOtherHomes: $atOtherHomes)\n\
|
\ isHousetrained(atOtherHomes: $atOtherHomes)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
@ -519,7 +507,7 @@ spec =
|
|||||||
it "rejects non-input types as variables" $
|
it "rejects non-input types as variables" $
|
||||||
let queryString = "query takesDogBang($dog: Dog!) {\n\
|
let queryString = "query takesDogBang($dog: Dog!) {\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ isHouseTrained(atOtherHomes: $dog)\n\
|
\ isHousetrained(atOtherHomes: $dog)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
@ -534,12 +522,12 @@ spec =
|
|||||||
it "rejects undefined variables" $
|
it "rejects undefined variables" $
|
||||||
let queryString = "query variableIsNotDefinedUsedInSingleFragment {\n\
|
let queryString = "query variableIsNotDefinedUsedInSingleFragment {\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ ...isHouseTrainedFragment\n\
|
\ ...isHousetrainedFragment\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}\n\
|
\}\n\
|
||||||
\\n\
|
\\n\
|
||||||
\fragment isHouseTrainedFragment on Dog {\n\
|
\fragment isHousetrainedFragment on Dog {\n\
|
||||||
\ isHouseTrained(atOtherHomes: $atOtherHomes)\n\
|
\ isHousetrained(atOtherHomes: $atOtherHomes)\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
{ message =
|
{ message =
|
||||||
@ -578,7 +566,7 @@ spec =
|
|||||||
it "rejects unused variables" $
|
it "rejects unused variables" $
|
||||||
let queryString = "query variableUnused($atOtherHomes: Boolean) {\n\
|
let queryString = "query variableUnused($atOtherHomes: Boolean) {\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ isHouseTrained\n\
|
\ isHousetrained\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
@ -660,7 +648,7 @@ spec =
|
|||||||
it "rejects directive arguments missing in the definition" $
|
it "rejects directive arguments missing in the definition" $
|
||||||
let queryString = "{\n\
|
let queryString = "{\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ isHouseTrained(atOtherHomes: true) @include(unless: false, if: true)\n\
|
\ isHousetrained(atOtherHomes: true) @include(unless: false, if: true)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
@ -675,7 +663,7 @@ spec =
|
|||||||
it "rejects undefined directives" $
|
it "rejects undefined directives" $
|
||||||
let queryString = "{\n\
|
let queryString = "{\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ isHouseTrained(atOtherHomes: true) @ignore(if: true)\n\
|
\ isHousetrained(atOtherHomes: true) @ignore(if: true)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
@ -752,13 +740,13 @@ spec =
|
|||||||
let queryString = "{\n\
|
let queryString = "{\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ doesKnowCommand(dogCommand: SIT)\n\
|
\ doesKnowCommand(dogCommand: SIT)\n\
|
||||||
\ doesKnowCommand: isHouseTrained(atOtherHomes: true)\n\
|
\ doesKnowCommand: isHousetrained(atOtherHomes: true)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
{ message =
|
{ message =
|
||||||
"Fields \"doesKnowCommand\" conflict because \
|
"Fields \"doesKnowCommand\" conflict because \
|
||||||
\\"doesKnowCommand\" and \"isHouseTrained\" are \
|
\\"doesKnowCommand\" and \"isHousetrained\" are \
|
||||||
\different fields. Use different aliases on the \
|
\different fields. Use different aliases on the \
|
||||||
\fields to fetch both if this was intentional."
|
\fields to fetch both if this was intentional."
|
||||||
, locations = [AST.Location 3 5, AST.Location 4 5]
|
, locations = [AST.Location 3 5, AST.Location 4 5]
|
||||||
@ -773,13 +761,13 @@ spec =
|
|||||||
\ }\n\
|
\ }\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ name\n\
|
\ name\n\
|
||||||
\ doesKnowCommand: isHouseTrained(atOtherHomes: true)\n\
|
\ doesKnowCommand: isHousetrained(atOtherHomes: true)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
{ message =
|
{ message =
|
||||||
"Fields \"doesKnowCommand\" conflict because \
|
"Fields \"doesKnowCommand\" conflict because \
|
||||||
\\"doesKnowCommand\" and \"isHouseTrained\" are \
|
\\"doesKnowCommand\" and \"isHousetrained\" are \
|
||||||
\different fields. Use different aliases on the \
|
\different fields. Use different aliases on the \
|
||||||
\fields to fetch both if this was intentional."
|
\fields to fetch both if this was intentional."
|
||||||
, locations = [AST.Location 4 5, AST.Location 8 5]
|
, locations = [AST.Location 4 5, AST.Location 8 5]
|
||||||
@ -872,7 +860,7 @@ spec =
|
|||||||
it "rejects wrongly typed variable arguments" $
|
it "rejects wrongly typed variable arguments" $
|
||||||
let queryString = "query intCannotGoIntoBoolean($intArg: Int) {\n\
|
let queryString = "query intCannotGoIntoBoolean($intArg: Int) {\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ isHouseTrained(atOtherHomes: $intArg)\n\
|
\ isHousetrained(atOtherHomes: $intArg)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
@ -887,7 +875,7 @@ spec =
|
|||||||
it "rejects values of incorrect types" $
|
it "rejects values of incorrect types" $
|
||||||
let queryString = "{\n\
|
let queryString = "{\n\
|
||||||
\ dog {\n\
|
\ dog {\n\
|
||||||
\ isHouseTrained(atOtherHomes: 3)\n\
|
\ isHousetrained(atOtherHomes: 3)\n\
|
||||||
\ }\n\
|
\ }\n\
|
||||||
\}"
|
\}"
|
||||||
expected = Error
|
expected = Error
|
||||||
|
Loading…
x
Reference in New Issue
Block a user