Merge pull request #346 from simPod/fix-cs-tests-validator

Fix CS in tests/Validator
This commit is contained in:
Vladimir Razuvaev 2018-09-02 21:29:33 +07:00 committed by GitHub
commit ec43a2e01a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 3694 additions and 2359 deletions

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,13 +11,14 @@ use GraphQL\Validator\Rules\DisableIntrospection;
class DisableIntrospectionTest extends ValidatorTestCase
{
// Validate: Disable Introspection
/**
* @see it('fails if the query contains __schema')
*/
public function testQueryContainsSchema() : void
{
$this->expectFailsRule(new DisableIntrospection(DisableIntrospection::ENABLED), '
$this->expectFailsRule(
new DisableIntrospection(DisableIntrospection::ENABLED),
'
query {
__schema {
queryType {
@ -27,12 +31,22 @@ class DisableIntrospectionTest extends ValidatorTestCase
);
}
private function error($line, $column)
{
return FormattedError::create(
DisableIntrospection::introspectionDisabledMessage(),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('fails if the query contains __type')
*/
public function testQueryContainsType() : void
{
$this->expectFailsRule(new DisableIntrospection(DisableIntrospection::ENABLED), '
$this->expectFailsRule(
new DisableIntrospection(DisableIntrospection::ENABLED),
'
query {
__type(
name: "Query"
@ -50,7 +64,9 @@ class DisableIntrospectionTest extends ValidatorTestCase
*/
public function testValidQuery() : void
{
$this->expectPassesRule(new DisableIntrospection(DisableIntrospection::ENABLED), '
$this->expectPassesRule(
new DisableIntrospection(DisableIntrospection::ENABLED),
'
query {
user {
name
@ -60,7 +76,8 @@ class DisableIntrospectionTest extends ValidatorTestCase
}
}
}
');
'
);
}
/**
@ -68,7 +85,9 @@ class DisableIntrospectionTest extends ValidatorTestCase
*/
public function testQueryWhenDisabled() : void
{
$this->expectPassesRule(new DisableIntrospection(DisableIntrospection::DISABLED), '
$this->expectPassesRule(
new DisableIntrospection(DisableIntrospection::DISABLED),
'
query {
__type(
name: "Query"
@ -76,7 +95,8 @@ class DisableIntrospectionTest extends ValidatorTestCase
name
}
}
');
'
);
}
/**
@ -86,7 +106,9 @@ class DisableIntrospectionTest extends ValidatorTestCase
{
$disableIntrospection = new DisableIntrospection(DisableIntrospection::DISABLED);
$disableIntrospection->setEnabled(DisableIntrospection::ENABLED);
$this->expectFailsRule($disableIntrospection, '
$this->expectFailsRule(
$disableIntrospection,
'
query {
__type(
name: "Query"
@ -106,7 +128,9 @@ class DisableIntrospectionTest extends ValidatorTestCase
{
$disableIntrospection = new DisableIntrospection(DisableIntrospection::ENABLED);
$disableIntrospection->setEnabled(DisableIntrospection::DISABLED);
$this->expectPassesRule($disableIntrospection, '
$this->expectPassesRule(
$disableIntrospection,
'
query {
__type(
name: "Query"
@ -114,15 +138,7 @@ class DisableIntrospectionTest extends ValidatorTestCase
name
}
}
');
}
private function error($line, $column)
{
return FormattedError::create(
DisableIntrospection::introspectionDisabledMessage(),
[ new SourceLocation($line, $column) ]
'
);
}
}

View File

@ -1,27 +1,31 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
use GraphQL\Language\SourceLocation;
use GraphQL\Validator\Rules\ExecutableDefinitions;
use GraphQL\Validator\Rules\KnownDirectives;
class ExecutableDefinitionsTest extends ValidatorTestCase
{
// Validate: Executable definitions
/**
* @see it('with only operation')
*/
public function testWithOnlyOperation() : void
{
$this->expectPassesRule(new ExecutableDefinitions, '
$this->expectPassesRule(
new ExecutableDefinitions(),
'
query Foo {
dog {
name
}
}
');
'
);
}
/**
@ -29,7 +33,9 @@ class ExecutableDefinitionsTest extends ValidatorTestCase
*/
public function testWithOperationAndFragment() : void
{
$this->expectPassesRule(new ExecutableDefinitions, '
$this->expectPassesRule(
new ExecutableDefinitions(),
'
query Foo {
dog {
name
@ -40,7 +46,8 @@ class ExecutableDefinitionsTest extends ValidatorTestCase
fragment Frag on Dog {
name
}
');
'
);
}
/**
@ -48,7 +55,9 @@ class ExecutableDefinitionsTest extends ValidatorTestCase
*/
public function testWithTypeDefinition() : void
{
$this->expectFailsRule(new ExecutableDefinitions, '
$this->expectFailsRule(
new ExecutableDefinitions(),
'
query Foo {
dog {
name
@ -66,7 +75,8 @@ class ExecutableDefinitionsTest extends ValidatorTestCase
[
$this->nonExecutableDefinition('Cow', 8, 12),
$this->nonExecutableDefinition('Dog', 12, 19),
]);
]
);
}
private function nonExecutableDefinition($defName, $line, $column)

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,18 +11,20 @@ use GraphQL\Validator\Rules\FieldsOnCorrectType;
class FieldsOnCorrectTypeTest extends ValidatorTestCase
{
// Validate: Fields on correct type
/**
* @see it('Object field selection')
*/
public function testObjectFieldSelection() : void
{
$this->expectPassesRule(new FieldsOnCorrectType(), '
$this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment objectFieldSelection on Dog {
__typename
name
}
');
'
);
}
/**
@ -27,12 +32,15 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testAliasedObjectFieldSelection() : void
{
$this->expectPassesRule(new FieldsOnCorrectType, '
$this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment aliasedObjectFieldSelection on Dog {
tn : __typename
otherName : name
}
');
'
);
}
/**
@ -40,12 +48,15 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testInterfaceFieldSelection() : void
{
$this->expectPassesRule(new FieldsOnCorrectType, '
$this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment interfaceFieldSelection on Pet {
__typename
name
}
');
'
);
}
/**
@ -53,11 +64,14 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testAliasedInterfaceFieldSelection() : void
{
$this->expectPassesRule(new FieldsOnCorrectType, '
$this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment interfaceFieldSelection on Pet {
otherName : name
}
');
'
);
}
/**
@ -65,11 +79,14 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testLyingAliasSelection() : void
{
$this->expectPassesRule(new FieldsOnCorrectType, '
$this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment lyingAliasSelection on Dog {
name : nickname
}
');
'
);
}
/**
@ -77,11 +94,14 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testIgnoresFieldsOnUnknownType() : void
{
$this->expectPassesRule(new FieldsOnCorrectType, '
$this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment unknownSelection on UnknownType {
unknownField
}
');
'
);
}
/**
@ -89,7 +109,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testReportsErrorsWhenTypeIsKnownAgain() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment typeKnownAgain on Pet {
unknown_pet_field {
... on Cat {
@ -99,17 +121,27 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
}',
[
$this->undefinedField('unknown_pet_field', 'Pet', [], [], 3, 9),
$this->undefinedField('unknown_cat_field', 'Cat', [], [], 5, 13)
$this->undefinedField('unknown_cat_field', 'Cat', [], [], 5, 13),
]
);
}
private function undefinedField($field, $type, $suggestedTypes, $suggestedFields, $line, $column)
{
return FormattedError::create(
FieldsOnCorrectType::undefinedFieldMessage($field, $type, $suggestedTypes, $suggestedFields),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('Field not defined on fragment')
*/
public function testFieldNotDefinedOnFragment() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment fieldNotDefined on Dog {
meowVolume
}',
@ -122,7 +154,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testIgnoresDeeplyUnknownField() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment deepFieldNotDefined on Dog {
unknown_field {
deeper_unknown_field
@ -137,7 +171,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testSubFieldNotDefined() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment subFieldNotDefined on Human {
pets {
unknown_field
@ -152,7 +188,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testFieldNotDefinedOnInlineFragment() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment fieldNotDefined on Pet {
... on Dog {
meowVolume
@ -167,7 +205,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testAliasedFieldTargetNotDefined() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment aliasedFieldTargetNotDefined on Dog {
volume : mooVolume
}',
@ -180,7 +220,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testAliasedLyingFieldTargetNotDefined() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment aliasedLyingFieldTargetNotDefined on Dog {
barkVolume : kawVolume
}',
@ -193,7 +235,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testNotDefinedOnInterface() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment notDefinedOnInterface on Pet {
tailLength
}',
@ -206,7 +250,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testDefinedOnImplmentorsButNotOnInterface() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment definedOnImplementorsButNotInterface on Pet {
nickname
}',
@ -219,7 +265,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testMetaFieldSelectionOnUnion() : void
{
$this->expectPassesRule(new FieldsOnCorrectType, '
$this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment directFieldSelectionOnUnion on CatOrDog {
__typename
}'
@ -231,7 +279,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testDirectFieldSelectionOnUnion() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment directFieldSelectionOnUnion on CatOrDog {
directField
}',
@ -244,7 +294,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/
public function testDefinedOnImplementorsQueriedOnUnion() : void
{
$this->expectFailsRule(new FieldsOnCorrectType, '
$this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment definedOnImplementorsQueriedOnUnion on CatOrDog {
name
}',
@ -255,32 +307,39 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
[],
3,
9
)]
),
]
);
}
// Describe: Fields on correct type error message
/**
* @see it('valid field in inline fragment')
*/
public function testValidFieldInInlineFragment() : void
{
$this->expectPassesRule(new FieldsOnCorrectType, '
$this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment objectFieldSelection on Pet {
... on Dog {
name
}
}
');
'
);
}
// Describe: Fields on correct type error message
/**
* @see it('Works with no suggestions')
*/
public function testWorksWithNoSuggestions() : void
{
$this->assertEquals('Cannot query field "f" on type "T".', FieldsOnCorrectType::undefinedFieldMessage('f', 'T', [], []));
$this->assertEquals(
'Cannot query field "f" on type "T".',
FieldsOnCorrectType::undefinedFieldMessage('f', 'T', [], [])
);
}
/**
@ -324,12 +383,15 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
$expected = 'Cannot query field "f" on type "T". ' .
'Did you mean to use an inline fragment on "A", "B", "C", "D", or "E"?';
$this->assertEquals($expected, FieldsOnCorrectType::undefinedFieldMessage(
$this->assertEquals(
$expected,
FieldsOnCorrectType::undefinedFieldMessage(
'f',
'T',
['A', 'B', 'C', 'D', 'E', 'F'],
[]
));
)
);
}
/**
@ -340,19 +402,14 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
$expected = 'Cannot query field "f" on type "T". ' .
'Did you mean "z", "y", "x", "w", or "v"?';
$this->assertEquals($expected, FieldsOnCorrectType::undefinedFieldMessage(
$this->assertEquals(
$expected,
FieldsOnCorrectType::undefinedFieldMessage(
'f',
'T',
[],
['z', 'y', 'x', 'w', 'v', 'u']
));
}
private function undefinedField($field, $type, $suggestedTypes, $suggestedFields, $line, $column)
{
return FormattedError::create(
FieldsOnCorrectType::undefinedFieldMessage($field, $type, $suggestedTypes, $suggestedFields),
[new SourceLocation($line, $column)]
)
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\FragmentsOnCompositeTypes;
class FragmentsOnCompositeTypesTest extends ValidatorTestCase
{
// Validate: Fragments on composite types
/**
* @see it('object is valid fragment type')
*/
public function testObjectIsValidFragmentType() : void
{
$this->expectPassesRule(new FragmentsOnCompositeTypes, '
$this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on Dog {
barks
}
');
'
);
}
/**
@ -26,11 +31,14 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/
public function testInterfaceIsValidFragmentType() : void
{
$this->expectPassesRule(new FragmentsOnCompositeTypes, '
$this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on Pet {
name
}
');
'
);
}
/**
@ -38,13 +46,16 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/
public function testObjectIsValidInlineFragmentType() : void
{
$this->expectPassesRule(new FragmentsOnCompositeTypes, '
$this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on Pet {
... on Dog {
barks
}
}
');
'
);
}
/**
@ -52,13 +63,16 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/
public function testInlineFragmentWithoutTypeIsValid() : void
{
$this->expectPassesRule(new FragmentsOnCompositeTypes, '
$this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on Pet {
... {
name
}
}
');
'
);
}
/**
@ -66,11 +80,14 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/
public function testUnionIsValidFragmentType() : void
{
$this->expectPassesRule(new FragmentsOnCompositeTypes, '
$this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on CatOrDog {
__typename
}
');
'
);
}
/**
@ -78,56 +95,14 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/
public function testScalarIsInvalidFragmentType() : void
{
$this->expectFailsRule(new FragmentsOnCompositeTypes, '
$this->expectFailsRule(
new FragmentsOnCompositeTypes(),
'
fragment scalarFragment on Boolean {
bad
}
',
[$this->error('scalarFragment', 'Boolean', 2, 34)]);
}
/**
* @see it('enum is invalid fragment type')
*/
public function testEnumIsInvalidFragmentType() : void
{
$this->expectFailsRule(new FragmentsOnCompositeTypes, '
fragment scalarFragment on FurColor {
bad
}
',
[$this->error('scalarFragment', 'FurColor', 2, 34)]);
}
/**
* @see it('input object is invalid fragment type')
*/
public function testInputObjectIsInvalidFragmentType() : void
{
$this->expectFailsRule(new FragmentsOnCompositeTypes, '
fragment inputFragment on ComplexInput {
stringField
}
',
[$this->error('inputFragment', 'ComplexInput', 2, 33)]);
}
/**
* @see it('scalar is invalid inline fragment type')
*/
public function testScalarIsInvalidInlineFragmentType() : void
{
$this->expectFailsRule(new FragmentsOnCompositeTypes, '
fragment invalidFragment on Pet {
... on String {
barks
}
}
',
[FormattedError::create(
FragmentsOnCompositeTypes::inlineFragmentOnNonCompositeErrorMessage('String'),
[new SourceLocation(3, 16)]
)]
[$this->error('scalarFragment', 'Boolean', 2, 34)]
);
}
@ -138,4 +113,58 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
[new SourceLocation($line, $column)]
);
}
/**
* @see it('enum is invalid fragment type')
*/
public function testEnumIsInvalidFragmentType() : void
{
$this->expectFailsRule(
new FragmentsOnCompositeTypes(),
'
fragment scalarFragment on FurColor {
bad
}
',
[$this->error('scalarFragment', 'FurColor', 2, 34)]
);
}
/**
* @see it('input object is invalid fragment type')
*/
public function testInputObjectIsInvalidFragmentType() : void
{
$this->expectFailsRule(
new FragmentsOnCompositeTypes(),
'
fragment inputFragment on ComplexInput {
stringField
}
',
[$this->error('inputFragment', 'ComplexInput', 2, 33)]
);
}
/**
* @see it('scalar is invalid inline fragment type')
*/
public function testScalarIsInvalidInlineFragmentType() : void
{
$this->expectFailsRule(
new FragmentsOnCompositeTypes(),
'
fragment invalidFragment on Pet {
... on String {
barks
}
}
',
[FormattedError::create(
FragmentsOnCompositeTypes::inlineFragmentOnNonCompositeErrorMessage('String'),
[new SourceLocation(3, 16)]
),
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\KnownArgumentNames;
class KnownArgumentNamesTest extends ValidatorTestCase
{
// Validate: Known argument names:
/**
* @see it('single arg is known')
*/
public function testSingleArgIsKnown() : void
{
$this->expectPassesRule(new KnownArgumentNames, '
$this->expectPassesRule(
new KnownArgumentNames(),
'
fragment argOnRequiredArg on Dog {
doesKnowCommand(dogCommand: SIT)
}
');
'
);
}
/**
@ -26,11 +31,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/
public function testMultipleArgsAreKnown() : void
{
$this->expectPassesRule(new KnownArgumentNames, '
$this->expectPassesRule(
new KnownArgumentNames(),
'
fragment multipleArgs on ComplicatedArgs {
multipleReqs(req1: 1, req2: 2)
}
');
'
);
}
/**
@ -38,11 +46,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/
public function testIgnoresArgsOfUnknownFields() : void
{
$this->expectPassesRule(new KnownArgumentNames, '
$this->expectPassesRule(
new KnownArgumentNames(),
'
fragment argOnUnknownField on Dog {
unknownField(unknownArg: SIT)
}
');
'
);
}
/**
@ -50,11 +61,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/
public function testMultipleArgsInReverseOrderAreKnown() : void
{
$this->expectPassesRule(new KnownArgumentNames, '
$this->expectPassesRule(
new KnownArgumentNames(),
'
fragment multipleArgsReverseOrder on ComplicatedArgs {
multipleReqs(req2: 2, req1: 1)
}
');
'
);
}
/**
@ -62,11 +76,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/
public function testNoArgsOnOptionalArg() : void
{
$this->expectPassesRule(new KnownArgumentNames, '
$this->expectPassesRule(
new KnownArgumentNames(),
'
fragment noArgOnOptionalArg on Dog {
isHousetrained
}
');
'
);
}
/**
@ -74,7 +91,9 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/
public function testArgsAreKnownDeeply() : void
{
$this->expectPassesRule(new KnownArgumentNames, '
$this->expectPassesRule(
new KnownArgumentNames(),
'
{
dog {
doesKnowCommand(dogCommand: SIT)
@ -87,7 +106,8 @@ class KnownArgumentNamesTest extends ValidatorTestCase
}
}
}
');
'
);
}
/**
@ -95,11 +115,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/
public function testDirectiveArgsAreKnown() : void
{
$this->expectPassesRule(new KnownArgumentNames, '
$this->expectPassesRule(
new KnownArgumentNames(),
'
{
dog @skip(if: true)
}
');
'
);
}
/**
@ -107,101 +130,16 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/
public function testUndirectiveArgsAreInvalid() : void
{
$this->expectFailsRule(new KnownArgumentNames, '
$this->expectFailsRule(
new KnownArgumentNames(),
'
{
dog @skip(unless: true)
}
', [
',
[
$this->unknownDirectiveArg('unless', 'skip', [], 3, 19),
]);
}
/**
* @see it('misspelled directive args are reported')
*/
public function testMisspelledDirectiveArgsAreReported() : void
{
$this->expectFailsRule(new KnownArgumentNames, '
{
dog @skip(iff: true)
}
', [
$this->unknownDirectiveArg('iff', 'skip', ['if'], 3, 19),
]);
}
/**
* @see it('invalid arg name')
*/
public function testInvalidArgName() : void
{
$this->expectFailsRule(new KnownArgumentNames, '
fragment invalidArgName on Dog {
doesKnowCommand(unknown: true)
}
', [
$this->unknownArg('unknown', 'doesKnowCommand', 'Dog', [],3, 25),
]);
}
/**
* @see it('misspelled arg name is reported')
*/
public function testMisspelledArgNameIsReported() : void
{
$this->expectFailsRule(new KnownArgumentNames, '
fragment invalidArgName on Dog {
doesKnowCommand(dogcommand: true)
}
', [
$this->unknownArg('dogcommand', 'doesKnowCommand', 'Dog', ['dogCommand'],3, 25),
]);
}
/**
* @see it('unknown args amongst known args')
*/
public function testUnknownArgsAmongstKnownArgs() : void
{
$this->expectFailsRule(new KnownArgumentNames, '
fragment oneGoodArgOneInvalidArg on Dog {
doesKnowCommand(whoknows: 1, dogCommand: SIT, unknown: true)
}
', [
$this->unknownArg('whoknows', 'doesKnowCommand', 'Dog', [], 3, 25),
$this->unknownArg('unknown', 'doesKnowCommand', 'Dog', [], 3, 55),
]);
}
/**
* @see it('unknown args deeply')
*/
public function testUnknownArgsDeeply() : void
{
$this->expectFailsRule(new KnownArgumentNames, '
{
dog {
doesKnowCommand(unknown: true)
}
human {
pet {
... on Dog {
doesKnowCommand(unknown: true)
}
}
}
}
', [
$this->unknownArg('unknown', 'doesKnowCommand', 'Dog', [], 4, 27),
$this->unknownArg('unknown', 'doesKnowCommand', 'Dog', [], 9, 31),
]);
}
private function unknownArg($argName, $fieldName, $typeName, $suggestedArgs, $line, $column)
{
return FormattedError::create(
KnownArgumentNames::unknownArgMessage($argName, $fieldName, $typeName, $suggestedArgs),
[new SourceLocation($line, $column)]
]
);
}
@ -212,4 +150,113 @@ class KnownArgumentNamesTest extends ValidatorTestCase
[new SourceLocation($line, $column)]
);
}
/**
* @see it('misspelled directive args are reported')
*/
public function testMisspelledDirectiveArgsAreReported() : void
{
$this->expectFailsRule(
new KnownArgumentNames(),
'
{
dog @skip(iff: true)
}
',
[
$this->unknownDirectiveArg('iff', 'skip', ['if'], 3, 19),
]
);
}
/**
* @see it('invalid arg name')
*/
public function testInvalidArgName() : void
{
$this->expectFailsRule(
new KnownArgumentNames(),
'
fragment invalidArgName on Dog {
doesKnowCommand(unknown: true)
}
',
[
$this->unknownArg('unknown', 'doesKnowCommand', 'Dog', [], 3, 25),
]
);
}
private function unknownArg($argName, $fieldName, $typeName, $suggestedArgs, $line, $column)
{
return FormattedError::create(
KnownArgumentNames::unknownArgMessage($argName, $fieldName, $typeName, $suggestedArgs),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('misspelled arg name is reported')
*/
public function testMisspelledArgNameIsReported() : void
{
$this->expectFailsRule(
new KnownArgumentNames(),
'
fragment invalidArgName on Dog {
doesKnowCommand(dogcommand: true)
}
',
[
$this->unknownArg('dogcommand', 'doesKnowCommand', 'Dog', ['dogCommand'], 3, 25),
]
);
}
/**
* @see it('unknown args amongst known args')
*/
public function testUnknownArgsAmongstKnownArgs() : void
{
$this->expectFailsRule(
new KnownArgumentNames(),
'
fragment oneGoodArgOneInvalidArg on Dog {
doesKnowCommand(whoknows: 1, dogCommand: SIT, unknown: true)
}
',
[
$this->unknownArg('whoknows', 'doesKnowCommand', 'Dog', [], 3, 25),
$this->unknownArg('unknown', 'doesKnowCommand', 'Dog', [], 3, 55),
]
);
}
/**
* @see it('unknown args deeply')
*/
public function testUnknownArgsDeeply() : void
{
$this->expectFailsRule(
new KnownArgumentNames(),
'
{
dog {
doesKnowCommand(unknown: true)
}
human {
pet {
... on Dog {
doesKnowCommand(unknown: true)
}
}
}
}
',
[
$this->unknownArg('unknown', 'doesKnowCommand', 'Dog', [], 4, 27),
$this->unknownArg('unknown', 'doesKnowCommand', 'Dog', [], 9, 31),
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,13 +11,14 @@ use GraphQL\Validator\Rules\KnownDirectives;
class KnownDirectivesTest extends ValidatorTestCase
{
// Validate: Known directives
/**
* @see it('with no directives')
*/
public function testWithNoDirectives() : void
{
$this->expectPassesRule(new KnownDirectives, '
$this->expectPassesRule(
new KnownDirectives(),
'
query Foo {
name
...Frag
@ -23,7 +27,8 @@ class KnownDirectivesTest extends ValidatorTestCase
fragment Frag on Dog {
name
}
');
'
);
}
/**
@ -31,7 +36,9 @@ class KnownDirectivesTest extends ValidatorTestCase
*/
public function testWithKnownDirectives() : void
{
$this->expectPassesRule(new KnownDirectives, '
$this->expectPassesRule(
new KnownDirectives(),
'
{
dog @include(if: true) {
name
@ -40,7 +47,8 @@ class KnownDirectivesTest extends ValidatorTestCase
name
}
}
');
'
);
}
/**
@ -48,15 +56,25 @@ class KnownDirectivesTest extends ValidatorTestCase
*/
public function testWithUnknownDirective() : void
{
$this->expectFailsRule(new KnownDirectives, '
$this->expectFailsRule(
new KnownDirectives(),
'
{
dog @unknown(directive: "value") {
name
}
}
', [
$this->unknownDirective('unknown', 3, 13)
]);
',
[$this->unknownDirective('unknown', 3, 13)]
);
}
private function unknownDirective($directiveName, $line, $column)
{
return FormattedError::create(
KnownDirectives::unknownDirectiveMessage($directiveName),
[new SourceLocation($line, $column)]
);
}
/**
@ -64,7 +82,9 @@ class KnownDirectivesTest extends ValidatorTestCase
*/
public function testWithManyUnknownDirectives() : void
{
$this->expectFailsRule(new KnownDirectives, '
$this->expectFailsRule(
new KnownDirectives(),
'
{
dog @unknown(directive: "value") {
name
@ -76,11 +96,13 @@ class KnownDirectivesTest extends ValidatorTestCase
}
}
}
', [
',
[
$this->unknownDirective('unknown', 3, 13),
$this->unknownDirective('unknown', 6, 15),
$this->unknownDirective('unknown', 8, 16)
]);
$this->unknownDirective('unknown', 8, 16),
]
);
}
/**
@ -88,7 +110,9 @@ class KnownDirectivesTest extends ValidatorTestCase
*/
public function testWithWellPlacedDirectives() : void
{
$this->expectPassesRule(new KnownDirectives, '
$this->expectPassesRule(
new KnownDirectives(),
'
query Foo @onQuery {
name @include(if: true)
...Frag @include(if: true)
@ -99,15 +123,20 @@ class KnownDirectivesTest extends ValidatorTestCase
mutation Bar @onMutation {
someField
}
');
'
);
}
// within schema language
/**
* @see it('with misplaced directives')
*/
public function testWithMisplacedDirectives() : void
{
$this->expectFailsRule(new KnownDirectives, '
$this->expectFailsRule(
new KnownDirectives(),
'
query Foo @include(if: true) {
name @onQuery
...Frag @onQuery
@ -116,22 +145,32 @@ class KnownDirectivesTest extends ValidatorTestCase
mutation Bar @onQuery {
someField
}
', [
',
[
$this->misplacedDirective('include', 'QUERY', 2, 17),
$this->misplacedDirective('onQuery', 'FIELD', 3, 14),
$this->misplacedDirective('onQuery', 'FRAGMENT_SPREAD', 4, 17),
$this->misplacedDirective('onQuery', 'MUTATION', 7, 20),
]);
]
);
}
// within schema language
private function misplacedDirective($directiveName, $placement, $line, $column)
{
return FormattedError::create(
KnownDirectives::misplacedDirectiveMessage($directiveName, $placement),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('with well placed directives')
*/
public function testWSLWithWellPlacedDirectives() : void
{
$this->expectPassesRule(new KnownDirectives, '
$this->expectPassesRule(
new KnownDirectives(),
'
type MyObj implements MyInterface @onObject {
myField(myArg: Int @onArgumentDefinition): String @onFieldDefinition
}
@ -167,7 +206,8 @@ class KnownDirectivesTest extends ValidatorTestCase
schema @onSchema {
query: MyQuery
}
');
'
);
}
/**
@ -175,7 +215,9 @@ class KnownDirectivesTest extends ValidatorTestCase
*/
public function testWSLWithMisplacedDirectives() : void
{
$this->expectFailsRule(new KnownDirectives, '
$this->expectFailsRule(
new KnownDirectives(),
'
type MyObj implements MyInterface @onInterface {
myField(myArg: Int @onInputFieldDefinition): String @onInputFieldDefinition
}
@ -217,20 +259,4 @@ class KnownDirectivesTest extends ValidatorTestCase
]
);
}
private function unknownDirective($directiveName, $line, $column)
{
return FormattedError::create(
KnownDirectives::unknownDirectiveMessage($directiveName),
[ new SourceLocation($line, $column) ]
);
}
function misplacedDirective($directiveName, $placement, $line, $column)
{
return FormattedError::create(
KnownDirectives::misplacedDirectiveMessage($directiveName, $placement),
[new SourceLocation($line, $column)]
);
}
}

View File

@ -1,20 +1,24 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Validator\Rules\KnownFragmentNames;
use GraphQL\Error\FormattedError;
use GraphQL\Language\SourceLocation;
use GraphQL\Validator\Rules\KnownFragmentNames;
class KnownFragmentNamesTest extends ValidatorTestCase
{
// Validate: Known fragment names
/**
* @see it('known fragment names are valid')
*/
public function testKnownFragmentNamesAreValid() : void
{
$this->expectPassesRule(new KnownFragmentNames, '
$this->expectPassesRule(
new KnownFragmentNames(),
'
{
human(id: 4) {
...HumanFields1
@ -33,7 +37,8 @@ class KnownFragmentNamesTest extends ValidatorTestCase
fragment HumanFields3 on Human {
name
}
');
'
);
}
/**
@ -41,7 +46,9 @@ class KnownFragmentNamesTest extends ValidatorTestCase
*/
public function testUnknownFragmentNamesAreInvalid() : void
{
$this->expectFailsRule(new KnownFragmentNames, '
$this->expectFailsRule(
new KnownFragmentNames(),
'
{
human(id: 4) {
...UnknownFragment1
@ -54,11 +61,13 @@ class KnownFragmentNamesTest extends ValidatorTestCase
name
...UnknownFragment3
}
', [
',
[
$this->undefFrag('UnknownFragment1', 4, 14),
$this->undefFrag('UnknownFragment2', 6, 16),
$this->undefFrag('UnknownFragment3', 12, 12)
]);
$this->undefFrag('UnknownFragment3', 12, 12),
]
);
}
private function undefFrag($fragName, $line, $column)

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,13 +11,14 @@ use GraphQL\Validator\Rules\KnownTypeNames;
class KnownTypeNamesTest extends ValidatorTestCase
{
// Validate: Known type names
/**
* @see it('known type names are valid')
*/
public function testKnownTypeNamesAreValid() : void
{
$this->expectPassesRule(new KnownTypeNames, '
$this->expectPassesRule(
new KnownTypeNames(),
'
query Foo($var: String, $required: [String!]!) {
user(id: 4) {
pets { ... on Pet { name }, ...PetFields }
@ -23,7 +27,8 @@ class KnownTypeNamesTest extends ValidatorTestCase
fragment PetFields on Pet {
name
}
');
'
);
}
/**
@ -31,7 +36,9 @@ class KnownTypeNamesTest extends ValidatorTestCase
*/
public function testUnknownTypeNamesAreInvalid() : void
{
$this->expectFailsRule(new KnownTypeNames, '
$this->expectFailsRule(
new KnownTypeNames(),
'
query Foo($var: JumbledUpLetters) {
user(id: 4) {
name
@ -41,11 +48,21 @@ class KnownTypeNamesTest extends ValidatorTestCase
fragment PetFields on Peettt {
name
}
', [
',
[
$this->unknownType('JumbledUpLetters', [], 2, 23),
$this->unknownType('Badger', [], 5, 25),
$this->unknownType('Peettt', ['Pet'], 8, 29)
]);
$this->unknownType('Peettt', ['Pet'], 8, 29),
]
);
}
private function unknownType($typeName, $suggestedTypes, $line, $column)
{
return FormattedError::create(
KnownTypeNames::unknownTypeMessage($typeName, $suggestedTypes),
[new SourceLocation($line, $column)]
);
}
/**
@ -53,7 +70,9 @@ class KnownTypeNamesTest extends ValidatorTestCase
*/
public function testIgnoresTypeDefinitions() : void
{
$this->expectFailsRule(new KnownTypeNames, '
$this->expectFailsRule(
new KnownTypeNames(),
'
type NotInTheSchema {
field: FooBar
}
@ -69,16 +88,10 @@ class KnownTypeNamesTest extends ValidatorTestCase
id
}
}
', [
',
[
$this->unknownType('NotInTheSchema', [], 12, 23),
]);
}
private function unknownType($typeName, $suggestedTypes, $line, $column)
{
return FormattedError::create(
KnownTypeNames::unknownTypeMessage($typeName, $suggestedTypes),
[new SourceLocation($line, $column)]
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\LoneAnonymousOperation;
class LoneAnonymousOperationTest extends ValidatorTestCase
{
// Validate: Anonymous operation must be alone
/**
* @see it('no operations')
*/
public function testNoOperations() : void
{
$this->expectPassesRule(new LoneAnonymousOperation, '
$this->expectPassesRule(
new LoneAnonymousOperation(),
'
fragment fragA on Type {
field
}
');
'
);
}
/**
@ -26,11 +31,14 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
*/
public function testOneAnonOperation() : void
{
$this->expectPassesRule(new LoneAnonymousOperation, '
$this->expectPassesRule(
new LoneAnonymousOperation(),
'
{
field
}
');
'
);
}
/**
@ -38,7 +46,9 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
*/
public function testMultipleNamedOperations() : void
{
$this->expectPassesRule(new LoneAnonymousOperation, '
$this->expectPassesRule(
new LoneAnonymousOperation(),
'
query Foo {
field
}
@ -46,7 +56,8 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
query Bar {
field
}
');
'
);
}
/**
@ -54,14 +65,17 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
*/
public function testAnonOperationWithFragment() : void
{
$this->expectPassesRule(new LoneAnonymousOperation, '
$this->expectPassesRule(
new LoneAnonymousOperation(),
'
{
...Foo
}
fragment Foo on Type {
field
}
');
'
);
}
/**
@ -69,51 +83,21 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
*/
public function testMultipleAnonOperations() : void
{
$this->expectFailsRule(new LoneAnonymousOperation, '
$this->expectFailsRule(
new LoneAnonymousOperation(),
'
{
fieldA
}
{
fieldB
}
', [
',
[
$this->anonNotAlone(2, 7),
$this->anonNotAlone(5, 7)
]);
}
/**
* @see it('anon operation with a mutation')
*/
public function testAnonOperationWithMutation() : void
{
$this->expectFailsRule(new LoneAnonymousOperation, '
{
fieldA
}
mutation Foo {
fieldB
}
', [
$this->anonNotAlone(2, 7)
]);
}
/**
* @see it('anon operation with a subscription')
*/
public function testAnonOperationWithSubscription() : void
{
$this->expectFailsRule(new LoneAnonymousOperation, '
{
fieldA
}
subscription Foo {
fieldB
}
', [
$this->anonNotAlone(2, 7)
]);
$this->anonNotAlone(5, 7),
]
);
}
private function anonNotAlone($line, $column)
@ -122,6 +106,47 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
LoneAnonymousOperation::anonOperationNotAloneMessage(),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('anon operation with a mutation')
*/
public function testAnonOperationWithMutation() : void
{
$this->expectFailsRule(
new LoneAnonymousOperation(),
'
{
fieldA
}
mutation Foo {
fieldB
}
',
[
$this->anonNotAlone(2, 7),
]
);
}
/**
* @see it('anon operation with a subscription')
*/
public function testAnonOperationWithSubscription() : void
{
$this->expectFailsRule(
new LoneAnonymousOperation(),
'
{
fieldA
}
subscription Foo {
fieldB
}
',
[
$this->anonNotAlone(2, 7),
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,16 +11,18 @@ use GraphQL\Validator\Rules\NoFragmentCycles;
class NoFragmentCyclesTest extends ValidatorTestCase
{
// Validate: No circular fragment spreads
/**
* @see it('single reference is valid')
*/
public function testSingleReferenceIsValid() : void
{
$this->expectPassesRule(new NoFragmentCycles(), '
$this->expectPassesRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB }
fragment fragB on Dog { name }
');
'
);
}
/**
@ -25,10 +30,13 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testSpreadingTwiceIsNotCircular() : void
{
$this->expectPassesRule(new NoFragmentCycles, '
$this->expectPassesRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB, ...fragB }
fragment fragB on Dog { name }
');
'
);
}
/**
@ -36,11 +44,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testSpreadingTwiceIndirectlyIsNotCircular() : void
{
$this->expectPassesRule(new NoFragmentCycles, '
$this->expectPassesRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB, ...fragC }
fragment fragB on Dog { ...fragC }
fragment fragC on Dog { name }
');
'
);
}
/**
@ -48,7 +59,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testDoubleSpreadWithinAbstractTypes() : void
{
$this->expectPassesRule(new NoFragmentCycles, '
$this->expectPassesRule(
new NoFragmentCycles(),
'
fragment nameFragment on Pet {
... on Dog { name }
... on Cat { name }
@ -58,7 +71,8 @@ class NoFragmentCyclesTest extends ValidatorTestCase
... on Dog { ...nameFragment }
... on Cat { ...nameFragment }
}
');
'
);
}
/**
@ -66,11 +80,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testDoesNotFalsePositiveOnUnknownFragment() : void
{
$this->expectPassesRule(new NoFragmentCycles, '
$this->expectPassesRule(
new NoFragmentCycles(),
'
fragment nameFragment on Pet {
...UnknownFragment
}
');
'
);
}
/**
@ -78,11 +95,23 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testSpreadingRecursivelyWithinFieldFails() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Human { relatives { ...fragA } },
', [
$this->cycleError('fragA', [], 2, 45)
]);
',
[
$this->cycleError('fragA', [], 2, 45),
]
);
}
private function cycleError($fargment, $spreadNames, $line, $column)
{
return FormattedError::create(
NoFragmentCycles::cycleErrorMessage($fargment, $spreadNames),
[new SourceLocation($line, $column)]
);
}
/**
@ -90,11 +119,15 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfDirectly() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragA }
', [
$this->cycleError('fragA', [], 2, 31)
]);
',
[
$this->cycleError('fragA', [], 2, 31),
]
);
}
/**
@ -102,15 +135,19 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfDirectlyWithinInlineFragment() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Pet {
... on Dog {
...fragA
}
}
', [
$this->cycleError('fragA', [], 4, 11)
]);
',
[
$this->cycleError('fragA', [], 4, 11),
]
);
}
/**
@ -118,15 +155,19 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfIndirectly() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB }
fragment fragB on Dog { ...fragA }
', [
',
[
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']),
[new SourceLocation(2, 31), new SourceLocation(3, 31)]
)
]);
),
]
);
}
/**
@ -134,15 +175,19 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfIndirectlyReportsOppositeOrder() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragB on Dog { ...fragA }
fragment fragA on Dog { ...fragB }
', [
',
[
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragB', ['fragA']),
[new SourceLocation(2, 31), new SourceLocation(3, 31)]
)
]);
),
]
);
}
/**
@ -150,7 +195,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfIndirectlyWithinInlineFragment() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Pet {
... on Dog {
...fragB
@ -161,12 +208,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
...fragA
}
}
', [
',
[
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']),
[new SourceLocation(4, 11), new SourceLocation(9, 11)]
)
]);
),
]
);
}
/**
@ -174,7 +223,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfDeeply() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB }
fragment fragB on Dog { ...fragC }
fragment fragC on Dog { ...fragO }
@ -183,7 +234,8 @@ class NoFragmentCyclesTest extends ValidatorTestCase
fragment fragZ on Dog { ...fragO }
fragment fragO on Dog { ...fragP }
fragment fragP on Dog { ...fragA, ...fragX }
', [
',
[
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragB', 'fragC', 'fragO', 'fragP']),
[
@ -203,8 +255,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
new SourceLocation(6, 31),
new SourceLocation(7, 31),
]
)
]);
),
]
);
}
/**
@ -212,11 +265,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfDeeplyTwoPaths() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB, ...fragC }
fragment fragB on Dog { ...fragA }
fragment fragC on Dog { ...fragA }
', [
',
[
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']),
[new SourceLocation(2, 31), new SourceLocation(3, 31)]
@ -224,8 +280,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragC']),
[new SourceLocation(2, 41), new SourceLocation(4, 31)]
)
]);
),
]
);
}
/**
@ -233,11 +290,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfDeeplyTwoPathsTraverseOrder() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragC }
fragment fragB on Dog { ...fragC }
fragment fragC on Dog { ...fragA, ...fragB }
', [
',
[
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragC']),
[new SourceLocation(2, 31), new SourceLocation(4, 31)]
@ -245,8 +305,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragC', ['fragB']),
[new SourceLocation(4, 41), new SourceLocation(3, 31)]
)
]);
),
]
);
}
/**
@ -254,11 +315,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/
public function testNoSpreadingItselfDeeplyAndImmediately() : void
{
$this->expectFailsRule(new NoFragmentCycles, '
$this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB }
fragment fragB on Dog { ...fragB, ...fragC }
fragment fragC on Dog { ...fragA, ...fragB }
', [
',
[
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragB', []),
[new SourceLocation(3, 31)]
@ -268,21 +332,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
[
new SourceLocation(2, 31),
new SourceLocation(3, 41),
new SourceLocation(4, 31)
new SourceLocation(4, 31),
]
),
FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragB', ['fragC']),
[new SourceLocation(3, 41), new SourceLocation(4, 41)]
)
]);
}
private function cycleError($fargment, $spreadNames, $line, $column)
{
return FormattedError::create(
NoFragmentCycles::cycleErrorMessage($fargment, $spreadNames),
[new SourceLocation($line, $column)]
),
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\NoUndefinedVariables;
class NoUndefinedVariablesTest extends ValidatorTestCase
{
// Validate: No undefined variables
/**
* @see it('all variables defined')
*/
public function testAllVariablesDefined() : void
{
$this->expectPassesRule(new NoUndefinedVariables(), '
$this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
field(a: $a, b: $b, c: $c)
}
');
'
);
}
/**
@ -26,7 +31,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testAllVariablesDeeplyDefined() : void
{
$this->expectPassesRule(new NoUndefinedVariables, '
$this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
field(a: $a) {
field(b: $b) {
@ -34,7 +41,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
}
}
}
');
'
);
}
/**
@ -42,7 +50,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testAllVariablesDeeplyInInlineFragmentsDefined() : void
{
$this->expectPassesRule(new NoUndefinedVariables, '
$this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
... on Type {
field(a: $a) {
@ -54,7 +64,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
}
}
}
');
'
);
}
/**
@ -62,7 +73,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testAllVariablesInFragmentsDeeplyDefined() : void
{
$this->expectPassesRule(new NoUndefinedVariables, '
$this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
...FragA
}
@ -79,7 +92,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragC on Type {
field(c: $c)
}
');
'
);
}
/**
@ -88,7 +102,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
public function testVariableWithinSingleFragmentDefinedInMultipleOperations() : void
{
// variable within single fragment defined in multiple operations
$this->expectPassesRule(new NoUndefinedVariables, '
$this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String) {
...FragA
}
@ -98,7 +114,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragA on Type {
field(a: $a)
}
');
'
);
}
/**
@ -106,7 +123,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testVariableWithinFragmentsDefinedInOperations() : void
{
$this->expectPassesRule(new NoUndefinedVariables, '
$this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String) {
...FragA
}
@ -119,7 +138,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragB on Type {
field(b: $b)
}
');
'
);
}
/**
@ -127,7 +147,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testVariableWithinRecursiveFragmentDefined() : void
{
$this->expectPassesRule(new NoUndefinedVariables, '
$this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String) {
...FragA
}
@ -136,7 +158,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
...FragA
}
}
');
'
);
}
/**
@ -144,13 +167,31 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testVariableNotDefined() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
field(a: $a, b: $b, c: $c, d: $d)
}
', [
$this->undefVar('d', 3, 39, 'Foo', 2, 7)
]);
',
[
$this->undefVar('d', 3, 39, 'Foo', 2, 7),
]
);
}
private function undefVar($varName, $line, $column, $opName = null, $l2 = null, $c2 = null)
{
$locs = [new SourceLocation($line, $column)];
if ($l2 && $c2) {
$locs[] = new SourceLocation($l2, $c2);
}
return FormattedError::create(
NoUndefinedVariables::undefinedVarMessage($varName, $opName),
$locs
);
}
/**
@ -158,13 +199,17 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testVariableNotDefinedByUnNamedQuery() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
{
field(a: $a)
}
', [
$this->undefVar('a', 3, 18, '', 2, 7)
]);
',
[
$this->undefVar('a', 3, 18, '', 2, 7),
]
);
}
/**
@ -172,14 +217,18 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testMultipleVariablesNotDefined() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) {
field(a: $a, b: $b, c: $c)
}
', [
',
[
$this->undefVar('a', 3, 18, 'Foo', 2, 7),
$this->undefVar('c', 3, 32, 'Foo', 2, 7)
]);
$this->undefVar('c', 3, 32, 'Foo', 2, 7),
]
);
}
/**
@ -187,16 +236,20 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testVariableInFragmentNotDefinedByUnNamedQuery() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
{
...FragA
}
fragment FragA on Type {
field(a: $a)
}
', [
$this->undefVar('a', 6, 18, '', 2, 7)
]);
',
[
$this->undefVar('a', 6, 18, '', 2, 7),
]
);
}
/**
@ -204,7 +257,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testVariableInFragmentNotDefinedByOperation() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String) {
...FragA
}
@ -221,9 +276,11 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragC on Type {
field(c: $c)
}
', [
$this->undefVar('c', 16, 18, 'Foo', 2, 7)
]);
',
[
$this->undefVar('c', 16, 18, 'Foo', 2, 7),
]
);
}
/**
@ -231,7 +288,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testMultipleVariablesInFragmentsNotDefined() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) {
...FragA
}
@ -248,10 +307,12 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragC on Type {
field(c: $c)
}
', [
',
[
$this->undefVar('a', 6, 18, 'Foo', 2, 7),
$this->undefVar('c', 16, 18, 'Foo', 2, 7)
]);
$this->undefVar('c', 16, 18, 'Foo', 2, 7),
]
);
}
/**
@ -259,7 +320,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testSingleVariableInFragmentNotDefinedByMultipleOperations() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($a: String) {
...FragAB
}
@ -269,10 +332,12 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragAB on Type {
field(a: $a, b: $b)
}
', [
',
[
$this->undefVar('b', 9, 25, 'Foo', 2, 7),
$this->undefVar('b', 9, 25, 'Bar', 5, 7)
]);
$this->undefVar('b', 9, 25, 'Bar', 5, 7),
]
);
}
/**
@ -280,7 +345,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testVariablesInFragmentNotDefinedByMultipleOperations() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) {
...FragAB
}
@ -290,10 +357,12 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragAB on Type {
field(a: $a, b: $b)
}
', [
',
[
$this->undefVar('a', 9, 18, 'Foo', 2, 7),
$this->undefVar('b', 9, 25, 'Bar', 5, 7)
]);
$this->undefVar('b', 9, 25, 'Bar', 5, 7),
]
);
}
/**
@ -301,7 +370,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testVariableInFragmentUsedByOtherOperation() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) {
...FragA
}
@ -314,10 +385,12 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragB on Type {
field(b: $b)
}
', [
',
[
$this->undefVar('a', 9, 18, 'Foo', 2, 7),
$this->undefVar('b', 12, 18, 'Bar', 5, 7)
]);
$this->undefVar('b', 12, 18, 'Bar', 5, 7),
]
);
}
/**
@ -325,7 +398,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/
public function testMultipleUndefinedVariablesProduceMultipleErrors() : void
{
$this->expectFailsRule(new NoUndefinedVariables, '
$this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) {
...FragAB
}
@ -340,28 +415,15 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragC on Type {
field2(c: $c)
}
', [
',
[
$this->undefVar('a', 9, 19, 'Foo', 2, 7),
$this->undefVar('a', 11, 19, 'Foo', 2, 7),
$this->undefVar('c', 14, 19, 'Foo', 2, 7),
$this->undefVar('b', 9, 26, 'Bar', 5, 7),
$this->undefVar('b', 11, 26, 'Bar', 5, 7),
$this->undefVar('c', 14, 19, 'Bar', 5, 7),
]);
}
private function undefVar($varName, $line, $column, $opName = null, $l2 = null, $c2 = null)
{
$locs = [new SourceLocation($line, $column)];
if ($l2 && $c2) {
$locs[] = new SourceLocation($l2, $c2);
}
return FormattedError::create(
NoUndefinedVariables::undefinedVarMessage($varName, $opName),
$locs
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,13 +11,14 @@ use GraphQL\Validator\Rules\NoUnusedFragments;
class NoUnusedFragmentsTest extends ValidatorTestCase
{
// Validate: No unused fragments
/**
* @see it('all fragment names are used')
*/
public function testAllFragmentNamesAreUsed() : void
{
$this->expectPassesRule(new NoUnusedFragments(), '
$this->expectPassesRule(
new NoUnusedFragments(),
'
{
human(id: 4) {
...HumanFields1
@ -33,7 +37,8 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
fragment HumanFields3 on Human {
name
}
');
'
);
}
/**
@ -41,7 +46,9 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
*/
public function testAllFragmentNamesAreUsedByMultipleOperations() : void
{
$this->expectPassesRule(new NoUnusedFragments, '
$this->expectPassesRule(
new NoUnusedFragments(),
'
query Foo {
human(id: 4) {
...HumanFields1
@ -62,7 +69,8 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
fragment HumanFields3 on Human {
name
}
');
'
);
}
/**
@ -70,7 +78,9 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
*/
public function testContainsUnknownFragments() : void
{
$this->expectFailsRule(new NoUnusedFragments, '
$this->expectFailsRule(
new NoUnusedFragments(),
'
query Foo {
human(id: 4) {
...HumanFields1
@ -97,10 +107,20 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
fragment Unused2 on Human {
name
}
', [
',
[
$this->unusedFrag('Unused1', 22, 7),
$this->unusedFrag('Unused2', 25, 7),
]);
]
);
}
private function unusedFrag($fragName, $line, $column)
{
return FormattedError::create(
NoUnusedFragments::unusedFragMessage($fragName),
[new SourceLocation($line, $column)]
);
}
/**
@ -108,7 +128,9 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
*/
public function testContainsUnknownFragmentsWithRefCycle() : void
{
$this->expectFailsRule(new NoUnusedFragments, '
$this->expectFailsRule(
new NoUnusedFragments(),
'
query Foo {
human(id: 4) {
...HumanFields1
@ -137,10 +159,12 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
name
...Unused1
}
', [
',
[
$this->unusedFrag('Unused1', 22, 7),
$this->unusedFrag('Unused2', 26, 7),
]);
]
);
}
/**
@ -148,8 +172,9 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
*/
public function testContainsUnknownAndUndefFragments() : void
{
$this->expectFailsRule(new NoUnusedFragments, '
$this->expectFailsRule(
new NoUnusedFragments(),
'
query Foo {
human(id: 4) {
...bar
@ -158,16 +183,10 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
fragment foo on Human {
name
}
', [
',
[
$this->unusedFrag('foo', 7, 7),
]);
}
private function unusedFrag($fragName, $line, $column)
{
return FormattedError::create(
NoUnusedFragments::unusedFragMessage($fragName),
[new SourceLocation($line, $column)]
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\NoUnusedVariables;
class NoUnusedVariablesTest extends ValidatorTestCase
{
// Validate: No unused variables
/**
* @see it('uses all variables')
*/
public function testUsesAllVariables() : void
{
$this->expectPassesRule(new NoUnusedVariables(), '
$this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
field(a: $a, b: $b, c: $c)
}
');
'
);
}
/**
@ -26,7 +31,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testUsesAllVariablesDeeply() : void
{
$this->expectPassesRule(new NoUnusedVariables, '
$this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
field(a: $a) {
field(b: $b) {
@ -34,7 +41,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
}
}
}
');
'
);
}
/**
@ -42,7 +50,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testUsesAllVariablesDeeplyInInlineFragments() : void
{
$this->expectPassesRule(new NoUnusedVariables, '
$this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
... on Type {
field(a: $a) {
@ -54,7 +64,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
}
}
}
');
'
);
}
/**
@ -62,7 +73,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testUsesAllVariablesInFragments() : void
{
$this->expectPassesRule(new NoUnusedVariables, '
$this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
...FragA
}
@ -79,7 +92,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragC on Type {
field(c: $c)
}
');
'
);
}
/**
@ -87,7 +101,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testVariableUsedByFragmentInMultipleOperations() : void
{
$this->expectPassesRule(new NoUnusedVariables, '
$this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String) {
...FragA
}
@ -100,7 +116,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragB on Type {
field(b: $b)
}
');
'
);
}
/**
@ -108,7 +125,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testVariableUsedByRecursiveFragment() : void
{
$this->expectPassesRule(new NoUnusedVariables, '
$this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String) {
...FragA
}
@ -117,7 +136,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
...FragA
}
}
');
'
);
}
/**
@ -125,13 +145,25 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testVariableNotUsed() : void
{
$this->expectFailsRule(new NoUnusedVariables, '
$this->expectFailsRule(
new NoUnusedVariables(),
'
query ($a: String, $b: String, $c: String) {
field(a: $a, b: $b)
}
', [
$this->unusedVar('c', null, 2, 38)
]);
',
[
$this->unusedVar('c', null, 2, 38),
]
);
}
private function unusedVar($varName, $opName, $line, $column)
{
return FormattedError::create(
NoUnusedVariables::unusedVariableMessage($varName, $opName),
[new SourceLocation($line, $column)]
);
}
/**
@ -139,14 +171,18 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testMultipleVariablesNotUsed() : void
{
$this->expectFailsRule(new NoUnusedVariables, '
$this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
field(b: $b)
}
', [
',
[
$this->unusedVar('a', 'Foo', 2, 17),
$this->unusedVar('c', 'Foo', 2, 41)
]);
$this->unusedVar('c', 'Foo', 2, 41),
]
);
}
/**
@ -154,7 +190,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testVariableNotUsedInFragments() : void
{
$this->expectFailsRule(new NoUnusedVariables, '
$this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
...FragA
}
@ -171,9 +209,11 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragC on Type {
field
}
', [
$this->unusedVar('c', 'Foo', 2, 41)
]);
',
[
$this->unusedVar('c', 'Foo', 2, 41),
]
);
}
/**
@ -181,7 +221,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testMultipleVariablesNotUsed2() : void
{
$this->expectFailsRule(new NoUnusedVariables, '
$this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) {
...FragA
}
@ -198,10 +240,12 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragC on Type {
field
}
', [
',
[
$this->unusedVar('a', 'Foo', 2, 17),
$this->unusedVar('c', 'Foo', 2, 41)
]);
$this->unusedVar('c', 'Foo', 2, 41),
]
);
}
/**
@ -209,7 +253,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testVariableNotUsedByUnreferencedFragment() : void
{
$this->expectFailsRule(new NoUnusedVariables, '
$this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($b: String) {
...FragA
}
@ -219,9 +265,11 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragB on Type {
field(b: $b)
}
', [
$this->unusedVar('b', 'Foo', 2, 17)
]);
',
[
$this->unusedVar('b', 'Foo', 2, 17),
]
);
}
/**
@ -229,7 +277,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/
public function testVariableNotUsedByFragmentUsedByOtherOperation() : void
{
$this->expectFailsRule(new NoUnusedVariables, '
$this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($b: String) {
...FragA
}
@ -242,17 +292,11 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragB on Type {
field(b: $b)
}
', [
',
[
$this->unusedVar('b', 'Foo', 2, 17),
$this->unusedVar('a', 'Bar', 5, 17)
]);
}
private function unusedVar($varName, $opName, $line, $column)
{
return FormattedError::create(
NoUnusedVariables::unusedVariableMessage($varName, $opName),
[new SourceLocation($line, $column)]
$this->unusedVar('a', 'Bar', 5, 17),
]
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,16 +11,18 @@ use GraphQL\Validator\Rules\PossibleFragmentSpreads;
class PossibleFragmentSpreadsTest extends ValidatorTestCase
{
// Validate: Possible fragment spreads
/**
* @see it('of the same object')
*/
public function testOfTheSameObject() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads(), '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment objectWithinObject on Dog { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
');
'
);
}
/**
@ -25,9 +30,12 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testOfTheSameObjectWithInlineFragment() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } }
');
'
);
}
/**
@ -35,10 +43,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testObjectIntoAnImplementedInterface() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment objectWithinInterface on Pet { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
');
'
);
}
/**
@ -46,10 +57,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testObjectIntoContainingUnion() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment objectWithinUnion on CatOrDog { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
');
'
);
}
/**
@ -57,10 +71,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testUnionIntoContainedObject() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment unionWithinObject on Dog { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
');
'
);
}
/**
@ -68,10 +85,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testUnionIntoOverlappingInterface() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment unionWithinInterface on Pet { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
');
'
);
}
/**
@ -79,10 +99,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testUnionIntoOverlappingUnion() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
');
'
);
}
/**
@ -90,10 +113,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testInterfaceIntoImplementedObject() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment interfaceWithinObject on Dog { ...petFragment }
fragment petFragment on Pet { name }
');
'
);
}
/**
@ -101,10 +127,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testInterfaceIntoOverlappingInterface() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment interfaceWithinInterface on Pet { ...beingFragment }
fragment beingFragment on Being { name }
');
'
);
}
/**
@ -112,9 +141,12 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testInterfaceIntoOverlappingInterfaceInInlineFragment() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment interfaceWithinInterface on Pet { ... on Being { name } }
');
'
);
}
/**
@ -122,10 +154,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testInterfaceIntoOverlappingUnion() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment interfaceWithinUnion on CatOrDog { ...petFragment }
fragment petFragment on Pet { name }
');
'
);
}
/**
@ -133,10 +168,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testIgnoresIncorrectTypeCaughtByFragmentsOnCompositeTypes() : void
{
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment petFragment on Pet { ...badInADifferentWay }
fragment badInADifferentWay on String { name }
');
'
);
}
/**
@ -144,7 +182,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testDifferentObjectIntoObject() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidObjectWithinObject on Cat { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
',
@ -152,12 +192,22 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
);
}
private function error($fragName, $parentType, $fragType, $line, $column)
{
return FormattedError::create(
PossibleFragmentSpreads::typeIncompatibleSpreadMessage($fragName, $parentType, $fragType),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('different object into object in inline fragment')
*/
public function testDifferentObjectIntoObjectInInlineFragment() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidObjectWithinObjectAnon on Cat {
... on Dog { barkVolume }
}
@ -166,12 +216,22 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
);
}
private function errorAnon($parentType, $fragType, $line, $column)
{
return FormattedError::create(
PossibleFragmentSpreads::typeIncompatibleAnonSpreadMessage($parentType, $fragType),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('object into not implementing interface')
*/
public function testObjectIntoNotImplementingInterface() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidObjectWithinInterface on Pet { ...humanFragment }
fragment humanFragment on Human { pets { name } }
',
@ -184,7 +244,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testObjectIntoNotContainingUnion() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment }
fragment humanFragment on Human { pets { name } }
',
@ -197,7 +259,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testUnionIntoNotContainedObject() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidUnionWithinObject on Human { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
',
@ -210,7 +274,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testUnionIntoNonOverlappingInterface() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment }
fragment humanOrAlienFragment on HumanOrAlien { __typename }
',
@ -223,7 +289,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testUnionIntoNonOverlappingUnion() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment }
fragment humanOrAlienFragment on HumanOrAlien { __typename }
',
@ -236,7 +304,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testInterfaceIntoNonImplementingObject() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment }
fragment intelligentFragment on Intelligent { iq }
',
@ -252,12 +322,15 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
// Ideally this should fail, but our new lazy schema doesn't scan through all types and fields
// So we don't have enough knowledge to check interface intersection and always allow this to pass:
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment invalidInterfaceWithinInterface on Pet {
...intelligentFragment
}
fragment intelligentFragment on Intelligent { iq }
');
'
);
}
/**
@ -268,11 +341,14 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
// Ideally this should fail, but our new lazy schema doesn't scan through all types and fields
// So we don't have enough knowledge to check interface intersection and always allow this to pass:
$this->expectPassesRule(new PossibleFragmentSpreads, '
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment invalidInterfaceWithinInterfaceAnon on Pet {
...on Intelligent { iq }
}
');
'
);
}
/**
@ -280,27 +356,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/
public function testInterfaceIntoNonOverlappingUnion() : void
{
$this->expectFailsRule(new PossibleFragmentSpreads, '
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment }
fragment petFragment on Pet { name }
',
[$this->error('petFragment', 'HumanOrAlien', 'Pet', 2, 62)]
);
}
private function error($fragName, $parentType, $fragType, $line, $column)
{
return FormattedError::create(
PossibleFragmentSpreads::typeIncompatibleSpreadMessage($fragName, $parentType, $fragType),
[new SourceLocation($line, $column)]
);
}
private function errorAnon($parentType, $fragType, $line, $column)
{
return FormattedError::create(
PossibleFragmentSpreads::typeIncompatibleAnonSpreadMessage($parentType, $fragType),
[new SourceLocation($line, $column)]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,20 +11,22 @@ use GraphQL\Validator\Rules\ProvidedNonNullArguments;
class ProvidedNonNullArgumentsTest extends ValidatorTestCase
{
// Validate: Provided required arguments
/**
* @see it('ignores unknown arguments')
*/
public function testIgnoresUnknownArguments() : void
{
// ignores unknown arguments
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
dog {
isHousetrained(unknownArgument: true)
}
}
');
'
);
}
// Valid non-nullable value:
@ -31,13 +36,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testArgOnOptionalArg() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
dog {
isHousetrained(atOtherHomes: true)
}
}
');
'
);
}
/**
@ -45,13 +53,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testNoArgOnOptionalArg() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
dog {
isHousetrained
}
}
');
'
);
}
/**
@ -59,13 +70,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testMultipleArgs() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleReqs(req1: 1, req2: 2)
}
}
');
'
);
}
/**
@ -73,13 +87,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testMultipleArgsReverseOrder() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleReqs(req2: 2, req1: 1)
}
}
');
'
);
}
/**
@ -87,13 +104,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testNoArgsOnMultipleOptional() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleOpts
}
}
');
'
);
}
/**
@ -101,13 +121,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testOneArgOnMultipleOptional() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleOpts(opt1: 1)
}
}
');
'
);
}
/**
@ -115,13 +138,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testSecondArgOnMultipleOptional() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleOpts(opt2: 1)
}
}
');
'
);
}
/**
@ -129,13 +155,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testMultipleReqsOnMixedList() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleOptAndReq(req1: 3, req2: 4)
}
}
');
'
);
}
/**
@ -143,13 +172,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testMultipleReqsAndOneOptOnMixedList() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleOptAndReq(req1: 3, req2: 4, opt1: 5)
}
}
');
'
);
}
/**
@ -157,13 +189,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testAllReqsAndOptsOnMixedList() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6)
}
}
');
'
);
}
// Invalid non-nullable value
@ -173,15 +208,25 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testMissingOneNonNullableArgument() : void
{
$this->expectFailsRule(new ProvidedNonNullArguments, '
$this->expectFailsRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleReqs(req2: 2)
}
}
', [
$this->missingFieldArg('multipleReqs', 'req1', 'Int!', 4, 13)
]);
',
[$this->missingFieldArg('multipleReqs', 'req1', 'Int!', 4, 13)]
);
}
private function missingFieldArg($fieldName, $argName, $typeName, $line, $column)
{
return FormattedError::create(
ProvidedNonNullArguments::missingFieldArgMessage($fieldName, $argName, $typeName),
[new SourceLocation($line, $column)]
);
}
/**
@ -189,46 +234,57 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testMissingMultipleNonNullableArguments() : void
{
$this->expectFailsRule(new ProvidedNonNullArguments, '
$this->expectFailsRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleReqs
}
}
', [
',
[
$this->missingFieldArg('multipleReqs', 'req1', 'Int!', 4, 13),
$this->missingFieldArg('multipleReqs', 'req2', 'Int!', 4, 13),
]);
]
);
}
// Describe: Directive arguments
/**
* @see it('Incorrect value and missing argument')
*/
public function testIncorrectValueAndMissingArgument() : void
{
$this->expectFailsRule(new ProvidedNonNullArguments, '
$this->expectFailsRule(
new ProvidedNonNullArguments(),
'
{
complicatedArgs {
multipleReqs(req1: "one")
}
}
', [
',
[
$this->missingFieldArg('multipleReqs', 'req2', 'Int!', 4, 13),
]);
]
);
}
// Describe: Directive arguments
/**
* @see it('ignores unknown directives')
*/
public function testIgnoresUnknownDirectives() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
dog @unknown
}
');
'
);
}
/**
@ -236,7 +292,9 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testWithDirectivesOfValidTypes() : void
{
$this->expectPassesRule(new ProvidedNonNullArguments, '
$this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{
dog @include(if: true) {
name
@ -245,7 +303,8 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
name
}
}
');
'
);
}
/**
@ -253,23 +312,19 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/
public function testWithDirectiveWithMissingTypes() : void
{
$this->expectFailsRule(new ProvidedNonNullArguments, '
$this->expectFailsRule(
new ProvidedNonNullArguments(),
'
{
dog @include {
name @skip
}
}
', [
',
[
$this->missingDirectiveArg('include', 'if', 'Boolean!', 3, 15),
$this->missingDirectiveArg('skip', 'if', 'Boolean!', 4, 18)
]);
}
private function missingFieldArg($fieldName, $argName, $typeName, $line, $column)
{
return FormattedError::create(
ProvidedNonNullArguments::missingFieldArgMessage($fieldName, $argName, $typeName),
[new SourceLocation($line, $column)]
$this->missingDirectiveArg('skip', 'if', 'Boolean!', 4, 18),
]
);
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\Error;
@ -8,39 +11,13 @@ use GraphQL\Validator\DocumentValidator;
use GraphQL\Validator\Rules\CustomValidationRule;
use GraphQL\Validator\Rules\QueryComplexity;
use GraphQL\Validator\ValidationContext;
use function count;
class QueryComplexityTest extends QuerySecurityTestCase
{
/** @var QueryComplexity */
private static $rule;
/**
* @param $max
* @param $count
*
* @return string
*/
protected function getErrorMessage($max, $count)
{
return QueryComplexity::maxQueryComplexityErrorMessage($max, $count);
}
/**
* @param $maxDepth
*
* @return QueryComplexity
*/
protected function getRule($maxDepth = null)
{
if (null === self::$rule) {
self::$rule = new QueryComplexity($maxDepth);
} elseif (null !== $maxDepth) {
self::$rule->setMaxQueryComplexity($maxDepth);
}
return self::$rule;
}
public function testSimpleQueries() : void
{
$query = 'query MyQuery { human { firstName } }';
@ -48,6 +25,19 @@ class QueryComplexityTest extends QuerySecurityTestCase
$this->assertDocumentValidators($query, 2, 3);
}
private function assertDocumentValidators($query, $queryComplexity, $startComplexity)
{
for ($maxComplexity = $startComplexity; $maxComplexity >= 0; --$maxComplexity) {
$positions = [];
if ($maxComplexity < $queryComplexity && $maxComplexity !== QueryComplexity::DISABLED) {
$positions = [$this->createFormattedError($maxComplexity, $queryComplexity)];
}
$this->assertDocumentValidator($query, $maxComplexity, $positions);
}
}
public function testInlineFragmentQueries() : void
{
$query = 'query MyQuery { human { ... on Human { firstName } } }';
@ -92,6 +82,22 @@ class QueryComplexityTest extends QuerySecurityTestCase
$this->assertDocumentValidators($query, 3, 4);
}
/**
* @param int $maxDepth
*
* @return QueryComplexity
*/
protected function getRule($maxDepth = null)
{
if (self::$rule === null) {
self::$rule = new QueryComplexity($maxDepth);
} elseif ($maxDepth !== null) {
self::$rule->setMaxQueryComplexity($maxDepth);
}
return self::$rule;
}
public function testQueryWithEnabledIncludeDirectives() : void
{
$query = 'query MyQuery($withDogs: Boolean!) { human { dogs(name: "Root") @include(if:$withDogs) { name } } }';
@ -134,7 +140,7 @@ class QueryComplexityTest extends QuerySecurityTestCase
$this->getRule()->setRawVariableValues([
'withDogs' => true,
'withoutDogName' => true
'withoutDogName' => true,
]);
$this->assertDocumentValidators($query, 2, 3);
@ -159,16 +165,19 @@ class QueryComplexityTest extends QuerySecurityTestCase
{
$query = 'query MyQuery { human(name: INVALID_VALUE) { dogs {name} } }';
$reportedError = new Error("OtherValidatorError");
$otherRule = new CustomValidationRule('otherRule', function(ValidationContext $context) use ($reportedError) {
$reportedError = new Error('OtherValidatorError');
$otherRule = new CustomValidationRule(
'otherRule',
function (ValidationContext $context) use ($reportedError) {
return [
NodeKind::OPERATION_DEFINITION => [
'leave' => function () use ($context, $reportedError) {
$context->reportError($reportedError);
}
]
},
],
];
});
}
);
$errors = DocumentValidator::validate(
QuerySecuritySchema::buildSchema(),
@ -187,16 +196,14 @@ class QueryComplexityTest extends QuerySecurityTestCase
);
}
private function assertDocumentValidators($query, $queryComplexity, $startComplexity)
/**
* @param int $max
* @param int $count
*
* @return string
*/
protected function getErrorMessage($max, $count)
{
for ($maxComplexity = $startComplexity; $maxComplexity >= 0; --$maxComplexity) {
$positions = [];
if ($maxComplexity < $queryComplexity && $maxComplexity !== QueryComplexity::DISABLED) {
$positions = [$this->createFormattedError($maxComplexity, $queryComplexity)];
}
$this->assertDocumentValidator($query, $maxComplexity, $positions);
}
return QueryComplexity::maxQueryComplexityErrorMessage($max, $count);
}
}

View File

@ -1,35 +1,19 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Validator\Rules\QueryDepth;
use function sprintf;
use function str_replace;
class QueryDepthTest extends QuerySecurityTestCase
{
/**
* @param $max
* @param $count
*
* @return string
*/
protected function getErrorMessage($max, $count)
{
return QueryDepth::maxQueryDepthErrorMessage($max, $count);
}
/**
* @param $maxDepth
*
* @return QueryDepth
*/
protected function getRule($maxDepth)
{
return new QueryDepth($maxDepth);
}
/**
* @param $queryDepth
* @param int $queryDepth
* @param int $maxQueryDepth
* @param array $expectedErrors
* @param string[][] $expectedErrors
* @dataProvider queryDataProvider
*/
public function testSimpleQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void
@ -37,26 +21,81 @@ class QueryDepthTest extends QuerySecurityTestCase
$this->assertDocumentValidator($this->buildRecursiveQuery($queryDepth), $maxQueryDepth, $expectedErrors);
}
private function buildRecursiveQuery($depth)
{
$query = sprintf('query MyQuery { human%s }', $this->buildRecursiveQueryPart($depth));
return $query;
}
private function buildRecursiveQueryPart($depth)
{
$templates = [
'human' => ' { firstName%s } ',
'dog' => ' dogs { name%s } ',
];
$part = $templates['human'];
for ($i = 1; $i <= $depth; ++$i) {
$key = ($i % 2 === 1) ? 'human' : 'dog';
$template = $templates[$key];
$part = sprintf($part, ($key === 'human' ? ' owner ' : '') . $template);
}
$part = str_replace('%s', '', $part);
return $part;
}
/**
* @param $queryDepth
* @param int $queryDepth
* @param int $maxQueryDepth
* @param array $expectedErrors
* @param string[][] $expectedErrors
* @dataProvider queryDataProvider
*/
public function testFragmentQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void
{
$this->assertDocumentValidator($this->buildRecursiveUsingFragmentQuery($queryDepth), $maxQueryDepth, $expectedErrors);
$this->assertDocumentValidator(
$this->buildRecursiveUsingFragmentQuery($queryDepth),
$maxQueryDepth,
$expectedErrors
);
}
private function buildRecursiveUsingFragmentQuery($depth)
{
$query = sprintf(
'query MyQuery { human { ...F1 } } fragment F1 on Human %s',
$this->buildRecursiveQueryPart($depth)
);
return $query;
}
/**
* @param $queryDepth
* @param int $queryDepth
* @param int $maxQueryDepth
* @param array $expectedErrors
* @param string[][] $expectedErrors
* @dataProvider queryDataProvider
*/
public function testInlineFragmentQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void
{
$this->assertDocumentValidator($this->buildRecursiveUsingInlineFragmentQuery($queryDepth), $maxQueryDepth, $expectedErrors);
$this->assertDocumentValidator(
$this->buildRecursiveUsingInlineFragmentQuery($queryDepth),
$maxQueryDepth,
$expectedErrors
);
}
private function buildRecursiveUsingInlineFragmentQuery($depth)
{
$query = sprintf(
'query MyQuery { human { ...on Human %s } }',
$this->buildRecursiveQueryPart($depth)
);
return $query;
}
public function testComplexityIntrospectionQuery() : void
@ -99,50 +138,24 @@ class QueryDepthTest extends QuerySecurityTestCase
];
}
private function buildRecursiveQuery($depth)
/**
* @param int $max
* @param int $count
*
* @return string
*/
protected function getErrorMessage($max, $count)
{
$query = sprintf('query MyQuery { human%s }', $this->buildRecursiveQueryPart($depth));
return $query;
return QueryDepth::maxQueryDepthErrorMessage($max, $count);
}
private function buildRecursiveUsingFragmentQuery($depth)
/**
* @param int $maxDepth
*
* @return QueryDepth
*/
protected function getRule($maxDepth)
{
$query = sprintf(
'query MyQuery { human { ...F1 } } fragment F1 on Human %s',
$this->buildRecursiveQueryPart($depth)
);
return $query;
}
private function buildRecursiveUsingInlineFragmentQuery($depth)
{
$query = sprintf(
'query MyQuery { human { ...on Human %s } }',
$this->buildRecursiveQueryPart($depth)
);
return $query;
}
private function buildRecursiveQueryPart($depth)
{
$templates = [
'human' => ' { firstName%s } ',
'dog' => ' dogs { name%s } ',
];
$part = $templates['human'];
for ($i = 1; $i <= $depth; ++$i) {
$key = ($i % 2 == 1) ? 'human' : 'dog';
$template = $templates[$key];
$part = sprintf($part, ('human' == $key ? ' owner ' : '').$template);
}
$part = str_replace('%s', '', $part);
return $part;
return new QueryDepth($maxDepth);
}
}

View File

@ -1,18 +1,25 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
class QuerySecuritySchema
{
/** @var Schema */
private static $schema;
/** @var ObjectType */
private static $dogType;
/** @var ObjectType */
private static $humanType;
/** @var ObjectType */
private static $queryRootType;
/**
@ -20,12 +27,12 @@ class QuerySecuritySchema
*/
public static function buildSchema()
{
if (null !== self::$schema) {
if (self::$schema !== null) {
return self::$schema;
}
self::$schema = new Schema([
'query' => static::buildQueryRootType()
'query' => static::buildQueryRootType(),
]);
return self::$schema;
@ -33,7 +40,7 @@ class QuerySecuritySchema
public static function buildQueryRootType()
{
if (null !== self::$queryRootType) {
if (self::$queryRootType !== null) {
return self::$queryRootType;
}
@ -52,7 +59,7 @@ class QuerySecuritySchema
public static function buildHumanType()
{
if (null !== self::$humanType) {
if (self::$humanType !== null) {
return self::$humanType;
}
@ -85,7 +92,7 @@ class QuerySecuritySchema
public static function buildDogType()
{
if (null !== self::$dogType) {
if (self::$dogType !== null) {
return self::$dogType;
}

View File

@ -1,30 +1,20 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\Error;
use GraphQL\Error\FormattedError;
use GraphQL\Language\Parser;
use GraphQL\Type\Introspection;
use GraphQL\Validator\DocumentValidator;
use GraphQL\Validator\Rules\QuerySecurityRule;
use PHPUnit\Framework\TestCase;
use function array_map;
abstract class QuerySecurityTestCase extends TestCase
{
/**
* @param $max
*
* @return QuerySecurityRule
*/
abstract protected function getRule($max);
/**
* @param $max
* @param $count
*
* @return string
*/
abstract protected function getErrorMessage($max, $count);
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage argument must be greater or equal to 0.
@ -34,23 +24,12 @@ abstract class QuerySecurityTestCase extends TestCase
$this->getRule(-1);
}
protected function createFormattedError($max, $count, $locations = [])
{
return FormattedError::create($this->getErrorMessage($max, $count), $locations);
}
protected function assertDocumentValidator($queryString, $max, array $expectedErrors = [])
{
$errors = DocumentValidator::validate(
QuerySecuritySchema::buildSchema(),
Parser::parse($queryString),
[$this->getRule($max)]
);
$this->assertEquals($expectedErrors, array_map(['GraphQL\Error\Error', 'formatError'], $errors), $queryString);
return $errors;
}
/**
* @param int $max
*
* @return QuerySecurityRule
*/
abstract protected function getRule($max);
protected function assertIntrospectionQuery($maxExpected)
{
@ -59,6 +38,48 @@ abstract class QuerySecurityTestCase extends TestCase
$this->assertMaxValue($query, $maxExpected);
}
protected function assertMaxValue($query, $maxExpected)
{
$this->assertDocumentValidator($query, $maxExpected);
$newMax = $maxExpected - 1;
if ($newMax === QuerySecurityRule::DISABLED) {
return;
}
$this->assertDocumentValidator($query, $newMax, [$this->createFormattedError($newMax, $maxExpected)]);
}
/**
* @param string $queryString
* @param int $max
* @param string[][] $expectedErrors
* @return Error[]
*/
protected function assertDocumentValidator($queryString, $max, array $expectedErrors = []) : array
{
$errors = DocumentValidator::validate(
QuerySecuritySchema::buildSchema(),
Parser::parse($queryString),
[$this->getRule($max)]
);
$this->assertEquals($expectedErrors, array_map([Error::class, 'formatError'], $errors), $queryString);
return $errors;
}
protected function createFormattedError($max, $count, $locations = [])
{
return FormattedError::create($this->getErrorMessage($max, $count), $locations);
}
/**
* @param int $max
* @param int $count
*
* @return string
*/
abstract protected function getErrorMessage($max, $count);
protected function assertIntrospectionTypeMetaFieldQuery($maxExpected)
{
$query = '
@ -84,14 +105,4 @@ abstract class QuerySecurityTestCase extends TestCase
';
$this->assertMaxValue($query, $maxExpected);
}
protected function assertMaxValue($query, $maxExpected)
{
$this->assertDocumentValidator($query, $maxExpected);
$newMax = $maxExpected - 1;
if ($newMax === QuerySecurityRule::DISABLED) {
return;
}
$this->assertDocumentValidator($query, $newMax, [$this->createFormattedError($newMax, $maxExpected)]);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\ScalarLeafs;
class ScalarLeafsTest extends ValidatorTestCase
{
// Validate: Scalar leafs
/**
* @see it('valid scalar selection')
*/
public function testValidScalarSelection() : void
{
$this->expectPassesRule(new ScalarLeafs, '
$this->expectPassesRule(
new ScalarLeafs(),
'
fragment scalarSelection on Dog {
barks
}
');
'
);
}
/**
@ -26,11 +31,23 @@ class ScalarLeafsTest extends ValidatorTestCase
*/
public function testObjectTypeMissingSelection() : void
{
$this->expectFailsRule(new ScalarLeafs, '
$this->expectFailsRule(
new ScalarLeafs(),
'
query directQueryOnObjectWithoutSubFields {
human
}
', [$this->missingObjSubselection('human', 'Human', 3, 9)]);
',
[$this->missingObjSubselection('human', 'Human', 3, 9)]
);
}
private function missingObjSubselection($field, $type, $line, $column)
{
return FormattedError::create(
ScalarLeafs::requiredSubselectionMessage($field, $type),
[new SourceLocation($line, $column)]
);
}
/**
@ -38,11 +55,15 @@ class ScalarLeafsTest extends ValidatorTestCase
*/
public function testInterfaceTypeMissingSelection() : void
{
$this->expectFailsRule(new ScalarLeafs, '
$this->expectFailsRule(
new ScalarLeafs(),
'
{
human { pets }
}
', [$this->missingObjSubselection('pets', '[Pet]', 3, 17)]);
',
[$this->missingObjSubselection('pets', '[Pet]', 3, 17)]
);
}
/**
@ -50,11 +71,14 @@ class ScalarLeafsTest extends ValidatorTestCase
*/
public function testValidScalarSelectionWithArgs() : void
{
$this->expectPassesRule(new ScalarLeafs, '
$this->expectPassesRule(
new ScalarLeafs(),
'
fragment scalarSelectionWithArgs on Dog {
doesKnowCommand(dogCommand: SIT)
}
');
'
);
}
/**
@ -62,12 +86,23 @@ class ScalarLeafsTest extends ValidatorTestCase
*/
public function testScalarSelectionNotAllowedOnBoolean() : void
{
$this->expectFailsRule(new ScalarLeafs, '
$this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedOnBoolean on Dog {
barks { sinceWhen }
}
',
[$this->noScalarSubselection('barks', 'Boolean', 3, 15)]);
[$this->noScalarSubselection('barks', 'Boolean', 3, 15)]
);
}
private function noScalarSubselection($field, $type, $line, $column)
{
return FormattedError::create(
ScalarLeafs::noSubselectionAllowedMessage($field, $type),
[new SourceLocation($line, $column)]
);
}
/**
@ -75,7 +110,9 @@ class ScalarLeafsTest extends ValidatorTestCase
*/
public function testScalarSelectionNotAllowedOnEnum() : void
{
$this->expectFailsRule(new ScalarLeafs, '
$this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedOnEnum on Cat {
furColor { inHexdec }
}
@ -89,7 +126,9 @@ class ScalarLeafsTest extends ValidatorTestCase
*/
public function testScalarSelectionNotAllowedWithArgs() : void
{
$this->expectFailsRule(new ScalarLeafs, '
$this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedWithArgs on Dog {
doesKnowCommand(dogCommand: SIT) { sinceWhen }
}
@ -103,7 +142,9 @@ class ScalarLeafsTest extends ValidatorTestCase
*/
public function testScalarSelectionNotAllowedWithDirectives() : void
{
$this->expectFailsRule(new ScalarLeafs, '
$this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedWithDirectives on Dog {
name @include(if: true) { isAlsoHumanName }
}
@ -117,7 +158,9 @@ class ScalarLeafsTest extends ValidatorTestCase
*/
public function testScalarSelectionNotAllowedWithDirectivesAndArgs() : void
{
$this->expectFailsRule(new ScalarLeafs, '
$this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedWithDirectivesAndArgs on Dog {
doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen }
}
@ -125,20 +168,4 @@ class ScalarLeafsTest extends ValidatorTestCase
[$this->noScalarSubselection('doesKnowCommand', 'Boolean', 3, 61)]
);
}
private function noScalarSubselection($field, $type, $line, $column)
{
return FormattedError::create(
ScalarLeafs::noSubselectionAllowedMessage($field, $type),
[new SourceLocation($line, $column)]
);
}
private function missingObjSubselection($field, $type, $line, $column)
{
return FormattedError::create(
ScalarLeafs::requiredSubselectionMessage($field, $type),
[new SourceLocation($line, $column)]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\UniqueArgumentNames;
class UniqueArgumentNamesTest extends ValidatorTestCase
{
// Validate: Unique argument names
/**
* @see it('no arguments on field')
*/
public function testNoArgumentsOnField() : void
{
$this->expectPassesRule(new UniqueArgumentNames(), '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
field
}
');
'
);
}
/**
@ -26,11 +31,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testNoArgumentsOnDirective() : void
{
$this->expectPassesRule(new UniqueArgumentNames, '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
field @directive
}
');
'
);
}
/**
@ -38,11 +46,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testArgumentOnField() : void
{
$this->expectPassesRule(new UniqueArgumentNames, '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
field(arg: "value")
}
');
'
);
}
/**
@ -50,11 +61,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testArgumentOnDirective() : void
{
$this->expectPassesRule(new UniqueArgumentNames, '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
field @directive(arg: "value")
}
');
'
);
}
/**
@ -62,12 +76,15 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testSameArgumentOnTwoFields() : void
{
$this->expectPassesRule(new UniqueArgumentNames, '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
one: field(arg: "value")
two: field(arg: "value")
}
');
'
);
}
/**
@ -75,11 +92,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testSameArgumentOnFieldAndDirective() : void
{
$this->expectPassesRule(new UniqueArgumentNames, '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
field(arg: "value") @directive(arg: "value")
}
');
'
);
}
/**
@ -87,11 +107,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testSameArgumentOnTwoDirectives() : void
{
$this->expectPassesRule(new UniqueArgumentNames, '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
field @directive1(arg: "value") @directive2(arg: "value")
}
');
'
);
}
/**
@ -99,11 +122,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testMultipleFieldArguments() : void
{
$this->expectPassesRule(new UniqueArgumentNames, '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
field(arg1: "value", arg2: "value", arg3: "value")
}
');
'
);
}
/**
@ -111,11 +137,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testMultipleDirectiveArguments() : void
{
$this->expectPassesRule(new UniqueArgumentNames, '
$this->expectPassesRule(
new UniqueArgumentNames(),
'
{
field @directive(arg1: "value", arg2: "value", arg3: "value")
}
');
'
);
}
/**
@ -123,57 +152,15 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/
public function testDuplicateFieldArguments() : void
{
$this->expectFailsRule(new UniqueArgumentNames, '
$this->expectFailsRule(
new UniqueArgumentNames(),
'
{
field(arg1: "value", arg1: "value")
}
', [
$this->duplicateArg('arg1', 3, 15, 3, 30)
]);
}
/**
* @see it('many duplicate field arguments')
*/
public function testManyDuplicateFieldArguments() : void
{
$this->expectFailsRule(new UniqueArgumentNames, '
{
field(arg1: "value", arg1: "value", arg1: "value")
}
', [
$this->duplicateArg('arg1', 3, 15, 3, 30),
$this->duplicateArg('arg1', 3, 15, 3, 45)
]);
}
/**
* @see it('duplicate directive arguments')
*/
public function testDuplicateDirectiveArguments() : void
{
$this->expectFailsRule(new UniqueArgumentNames, '
{
field @directive(arg1: "value", arg1: "value")
}
', [
$this->duplicateArg('arg1', 3, 26, 3, 41)
]);
}
/**
* @see it('many duplicate directive arguments')
*/
public function testManyDuplicateDirectiveArguments() : void
{
$this->expectFailsRule(new UniqueArgumentNames, '
{
field @directive(arg1: "value", arg1: "value", arg1: "value")
}
', [
$this->duplicateArg('arg1', 3, 26, 3, 41),
$this->duplicateArg('arg1', 3, 26, 3, 56)
]);
',
[$this->duplicateArg('arg1', 3, 15, 3, 30)]
);
}
private function duplicateArg($argName, $l1, $c1, $l2, $c2)
@ -183,4 +170,58 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
[new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)]
);
}
/**
* @see it('many duplicate field arguments')
*/
public function testManyDuplicateFieldArguments() : void
{
$this->expectFailsRule(
new UniqueArgumentNames(),
'
{
field(arg1: "value", arg1: "value", arg1: "value")
}
',
[
$this->duplicateArg('arg1', 3, 15, 3, 30),
$this->duplicateArg('arg1', 3, 15, 3, 45),
]
);
}
/**
* @see it('duplicate directive arguments')
*/
public function testDuplicateDirectiveArguments() : void
{
$this->expectFailsRule(
new UniqueArgumentNames(),
'
{
field @directive(arg1: "value", arg1: "value")
}
',
[$this->duplicateArg('arg1', 3, 26, 3, 41)]
);
}
/**
* @see it('many duplicate directive arguments')
*/
public function testManyDuplicateDirectiveArguments() : void
{
$this->expectFailsRule(
new UniqueArgumentNames(),
'
{
field @directive(arg1: "value", arg1: "value", arg1: "value")
}
',
[
$this->duplicateArg('arg1', 3, 26, 3, 41),
$this->duplicateArg('arg1', 3, 26, 3, 56),
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Validator\Rules\UniqueDirectivesPerLocation;
@ -10,11 +13,14 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/
public function testNoDirectives() : void
{
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
$this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type {
field
}
');
'
);
}
/**
@ -22,11 +28,14 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/
public function testUniqueDirectivesInDifferentLocations() : void
{
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
$this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type @directiveA {
field @directiveB
}
');
'
);
}
/**
@ -34,11 +43,14 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/
public function testUniqueDirectivesInSameLocations() : void
{
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
$this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type @directiveA @directiveB {
field @directiveA @directiveB
}
');
'
);
}
/**
@ -46,11 +58,14 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/
public function testSameDirectivesInDifferentLocations() : void
{
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
$this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type @directiveA {
field @directiveA
}
');
'
);
}
/**
@ -58,12 +73,15 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/
public function testSameDirectivesInSimilarLocations() : void
{
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
$this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type {
field @directive
field @directive
}
');
'
);
}
/**
@ -71,58 +89,15 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/
public function testDuplicateDirectivesInOneLocation() : void
{
$this->expectFailsRule(new UniqueDirectivesPerLocation(), '
$this->expectFailsRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type {
field @directive @directive
}
', [
$this->duplicateDirective('directive', 3, 15, 3, 26)
]);
}
/**
* @see it('many duplicate directives in one location')
*/
public function testManyDuplicateDirectivesInOneLocation() : void
{
$this->expectFailsRule(new UniqueDirectivesPerLocation(), '
fragment Test on Type {
field @directive @directive @directive
}
', [
$this->duplicateDirective('directive', 3, 15, 3, 26),
$this->duplicateDirective('directive', 3, 15, 3, 37)
]);
}
/**
* @see it('different duplicate directives in one location')
*/
public function testDifferentDuplicateDirectivesInOneLocation() : void
{
$this->expectFailsRule(new UniqueDirectivesPerLocation, '
fragment Test on Type {
field @directiveA @directiveB @directiveA @directiveB
}
', [
$this->duplicateDirective('directiveA', 3, 15, 3, 39),
$this->duplicateDirective('directiveB', 3, 27, 3, 51)
]);
}
/**
* @see it('duplicate directives in many locations')
*/
public function testDuplicateDirectivesInManyLocations() : void
{
$this->expectFailsRule(new UniqueDirectivesPerLocation(), '
fragment Test on Type @directive @directive {
field @directive @directive
}
', [
$this->duplicateDirective('directive', 2, 29, 2, 40),
$this->duplicateDirective('directive', 3, 15, 3, 26)
]);
',
[$this->duplicateDirective('directive', 3, 15, 3, 26)]
);
}
private function duplicateDirective($directiveName, $l1, $c1, $l2, $c2)
@ -131,8 +106,65 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
'message' => UniqueDirectivesPerLocation::duplicateDirectiveMessage($directiveName),
'locations' => [
['line' => $l1, 'column' => $c1],
['line' => $l2, 'column' => $c2]
]
['line' => $l2, 'column' => $c2],
],
];
}
/**
* @see it('many duplicate directives in one location')
*/
public function testManyDuplicateDirectivesInOneLocation() : void
{
$this->expectFailsRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type {
field @directive @directive @directive
}
',
[
$this->duplicateDirective('directive', 3, 15, 3, 26),
$this->duplicateDirective('directive', 3, 15, 3, 37),
]
);
}
/**
* @see it('different duplicate directives in one location')
*/
public function testDifferentDuplicateDirectivesInOneLocation() : void
{
$this->expectFailsRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type {
field @directiveA @directiveB @directiveA @directiveB
}
',
[
$this->duplicateDirective('directiveA', 3, 15, 3, 39),
$this->duplicateDirective('directiveB', 3, 27, 3, 51),
]
);
}
/**
* @see it('duplicate directives in many locations')
*/
public function testDuplicateDirectivesInManyLocations() : void
{
$this->expectFailsRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type @directive @directive {
field @directive @directive
}
',
[
$this->duplicateDirective('directive', 2, 29, 2, 40),
$this->duplicateDirective('directive', 3, 15, 3, 26),
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\UniqueFragmentNames;
class UniqueFragmentNamesTest extends ValidatorTestCase
{
// Validate: Unique fragment names
/**
* @see it('no fragments')
*/
public function testNoFragments() : void
{
$this->expectPassesRule(new UniqueFragmentNames(), '
$this->expectPassesRule(
new UniqueFragmentNames(),
'
{
field
}
');
'
);
}
/**
@ -26,7 +31,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/
public function testOneFragment() : void
{
$this->expectPassesRule(new UniqueFragmentNames, '
$this->expectPassesRule(
new UniqueFragmentNames(),
'
{
...fragA
}
@ -34,7 +41,8 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
fragment fragA on Type {
field
}
');
'
);
}
/**
@ -42,7 +50,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/
public function testManyFragments() : void
{
$this->expectPassesRule(new UniqueFragmentNames, '
$this->expectPassesRule(
new UniqueFragmentNames(),
'
{
...fragA
...fragB
@ -57,7 +67,8 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
fragment fragC on Type {
fieldC
}
');
'
);
}
/**
@ -65,7 +76,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/
public function testInlineFragmentsAreAlwaysUnique() : void
{
$this->expectPassesRule(new UniqueFragmentNames, '
$this->expectPassesRule(
new UniqueFragmentNames(),
'
{
...on Type {
fieldA
@ -74,7 +87,8 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
fieldB
}
}
');
'
);
}
/**
@ -82,14 +96,17 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/
public function testFragmentAndOperationNamedTheSame() : void
{
$this->expectPassesRule(new UniqueFragmentNames, '
$this->expectPassesRule(
new UniqueFragmentNames(),
'
query Foo {
...Foo
}
fragment Foo on Type {
field
}
');
'
);
}
/**
@ -97,7 +114,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/
public function testFragmentsNamedTheSame() : void
{
$this->expectFailsRule(new UniqueFragmentNames, '
$this->expectFailsRule(
new UniqueFragmentNames(),
'
{
...fragA
}
@ -107,26 +126,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
fragment fragA on Type {
fieldB
}
', [
$this->duplicateFrag('fragA', 5, 16, 8, 16)
]);
}
/**
* @see it('fragments named the same without being referenced')
*/
public function testFragmentsNamedTheSameWithoutBeingReferenced() : void
{
$this->expectFailsRule(new UniqueFragmentNames, '
fragment fragA on Type {
fieldA
}
fragment fragA on Type {
fieldB
}
', [
$this->duplicateFrag('fragA', 2, 16, 5, 16)
]);
',
[$this->duplicateFrag('fragA', 5, 16, 8, 16)]
);
}
private function duplicateFrag($fragName, $l1, $c1, $l2, $c2)
@ -136,4 +138,23 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
[new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)]
);
}
/**
* @see it('fragments named the same without being referenced')
*/
public function testFragmentsNamedTheSameWithoutBeingReferenced() : void
{
$this->expectFailsRule(
new UniqueFragmentNames(),
'
fragment fragA on Type {
fieldA
}
fragment fragA on Type {
fieldB
}
',
[$this->duplicateFrag('fragA', 2, 16, 5, 16)]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\UniqueInputFieldNames;
class UniqueInputFieldNamesTest extends ValidatorTestCase
{
// Validate: Unique input field names
/**
* @see it('input object with fields')
*/
public function testInputObjectWithFields() : void
{
$this->expectPassesRule(new UniqueInputFieldNames(), '
$this->expectPassesRule(
new UniqueInputFieldNames(),
'
{
field(arg: { f: true })
}
');
'
);
}
/**
@ -26,11 +31,14 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
*/
public function testSameInputObjectWithinTwoArgs() : void
{
$this->expectPassesRule(new UniqueInputFieldNames, '
$this->expectPassesRule(
new UniqueInputFieldNames(),
'
{
field(arg1: { f: true }, arg2: { f: true })
}
');
'
);
}
/**
@ -38,11 +46,14 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
*/
public function testMultipleInputObjectFields() : void
{
$this->expectPassesRule(new UniqueInputFieldNames, '
$this->expectPassesRule(
new UniqueInputFieldNames(),
'
{
field(arg: { f1: "value", f2: "value", f3: "value" })
}
');
'
);
}
/**
@ -50,7 +61,9 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
*/
public function testAllowsForNestedInputObjectsWithSimilarFields() : void
{
$this->expectPassesRule(new UniqueInputFieldNames, '
$this->expectPassesRule(
new UniqueInputFieldNames(),
'
{
field(arg: {
deep: {
@ -62,7 +75,8 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
id: 1
})
}
');
'
);
}
/**
@ -70,28 +84,15 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
*/
public function testDuplicateInputObjectFields() : void
{
$this->expectFailsRule(new UniqueInputFieldNames, '
$this->expectFailsRule(
new UniqueInputFieldNames(),
'
{
field(arg: { f1: "value", f1: "value" })
}
', [
$this->duplicateField('f1', 3, 22, 3, 35)
]);
}
/**
* @see it('many duplicate input object fields')
*/
public function testManyDuplicateInputObjectFields() : void
{
$this->expectFailsRule(new UniqueInputFieldNames, '
{
field(arg: { f1: "value", f1: "value", f1: "value" })
}
', [
$this->duplicateField('f1', 3, 22, 3, 35),
$this->duplicateField('f1', 3, 22, 3, 48)
]);
',
[$this->duplicateField('f1', 3, 22, 3, 35)]
);
}
private function duplicateField($name, $l1, $c1, $l2, $c2)
@ -101,4 +102,23 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
[new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)]
);
}
/**
* @see it('many duplicate input object fields')
*/
public function testManyDuplicateInputObjectFields() : void
{
$this->expectFailsRule(
new UniqueInputFieldNames(),
'
{
field(arg: { f1: "value", f1: "value", f1: "value" })
}
',
[
$this->duplicateField('f1', 3, 22, 3, 35),
$this->duplicateField('f1', 3, 22, 3, 48),
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\UniqueOperationNames;
class UniqueOperationNamesTest extends ValidatorTestCase
{
// Validate: Unique operation names
/**
* @see it('no operations')
*/
public function testNoOperations() : void
{
$this->expectPassesRule(new UniqueOperationNames(), '
$this->expectPassesRule(
new UniqueOperationNames(),
'
fragment fragA on Type {
field
}
');
'
);
}
/**
@ -26,11 +31,14 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/
public function testOneAnonOperation() : void
{
$this->expectPassesRule(new UniqueOperationNames, '
$this->expectPassesRule(
new UniqueOperationNames(),
'
{
field
}
');
'
);
}
/**
@ -38,11 +46,14 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/
public function testOneNamedOperation() : void
{
$this->expectPassesRule(new UniqueOperationNames, '
$this->expectPassesRule(
new UniqueOperationNames(),
'
query Foo {
field
}
');
'
);
}
/**
@ -50,7 +61,9 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/
public function testMultipleOperations() : void
{
$this->expectPassesRule(new UniqueOperationNames, '
$this->expectPassesRule(
new UniqueOperationNames(),
'
query Foo {
field
}
@ -58,7 +71,8 @@ class UniqueOperationNamesTest extends ValidatorTestCase
query Bar {
field
}
');
'
);
}
/**
@ -66,7 +80,9 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/
public function testMultipleOperationsOfDifferentTypes() : void
{
$this->expectPassesRule(new UniqueOperationNames, '
$this->expectPassesRule(
new UniqueOperationNames(),
'
query Foo {
field
}
@ -78,7 +94,8 @@ class UniqueOperationNamesTest extends ValidatorTestCase
subscription Baz {
field
}
');
'
);
}
/**
@ -86,14 +103,17 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/
public function testFragmentAndOperationNamedTheSame() : void
{
$this->expectPassesRule(new UniqueOperationNames, '
$this->expectPassesRule(
new UniqueOperationNames(),
'
query Foo {
...Foo
}
fragment Foo on Type {
field
}
');
'
);
}
/**
@ -101,50 +121,18 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/
public function testMultipleOperationsOfSameName() : void
{
$this->expectFailsRule(new UniqueOperationNames, '
$this->expectFailsRule(
new UniqueOperationNames(),
'
query Foo {
fieldA
}
query Foo {
fieldB
}
', [
$this->duplicateOp('Foo', 2, 13, 5, 13)
]);
}
/**
* @see it('multiple ops of same name of different types (mutation)')
*/
public function testMultipleOpsOfSameNameOfDifferentTypesMutation() : void
{
$this->expectFailsRule(new UniqueOperationNames, '
query Foo {
fieldA
}
mutation Foo {
fieldB
}
', [
$this->duplicateOp('Foo', 2, 13, 5, 16)
]);
}
/**
* @see it('multiple ops of same name of different types (subscription)')
*/
public function testMultipleOpsOfSameNameOfDifferentTypesSubscription() : void
{
$this->expectFailsRule(new UniqueOperationNames, '
query Foo {
fieldA
}
subscription Foo {
fieldB
}
', [
$this->duplicateOp('Foo', 2, 13, 5, 20)
]);
',
[$this->duplicateOp('Foo', 2, 13, 5, 13)]
);
}
private function duplicateOp($opName, $l1, $c1, $l2, $c2)
@ -154,4 +142,42 @@ class UniqueOperationNamesTest extends ValidatorTestCase
[new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)]
);
}
/**
* @see it('multiple ops of same name of different types (mutation)')
*/
public function testMultipleOpsOfSameNameOfDifferentTypesMutation() : void
{
$this->expectFailsRule(
new UniqueOperationNames(),
'
query Foo {
fieldA
}
mutation Foo {
fieldB
}
',
[$this->duplicateOp('Foo', 2, 13, 5, 16)]
);
}
/**
* @see it('multiple ops of same name of different types (subscription)')
*/
public function testMultipleOpsOfSameNameOfDifferentTypesSubscription() : void
{
$this->expectFailsRule(
new UniqueOperationNames(),
'
query Foo {
fieldA
}
subscription Foo {
fieldB
}
',
[$this->duplicateOp('Foo', 2, 13, 5, 20)]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,16 +11,18 @@ use GraphQL\Validator\Rules\UniqueVariableNames;
class UniqueVariableNamesTest extends ValidatorTestCase
{
// Validate: Unique variable names
/**
* @see it('unique variable names')
*/
public function testUniqueVariableNames() : void
{
$this->expectPassesRule(new UniqueVariableNames(), '
$this->expectPassesRule(
new UniqueVariableNames(),
'
query A($x: Int, $y: String) { __typename }
query B($x: String, $y: Int) { __typename }
');
'
);
}
/**
@ -25,16 +30,20 @@ class UniqueVariableNamesTest extends ValidatorTestCase
*/
public function testDuplicateVariableNames() : void
{
$this->expectFailsRule(new UniqueVariableNames, '
$this->expectFailsRule(
new UniqueVariableNames(),
'
query A($x: Int, $x: Int, $x: String) { __typename }
query B($x: String, $x: Int) { __typename }
query C($x: Int, $x: Int) { __typename }
', [
',
[
$this->duplicateVariable('x', 2, 16, 2, 25),
$this->duplicateVariable('x', 2, 16, 2, 34),
$this->duplicateVariable('x', 3, 16, 3, 28),
$this->duplicateVariable('x', 4, 16, 4, 25)
]);
$this->duplicateVariable('x', 4, 16, 4, 25),
]
);
}
private function duplicateVariable($name, $l1, $c1, $l2, $c2)

View File

@ -1,10 +1,12 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
class ValidationTest extends ValidatorTestCase
{
// Validate: Supports full validation
/**
* @see it('validates queries')
*/
@ -36,8 +38,8 @@ class ValidationTest extends ValidatorTestCase
';
$expectedError = [
'message' => "Expected type Invalid, found \"bad value\"; Invalid scalar is always invalid: bad value",
'locations' => [ ['line' => 3, 'column' => 25] ]
'message' => 'Expected type Invalid, found "bad value"; Invalid scalar is always invalid: bad value',
'locations' => [['line' => 3, 'column' => 25]],
];
$this->expectInvalid(
@ -54,7 +56,7 @@ class ValidationTest extends ValidatorTestCase
$expectedError = [
'message' => 'Cannot query field "invalid" on type "QueryRoot". Did you mean "invalidArg"?',
'locations' => [ ['line' => 1, 'column' => 2] ]
'locations' => [['line' => 1, 'column' => 2]],
];
$this->expectFailsCompleteValidation($query, [$expectedError]);
$this->expectValid($this->getTestSchema(), [], $query);

View File

@ -1,8 +1,10 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Language\Parser;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\CustomScalarType;
use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\EnumType;
@ -11,11 +13,27 @@ use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Schema;
use GraphQL\Validator\DocumentValidator;
use PHPUnit\Framework\TestCase;
use function array_map;
abstract class ValidatorTestCase extends TestCase
{
protected function expectPassesRule($rule, $queryString) : void
{
$this->expectValid(self::getTestSchema(), [$rule], $queryString);
}
protected function expectValid($schema, $rules, $queryString) : void
{
$this->assertEquals(
[],
DocumentValidator::validate($schema, Parser::parse($queryString), $rules),
'Should validate'
);
}
/**
* @return Schema
*/
@ -28,8 +46,8 @@ abstract class ValidatorTestCase extends TestCase
'fields' => [
'name' => [
'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]]
]
'args' => ['surname' => ['type' => Type::boolean()]],
],
],
]);
@ -38,8 +56,8 @@ abstract class ValidatorTestCase extends TestCase
'fields' => [
'name' => [
'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]]
]
'args' => ['surname' => ['type' => Type::boolean()]],
],
],
]);
@ -49,10 +67,10 @@ abstract class ValidatorTestCase extends TestCase
return [
'name' => [
'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]]
]
'args' => ['surname' => ['type' => Type::boolean()]],
],
];
}
},
]);
$DogCommand = new EnumType([
@ -60,8 +78,8 @@ abstract class ValidatorTestCase extends TestCase
'values' => [
'SIT' => ['value' => 0],
'HEEL' => ['value' => 1],
'DOWN' => ['value' => 2]
]
'DOWN' => ['value' => 2],
],
]);
$Dog = new ObjectType([
@ -69,25 +87,25 @@ abstract class ValidatorTestCase extends TestCase
'fields' => [
'name' => [
'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]]
'args' => ['surname' => ['type' => Type::boolean()]],
],
'nickname' => ['type' => Type::string()],
'barkVolume' => ['type' => Type::int()],
'barks' => ['type' => Type::boolean()],
'doesKnowCommand' => [
'type' => Type::boolean(),
'args' => ['dogCommand' => ['type' => $DogCommand]]
'args' => ['dogCommand' => ['type' => $DogCommand]],
],
'isHousetrained' => [
'type' => Type::boolean(),
'args' => ['atOtherHomes' => ['type' => Type::boolean(), 'defaultValue' => true]]
'args' => ['atOtherHomes' => ['type' => Type::boolean(), 'defaultValue' => true]],
],
'isAtLocation' => [
'type' => Type::boolean(),
'args' => ['x' => ['type' => Type::int()], 'y' => ['type' => Type::int()]]
]
'args' => ['x' => ['type' => Type::int()], 'y' => ['type' => Type::int()]],
],
'interfaces' => [$Being, $Pet, $Canine]
],
'interfaces' => [$Being, $Pet, $Canine],
]);
$Cat = new ObjectType([
@ -96,15 +114,15 @@ abstract class ValidatorTestCase extends TestCase
return [
'name' => [
'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]]
'args' => ['surname' => ['type' => Type::boolean()]],
],
'nickname' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()],
'meowVolume' => ['type' => Type::int()],
'furColor' => $FurColor
'furColor' => $FurColor,
];
},
'interfaces' => [$Being, $Pet]
'interfaces' => [$Being, $Pet],
]);
$CatOrDog = new UnionType([
@ -115,8 +133,8 @@ abstract class ValidatorTestCase extends TestCase
$Intelligent = new InterfaceType([
'name' => 'Intelligent',
'fields' => [
'iq' => ['type' => Type::int()]
]
'iq' => ['type' => Type::int()],
],
]);
$Human = null;
@ -127,13 +145,13 @@ abstract class ValidatorTestCase extends TestCase
return [
'name' => [
'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]]
'args' => ['surname' => ['type' => Type::boolean()]],
],
'pets' => ['type' => Type::listOf($Pet)],
'relatives' => ['type' => Type::listOf($Human)],
'iq' => ['type' => Type::int()]
'iq' => ['type' => Type::int()],
];
}
},
]);
$Alien = new ObjectType([
@ -143,10 +161,10 @@ abstract class ValidatorTestCase extends TestCase
'iq' => ['type' => Type::int()],
'name' => [
'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]]
'args' => ['surname' => ['type' => Type::boolean()]],
],
'numEyes' => ['type' => Type::int()],
],
'numEyes' => ['type' => Type::int()]
]
]);
$DogOrHuman = new UnionType([
@ -177,8 +195,8 @@ abstract class ValidatorTestCase extends TestCase
'intField' => ['type' => Type::int()],
'stringField' => ['type' => Type::string()],
'booleanField' => ['type' => Type::boolean()],
'stringListField' => ['type' => Type::listOf(Type::string())]
]
'stringListField' => ['type' => Type::listOf(Type::string())],
],
]);
$ComplicatedArgs = new ObjectType([
@ -266,7 +284,7 @@ abstract class ValidatorTestCase extends TestCase
],
],
],
]
],
]);
$invalidScalar = new CustomScalarType([
@ -300,7 +318,7 @@ abstract class ValidatorTestCase extends TestCase
'fields' => [
'human' => [
'args' => ['id' => ['type' => Type::id()]],
'type' => $Human
'type' => $Human,
],
'alien' => ['type' => $Alien],
'dog' => ['type' => $Dog],
@ -312,7 +330,7 @@ abstract class ValidatorTestCase extends TestCase
'complicatedArgs' => ['type' => $ComplicatedArgs],
'invalidArg' => [
'args' => [
'arg' => ['type' => $invalidScalar]
'arg' => ['type' => $invalidScalar],
],
'type' => Type::string(),
],
@ -320,7 +338,7 @@ abstract class ValidatorTestCase extends TestCase
'args' => ['arg' => ['type' => $anyScalar]],
'type' => Type::string(),
],
]
],
]);
$testSchema = new Schema([
@ -402,19 +420,16 @@ abstract class ValidatorTestCase extends TestCase
]),
],
]);
return $testSchema;
}
function expectValid($schema, $rules, $queryString)
protected function expectFailsRule($rule, $queryString, $errors)
{
$this->assertEquals(
[],
DocumentValidator::validate($schema, Parser::parse($queryString), $rules),
'Should validate'
);
return $this->expectInvalid(self::getTestSchema(), [$rule], $queryString, $errors);
}
function expectInvalid($schema, $rules, $queryString, $expectedErrors)
protected function expectInvalid($schema, $rules, $queryString, $expectedErrors)
{
$errors = DocumentValidator::validate($schema, Parser::parse($queryString), $rules);
@ -424,33 +439,23 @@ abstract class ValidatorTestCase extends TestCase
return $errors;
}
function expectPassesRule($rule, $queryString)
{
$this->expectValid($this->getTestSchema(), [$rule], $queryString);
}
function expectFailsRule($rule, $queryString, $errors)
{
return $this->expectInvalid($this->getTestSchema(), [$rule], $queryString, $errors);
}
function expectPassesRuleWithSchema($schema, $rule, $queryString)
protected function expectPassesRuleWithSchema($schema, $rule, $queryString) : void
{
$this->expectValid($schema, [$rule], $queryString);
}
function expectFailsRuleWithSchema($schema, $rule, $queryString, $errors)
protected function expectFailsRuleWithSchema($schema, $rule, $queryString, $errors) : void
{
$this->expectInvalid($schema, [$rule], $queryString, $errors);
}
function expectPassesCompleteValidation($queryString)
protected function expectPassesCompleteValidation($queryString) : void
{
$this->expectValid($this->getTestSchema(), DocumentValidator::allRules(), $queryString);
$this->expectValid(self::getTestSchema(), DocumentValidator::allRules(), $queryString);
}
function expectFailsCompleteValidation($queryString, $errors)
protected function expectFailsCompleteValidation($queryString, $errors) : void
{
$this->expectInvalid($this->getTestSchema(), DocumentValidator::allRules(), $queryString, $errors);
$this->expectInvalid(self::getTestSchema(), DocumentValidator::allRules(), $queryString, $errors);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\VariablesAreInputTypes;
class VariablesAreInputTypesTest extends ValidatorTestCase
{
// Validate: Variables are input types
/**
* @see it('input types are valid')
*/
public function testInputTypesAreValid() : void
{
$this->expectPassesRule(new VariablesAreInputTypes(), '
$this->expectPassesRule(
new VariablesAreInputTypes(),
'
query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) {
field(a: $a, b: $b, c: $c)
}
');
'
);
}
/**
@ -26,11 +31,14 @@ class VariablesAreInputTypesTest extends ValidatorTestCase
*/
public function testOutputTypesAreInvalid() : void
{
$this->expectFailsRule(new VariablesAreInputTypes, '
$this->expectFailsRule(
new VariablesAreInputTypes(),
'
query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) {
field(a: $a, b: $b, c: $c)
}
', [
',
[
FormattedError::create(
VariablesAreInputTypes::nonInputTypeOnVarMessage('a', 'Dog'),
[new SourceLocation(2, 21)]
@ -42,7 +50,7 @@ class VariablesAreInputTypesTest extends ValidatorTestCase
FormattedError::create(
VariablesAreInputTypes::nonInputTypeOnVarMessage('c', 'Pet'),
[new SourceLocation(2, 50)]
)
),
]
);
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -7,6 +10,95 @@ use GraphQL\Validator\Rules\VariablesDefaultValueAllowed;
class VariablesDefaultValueAllowedTest extends ValidatorTestCase
{
/**
* @see it('variables with no default values')
*/
public function testVariablesWithNoDefaultValues() : void
{
$this->expectPassesRule(
new VariablesDefaultValueAllowed(),
'
query NullableValues($a: Int, $b: String, $c: ComplexInput) {
dog { name }
}
'
);
}
// DESCRIBE: Validate: Variable default value is allowed
/**
* @see it('required variables without default values')
*/
public function testRequiredVariablesWithoutDefaultValues() : void
{
$this->expectPassesRule(
new VariablesDefaultValueAllowed(),
'
query RequiredValues($a: Int!, $b: String!) {
dog { name }
}
'
);
}
/**
* @see it('variables with valid default values')
*/
public function testVariablesWithValidDefaultValues() : void
{
$this->expectPassesRule(
new VariablesDefaultValueAllowed(),
'
query WithDefaultValues(
$a: Int = 1,
$b: String = "ok",
$c: ComplexInput = { requiredField: true, intField: 3 }
) {
dog { name }
}
'
);
}
/**
* @see it('variables with valid default null values')
*/
public function testVariablesWithValidDefaultNullValues() : void
{
$this->expectPassesRule(
new VariablesDefaultValueAllowed(),
'
query WithDefaultValues(
$a: Int = null,
$b: String = null,
$c: ComplexInput = { requiredField: true, intField: null }
) {
dog { name }
}
'
);
}
/**
* @see it('no required variables with default values')
*/
public function testNoRequiredVariablesWithDefaultValues() : void
{
$this->expectFailsRule(
new VariablesDefaultValueAllowed(),
'
query UnreachableDefaultValues($a: Int! = 3, $b: String! = "default") {
dog { name }
}
',
[
$this->defaultForRequiredVar('a', 'Int!', 'Int', 2, 49),
$this->defaultForRequiredVar('b', 'String!', 'String', 2, 66),
]
);
}
private function defaultForRequiredVar($varName, $typeName, $guessTypeName, $line, $column)
{
return FormattedError::create(
@ -19,91 +111,22 @@ class VariablesDefaultValueAllowedTest extends ValidatorTestCase
);
}
// DESCRIBE: Validate: Variable default value is allowed
/**
* @see it('variables with no default values')
*/
public function testVariablesWithNoDefaultValues() : void
{
$this->expectPassesRule(new VariablesDefaultValueAllowed(), '
query NullableValues($a: Int, $b: String, $c: ComplexInput) {
dog { name }
}
');
}
/**
* @see it('required variables without default values')
*/
public function testRequiredVariablesWithoutDefaultValues() : void
{
$this->expectPassesRule(new VariablesDefaultValueAllowed(), '
query RequiredValues($a: Int!, $b: String!) {
dog { name }
}
');
}
/**
* @see it('variables with valid default values')
*/
public function testVariablesWithValidDefaultValues() : void
{
$this->expectPassesRule(new VariablesDefaultValueAllowed(), '
query WithDefaultValues(
$a: Int = 1,
$b: String = "ok",
$c: ComplexInput = { requiredField: true, intField: 3 }
) {
dog { name }
}
');
}
/**
* @see it('variables with valid default null values')
*/
public function testVariablesWithValidDefaultNullValues() : void
{
$this->expectPassesRule(new VariablesDefaultValueAllowed(), '
query WithDefaultValues(
$a: Int = null,
$b: String = null,
$c: ComplexInput = { requiredField: true, intField: null }
) {
dog { name }
}
');
}
/**
* @see it('no required variables with default values')
*/
public function testNoRequiredVariablesWithDefaultValues() : void
{
$this->expectFailsRule(new VariablesDefaultValueAllowed(), '
query UnreachableDefaultValues($a: Int! = 3, $b: String! = "default") {
dog { name }
}
', [
$this->defaultForRequiredVar('a', 'Int!', 'Int', 2, 49),
$this->defaultForRequiredVar('b', 'String!', 'String', 2, 66),
]);
}
/**
* @see it('variables with invalid default null values')
*/
public function testNullIntoNullableType() : void
{
$this->expectFailsRule(new VariablesDefaultValueAllowed(), '
$this->expectFailsRule(
new VariablesDefaultValueAllowed(),
'
query WithDefaultValues($a: Int! = null, $b: String! = null) {
dog { name }
}
', [
',
[
$this->defaultForRequiredVar('a', 'Int!', 'Int', 2, 42),
$this->defaultForRequiredVar('b', 'String!', 'String', 2, 62),
]);
]
);
}
}

View File

@ -1,4 +1,7 @@
<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError;
@ -8,21 +11,23 @@ use GraphQL\Validator\Rules\VariablesInAllowedPosition;
class VariablesInAllowedPositionTest extends ValidatorTestCase
{
// Validate: Variables are in allowed positions
/**
* @see it('Boolean => Boolean')
*/
public function testBooleanXBoolean() : void
{
// Boolean => Boolean
$this->expectPassesRule(new VariablesInAllowedPosition(), '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($booleanArg: Boolean)
{
complicatedArgs {
booleanArgField(booleanArg: $booleanArg)
}
}
');
'
);
}
/**
@ -31,7 +36,9 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
public function testBooleanXBooleanWithinFragment() : void
{
// Boolean => Boolean within fragment
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
fragment booleanArgFrag on ComplicatedArgs {
booleanArgField(booleanArg: $booleanArg)
}
@ -41,9 +48,12 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
...booleanArgFrag
}
}
');
'
);
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($booleanArg: Boolean)
{
complicatedArgs {
@ -53,7 +63,8 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
fragment booleanArgFrag on ComplicatedArgs {
booleanArgField(booleanArg: $booleanArg)
}
');
'
);
}
/**
@ -62,14 +73,17 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
public function testBooleanNonNullXBoolean() : void
{
// Boolean! => Boolean
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($nonNullBooleanArg: Boolean!)
{
complicatedArgs {
booleanArgField(booleanArg: $nonNullBooleanArg)
}
}
');
'
);
}
/**
@ -78,7 +92,9 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
public function testBooleanNonNullXBooleanWithinFragment() : void
{
// Boolean! => Boolean within fragment
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
fragment booleanArgFrag on ComplicatedArgs {
booleanArgField(booleanArg: $nonNullBooleanArg)
}
@ -89,7 +105,8 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
...booleanArgFrag
}
}
');
'
);
}
/**
@ -98,14 +115,17 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
public function testIntXIntNonNullWithDefault() : void
{
// Int => Int! with default
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($intArg: Int = 1)
{
complicatedArgs {
nonNullIntArgField(nonNullIntArg: $intArg)
}
}
');
'
);
}
/**
@ -113,14 +133,17 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testListOfStringXListOfString() : void
{
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($stringListVar: [String])
{
complicatedArgs {
stringListArgField(stringListArg: $stringListVar)
}
}
');
'
);
}
/**
@ -128,14 +151,17 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testListOfStringNonNullXListOfString() : void
{
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($stringListVar: [String!])
{
complicatedArgs {
stringListArgField(stringListArg: $stringListVar)
}
}
');
'
);
}
/**
@ -143,14 +169,17 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testStringXListOfStringInItemPosition() : void
{
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($stringVar: String)
{
complicatedArgs {
stringListArgField(stringListArg: [$stringVar])
}
}
');
'
);
}
/**
@ -158,14 +187,17 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testStringNonNullXListOfStringInItemPosition() : void
{
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($stringVar: String!)
{
complicatedArgs {
stringListArgField(stringListArg: [$stringVar])
}
}
');
'
);
}
/**
@ -173,14 +205,17 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testComplexInputXComplexInput() : void
{
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($complexVar: ComplexInput)
{
complicatedArgs {
complexArgField(complexArg: $ComplexInput)
}
}
');
'
);
}
/**
@ -188,14 +223,17 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testComplexInputXComplexInputInFieldPosition() : void
{
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($boolVar: Boolean = false)
{
complicatedArgs {
complexArgField(complexArg: {requiredArg: $boolVar})
}
}
');
'
);
}
/**
@ -203,12 +241,15 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testBooleanNonNullXBooleanNonNullInDirective() : void
{
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($boolVar: Boolean!)
{
dog @include(if: $boolVar)
}
');
'
);
}
/**
@ -216,12 +257,15 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testBooleanXBooleanNonNullInDirectiveWithDefault() : void
{
$this->expectPassesRule(new VariablesInAllowedPosition, '
$this->expectPassesRule(
new VariablesInAllowedPosition(),
'
query Query($boolVar: Boolean = false)
{
dog @include(if: $boolVar)
}
');
'
);
}
/**
@ -229,18 +273,22 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testIntXIntNonNull() : void
{
$this->expectFailsRule(new VariablesInAllowedPosition, '
$this->expectFailsRule(
new VariablesInAllowedPosition(),
'
query Query($intArg: Int) {
complicatedArgs {
nonNullIntArgField(nonNullIntArg: $intArg)
}
}
', [
',
[
FormattedError::create(
VariablesInAllowedPosition::badVarPosMessage('intArg', 'Int', 'Int!'),
[new SourceLocation(2, 19), new SourceLocation(4, 45)]
)
]);
),
]
);
}
/**
@ -248,7 +296,9 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testIntXIntNonNullWithinFragment() : void
{
$this->expectFailsRule(new VariablesInAllowedPosition, '
$this->expectFailsRule(
new VariablesInAllowedPosition(),
'
fragment nonNullIntArgFieldFrag on ComplicatedArgs {
nonNullIntArgField(nonNullIntArg: $intArg)
}
@ -258,12 +308,14 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
...nonNullIntArgFieldFrag
}
}
', [
',
[
FormattedError::create(
VariablesInAllowedPosition::badVarPosMessage('intArg', 'Int', 'Int!'),
[new SourceLocation(6, 19), new SourceLocation(3, 43)]
)
]);
),
]
);
}
/**
@ -272,7 +324,9 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
public function testIntXIntNonNullWithinNestedFragment() : void
{
// Int => Int! within nested fragment
$this->expectFailsRule(new VariablesInAllowedPosition, '
$this->expectFailsRule(
new VariablesInAllowedPosition(),
'
fragment outerFrag on ComplicatedArgs {
...nonNullIntArgFieldFrag
}
@ -287,12 +341,14 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
...outerFrag
}
}
', [
',
[
FormattedError::create(
VariablesInAllowedPosition::badVarPosMessage('intArg', 'Int', 'Int!'),
[new SourceLocation(10, 19), new SourceLocation(7, 43)]
)
]);
),
]
);
}
/**
@ -300,18 +356,22 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testStringOverBoolean() : void
{
$this->expectFailsRule(new VariablesInAllowedPosition, '
$this->expectFailsRule(
new VariablesInAllowedPosition(),
'
query Query($stringVar: String) {
complicatedArgs {
booleanArgField(booleanArg: $stringVar)
}
}
', [
',
[
FormattedError::create(
VariablesInAllowedPosition::badVarPosMessage('stringVar', 'String', 'Boolean'),
[new SourceLocation(2, 19), new SourceLocation(4, 39)]
)
]);
),
]
);
}
/**
@ -319,18 +379,22 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testStringXListOfString() : void
{
$this->expectFailsRule(new VariablesInAllowedPosition, '
$this->expectFailsRule(
new VariablesInAllowedPosition(),
'
query Query($stringVar: String) {
complicatedArgs {
stringListArgField(stringListArg: $stringVar)
}
}
', [
',
[
FormattedError::create(
VariablesInAllowedPosition::badVarPosMessage('stringVar', 'String', '[String]'),
[new SourceLocation(2, 19), new SourceLocation(4, 45)]
)
]);
),
]
);
}
/**
@ -338,16 +402,20 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
*/
public function testBooleanXBooleanNonNullInDirective() : void
{
$this->expectFailsRule(new VariablesInAllowedPosition, '
$this->expectFailsRule(
new VariablesInAllowedPosition(),
'
query Query($boolVar: Boolean) {
dog @include(if: $boolVar)
}
', [
',
[
FormattedError::create(
VariablesInAllowedPosition::badVarPosMessage('boolVar', 'Boolean', 'Boolean!'),
[new SourceLocation(2, 19), new SourceLocation(3, 26)]
)
]);
),
]
);
}
/**
@ -356,16 +424,20 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
public function testStringXBooleanNonNullInDirective() : void
{
// String => Boolean! in directive
$this->expectFailsRule(new VariablesInAllowedPosition, '
$this->expectFailsRule(
new VariablesInAllowedPosition(),
'
query Query($stringVar: String) {
dog @include(if: $stringVar)
}
', [
',
[
FormattedError::create(
VariablesInAllowedPosition::badVarPosMessage('stringVar', 'String', 'Boolean!'),
[new SourceLocation(2, 19), new SourceLocation(3, 26)]
)
]);
),
]
);
}
/**
@ -374,7 +446,7 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
public function testStringArrayXStringNonNullArray() : void
{
$this->expectFailsRule(
new VariablesInAllowedPosition,
new VariablesInAllowedPosition(),
'
query Query($stringListVar: [String])
{
@ -382,11 +454,12 @@ class VariablesInAllowedPositionTest extends ValidatorTestCase
stringListNonNullArgField(stringListNonNullArg: $stringListVar)
}
}
', [
',
[
FormattedError::create(
VariablesInAllowedPosition::badVarPosMessage('stringListVar', '[String]', '[String!]'),
[new SourceLocation(2, 19), new SourceLocation(5, 59)]
)
),
]
);
}