Emit list item errors once

This commit is contained in:
Eugen Wissner 2021-03-16 10:08:13 +01:00
parent 4d762d6356
commit 328e6acdee
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
4 changed files with 39 additions and 16 deletions

View File

@ -14,6 +14,12 @@ and this project adheres to
### Fixed ### Fixed
- Parser now accepts empty lists and objects. - Parser now accepts empty lists and objects.
- Parser now accepts all directive locations. - Parser now accepts all directive locations.
- `valuesOfCorrectTypeRule` doesn't check list items recursively since the
validation traverser calls it on all list items.
### Changed
- `AST.Document.Value.List` and `AST.Document.ConstValue.ConstList` contain
location information for each list item.
## [0.11.1.0] - 2021-02-07 ## [0.11.1.0] - 2021-02-07
### Added ### Added

View File

@ -1540,7 +1540,7 @@ valuesOfCorrectTypeRule = ValueRule go constGo
go (Just inputType) value go (Just inputType) value
| Just constValue <- toConstNode value = | Just constValue <- toConstNode value =
lift $ check inputType constValue lift $ check inputType constValue
go _ _ = lift mempty go _ _ = lift mempty -- This rule checks only literals.
toConstNode Full.Node{..} = flip Full.Node location <$> toConst node toConstNode Full.Node{..} = flip Full.Node location <$> toConst node
toConst (Full.Variable _) = Nothing toConst (Full.Variable _) = Nothing
toConst (Full.Int integer) = Just $ Full.ConstInt integer toConst (Full.Int integer) = Just $ Full.ConstInt integer
@ -1586,8 +1586,8 @@ valuesOfCorrectTypeRule = ValueRule go constGo
, Full.ConstObject valueFields <- node = , Full.ConstObject valueFields <- node =
foldMap (checkObjectField typeFields) valueFields foldMap (checkObjectField typeFields) valueFields
check (In.ListBaseType listType) constValue@Full.Node{ .. } check (In.ListBaseType listType) constValue@Full.Node{ .. }
| Full.ConstList listValues <- node = -- Skip, lists are checked recursively by the validation traverser.
foldMap (check listType) listValues | Full.ConstList _ <- node = mempty
| otherwise = check listType constValue | otherwise = check listType constValue
check inputType Full.Node{ .. } = pure $ Error check inputType Full.Node{ .. } = pure $ Error
{ message = concat { message = concat

View File

@ -1,4 +1,4 @@
resolver: lts-17.3 resolver: lts-17.6
packages: packages:
- . - .

View File

@ -49,16 +49,18 @@ catType :: ObjectType IO
catType = ObjectType "Cat" Nothing [petType] $ HashMap.fromList catType = ObjectType "Cat" Nothing [petType] $ HashMap.fromList
[ ("name", nameResolver) [ ("name", nameResolver)
, ("nickname", nicknameResolver) , ("nickname", nicknameResolver)
, ("doesKnowCommand", doesKnowCommandResolver) , ("doesKnowCommands", doesKnowCommandsResolver)
, ("meowVolume", meowVolumeResolver) , ("meowVolume", meowVolumeResolver)
] ]
where where
meowVolumeField = Field Nothing (Out.NamedScalarType int) mempty meowVolumeField = Field Nothing (Out.NamedScalarType int) mempty
meowVolumeResolver = ValueResolver meowVolumeField $ pure $ Int 3 meowVolumeResolver = ValueResolver meowVolumeField $ pure $ Int 3
doesKnowCommandField = Field Nothing (Out.NonNullScalarType boolean) doesKnowCommandsType = In.NonNullListType
$ HashMap.singleton "catCommand" $ In.NonNullEnumType catCommandType
$ In.Argument Nothing (In.NonNullEnumType catCommandType) Nothing doesKnowCommandsField = Field Nothing (Out.NonNullScalarType boolean)
doesKnowCommandResolver = ValueResolver doesKnowCommandField $ HashMap.singleton "catCommands"
$ In.Argument Nothing doesKnowCommandsType Nothing
doesKnowCommandsResolver = ValueResolver doesKnowCommandsField
$ pure $ Boolean True $ pure $ Boolean True
nameResolver :: Resolver IO nameResolver :: Resolver IO
@ -866,17 +868,17 @@ spec =
context "variablesInAllowedPositionRule" $ do context "variablesInAllowedPositionRule" $ do
it "rejects wrongly typed variable arguments" $ it "rejects wrongly typed variable arguments" $
let queryString = [r| let queryString = [r|
query catCommandArgQuery($catCommandArg: CatCommand) { query dogCommandArgQuery($dogCommandArg: DogCommand) {
cat { dog {
doesKnowCommand(catCommand: $catCommandArg) doesKnowCommand(dogCommand: $dogCommandArg)
} }
} }
|] |]
expected = Error expected = Error
{ message = { message =
"Variable \"$catCommandArg\" of type \ "Variable \"$dogCommandArg\" of type \
\\"CatCommand\" used in position expecting type \ \\"DogCommand\" used in position expecting type \
\\"!CatCommand\"." \\"!DogCommand\"."
, locations = [AST.Location 2 44] , locations = [AST.Location 2 44]
} }
in validate queryString `shouldBe` [expected] in validate queryString `shouldBe` [expected]
@ -897,7 +899,7 @@ spec =
} }
in validate queryString `shouldBe` [expected] in validate queryString `shouldBe` [expected]
context "valuesOfCorrectTypeRule" $ context "valuesOfCorrectTypeRule" $ do
it "rejects values of incorrect types" $ it "rejects values of incorrect types" $
let queryString = [r| let queryString = [r|
{ {
@ -912,3 +914,18 @@ spec =
, locations = [AST.Location 4 52] , locations = [AST.Location 4 52]
} }
in validate queryString `shouldBe` [expected] in validate queryString `shouldBe` [expected]
it "uses the location of a single list value" $
let queryString = [r|
{
cat {
doesKnowCommands(catCommands: [3])
}
}
|]
expected = Error
{ message =
"Value 3 cannot be coerced to type \"!CatCommand\"."
, locations = [AST.Location 4 54]
}
in validate queryString `shouldBe` [expected]