diff --git a/src/Validator/InputValidator.php b/src/Validator/InputValidator.php index 013fd45bc..18846c393 100644 --- a/src/Validator/InputValidator.php +++ b/src/Validator/InputValidator.php @@ -140,6 +140,11 @@ private function buildValidationTree(ValidationNode $rootObject, iterable $field $property = $arg['name'] ?? $name; $config = static::normalizeConfig($arg['validation'] ?? []); + if (!array_key_exists($property, $inputData)) { + // This field was not provided in the inputData. Do not attempt to validate it. + continue; + } + if (isset($config['cascade']) && isset($inputData[$property])) { $groups = $config['cascade']; $argType = $this->unclosure($arg['type']); diff --git a/tests/Functional/App/config/validator/mapping/Mutation.types.yml b/tests/Functional/App/config/validator/mapping/Mutation.types.yml index ede5d948b..e320f09ac 100644 --- a/tests/Functional/App/config/validator/mapping/Mutation.types.yml +++ b/tests/Functional/App/config/validator/mapping/Mutation.types.yml @@ -138,3 +138,11 @@ Mutation: validation: cascade: groups: ['group2'] + + onlyPassedFieldsValidation: + type: Boolean + resolve: '@=m("mutation_mock", args)' + args: + person: + validation: cascade + type: Person! diff --git a/tests/Functional/App/config/validator/mapping/Person.types.yml b/tests/Functional/App/config/validator/mapping/Person.types.yml new file mode 100644 index 000000000..bb8e29642 --- /dev/null +++ b/tests/Functional/App/config/validator/mapping/Person.types.yml @@ -0,0 +1,14 @@ +Person: + type: input-object + config: + fields: + firstName: + type: String + validation: + - NotBlank: ~ + - NotNull: ~ + surname: + type: String + validation: + - NotBlank: ~ + - NotNull: ~ diff --git a/tests/Functional/Validator/InputValidatorTest.php b/tests/Functional/Validator/InputValidatorTest.php index 4bd76823c..f454ab057 100644 --- a/tests/Functional/Validator/InputValidatorTest.php +++ b/tests/Functional/Validator/InputValidatorTest.php @@ -87,6 +87,22 @@ public function testLinkedConstraintsValidationPasses(): void $this->assertTrue($result['data']['linkedConstraintsValidation']); } + public function testOnlyPassedFieldsValidated(): void + { + $query = ' + mutation { + onlyPassedFieldsValidation( + person: { firstName: "Joe" } + ) + } + '; + + $result = $this->executeGraphQLRequest($query); + + $this->assertTrue(empty($result['errors'])); + $this->assertTrue($result['data']['onlyPassedFieldsValidation']); + } + public function testLinkedConstraintsValidationFails(): void { $query = '