Fix CS in tests/Validator

This commit is contained in:
Simon Podlipsky 2018-09-02 13:08:49 +02:00
parent ec54d6152b
commit caa50d6db9
No known key found for this signature in database
GPG Key ID: 725C2BD962B42663
33 changed files with 3694 additions and 2359 deletions

View File

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

View File

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

View File

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,18 +11,20 @@ use GraphQL\Validator\Rules\FieldsOnCorrectType;
class FieldsOnCorrectTypeTest extends ValidatorTestCase class FieldsOnCorrectTypeTest extends ValidatorTestCase
{ {
// Validate: Fields on correct type // Validate: Fields on correct type
/** /**
* @see it('Object field selection') * @see it('Object field selection')
*/ */
public function testObjectFieldSelection() : void public function testObjectFieldSelection() : void
{ {
$this->expectPassesRule(new FieldsOnCorrectType(), ' $this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment objectFieldSelection on Dog { fragment objectFieldSelection on Dog {
__typename __typename
name name
} }
'); '
);
} }
/** /**
@ -27,12 +32,15 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testAliasedObjectFieldSelection() : void public function testAliasedObjectFieldSelection() : void
{ {
$this->expectPassesRule(new FieldsOnCorrectType, ' $this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment aliasedObjectFieldSelection on Dog { fragment aliasedObjectFieldSelection on Dog {
tn : __typename tn : __typename
otherName : name otherName : name
} }
'); '
);
} }
/** /**
@ -40,12 +48,15 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testInterfaceFieldSelection() : void public function testInterfaceFieldSelection() : void
{ {
$this->expectPassesRule(new FieldsOnCorrectType, ' $this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment interfaceFieldSelection on Pet { fragment interfaceFieldSelection on Pet {
__typename __typename
name name
} }
'); '
);
} }
/** /**
@ -53,11 +64,14 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testAliasedInterfaceFieldSelection() : void public function testAliasedInterfaceFieldSelection() : void
{ {
$this->expectPassesRule(new FieldsOnCorrectType, ' $this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment interfaceFieldSelection on Pet { fragment interfaceFieldSelection on Pet {
otherName : name otherName : name
} }
'); '
);
} }
/** /**
@ -65,11 +79,14 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testLyingAliasSelection() : void public function testLyingAliasSelection() : void
{ {
$this->expectPassesRule(new FieldsOnCorrectType, ' $this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment lyingAliasSelection on Dog { fragment lyingAliasSelection on Dog {
name : nickname name : nickname
} }
'); '
);
} }
/** /**
@ -77,11 +94,14 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testIgnoresFieldsOnUnknownType() : void public function testIgnoresFieldsOnUnknownType() : void
{ {
$this->expectPassesRule(new FieldsOnCorrectType, ' $this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment unknownSelection on UnknownType { fragment unknownSelection on UnknownType {
unknownField unknownField
} }
'); '
);
} }
/** /**
@ -89,7 +109,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testReportsErrorsWhenTypeIsKnownAgain() : void public function testReportsErrorsWhenTypeIsKnownAgain() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment typeKnownAgain on Pet { fragment typeKnownAgain on Pet {
unknown_pet_field { unknown_pet_field {
... on Cat { ... on Cat {
@ -99,17 +121,27 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
}', }',
[ [
$this->undefinedField('unknown_pet_field', 'Pet', [], [], 3, 9), $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') * @see it('Field not defined on fragment')
*/ */
public function testFieldNotDefinedOnFragment() : void public function testFieldNotDefinedOnFragment() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment fieldNotDefined on Dog { fragment fieldNotDefined on Dog {
meowVolume meowVolume
}', }',
@ -122,7 +154,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testIgnoresDeeplyUnknownField() : void public function testIgnoresDeeplyUnknownField() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment deepFieldNotDefined on Dog { fragment deepFieldNotDefined on Dog {
unknown_field { unknown_field {
deeper_unknown_field deeper_unknown_field
@ -137,7 +171,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testSubFieldNotDefined() : void public function testSubFieldNotDefined() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment subFieldNotDefined on Human { fragment subFieldNotDefined on Human {
pets { pets {
unknown_field unknown_field
@ -152,7 +188,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testFieldNotDefinedOnInlineFragment() : void public function testFieldNotDefinedOnInlineFragment() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment fieldNotDefined on Pet { fragment fieldNotDefined on Pet {
... on Dog { ... on Dog {
meowVolume meowVolume
@ -167,7 +205,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testAliasedFieldTargetNotDefined() : void public function testAliasedFieldTargetNotDefined() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment aliasedFieldTargetNotDefined on Dog { fragment aliasedFieldTargetNotDefined on Dog {
volume : mooVolume volume : mooVolume
}', }',
@ -180,7 +220,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testAliasedLyingFieldTargetNotDefined() : void public function testAliasedLyingFieldTargetNotDefined() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment aliasedLyingFieldTargetNotDefined on Dog { fragment aliasedLyingFieldTargetNotDefined on Dog {
barkVolume : kawVolume barkVolume : kawVolume
}', }',
@ -193,7 +235,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testNotDefinedOnInterface() : void public function testNotDefinedOnInterface() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment notDefinedOnInterface on Pet { fragment notDefinedOnInterface on Pet {
tailLength tailLength
}', }',
@ -206,7 +250,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testDefinedOnImplmentorsButNotOnInterface() : void public function testDefinedOnImplmentorsButNotOnInterface() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment definedOnImplementorsButNotInterface on Pet { fragment definedOnImplementorsButNotInterface on Pet {
nickname nickname
}', }',
@ -219,7 +265,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testMetaFieldSelectionOnUnion() : void public function testMetaFieldSelectionOnUnion() : void
{ {
$this->expectPassesRule(new FieldsOnCorrectType, ' $this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment directFieldSelectionOnUnion on CatOrDog { fragment directFieldSelectionOnUnion on CatOrDog {
__typename __typename
}' }'
@ -231,7 +279,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testDirectFieldSelectionOnUnion() : void public function testDirectFieldSelectionOnUnion() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment directFieldSelectionOnUnion on CatOrDog { fragment directFieldSelectionOnUnion on CatOrDog {
directField directField
}', }',
@ -244,7 +294,9 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
*/ */
public function testDefinedOnImplementorsQueriedOnUnion() : void public function testDefinedOnImplementorsQueriedOnUnion() : void
{ {
$this->expectFailsRule(new FieldsOnCorrectType, ' $this->expectFailsRule(
new FieldsOnCorrectType(),
'
fragment definedOnImplementorsQueriedOnUnion on CatOrDog { fragment definedOnImplementorsQueriedOnUnion on CatOrDog {
name name
}', }',
@ -255,32 +307,39 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
[], [],
3, 3,
9 9
)] ),
]
); );
} }
// Describe: Fields on correct type error message
/** /**
* @see it('valid field in inline fragment') * @see it('valid field in inline fragment')
*/ */
public function testValidFieldInInlineFragment() : void public function testValidFieldInInlineFragment() : void
{ {
$this->expectPassesRule(new FieldsOnCorrectType, ' $this->expectPassesRule(
new FieldsOnCorrectType(),
'
fragment objectFieldSelection on Pet { fragment objectFieldSelection on Pet {
... on Dog { ... on Dog {
name name
} }
} }
'); '
);
} }
// Describe: Fields on correct type error message
/** /**
* @see it('Works with no suggestions') * @see it('Works with no suggestions')
*/ */
public function testWorksWithNoSuggestions() : void 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". ' . $expected = 'Cannot query field "f" on type "T". ' .
'Did you mean to use an inline fragment on "A", "B", "C", "D", or "E"?'; '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', 'f',
'T', 'T',
['A', 'B', 'C', 'D', 'E', 'F'], ['A', 'B', 'C', 'D', 'E', 'F'],
[] []
)); )
);
} }
/** /**
@ -340,19 +402,14 @@ class FieldsOnCorrectTypeTest extends ValidatorTestCase
$expected = 'Cannot query field "f" on type "T". ' . $expected = 'Cannot query field "f" on type "T". ' .
'Did you mean "z", "y", "x", "w", or "v"?'; 'Did you mean "z", "y", "x", "w", or "v"?';
$this->assertEquals($expected, FieldsOnCorrectType::undefinedFieldMessage( $this->assertEquals(
$expected,
FieldsOnCorrectType::undefinedFieldMessage(
'f', 'f',
'T', 'T',
[], [],
['z', 'y', 'x', 'w', 'v', 'u'] ['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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\FragmentsOnCompositeTypes;
class FragmentsOnCompositeTypesTest extends ValidatorTestCase class FragmentsOnCompositeTypesTest extends ValidatorTestCase
{ {
// Validate: Fragments on composite types // Validate: Fragments on composite types
/** /**
* @see it('object is valid fragment type') * @see it('object is valid fragment type')
*/ */
public function testObjectIsValidFragmentType() : void public function testObjectIsValidFragmentType() : void
{ {
$this->expectPassesRule(new FragmentsOnCompositeTypes, ' $this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on Dog { fragment validFragment on Dog {
barks barks
} }
'); '
);
} }
/** /**
@ -26,11 +31,14 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/ */
public function testInterfaceIsValidFragmentType() : void public function testInterfaceIsValidFragmentType() : void
{ {
$this->expectPassesRule(new FragmentsOnCompositeTypes, ' $this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on Pet { fragment validFragment on Pet {
name name
} }
'); '
);
} }
/** /**
@ -38,13 +46,16 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/ */
public function testObjectIsValidInlineFragmentType() : void public function testObjectIsValidInlineFragmentType() : void
{ {
$this->expectPassesRule(new FragmentsOnCompositeTypes, ' $this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on Pet { fragment validFragment on Pet {
... on Dog { ... on Dog {
barks barks
} }
} }
'); '
);
} }
/** /**
@ -52,13 +63,16 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/ */
public function testInlineFragmentWithoutTypeIsValid() : void public function testInlineFragmentWithoutTypeIsValid() : void
{ {
$this->expectPassesRule(new FragmentsOnCompositeTypes, ' $this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on Pet { fragment validFragment on Pet {
... { ... {
name name
} }
} }
'); '
);
} }
/** /**
@ -66,11 +80,14 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/ */
public function testUnionIsValidFragmentType() : void public function testUnionIsValidFragmentType() : void
{ {
$this->expectPassesRule(new FragmentsOnCompositeTypes, ' $this->expectPassesRule(
new FragmentsOnCompositeTypes(),
'
fragment validFragment on CatOrDog { fragment validFragment on CatOrDog {
__typename __typename
} }
'); '
);
} }
/** /**
@ -78,56 +95,14 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
*/ */
public function testScalarIsInvalidFragmentType() : void public function testScalarIsInvalidFragmentType() : void
{ {
$this->expectFailsRule(new FragmentsOnCompositeTypes, ' $this->expectFailsRule(
new FragmentsOnCompositeTypes(),
'
fragment scalarFragment on Boolean { fragment scalarFragment on Boolean {
bad bad
} }
', ',
[$this->error('scalarFragment', 'Boolean', 2, 34)]); [$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)]
)]
); );
} }
@ -138,4 +113,58 @@ class FragmentsOnCompositeTypesTest extends ValidatorTestCase
[new SourceLocation($line, $column)] [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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\KnownArgumentNames;
class KnownArgumentNamesTest extends ValidatorTestCase class KnownArgumentNamesTest extends ValidatorTestCase
{ {
// Validate: Known argument names: // Validate: Known argument names:
/** /**
* @see it('single arg is known') * @see it('single arg is known')
*/ */
public function testSingleArgIsKnown() : void public function testSingleArgIsKnown() : void
{ {
$this->expectPassesRule(new KnownArgumentNames, ' $this->expectPassesRule(
new KnownArgumentNames(),
'
fragment argOnRequiredArg on Dog { fragment argOnRequiredArg on Dog {
doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: SIT)
} }
'); '
);
} }
/** /**
@ -26,11 +31,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/ */
public function testMultipleArgsAreKnown() : void public function testMultipleArgsAreKnown() : void
{ {
$this->expectPassesRule(new KnownArgumentNames, ' $this->expectPassesRule(
new KnownArgumentNames(),
'
fragment multipleArgs on ComplicatedArgs { fragment multipleArgs on ComplicatedArgs {
multipleReqs(req1: 1, req2: 2) multipleReqs(req1: 1, req2: 2)
} }
'); '
);
} }
/** /**
@ -38,11 +46,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/ */
public function testIgnoresArgsOfUnknownFields() : void public function testIgnoresArgsOfUnknownFields() : void
{ {
$this->expectPassesRule(new KnownArgumentNames, ' $this->expectPassesRule(
new KnownArgumentNames(),
'
fragment argOnUnknownField on Dog { fragment argOnUnknownField on Dog {
unknownField(unknownArg: SIT) unknownField(unknownArg: SIT)
} }
'); '
);
} }
/** /**
@ -50,11 +61,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/ */
public function testMultipleArgsInReverseOrderAreKnown() : void public function testMultipleArgsInReverseOrderAreKnown() : void
{ {
$this->expectPassesRule(new KnownArgumentNames, ' $this->expectPassesRule(
new KnownArgumentNames(),
'
fragment multipleArgsReverseOrder on ComplicatedArgs { fragment multipleArgsReverseOrder on ComplicatedArgs {
multipleReqs(req2: 2, req1: 1) multipleReqs(req2: 2, req1: 1)
} }
'); '
);
} }
/** /**
@ -62,11 +76,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/ */
public function testNoArgsOnOptionalArg() : void public function testNoArgsOnOptionalArg() : void
{ {
$this->expectPassesRule(new KnownArgumentNames, ' $this->expectPassesRule(
new KnownArgumentNames(),
'
fragment noArgOnOptionalArg on Dog { fragment noArgOnOptionalArg on Dog {
isHousetrained isHousetrained
} }
'); '
);
} }
/** /**
@ -74,7 +91,9 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/ */
public function testArgsAreKnownDeeply() : void public function testArgsAreKnownDeeply() : void
{ {
$this->expectPassesRule(new KnownArgumentNames, ' $this->expectPassesRule(
new KnownArgumentNames(),
'
{ {
dog { dog {
doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: SIT)
@ -87,7 +106,8 @@ class KnownArgumentNamesTest extends ValidatorTestCase
} }
} }
} }
'); '
);
} }
/** /**
@ -95,11 +115,14 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/ */
public function testDirectiveArgsAreKnown() : void public function testDirectiveArgsAreKnown() : void
{ {
$this->expectPassesRule(new KnownArgumentNames, ' $this->expectPassesRule(
new KnownArgumentNames(),
'
{ {
dog @skip(if: true) dog @skip(if: true)
} }
'); '
);
} }
/** /**
@ -107,101 +130,16 @@ class KnownArgumentNamesTest extends ValidatorTestCase
*/ */
public function testUndirectiveArgsAreInvalid() : void public function testUndirectiveArgsAreInvalid() : void
{ {
$this->expectFailsRule(new KnownArgumentNames, ' $this->expectFailsRule(
new KnownArgumentNames(),
'
{ {
dog @skip(unless: true) dog @skip(unless: true)
} }
', [ ',
[
$this->unknownDirectiveArg('unless', 'skip', [], 3, 19), $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)] [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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,13 +11,14 @@ use GraphQL\Validator\Rules\KnownDirectives;
class KnownDirectivesTest extends ValidatorTestCase class KnownDirectivesTest extends ValidatorTestCase
{ {
// Validate: Known directives // Validate: Known directives
/** /**
* @see it('with no directives') * @see it('with no directives')
*/ */
public function testWithNoDirectives() : void public function testWithNoDirectives() : void
{ {
$this->expectPassesRule(new KnownDirectives, ' $this->expectPassesRule(
new KnownDirectives(),
'
query Foo { query Foo {
name name
...Frag ...Frag
@ -23,7 +27,8 @@ class KnownDirectivesTest extends ValidatorTestCase
fragment Frag on Dog { fragment Frag on Dog {
name name
} }
'); '
);
} }
/** /**
@ -31,7 +36,9 @@ class KnownDirectivesTest extends ValidatorTestCase
*/ */
public function testWithKnownDirectives() : void public function testWithKnownDirectives() : void
{ {
$this->expectPassesRule(new KnownDirectives, ' $this->expectPassesRule(
new KnownDirectives(),
'
{ {
dog @include(if: true) { dog @include(if: true) {
name name
@ -40,7 +47,8 @@ class KnownDirectivesTest extends ValidatorTestCase
name name
} }
} }
'); '
);
} }
/** /**
@ -48,15 +56,25 @@ class KnownDirectivesTest extends ValidatorTestCase
*/ */
public function testWithUnknownDirective() : void public function testWithUnknownDirective() : void
{ {
$this->expectFailsRule(new KnownDirectives, ' $this->expectFailsRule(
new KnownDirectives(),
'
{ {
dog @unknown(directive: "value") { dog @unknown(directive: "value") {
name 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 public function testWithManyUnknownDirectives() : void
{ {
$this->expectFailsRule(new KnownDirectives, ' $this->expectFailsRule(
new KnownDirectives(),
'
{ {
dog @unknown(directive: "value") { dog @unknown(directive: "value") {
name name
@ -76,11 +96,13 @@ class KnownDirectivesTest extends ValidatorTestCase
} }
} }
} }
', [ ',
[
$this->unknownDirective('unknown', 3, 13), $this->unknownDirective('unknown', 3, 13),
$this->unknownDirective('unknown', 6, 15), $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 public function testWithWellPlacedDirectives() : void
{ {
$this->expectPassesRule(new KnownDirectives, ' $this->expectPassesRule(
new KnownDirectives(),
'
query Foo @onQuery { query Foo @onQuery {
name @include(if: true) name @include(if: true)
...Frag @include(if: true) ...Frag @include(if: true)
@ -99,15 +123,20 @@ class KnownDirectivesTest extends ValidatorTestCase
mutation Bar @onMutation { mutation Bar @onMutation {
someField someField
} }
'); '
);
} }
// within schema language
/** /**
* @see it('with misplaced directives') * @see it('with misplaced directives')
*/ */
public function testWithMisplacedDirectives() : void public function testWithMisplacedDirectives() : void
{ {
$this->expectFailsRule(new KnownDirectives, ' $this->expectFailsRule(
new KnownDirectives(),
'
query Foo @include(if: true) { query Foo @include(if: true) {
name @onQuery name @onQuery
...Frag @onQuery ...Frag @onQuery
@ -116,22 +145,32 @@ class KnownDirectivesTest extends ValidatorTestCase
mutation Bar @onQuery { mutation Bar @onQuery {
someField someField
} }
', [ ',
[
$this->misplacedDirective('include', 'QUERY', 2, 17), $this->misplacedDirective('include', 'QUERY', 2, 17),
$this->misplacedDirective('onQuery', 'FIELD', 3, 14), $this->misplacedDirective('onQuery', 'FIELD', 3, 14),
$this->misplacedDirective('onQuery', 'FRAGMENT_SPREAD', 4, 17), $this->misplacedDirective('onQuery', 'FRAGMENT_SPREAD', 4, 17),
$this->misplacedDirective('onQuery', 'MUTATION', 7, 20), $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') * @see it('with well placed directives')
*/ */
public function testWSLWithWellPlacedDirectives() : void public function testWSLWithWellPlacedDirectives() : void
{ {
$this->expectPassesRule(new KnownDirectives, ' $this->expectPassesRule(
new KnownDirectives(),
'
type MyObj implements MyInterface @onObject { type MyObj implements MyInterface @onObject {
myField(myArg: Int @onArgumentDefinition): String @onFieldDefinition myField(myArg: Int @onArgumentDefinition): String @onFieldDefinition
} }
@ -167,7 +206,8 @@ class KnownDirectivesTest extends ValidatorTestCase
schema @onSchema { schema @onSchema {
query: MyQuery query: MyQuery
} }
'); '
);
} }
/** /**
@ -175,7 +215,9 @@ class KnownDirectivesTest extends ValidatorTestCase
*/ */
public function testWSLWithMisplacedDirectives() : void public function testWSLWithMisplacedDirectives() : void
{ {
$this->expectFailsRule(new KnownDirectives, ' $this->expectFailsRule(
new KnownDirectives(),
'
type MyObj implements MyInterface @onInterface { type MyObj implements MyInterface @onInterface {
myField(myArg: Int @onInputFieldDefinition): String @onInputFieldDefinition 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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Validator\Rules\KnownFragmentNames;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
use GraphQL\Language\SourceLocation; use GraphQL\Language\SourceLocation;
use GraphQL\Validator\Rules\KnownFragmentNames;
class KnownFragmentNamesTest extends ValidatorTestCase class KnownFragmentNamesTest extends ValidatorTestCase
{ {
// Validate: Known fragment names // Validate: Known fragment names
/** /**
* @see it('known fragment names are valid') * @see it('known fragment names are valid')
*/ */
public function testKnownFragmentNamesAreValid() : void public function testKnownFragmentNamesAreValid() : void
{ {
$this->expectPassesRule(new KnownFragmentNames, ' $this->expectPassesRule(
new KnownFragmentNames(),
'
{ {
human(id: 4) { human(id: 4) {
...HumanFields1 ...HumanFields1
@ -33,7 +37,8 @@ class KnownFragmentNamesTest extends ValidatorTestCase
fragment HumanFields3 on Human { fragment HumanFields3 on Human {
name name
} }
'); '
);
} }
/** /**
@ -41,7 +46,9 @@ class KnownFragmentNamesTest extends ValidatorTestCase
*/ */
public function testUnknownFragmentNamesAreInvalid() : void public function testUnknownFragmentNamesAreInvalid() : void
{ {
$this->expectFailsRule(new KnownFragmentNames, ' $this->expectFailsRule(
new KnownFragmentNames(),
'
{ {
human(id: 4) { human(id: 4) {
...UnknownFragment1 ...UnknownFragment1
@ -54,11 +61,13 @@ class KnownFragmentNamesTest extends ValidatorTestCase
name name
...UnknownFragment3 ...UnknownFragment3
} }
', [ ',
[
$this->undefFrag('UnknownFragment1', 4, 14), $this->undefFrag('UnknownFragment1', 4, 14),
$this->undefFrag('UnknownFragment2', 6, 16), $this->undefFrag('UnknownFragment2', 6, 16),
$this->undefFrag('UnknownFragment3', 12, 12) $this->undefFrag('UnknownFragment3', 12, 12),
]); ]
);
} }
private function undefFrag($fragName, $line, $column) private function undefFrag($fragName, $line, $column)

View File

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,13 +11,14 @@ use GraphQL\Validator\Rules\KnownTypeNames;
class KnownTypeNamesTest extends ValidatorTestCase class KnownTypeNamesTest extends ValidatorTestCase
{ {
// Validate: Known type names // Validate: Known type names
/** /**
* @see it('known type names are valid') * @see it('known type names are valid')
*/ */
public function testKnownTypeNamesAreValid() : void public function testKnownTypeNamesAreValid() : void
{ {
$this->expectPassesRule(new KnownTypeNames, ' $this->expectPassesRule(
new KnownTypeNames(),
'
query Foo($var: String, $required: [String!]!) { query Foo($var: String, $required: [String!]!) {
user(id: 4) { user(id: 4) {
pets { ... on Pet { name }, ...PetFields } pets { ... on Pet { name }, ...PetFields }
@ -23,7 +27,8 @@ class KnownTypeNamesTest extends ValidatorTestCase
fragment PetFields on Pet { fragment PetFields on Pet {
name name
} }
'); '
);
} }
/** /**
@ -31,7 +36,9 @@ class KnownTypeNamesTest extends ValidatorTestCase
*/ */
public function testUnknownTypeNamesAreInvalid() : void public function testUnknownTypeNamesAreInvalid() : void
{ {
$this->expectFailsRule(new KnownTypeNames, ' $this->expectFailsRule(
new KnownTypeNames(),
'
query Foo($var: JumbledUpLetters) { query Foo($var: JumbledUpLetters) {
user(id: 4) { user(id: 4) {
name name
@ -41,11 +48,21 @@ class KnownTypeNamesTest extends ValidatorTestCase
fragment PetFields on Peettt { fragment PetFields on Peettt {
name name
} }
', [ ',
[
$this->unknownType('JumbledUpLetters', [], 2, 23), $this->unknownType('JumbledUpLetters', [], 2, 23),
$this->unknownType('Badger', [], 5, 25), $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 public function testIgnoresTypeDefinitions() : void
{ {
$this->expectFailsRule(new KnownTypeNames, ' $this->expectFailsRule(
new KnownTypeNames(),
'
type NotInTheSchema { type NotInTheSchema {
field: FooBar field: FooBar
} }
@ -69,16 +88,10 @@ class KnownTypeNamesTest extends ValidatorTestCase
id id
} }
} }
', [ ',
[
$this->unknownType('NotInTheSchema', [], 12, 23), $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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\LoneAnonymousOperation;
class LoneAnonymousOperationTest extends ValidatorTestCase class LoneAnonymousOperationTest extends ValidatorTestCase
{ {
// Validate: Anonymous operation must be alone // Validate: Anonymous operation must be alone
/** /**
* @see it('no operations') * @see it('no operations')
*/ */
public function testNoOperations() : void public function testNoOperations() : void
{ {
$this->expectPassesRule(new LoneAnonymousOperation, ' $this->expectPassesRule(
new LoneAnonymousOperation(),
'
fragment fragA on Type { fragment fragA on Type {
field field
} }
'); '
);
} }
/** /**
@ -26,11 +31,14 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
*/ */
public function testOneAnonOperation() : void public function testOneAnonOperation() : void
{ {
$this->expectPassesRule(new LoneAnonymousOperation, ' $this->expectPassesRule(
new LoneAnonymousOperation(),
'
{ {
field field
} }
'); '
);
} }
/** /**
@ -38,7 +46,9 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
*/ */
public function testMultipleNamedOperations() : void public function testMultipleNamedOperations() : void
{ {
$this->expectPassesRule(new LoneAnonymousOperation, ' $this->expectPassesRule(
new LoneAnonymousOperation(),
'
query Foo { query Foo {
field field
} }
@ -46,7 +56,8 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
query Bar { query Bar {
field field
} }
'); '
);
} }
/** /**
@ -54,14 +65,17 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
*/ */
public function testAnonOperationWithFragment() : void public function testAnonOperationWithFragment() : void
{ {
$this->expectPassesRule(new LoneAnonymousOperation, ' $this->expectPassesRule(
new LoneAnonymousOperation(),
'
{ {
...Foo ...Foo
} }
fragment Foo on Type { fragment Foo on Type {
field field
} }
'); '
);
} }
/** /**
@ -69,51 +83,21 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
*/ */
public function testMultipleAnonOperations() : void public function testMultipleAnonOperations() : void
{ {
$this->expectFailsRule(new LoneAnonymousOperation, ' $this->expectFailsRule(
new LoneAnonymousOperation(),
'
{ {
fieldA fieldA
} }
{ {
fieldB fieldB
} }
', [ ',
[
$this->anonNotAlone(2, 7), $this->anonNotAlone(2, 7),
$this->anonNotAlone(5, 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)
]);
} }
private function anonNotAlone($line, $column) private function anonNotAlone($line, $column)
@ -122,6 +106,47 @@ class LoneAnonymousOperationTest extends ValidatorTestCase
LoneAnonymousOperation::anonOperationNotAloneMessage(), LoneAnonymousOperation::anonOperationNotAloneMessage(),
[new SourceLocation($line, $column)] [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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,16 +11,18 @@ use GraphQL\Validator\Rules\NoFragmentCycles;
class NoFragmentCyclesTest extends ValidatorTestCase class NoFragmentCyclesTest extends ValidatorTestCase
{ {
// Validate: No circular fragment spreads // Validate: No circular fragment spreads
/** /**
* @see it('single reference is valid') * @see it('single reference is valid')
*/ */
public function testSingleReferenceIsValid() : void public function testSingleReferenceIsValid() : void
{ {
$this->expectPassesRule(new NoFragmentCycles(), ' $this->expectPassesRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB } fragment fragA on Dog { ...fragB }
fragment fragB on Dog { name } fragment fragB on Dog { name }
'); '
);
} }
/** /**
@ -25,10 +30,13 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testSpreadingTwiceIsNotCircular() : void public function testSpreadingTwiceIsNotCircular() : void
{ {
$this->expectPassesRule(new NoFragmentCycles, ' $this->expectPassesRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB, ...fragB } fragment fragA on Dog { ...fragB, ...fragB }
fragment fragB on Dog { name } fragment fragB on Dog { name }
'); '
);
} }
/** /**
@ -36,11 +44,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testSpreadingTwiceIndirectlyIsNotCircular() : void public function testSpreadingTwiceIndirectlyIsNotCircular() : void
{ {
$this->expectPassesRule(new NoFragmentCycles, ' $this->expectPassesRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB, ...fragC } fragment fragA on Dog { ...fragB, ...fragC }
fragment fragB on Dog { ...fragC } fragment fragB on Dog { ...fragC }
fragment fragC on Dog { name } fragment fragC on Dog { name }
'); '
);
} }
/** /**
@ -48,7 +59,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testDoubleSpreadWithinAbstractTypes() : void public function testDoubleSpreadWithinAbstractTypes() : void
{ {
$this->expectPassesRule(new NoFragmentCycles, ' $this->expectPassesRule(
new NoFragmentCycles(),
'
fragment nameFragment on Pet { fragment nameFragment on Pet {
... on Dog { name } ... on Dog { name }
... on Cat { name } ... on Cat { name }
@ -58,7 +71,8 @@ class NoFragmentCyclesTest extends ValidatorTestCase
... on Dog { ...nameFragment } ... on Dog { ...nameFragment }
... on Cat { ...nameFragment } ... on Cat { ...nameFragment }
} }
'); '
);
} }
/** /**
@ -66,11 +80,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testDoesNotFalsePositiveOnUnknownFragment() : void public function testDoesNotFalsePositiveOnUnknownFragment() : void
{ {
$this->expectPassesRule(new NoFragmentCycles, ' $this->expectPassesRule(
new NoFragmentCycles(),
'
fragment nameFragment on Pet { fragment nameFragment on Pet {
...UnknownFragment ...UnknownFragment
} }
'); '
);
} }
/** /**
@ -78,11 +95,23 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testSpreadingRecursivelyWithinFieldFails() : void public function testSpreadingRecursivelyWithinFieldFails() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Human { relatives { ...fragA } }, 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 public function testNoSpreadingItselfDirectly() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragA } 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 public function testNoSpreadingItselfDirectlyWithinInlineFragment() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Pet { fragment fragA on Pet {
... on Dog { ... on Dog {
...fragA ...fragA
} }
} }
', [ ',
$this->cycleError('fragA', [], 4, 11) [
]); $this->cycleError('fragA', [], 4, 11),
]
);
} }
/** /**
@ -118,15 +155,19 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testNoSpreadingItselfIndirectly() : void public function testNoSpreadingItselfIndirectly() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB } fragment fragA on Dog { ...fragB }
fragment fragB on Dog { ...fragA } fragment fragB on Dog { ...fragA }
', [ ',
[
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']), NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']),
[new SourceLocation(2, 31), new SourceLocation(3, 31)] [new SourceLocation(2, 31), new SourceLocation(3, 31)]
) ),
]); ]
);
} }
/** /**
@ -134,15 +175,19 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testNoSpreadingItselfIndirectlyReportsOppositeOrder() : void public function testNoSpreadingItselfIndirectlyReportsOppositeOrder() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragB on Dog { ...fragA } fragment fragB on Dog { ...fragA }
fragment fragA on Dog { ...fragB } fragment fragA on Dog { ...fragB }
', [ ',
[
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragB', ['fragA']), NoFragmentCycles::cycleErrorMessage('fragB', ['fragA']),
[new SourceLocation(2, 31), new SourceLocation(3, 31)] [new SourceLocation(2, 31), new SourceLocation(3, 31)]
) ),
]); ]
);
} }
/** /**
@ -150,7 +195,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testNoSpreadingItselfIndirectlyWithinInlineFragment() : void public function testNoSpreadingItselfIndirectlyWithinInlineFragment() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Pet { fragment fragA on Pet {
... on Dog { ... on Dog {
...fragB ...fragB
@ -161,12 +208,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
...fragA ...fragA
} }
} }
', [ ',
[
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']), NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']),
[new SourceLocation(4, 11), new SourceLocation(9, 11)] [new SourceLocation(4, 11), new SourceLocation(9, 11)]
) ),
]); ]
);
} }
/** /**
@ -174,7 +223,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testNoSpreadingItselfDeeply() : void public function testNoSpreadingItselfDeeply() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB } fragment fragA on Dog { ...fragB }
fragment fragB on Dog { ...fragC } fragment fragB on Dog { ...fragC }
fragment fragC on Dog { ...fragO } fragment fragC on Dog { ...fragO }
@ -183,7 +234,8 @@ class NoFragmentCyclesTest extends ValidatorTestCase
fragment fragZ on Dog { ...fragO } fragment fragZ on Dog { ...fragO }
fragment fragO on Dog { ...fragP } fragment fragO on Dog { ...fragP }
fragment fragP on Dog { ...fragA, ...fragX } fragment fragP on Dog { ...fragA, ...fragX }
', [ ',
[
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragB', 'fragC', 'fragO', 'fragP']), NoFragmentCycles::cycleErrorMessage('fragA', ['fragB', 'fragC', 'fragO', 'fragP']),
[ [
@ -203,8 +255,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
new SourceLocation(6, 31), new SourceLocation(6, 31),
new SourceLocation(7, 31), new SourceLocation(7, 31),
] ]
) ),
]); ]
);
} }
/** /**
@ -212,11 +265,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testNoSpreadingItselfDeeplyTwoPaths() : void public function testNoSpreadingItselfDeeplyTwoPaths() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB, ...fragC } fragment fragA on Dog { ...fragB, ...fragC }
fragment fragB on Dog { ...fragA } fragment fragB on Dog { ...fragA }
fragment fragC on Dog { ...fragA } fragment fragC on Dog { ...fragA }
', [ ',
[
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']), NoFragmentCycles::cycleErrorMessage('fragA', ['fragB']),
[new SourceLocation(2, 31), new SourceLocation(3, 31)] [new SourceLocation(2, 31), new SourceLocation(3, 31)]
@ -224,8 +280,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragC']), NoFragmentCycles::cycleErrorMessage('fragA', ['fragC']),
[new SourceLocation(2, 41), new SourceLocation(4, 31)] [new SourceLocation(2, 41), new SourceLocation(4, 31)]
) ),
]); ]
);
} }
/** /**
@ -233,11 +290,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testNoSpreadingItselfDeeplyTwoPathsTraverseOrder() : void public function testNoSpreadingItselfDeeplyTwoPathsTraverseOrder() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragC } fragment fragA on Dog { ...fragC }
fragment fragB on Dog { ...fragC } fragment fragB on Dog { ...fragC }
fragment fragC on Dog { ...fragA, ...fragB } fragment fragC on Dog { ...fragA, ...fragB }
', [ ',
[
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragA', ['fragC']), NoFragmentCycles::cycleErrorMessage('fragA', ['fragC']),
[new SourceLocation(2, 31), new SourceLocation(4, 31)] [new SourceLocation(2, 31), new SourceLocation(4, 31)]
@ -245,8 +305,9 @@ class NoFragmentCyclesTest extends ValidatorTestCase
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragC', ['fragB']), NoFragmentCycles::cycleErrorMessage('fragC', ['fragB']),
[new SourceLocation(4, 41), new SourceLocation(3, 31)] [new SourceLocation(4, 41), new SourceLocation(3, 31)]
) ),
]); ]
);
} }
/** /**
@ -254,11 +315,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
*/ */
public function testNoSpreadingItselfDeeplyAndImmediately() : void public function testNoSpreadingItselfDeeplyAndImmediately() : void
{ {
$this->expectFailsRule(new NoFragmentCycles, ' $this->expectFailsRule(
new NoFragmentCycles(),
'
fragment fragA on Dog { ...fragB } fragment fragA on Dog { ...fragB }
fragment fragB on Dog { ...fragB, ...fragC } fragment fragB on Dog { ...fragB, ...fragC }
fragment fragC on Dog { ...fragA, ...fragB } fragment fragC on Dog { ...fragA, ...fragB }
', [ ',
[
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragB', []), NoFragmentCycles::cycleErrorMessage('fragB', []),
[new SourceLocation(3, 31)] [new SourceLocation(3, 31)]
@ -268,21 +332,14 @@ class NoFragmentCyclesTest extends ValidatorTestCase
[ [
new SourceLocation(2, 31), new SourceLocation(2, 31),
new SourceLocation(3, 41), new SourceLocation(3, 41),
new SourceLocation(4, 31) new SourceLocation(4, 31),
] ]
), ),
FormattedError::create( FormattedError::create(
NoFragmentCycles::cycleErrorMessage('fragB', ['fragC']), NoFragmentCycles::cycleErrorMessage('fragB', ['fragC']),
[new SourceLocation(3, 41), new SourceLocation(4, 41)] [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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\NoUndefinedVariables;
class NoUndefinedVariablesTest extends ValidatorTestCase class NoUndefinedVariablesTest extends ValidatorTestCase
{ {
// Validate: No undefined variables // Validate: No undefined variables
/** /**
* @see it('all variables defined') * @see it('all variables defined')
*/ */
public function testAllVariablesDefined() : void public function testAllVariablesDefined() : void
{ {
$this->expectPassesRule(new NoUndefinedVariables(), ' $this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
field(a: $a, b: $b, c: $c) field(a: $a, b: $b, c: $c)
} }
'); '
);
} }
/** /**
@ -26,7 +31,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/ */
public function testAllVariablesDeeplyDefined() : void public function testAllVariablesDeeplyDefined() : void
{ {
$this->expectPassesRule(new NoUndefinedVariables, ' $this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
field(a: $a) { field(a: $a) {
field(b: $b) { field(b: $b) {
@ -34,7 +41,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
} }
} }
} }
'); '
);
} }
/** /**
@ -42,7 +50,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/ */
public function testAllVariablesDeeplyInInlineFragmentsDefined() : void public function testAllVariablesDeeplyInInlineFragmentsDefined() : void
{ {
$this->expectPassesRule(new NoUndefinedVariables, ' $this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
... on Type { ... on Type {
field(a: $a) { field(a: $a) {
@ -54,7 +64,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
} }
} }
} }
'); '
);
} }
/** /**
@ -62,7 +73,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/ */
public function testAllVariablesInFragmentsDeeplyDefined() : void public function testAllVariablesInFragmentsDeeplyDefined() : void
{ {
$this->expectPassesRule(new NoUndefinedVariables, ' $this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
...FragA ...FragA
} }
@ -79,7 +92,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragC on Type { fragment FragC on Type {
field(c: $c) field(c: $c)
} }
'); '
);
} }
/** /**
@ -88,7 +102,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
public function testVariableWithinSingleFragmentDefinedInMultipleOperations() : void public function testVariableWithinSingleFragmentDefinedInMultipleOperations() : void
{ {
// variable within single fragment defined in multiple operations // variable within single fragment defined in multiple operations
$this->expectPassesRule(new NoUndefinedVariables, ' $this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String) { query Foo($a: String) {
...FragA ...FragA
} }
@ -98,7 +114,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragA on Type { fragment FragA on Type {
field(a: $a) field(a: $a)
} }
'); '
);
} }
/** /**
@ -106,7 +123,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/ */
public function testVariableWithinFragmentsDefinedInOperations() : void public function testVariableWithinFragmentsDefinedInOperations() : void
{ {
$this->expectPassesRule(new NoUndefinedVariables, ' $this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String) { query Foo($a: String) {
...FragA ...FragA
} }
@ -119,7 +138,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragB on Type { fragment FragB on Type {
field(b: $b) field(b: $b)
} }
'); '
);
} }
/** /**
@ -127,7 +147,9 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/ */
public function testVariableWithinRecursiveFragmentDefined() : void public function testVariableWithinRecursiveFragmentDefined() : void
{ {
$this->expectPassesRule(new NoUndefinedVariables, ' $this->expectPassesRule(
new NoUndefinedVariables(),
'
query Foo($a: String) { query Foo($a: String) {
...FragA ...FragA
} }
@ -136,7 +158,8 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
...FragA ...FragA
} }
} }
'); '
);
} }
/** /**
@ -144,13 +167,31 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
*/ */
public function testVariableNotDefined() : void public function testVariableNotDefined() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
field(a: $a, b: $b, c: $c, d: $d) 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 public function testVariableNotDefinedByUnNamedQuery() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
{ {
field(a: $a) 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 public function testMultipleVariablesNotDefined() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) { query Foo($b: String) {
field(a: $a, b: $b, c: $c) field(a: $a, b: $b, c: $c)
} }
', [ ',
[
$this->undefVar('a', 3, 18, 'Foo', 2, 7), $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 public function testVariableInFragmentNotDefinedByUnNamedQuery() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
{ {
...FragA ...FragA
} }
fragment FragA on Type { fragment FragA on Type {
field(a: $a) 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 public function testVariableInFragmentNotDefinedByOperation() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($a: String, $b: String) { query Foo($a: String, $b: String) {
...FragA ...FragA
} }
@ -221,9 +276,11 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragC on Type { fragment FragC on Type {
field(c: $c) 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 public function testMultipleVariablesInFragmentsNotDefined() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) { query Foo($b: String) {
...FragA ...FragA
} }
@ -248,10 +307,12 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragC on Type { fragment FragC on Type {
field(c: $c) field(c: $c)
} }
', [ ',
[
$this->undefVar('a', 6, 18, 'Foo', 2, 7), $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 public function testSingleVariableInFragmentNotDefinedByMultipleOperations() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($a: String) { query Foo($a: String) {
...FragAB ...FragAB
} }
@ -269,10 +332,12 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragAB on Type { fragment FragAB on Type {
field(a: $a, b: $b) field(a: $a, b: $b)
} }
', [ ',
[
$this->undefVar('b', 9, 25, 'Foo', 2, 7), $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 public function testVariablesInFragmentNotDefinedByMultipleOperations() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) { query Foo($b: String) {
...FragAB ...FragAB
} }
@ -290,10 +357,12 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragAB on Type { fragment FragAB on Type {
field(a: $a, b: $b) field(a: $a, b: $b)
} }
', [ ',
[
$this->undefVar('a', 9, 18, 'Foo', 2, 7), $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 public function testVariableInFragmentUsedByOtherOperation() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) { query Foo($b: String) {
...FragA ...FragA
} }
@ -314,10 +385,12 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragB on Type { fragment FragB on Type {
field(b: $b) field(b: $b)
} }
', [ ',
[
$this->undefVar('a', 9, 18, 'Foo', 2, 7), $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 public function testMultipleUndefinedVariablesProduceMultipleErrors() : void
{ {
$this->expectFailsRule(new NoUndefinedVariables, ' $this->expectFailsRule(
new NoUndefinedVariables(),
'
query Foo($b: String) { query Foo($b: String) {
...FragAB ...FragAB
} }
@ -340,28 +415,15 @@ class NoUndefinedVariablesTest extends ValidatorTestCase
fragment FragC on Type { fragment FragC on Type {
field2(c: $c) field2(c: $c)
} }
', [ ',
[
$this->undefVar('a', 9, 19, 'Foo', 2, 7), $this->undefVar('a', 9, 19, 'Foo', 2, 7),
$this->undefVar('a', 11, 19, 'Foo', 2, 7), $this->undefVar('a', 11, 19, 'Foo', 2, 7),
$this->undefVar('c', 14, 19, 'Foo', 2, 7), $this->undefVar('c', 14, 19, 'Foo', 2, 7),
$this->undefVar('b', 9, 26, 'Bar', 5, 7), $this->undefVar('b', 9, 26, 'Bar', 5, 7),
$this->undefVar('b', 11, 26, 'Bar', 5, 7), $this->undefVar('b', 11, 26, 'Bar', 5, 7),
$this->undefVar('c', 14, 19, '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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,13 +11,14 @@ use GraphQL\Validator\Rules\NoUnusedFragments;
class NoUnusedFragmentsTest extends ValidatorTestCase class NoUnusedFragmentsTest extends ValidatorTestCase
{ {
// Validate: No unused fragments // Validate: No unused fragments
/** /**
* @see it('all fragment names are used') * @see it('all fragment names are used')
*/ */
public function testAllFragmentNamesAreUsed() : void public function testAllFragmentNamesAreUsed() : void
{ {
$this->expectPassesRule(new NoUnusedFragments(), ' $this->expectPassesRule(
new NoUnusedFragments(),
'
{ {
human(id: 4) { human(id: 4) {
...HumanFields1 ...HumanFields1
@ -33,7 +37,8 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
fragment HumanFields3 on Human { fragment HumanFields3 on Human {
name name
} }
'); '
);
} }
/** /**
@ -41,7 +46,9 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
*/ */
public function testAllFragmentNamesAreUsedByMultipleOperations() : void public function testAllFragmentNamesAreUsedByMultipleOperations() : void
{ {
$this->expectPassesRule(new NoUnusedFragments, ' $this->expectPassesRule(
new NoUnusedFragments(),
'
query Foo { query Foo {
human(id: 4) { human(id: 4) {
...HumanFields1 ...HumanFields1
@ -62,7 +69,8 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
fragment HumanFields3 on Human { fragment HumanFields3 on Human {
name name
} }
'); '
);
} }
/** /**
@ -70,7 +78,9 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
*/ */
public function testContainsUnknownFragments() : void public function testContainsUnknownFragments() : void
{ {
$this->expectFailsRule(new NoUnusedFragments, ' $this->expectFailsRule(
new NoUnusedFragments(),
'
query Foo { query Foo {
human(id: 4) { human(id: 4) {
...HumanFields1 ...HumanFields1
@ -97,10 +107,20 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
fragment Unused2 on Human { fragment Unused2 on Human {
name name
} }
', [ ',
[
$this->unusedFrag('Unused1', 22, 7), $this->unusedFrag('Unused1', 22, 7),
$this->unusedFrag('Unused2', 25, 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 public function testContainsUnknownFragmentsWithRefCycle() : void
{ {
$this->expectFailsRule(new NoUnusedFragments, ' $this->expectFailsRule(
new NoUnusedFragments(),
'
query Foo { query Foo {
human(id: 4) { human(id: 4) {
...HumanFields1 ...HumanFields1
@ -137,10 +159,12 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
name name
...Unused1 ...Unused1
} }
', [ ',
[
$this->unusedFrag('Unused1', 22, 7), $this->unusedFrag('Unused1', 22, 7),
$this->unusedFrag('Unused2', 26, 7), $this->unusedFrag('Unused2', 26, 7),
]); ]
);
} }
/** /**
@ -148,8 +172,9 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
*/ */
public function testContainsUnknownAndUndefFragments() : void public function testContainsUnknownAndUndefFragments() : void
{ {
$this->expectFailsRule(
$this->expectFailsRule(new NoUnusedFragments, ' new NoUnusedFragments(),
'
query Foo { query Foo {
human(id: 4) { human(id: 4) {
...bar ...bar
@ -158,16 +183,10 @@ class NoUnusedFragmentsTest extends ValidatorTestCase
fragment foo on Human { fragment foo on Human {
name name
} }
', [ ',
[
$this->unusedFrag('foo', 7, 7), $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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\NoUnusedVariables;
class NoUnusedVariablesTest extends ValidatorTestCase class NoUnusedVariablesTest extends ValidatorTestCase
{ {
// Validate: No unused variables // Validate: No unused variables
/** /**
* @see it('uses all variables') * @see it('uses all variables')
*/ */
public function testUsesAllVariables() : void public function testUsesAllVariables() : void
{ {
$this->expectPassesRule(new NoUnusedVariables(), ' $this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
field(a: $a, b: $b, c: $c) field(a: $a, b: $b, c: $c)
} }
'); '
);
} }
/** /**
@ -26,7 +31,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/ */
public function testUsesAllVariablesDeeply() : void public function testUsesAllVariablesDeeply() : void
{ {
$this->expectPassesRule(new NoUnusedVariables, ' $this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
field(a: $a) { field(a: $a) {
field(b: $b) { field(b: $b) {
@ -34,7 +41,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
} }
} }
} }
'); '
);
} }
/** /**
@ -42,7 +50,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/ */
public function testUsesAllVariablesDeeplyInInlineFragments() : void public function testUsesAllVariablesDeeplyInInlineFragments() : void
{ {
$this->expectPassesRule(new NoUnusedVariables, ' $this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
... on Type { ... on Type {
field(a: $a) { field(a: $a) {
@ -54,7 +64,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
} }
} }
} }
'); '
);
} }
/** /**
@ -62,7 +73,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/ */
public function testUsesAllVariablesInFragments() : void public function testUsesAllVariablesInFragments() : void
{ {
$this->expectPassesRule(new NoUnusedVariables, ' $this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
...FragA ...FragA
} }
@ -79,7 +92,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragC on Type { fragment FragC on Type {
field(c: $c) field(c: $c)
} }
'); '
);
} }
/** /**
@ -87,7 +101,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/ */
public function testVariableUsedByFragmentInMultipleOperations() : void public function testVariableUsedByFragmentInMultipleOperations() : void
{ {
$this->expectPassesRule(new NoUnusedVariables, ' $this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String) { query Foo($a: String) {
...FragA ...FragA
} }
@ -100,7 +116,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragB on Type { fragment FragB on Type {
field(b: $b) field(b: $b)
} }
'); '
);
} }
/** /**
@ -108,7 +125,9 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/ */
public function testVariableUsedByRecursiveFragment() : void public function testVariableUsedByRecursiveFragment() : void
{ {
$this->expectPassesRule(new NoUnusedVariables, ' $this->expectPassesRule(
new NoUnusedVariables(),
'
query Foo($a: String) { query Foo($a: String) {
...FragA ...FragA
} }
@ -117,7 +136,8 @@ class NoUnusedVariablesTest extends ValidatorTestCase
...FragA ...FragA
} }
} }
'); '
);
} }
/** /**
@ -125,13 +145,25 @@ class NoUnusedVariablesTest extends ValidatorTestCase
*/ */
public function testVariableNotUsed() : void public function testVariableNotUsed() : void
{ {
$this->expectFailsRule(new NoUnusedVariables, ' $this->expectFailsRule(
new NoUnusedVariables(),
'
query ($a: String, $b: String, $c: String) { query ($a: String, $b: String, $c: String) {
field(a: $a, b: $b) 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 public function testMultipleVariablesNotUsed() : void
{ {
$this->expectFailsRule(new NoUnusedVariables, ' $this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
field(b: $b) field(b: $b)
} }
', [ ',
[
$this->unusedVar('a', 'Foo', 2, 17), $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 public function testVariableNotUsedInFragments() : void
{ {
$this->expectFailsRule(new NoUnusedVariables, ' $this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
...FragA ...FragA
} }
@ -171,9 +209,11 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragC on Type { fragment FragC on Type {
field 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 public function testMultipleVariablesNotUsed2() : void
{ {
$this->expectFailsRule(new NoUnusedVariables, ' $this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($a: String, $b: String, $c: String) { query Foo($a: String, $b: String, $c: String) {
...FragA ...FragA
} }
@ -198,10 +240,12 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragC on Type { fragment FragC on Type {
field field
} }
', [ ',
[
$this->unusedVar('a', 'Foo', 2, 17), $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 public function testVariableNotUsedByUnreferencedFragment() : void
{ {
$this->expectFailsRule(new NoUnusedVariables, ' $this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($b: String) { query Foo($b: String) {
...FragA ...FragA
} }
@ -219,9 +265,11 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragB on Type { fragment FragB on Type {
field(b: $b) 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 public function testVariableNotUsedByFragmentUsedByOtherOperation() : void
{ {
$this->expectFailsRule(new NoUnusedVariables, ' $this->expectFailsRule(
new NoUnusedVariables(),
'
query Foo($b: String) { query Foo($b: String) {
...FragA ...FragA
} }
@ -242,17 +292,11 @@ class NoUnusedVariablesTest extends ValidatorTestCase
fragment FragB on Type { fragment FragB on Type {
field(b: $b) field(b: $b)
} }
', [ ',
[
$this->unusedVar('b', 'Foo', 2, 17), $this->unusedVar('b', 'Foo', 2, 17),
$this->unusedVar('a', 'Bar', 5, 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)]
); );
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,16 +11,18 @@ use GraphQL\Validator\Rules\PossibleFragmentSpreads;
class PossibleFragmentSpreadsTest extends ValidatorTestCase class PossibleFragmentSpreadsTest extends ValidatorTestCase
{ {
// Validate: Possible fragment spreads // Validate: Possible fragment spreads
/** /**
* @see it('of the same object') * @see it('of the same object')
*/ */
public function testOfTheSameObject() : void public function testOfTheSameObject() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads(), ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment objectWithinObject on Dog { ...dogFragment } fragment objectWithinObject on Dog { ...dogFragment }
fragment dogFragment on Dog { barkVolume } fragment dogFragment on Dog { barkVolume }
'); '
);
} }
/** /**
@ -25,9 +30,12 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testOfTheSameObjectWithInlineFragment() : void public function testOfTheSameObjectWithInlineFragment() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } } fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } }
'); '
);
} }
/** /**
@ -35,10 +43,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testObjectIntoAnImplementedInterface() : void public function testObjectIntoAnImplementedInterface() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment objectWithinInterface on Pet { ...dogFragment } fragment objectWithinInterface on Pet { ...dogFragment }
fragment dogFragment on Dog { barkVolume } fragment dogFragment on Dog { barkVolume }
'); '
);
} }
/** /**
@ -46,10 +57,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testObjectIntoContainingUnion() : void public function testObjectIntoContainingUnion() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment objectWithinUnion on CatOrDog { ...dogFragment } fragment objectWithinUnion on CatOrDog { ...dogFragment }
fragment dogFragment on Dog { barkVolume } fragment dogFragment on Dog { barkVolume }
'); '
);
} }
/** /**
@ -57,10 +71,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testUnionIntoContainedObject() : void public function testUnionIntoContainedObject() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment unionWithinObject on Dog { ...catOrDogFragment } fragment unionWithinObject on Dog { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename } fragment catOrDogFragment on CatOrDog { __typename }
'); '
);
} }
/** /**
@ -68,10 +85,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testUnionIntoOverlappingInterface() : void public function testUnionIntoOverlappingInterface() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment unionWithinInterface on Pet { ...catOrDogFragment } fragment unionWithinInterface on Pet { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename } fragment catOrDogFragment on CatOrDog { __typename }
'); '
);
} }
/** /**
@ -79,10 +99,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testUnionIntoOverlappingUnion() : void public function testUnionIntoOverlappingUnion() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment } fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename } fragment catOrDogFragment on CatOrDog { __typename }
'); '
);
} }
/** /**
@ -90,10 +113,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testInterfaceIntoImplementedObject() : void public function testInterfaceIntoImplementedObject() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment interfaceWithinObject on Dog { ...petFragment } fragment interfaceWithinObject on Dog { ...petFragment }
fragment petFragment on Pet { name } fragment petFragment on Pet { name }
'); '
);
} }
/** /**
@ -101,10 +127,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testInterfaceIntoOverlappingInterface() : void public function testInterfaceIntoOverlappingInterface() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment interfaceWithinInterface on Pet { ...beingFragment } fragment interfaceWithinInterface on Pet { ...beingFragment }
fragment beingFragment on Being { name } fragment beingFragment on Being { name }
'); '
);
} }
/** /**
@ -112,9 +141,12 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testInterfaceIntoOverlappingInterfaceInInlineFragment() : void public function testInterfaceIntoOverlappingInterfaceInInlineFragment() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment interfaceWithinInterface on Pet { ... on Being { name } } fragment interfaceWithinInterface on Pet { ... on Being { name } }
'); '
);
} }
/** /**
@ -122,10 +154,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testInterfaceIntoOverlappingUnion() : void public function testInterfaceIntoOverlappingUnion() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment interfaceWithinUnion on CatOrDog { ...petFragment } fragment interfaceWithinUnion on CatOrDog { ...petFragment }
fragment petFragment on Pet { name } fragment petFragment on Pet { name }
'); '
);
} }
/** /**
@ -133,10 +168,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testIgnoresIncorrectTypeCaughtByFragmentsOnCompositeTypes() : void public function testIgnoresIncorrectTypeCaughtByFragmentsOnCompositeTypes() : void
{ {
$this->expectPassesRule(new PossibleFragmentSpreads, ' $this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment petFragment on Pet { ...badInADifferentWay } fragment petFragment on Pet { ...badInADifferentWay }
fragment badInADifferentWay on String { name } fragment badInADifferentWay on String { name }
'); '
);
} }
/** /**
@ -144,7 +182,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testDifferentObjectIntoObject() : void public function testDifferentObjectIntoObject() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidObjectWithinObject on Cat { ...dogFragment } fragment invalidObjectWithinObject on Cat { ...dogFragment }
fragment dogFragment on Dog { barkVolume } 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') * @see it('different object into object in inline fragment')
*/ */
public function testDifferentObjectIntoObjectInInlineFragment() : void public function testDifferentObjectIntoObjectInInlineFragment() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidObjectWithinObjectAnon on Cat { fragment invalidObjectWithinObjectAnon on Cat {
... on Dog { barkVolume } ... 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') * @see it('object into not implementing interface')
*/ */
public function testObjectIntoNotImplementingInterface() : void public function testObjectIntoNotImplementingInterface() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidObjectWithinInterface on Pet { ...humanFragment } fragment invalidObjectWithinInterface on Pet { ...humanFragment }
fragment humanFragment on Human { pets { name } } fragment humanFragment on Human { pets { name } }
', ',
@ -184,7 +244,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testObjectIntoNotContainingUnion() : void public function testObjectIntoNotContainingUnion() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment } fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment }
fragment humanFragment on Human { pets { name } } fragment humanFragment on Human { pets { name } }
', ',
@ -197,7 +259,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testUnionIntoNotContainedObject() : void public function testUnionIntoNotContainedObject() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidUnionWithinObject on Human { ...catOrDogFragment } fragment invalidUnionWithinObject on Human { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename } fragment catOrDogFragment on CatOrDog { __typename }
', ',
@ -210,7 +274,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testUnionIntoNonOverlappingInterface() : void public function testUnionIntoNonOverlappingInterface() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment } fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment }
fragment humanOrAlienFragment on HumanOrAlien { __typename } fragment humanOrAlienFragment on HumanOrAlien { __typename }
', ',
@ -223,7 +289,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testUnionIntoNonOverlappingUnion() : void public function testUnionIntoNonOverlappingUnion() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment } fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment }
fragment humanOrAlienFragment on HumanOrAlien { __typename } fragment humanOrAlienFragment on HumanOrAlien { __typename }
', ',
@ -236,7 +304,9 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testInterfaceIntoNonImplementingObject() : void public function testInterfaceIntoNonImplementingObject() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment } fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment }
fragment intelligentFragment on Intelligent { iq } 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 // 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: // 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 { fragment invalidInterfaceWithinInterface on Pet {
...intelligentFragment ...intelligentFragment
} }
fragment intelligentFragment on Intelligent { iq } 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 // 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: // 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 { fragment invalidInterfaceWithinInterfaceAnon on Pet {
...on Intelligent { iq } ...on Intelligent { iq }
} }
'); '
);
} }
/** /**
@ -280,27 +356,13 @@ class PossibleFragmentSpreadsTest extends ValidatorTestCase
*/ */
public function testInterfaceIntoNonOverlappingUnion() : void public function testInterfaceIntoNonOverlappingUnion() : void
{ {
$this->expectFailsRule(new PossibleFragmentSpreads, ' $this->expectFailsRule(
new PossibleFragmentSpreads(),
'
fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment } fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment }
fragment petFragment on Pet { name } fragment petFragment on Pet { name }
', ',
[$this->error('petFragment', 'HumanOrAlien', 'Pet', 2, 62)] [$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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,20 +11,22 @@ use GraphQL\Validator\Rules\ProvidedNonNullArguments;
class ProvidedNonNullArgumentsTest extends ValidatorTestCase class ProvidedNonNullArgumentsTest extends ValidatorTestCase
{ {
// Validate: Provided required arguments // Validate: Provided required arguments
/** /**
* @see it('ignores unknown arguments') * @see it('ignores unknown arguments')
*/ */
public function testIgnoresUnknownArguments() : void public function testIgnoresUnknownArguments() : void
{ {
// ignores unknown arguments // ignores unknown arguments
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
dog { dog {
isHousetrained(unknownArgument: true) isHousetrained(unknownArgument: true)
} }
} }
'); '
);
} }
// Valid non-nullable value: // Valid non-nullable value:
@ -31,13 +36,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testArgOnOptionalArg() : void public function testArgOnOptionalArg() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
dog { dog {
isHousetrained(atOtherHomes: true) isHousetrained(atOtherHomes: true)
} }
} }
'); '
);
} }
/** /**
@ -45,13 +53,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testNoArgOnOptionalArg() : void public function testNoArgOnOptionalArg() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
dog { dog {
isHousetrained isHousetrained
} }
} }
'); '
);
} }
/** /**
@ -59,13 +70,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testMultipleArgs() : void public function testMultipleArgs() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleReqs(req1: 1, req2: 2) multipleReqs(req1: 1, req2: 2)
} }
} }
'); '
);
} }
/** /**
@ -73,13 +87,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testMultipleArgsReverseOrder() : void public function testMultipleArgsReverseOrder() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleReqs(req2: 2, req1: 1) multipleReqs(req2: 2, req1: 1)
} }
} }
'); '
);
} }
/** /**
@ -87,13 +104,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testNoArgsOnMultipleOptional() : void public function testNoArgsOnMultipleOptional() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleOpts multipleOpts
} }
} }
'); '
);
} }
/** /**
@ -101,13 +121,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testOneArgOnMultipleOptional() : void public function testOneArgOnMultipleOptional() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleOpts(opt1: 1) multipleOpts(opt1: 1)
} }
} }
'); '
);
} }
/** /**
@ -115,13 +138,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testSecondArgOnMultipleOptional() : void public function testSecondArgOnMultipleOptional() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleOpts(opt2: 1) multipleOpts(opt2: 1)
} }
} }
'); '
);
} }
/** /**
@ -129,13 +155,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testMultipleReqsOnMixedList() : void public function testMultipleReqsOnMixedList() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleOptAndReq(req1: 3, req2: 4) multipleOptAndReq(req1: 3, req2: 4)
} }
} }
'); '
);
} }
/** /**
@ -143,13 +172,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testMultipleReqsAndOneOptOnMixedList() : void public function testMultipleReqsAndOneOptOnMixedList() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleOptAndReq(req1: 3, req2: 4, opt1: 5) multipleOptAndReq(req1: 3, req2: 4, opt1: 5)
} }
} }
'); '
);
} }
/** /**
@ -157,13 +189,16 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testAllReqsAndOptsOnMixedList() : void public function testAllReqsAndOptsOnMixedList() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6) multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6)
} }
} }
'); '
);
} }
// Invalid non-nullable value // Invalid non-nullable value
@ -173,15 +208,25 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testMissingOneNonNullableArgument() : void public function testMissingOneNonNullableArgument() : void
{ {
$this->expectFailsRule(new ProvidedNonNullArguments, ' $this->expectFailsRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleReqs(req2: 2) 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 public function testMissingMultipleNonNullableArguments() : void
{ {
$this->expectFailsRule(new ProvidedNonNullArguments, ' $this->expectFailsRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleReqs multipleReqs
} }
} }
', [ ',
[
$this->missingFieldArg('multipleReqs', 'req1', 'Int!', 4, 13), $this->missingFieldArg('multipleReqs', 'req1', 'Int!', 4, 13),
$this->missingFieldArg('multipleReqs', 'req2', 'Int!', 4, 13), $this->missingFieldArg('multipleReqs', 'req2', 'Int!', 4, 13),
]); ]
);
} }
// Describe: Directive arguments
/** /**
* @see it('Incorrect value and missing argument') * @see it('Incorrect value and missing argument')
*/ */
public function testIncorrectValueAndMissingArgument() : void public function testIncorrectValueAndMissingArgument() : void
{ {
$this->expectFailsRule(new ProvidedNonNullArguments, ' $this->expectFailsRule(
new ProvidedNonNullArguments(),
'
{ {
complicatedArgs { complicatedArgs {
multipleReqs(req1: "one") multipleReqs(req1: "one")
} }
} }
', [ ',
[
$this->missingFieldArg('multipleReqs', 'req2', 'Int!', 4, 13), $this->missingFieldArg('multipleReqs', 'req2', 'Int!', 4, 13),
]); ]
);
} }
// Describe: Directive arguments
/** /**
* @see it('ignores unknown directives') * @see it('ignores unknown directives')
*/ */
public function testIgnoresUnknownDirectives() : void public function testIgnoresUnknownDirectives() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
dog @unknown dog @unknown
} }
'); '
);
} }
/** /**
@ -236,7 +292,9 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testWithDirectivesOfValidTypes() : void public function testWithDirectivesOfValidTypes() : void
{ {
$this->expectPassesRule(new ProvidedNonNullArguments, ' $this->expectPassesRule(
new ProvidedNonNullArguments(),
'
{ {
dog @include(if: true) { dog @include(if: true) {
name name
@ -245,7 +303,8 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
name name
} }
} }
'); '
);
} }
/** /**
@ -253,23 +312,19 @@ class ProvidedNonNullArgumentsTest extends ValidatorTestCase
*/ */
public function testWithDirectiveWithMissingTypes() : void public function testWithDirectiveWithMissingTypes() : void
{ {
$this->expectFailsRule(new ProvidedNonNullArguments, ' $this->expectFailsRule(
new ProvidedNonNullArguments(),
'
{ {
dog @include { dog @include {
name @skip name @skip
} }
} }
', [ ',
[
$this->missingDirectiveArg('include', 'if', 'Boolean!', 3, 15), $this->missingDirectiveArg('include', 'if', 'Boolean!', 3, 15),
$this->missingDirectiveArg('skip', 'if', 'Boolean!', 4, 18) $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)]
); );
} }

View File

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

View File

@ -1,35 +1,19 @@
<?php <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Validator\Rules\QueryDepth; use GraphQL\Validator\Rules\QueryDepth;
use function sprintf;
use function str_replace;
class QueryDepthTest extends QuerySecurityTestCase class QueryDepthTest extends QuerySecurityTestCase
{ {
/** /**
* @param $max * @param int $queryDepth
* @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 $maxQueryDepth * @param int $maxQueryDepth
* @param array $expectedErrors * @param string[][] $expectedErrors
* @dataProvider queryDataProvider * @dataProvider queryDataProvider
*/ */
public function testSimpleQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void public function testSimpleQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void
@ -37,26 +21,81 @@ class QueryDepthTest extends QuerySecurityTestCase
$this->assertDocumentValidator($this->buildRecursiveQuery($queryDepth), $maxQueryDepth, $expectedErrors); $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 int $maxQueryDepth
* @param array $expectedErrors * @param string[][] $expectedErrors
* @dataProvider queryDataProvider * @dataProvider queryDataProvider
*/ */
public function testFragmentQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void 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 int $maxQueryDepth
* @param array $expectedErrors * @param string[][] $expectedErrors
* @dataProvider queryDataProvider * @dataProvider queryDataProvider
*/ */
public function testInlineFragmentQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void 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 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 QueryDepth::maxQueryDepthErrorMessage($max, $count);
return $query;
} }
private function buildRecursiveUsingFragmentQuery($depth) /**
* @param int $maxDepth
*
* @return QueryDepth
*/
protected function getRule($maxDepth)
{ {
$query = sprintf( return new QueryDepth($maxDepth);
'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;
} }
} }

View File

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

View File

@ -1,30 +1,20 @@
<?php <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\Error;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
use GraphQL\Type\Introspection; use GraphQL\Type\Introspection;
use GraphQL\Validator\DocumentValidator; use GraphQL\Validator\DocumentValidator;
use GraphQL\Validator\Rules\QuerySecurityRule; use GraphQL\Validator\Rules\QuerySecurityRule;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use function array_map;
abstract class QuerySecurityTestCase extends TestCase 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 * @expectedException \InvalidArgumentException
* @expectedExceptionMessage argument must be greater or equal to 0. * @expectedExceptionMessage argument must be greater or equal to 0.
@ -34,23 +24,12 @@ abstract class QuerySecurityTestCase extends TestCase
$this->getRule(-1); $this->getRule(-1);
} }
protected function createFormattedError($max, $count, $locations = []) /**
{ * @param int $max
return FormattedError::create($this->getErrorMessage($max, $count), $locations); *
} * @return QuerySecurityRule
*/
protected function assertDocumentValidator($queryString, $max, array $expectedErrors = []) abstract protected function getRule($max);
{
$errors = DocumentValidator::validate(
QuerySecuritySchema::buildSchema(),
Parser::parse($queryString),
[$this->getRule($max)]
);
$this->assertEquals($expectedErrors, array_map(['GraphQL\Error\Error', 'formatError'], $errors), $queryString);
return $errors;
}
protected function assertIntrospectionQuery($maxExpected) protected function assertIntrospectionQuery($maxExpected)
{ {
@ -59,6 +38,48 @@ abstract class QuerySecurityTestCase extends TestCase
$this->assertMaxValue($query, $maxExpected); $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) protected function assertIntrospectionTypeMetaFieldQuery($maxExpected)
{ {
$query = ' $query = '
@ -84,14 +105,4 @@ abstract class QuerySecurityTestCase extends TestCase
'; ';
$this->assertMaxValue($query, $maxExpected); $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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\ScalarLeafs;
class ScalarLeafsTest extends ValidatorTestCase class ScalarLeafsTest extends ValidatorTestCase
{ {
// Validate: Scalar leafs // Validate: Scalar leafs
/** /**
* @see it('valid scalar selection') * @see it('valid scalar selection')
*/ */
public function testValidScalarSelection() : void public function testValidScalarSelection() : void
{ {
$this->expectPassesRule(new ScalarLeafs, ' $this->expectPassesRule(
new ScalarLeafs(),
'
fragment scalarSelection on Dog { fragment scalarSelection on Dog {
barks barks
} }
'); '
);
} }
/** /**
@ -26,11 +31,23 @@ class ScalarLeafsTest extends ValidatorTestCase
*/ */
public function testObjectTypeMissingSelection() : void public function testObjectTypeMissingSelection() : void
{ {
$this->expectFailsRule(new ScalarLeafs, ' $this->expectFailsRule(
new ScalarLeafs(),
'
query directQueryOnObjectWithoutSubFields { query directQueryOnObjectWithoutSubFields {
human 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 public function testInterfaceTypeMissingSelection() : void
{ {
$this->expectFailsRule(new ScalarLeafs, ' $this->expectFailsRule(
new ScalarLeafs(),
'
{ {
human { pets } 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 public function testValidScalarSelectionWithArgs() : void
{ {
$this->expectPassesRule(new ScalarLeafs, ' $this->expectPassesRule(
new ScalarLeafs(),
'
fragment scalarSelectionWithArgs on Dog { fragment scalarSelectionWithArgs on Dog {
doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: SIT)
} }
'); '
);
} }
/** /**
@ -62,12 +86,23 @@ class ScalarLeafsTest extends ValidatorTestCase
*/ */
public function testScalarSelectionNotAllowedOnBoolean() : void public function testScalarSelectionNotAllowedOnBoolean() : void
{ {
$this->expectFailsRule(new ScalarLeafs, ' $this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedOnBoolean on Dog { fragment scalarSelectionsNotAllowedOnBoolean on Dog {
barks { sinceWhen } 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 public function testScalarSelectionNotAllowedOnEnum() : void
{ {
$this->expectFailsRule(new ScalarLeafs, ' $this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedOnEnum on Cat { fragment scalarSelectionsNotAllowedOnEnum on Cat {
furColor { inHexdec } furColor { inHexdec }
} }
@ -89,7 +126,9 @@ class ScalarLeafsTest extends ValidatorTestCase
*/ */
public function testScalarSelectionNotAllowedWithArgs() : void public function testScalarSelectionNotAllowedWithArgs() : void
{ {
$this->expectFailsRule(new ScalarLeafs, ' $this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedWithArgs on Dog { fragment scalarSelectionsNotAllowedWithArgs on Dog {
doesKnowCommand(dogCommand: SIT) { sinceWhen } doesKnowCommand(dogCommand: SIT) { sinceWhen }
} }
@ -103,7 +142,9 @@ class ScalarLeafsTest extends ValidatorTestCase
*/ */
public function testScalarSelectionNotAllowedWithDirectives() : void public function testScalarSelectionNotAllowedWithDirectives() : void
{ {
$this->expectFailsRule(new ScalarLeafs, ' $this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedWithDirectives on Dog { fragment scalarSelectionsNotAllowedWithDirectives on Dog {
name @include(if: true) { isAlsoHumanName } name @include(if: true) { isAlsoHumanName }
} }
@ -117,7 +158,9 @@ class ScalarLeafsTest extends ValidatorTestCase
*/ */
public function testScalarSelectionNotAllowedWithDirectivesAndArgs() : void public function testScalarSelectionNotAllowedWithDirectivesAndArgs() : void
{ {
$this->expectFailsRule(new ScalarLeafs, ' $this->expectFailsRule(
new ScalarLeafs(),
'
fragment scalarSelectionsNotAllowedWithDirectivesAndArgs on Dog { fragment scalarSelectionsNotAllowedWithDirectivesAndArgs on Dog {
doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen } doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen }
} }
@ -125,20 +168,4 @@ class ScalarLeafsTest extends ValidatorTestCase
[$this->noScalarSubselection('doesKnowCommand', 'Boolean', 3, 61)] [$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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\UniqueArgumentNames;
class UniqueArgumentNamesTest extends ValidatorTestCase class UniqueArgumentNamesTest extends ValidatorTestCase
{ {
// Validate: Unique argument names // Validate: Unique argument names
/** /**
* @see it('no arguments on field') * @see it('no arguments on field')
*/ */
public function testNoArgumentsOnField() : void public function testNoArgumentsOnField() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames(), ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
field field
} }
'); '
);
} }
/** /**
@ -26,11 +31,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testNoArgumentsOnDirective() : void public function testNoArgumentsOnDirective() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames, ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
field @directive field @directive
} }
'); '
);
} }
/** /**
@ -38,11 +46,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testArgumentOnField() : void public function testArgumentOnField() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames, ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
field(arg: "value") field(arg: "value")
} }
'); '
);
} }
/** /**
@ -50,11 +61,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testArgumentOnDirective() : void public function testArgumentOnDirective() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames, ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
field @directive(arg: "value") field @directive(arg: "value")
} }
'); '
);
} }
/** /**
@ -62,12 +76,15 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testSameArgumentOnTwoFields() : void public function testSameArgumentOnTwoFields() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames, ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
one: field(arg: "value") one: field(arg: "value")
two: field(arg: "value") two: field(arg: "value")
} }
'); '
);
} }
/** /**
@ -75,11 +92,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testSameArgumentOnFieldAndDirective() : void public function testSameArgumentOnFieldAndDirective() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames, ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
field(arg: "value") @directive(arg: "value") field(arg: "value") @directive(arg: "value")
} }
'); '
);
} }
/** /**
@ -87,11 +107,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testSameArgumentOnTwoDirectives() : void public function testSameArgumentOnTwoDirectives() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames, ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
field @directive1(arg: "value") @directive2(arg: "value") field @directive1(arg: "value") @directive2(arg: "value")
} }
'); '
);
} }
/** /**
@ -99,11 +122,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testMultipleFieldArguments() : void public function testMultipleFieldArguments() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames, ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
field(arg1: "value", arg2: "value", arg3: "value") field(arg1: "value", arg2: "value", arg3: "value")
} }
'); '
);
} }
/** /**
@ -111,11 +137,14 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testMultipleDirectiveArguments() : void public function testMultipleDirectiveArguments() : void
{ {
$this->expectPassesRule(new UniqueArgumentNames, ' $this->expectPassesRule(
new UniqueArgumentNames(),
'
{ {
field @directive(arg1: "value", arg2: "value", arg3: "value") field @directive(arg1: "value", arg2: "value", arg3: "value")
} }
'); '
);
} }
/** /**
@ -123,57 +152,15 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
*/ */
public function testDuplicateFieldArguments() : void public function testDuplicateFieldArguments() : void
{ {
$this->expectFailsRule(new UniqueArgumentNames, ' $this->expectFailsRule(
new UniqueArgumentNames(),
'
{ {
field(arg1: "value", arg1: "value") field(arg1: "value", arg1: "value")
} }
', [ ',
$this->duplicateArg('arg1', 3, 15, 3, 30) [$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)
]);
} }
private function duplicateArg($argName, $l1, $c1, $l2, $c2) private function duplicateArg($argName, $l1, $c1, $l2, $c2)
@ -183,4 +170,58 @@ class UniqueArgumentNamesTest extends ValidatorTestCase
[new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)] [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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Validator\Rules\UniqueDirectivesPerLocation; use GraphQL\Validator\Rules\UniqueDirectivesPerLocation;
@ -10,11 +13,14 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/ */
public function testNoDirectives() : void public function testNoDirectives() : void
{ {
$this->expectPassesRule(new UniqueDirectivesPerLocation(), ' $this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type { fragment Test on Type {
field field
} }
'); '
);
} }
/** /**
@ -22,11 +28,14 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/ */
public function testUniqueDirectivesInDifferentLocations() : void public function testUniqueDirectivesInDifferentLocations() : void
{ {
$this->expectPassesRule(new UniqueDirectivesPerLocation(), ' $this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type @directiveA { fragment Test on Type @directiveA {
field @directiveB field @directiveB
} }
'); '
);
} }
/** /**
@ -34,11 +43,14 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/ */
public function testUniqueDirectivesInSameLocations() : void public function testUniqueDirectivesInSameLocations() : void
{ {
$this->expectPassesRule(new UniqueDirectivesPerLocation(), ' $this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type @directiveA @directiveB { fragment Test on Type @directiveA @directiveB {
field @directiveA @directiveB field @directiveA @directiveB
} }
'); '
);
} }
/** /**
@ -46,11 +58,14 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/ */
public function testSameDirectivesInDifferentLocations() : void public function testSameDirectivesInDifferentLocations() : void
{ {
$this->expectPassesRule(new UniqueDirectivesPerLocation(), ' $this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type @directiveA { fragment Test on Type @directiveA {
field @directiveA field @directiveA
} }
'); '
);
} }
/** /**
@ -58,12 +73,15 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/ */
public function testSameDirectivesInSimilarLocations() : void public function testSameDirectivesInSimilarLocations() : void
{ {
$this->expectPassesRule(new UniqueDirectivesPerLocation(), ' $this->expectPassesRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type { fragment Test on Type {
field @directive field @directive
field @directive field @directive
} }
'); '
);
} }
/** /**
@ -71,58 +89,15 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
*/ */
public function testDuplicateDirectivesInOneLocation() : void public function testDuplicateDirectivesInOneLocation() : void
{ {
$this->expectFailsRule(new UniqueDirectivesPerLocation(), ' $this->expectFailsRule(
new UniqueDirectivesPerLocation(),
'
fragment Test on Type { fragment Test on Type {
field @directive @directive field @directive @directive
} }
', [ ',
$this->duplicateDirective('directive', 3, 15, 3, 26) [$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)
]);
} }
private function duplicateDirective($directiveName, $l1, $c1, $l2, $c2) private function duplicateDirective($directiveName, $l1, $c1, $l2, $c2)
@ -131,8 +106,65 @@ class UniqueDirectivesPerLocationTest extends ValidatorTestCase
'message' => UniqueDirectivesPerLocation::duplicateDirectiveMessage($directiveName), 'message' => UniqueDirectivesPerLocation::duplicateDirectiveMessage($directiveName),
'locations' => [ 'locations' => [
['line' => $l1, 'column' => $c1], ['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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\UniqueFragmentNames;
class UniqueFragmentNamesTest extends ValidatorTestCase class UniqueFragmentNamesTest extends ValidatorTestCase
{ {
// Validate: Unique fragment names // Validate: Unique fragment names
/** /**
* @see it('no fragments') * @see it('no fragments')
*/ */
public function testNoFragments() : void public function testNoFragments() : void
{ {
$this->expectPassesRule(new UniqueFragmentNames(), ' $this->expectPassesRule(
new UniqueFragmentNames(),
'
{ {
field field
} }
'); '
);
} }
/** /**
@ -26,7 +31,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/ */
public function testOneFragment() : void public function testOneFragment() : void
{ {
$this->expectPassesRule(new UniqueFragmentNames, ' $this->expectPassesRule(
new UniqueFragmentNames(),
'
{ {
...fragA ...fragA
} }
@ -34,7 +41,8 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
fragment fragA on Type { fragment fragA on Type {
field field
} }
'); '
);
} }
/** /**
@ -42,7 +50,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/ */
public function testManyFragments() : void public function testManyFragments() : void
{ {
$this->expectPassesRule(new UniqueFragmentNames, ' $this->expectPassesRule(
new UniqueFragmentNames(),
'
{ {
...fragA ...fragA
...fragB ...fragB
@ -57,7 +67,8 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
fragment fragC on Type { fragment fragC on Type {
fieldC fieldC
} }
'); '
);
} }
/** /**
@ -65,7 +76,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/ */
public function testInlineFragmentsAreAlwaysUnique() : void public function testInlineFragmentsAreAlwaysUnique() : void
{ {
$this->expectPassesRule(new UniqueFragmentNames, ' $this->expectPassesRule(
new UniqueFragmentNames(),
'
{ {
...on Type { ...on Type {
fieldA fieldA
@ -74,7 +87,8 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
fieldB fieldB
} }
} }
'); '
);
} }
/** /**
@ -82,14 +96,17 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/ */
public function testFragmentAndOperationNamedTheSame() : void public function testFragmentAndOperationNamedTheSame() : void
{ {
$this->expectPassesRule(new UniqueFragmentNames, ' $this->expectPassesRule(
new UniqueFragmentNames(),
'
query Foo { query Foo {
...Foo ...Foo
} }
fragment Foo on Type { fragment Foo on Type {
field field
} }
'); '
);
} }
/** /**
@ -97,7 +114,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
*/ */
public function testFragmentsNamedTheSame() : void public function testFragmentsNamedTheSame() : void
{ {
$this->expectFailsRule(new UniqueFragmentNames, ' $this->expectFailsRule(
new UniqueFragmentNames(),
'
{ {
...fragA ...fragA
} }
@ -107,26 +126,9 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
fragment fragA on Type { fragment fragA on Type {
fieldB fieldB
} }
', [ ',
$this->duplicateFrag('fragA', 5, 16, 8, 16) [$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)
]);
} }
private function duplicateFrag($fragName, $l1, $c1, $l2, $c2) private function duplicateFrag($fragName, $l1, $c1, $l2, $c2)
@ -136,4 +138,23 @@ class UniqueFragmentNamesTest extends ValidatorTestCase
[new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)] [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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\UniqueInputFieldNames;
class UniqueInputFieldNamesTest extends ValidatorTestCase class UniqueInputFieldNamesTest extends ValidatorTestCase
{ {
// Validate: Unique input field names // Validate: Unique input field names
/** /**
* @see it('input object with fields') * @see it('input object with fields')
*/ */
public function testInputObjectWithFields() : void public function testInputObjectWithFields() : void
{ {
$this->expectPassesRule(new UniqueInputFieldNames(), ' $this->expectPassesRule(
new UniqueInputFieldNames(),
'
{ {
field(arg: { f: true }) field(arg: { f: true })
} }
'); '
);
} }
/** /**
@ -26,11 +31,14 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
*/ */
public function testSameInputObjectWithinTwoArgs() : void public function testSameInputObjectWithinTwoArgs() : void
{ {
$this->expectPassesRule(new UniqueInputFieldNames, ' $this->expectPassesRule(
new UniqueInputFieldNames(),
'
{ {
field(arg1: { f: true }, arg2: { f: true }) field(arg1: { f: true }, arg2: { f: true })
} }
'); '
);
} }
/** /**
@ -38,11 +46,14 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
*/ */
public function testMultipleInputObjectFields() : void public function testMultipleInputObjectFields() : void
{ {
$this->expectPassesRule(new UniqueInputFieldNames, ' $this->expectPassesRule(
new UniqueInputFieldNames(),
'
{ {
field(arg: { f1: "value", f2: "value", f3: "value" }) field(arg: { f1: "value", f2: "value", f3: "value" })
} }
'); '
);
} }
/** /**
@ -50,7 +61,9 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
*/ */
public function testAllowsForNestedInputObjectsWithSimilarFields() : void public function testAllowsForNestedInputObjectsWithSimilarFields() : void
{ {
$this->expectPassesRule(new UniqueInputFieldNames, ' $this->expectPassesRule(
new UniqueInputFieldNames(),
'
{ {
field(arg: { field(arg: {
deep: { deep: {
@ -62,7 +75,8 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
id: 1 id: 1
}) })
} }
'); '
);
} }
/** /**
@ -70,28 +84,15 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
*/ */
public function testDuplicateInputObjectFields() : void public function testDuplicateInputObjectFields() : void
{ {
$this->expectFailsRule(new UniqueInputFieldNames, ' $this->expectFailsRule(
new UniqueInputFieldNames(),
'
{ {
field(arg: { f1: "value", f1: "value" }) field(arg: { f1: "value", f1: "value" })
} }
', [ ',
$this->duplicateField('f1', 3, 22, 3, 35) [$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)
]);
} }
private function duplicateField($name, $l1, $c1, $l2, $c2) private function duplicateField($name, $l1, $c1, $l2, $c2)
@ -101,4 +102,23 @@ class UniqueInputFieldNamesTest extends ValidatorTestCase
[new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)] [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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\UniqueOperationNames;
class UniqueOperationNamesTest extends ValidatorTestCase class UniqueOperationNamesTest extends ValidatorTestCase
{ {
// Validate: Unique operation names // Validate: Unique operation names
/** /**
* @see it('no operations') * @see it('no operations')
*/ */
public function testNoOperations() : void public function testNoOperations() : void
{ {
$this->expectPassesRule(new UniqueOperationNames(), ' $this->expectPassesRule(
new UniqueOperationNames(),
'
fragment fragA on Type { fragment fragA on Type {
field field
} }
'); '
);
} }
/** /**
@ -26,11 +31,14 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/ */
public function testOneAnonOperation() : void public function testOneAnonOperation() : void
{ {
$this->expectPassesRule(new UniqueOperationNames, ' $this->expectPassesRule(
new UniqueOperationNames(),
'
{ {
field field
} }
'); '
);
} }
/** /**
@ -38,11 +46,14 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/ */
public function testOneNamedOperation() : void public function testOneNamedOperation() : void
{ {
$this->expectPassesRule(new UniqueOperationNames, ' $this->expectPassesRule(
new UniqueOperationNames(),
'
query Foo { query Foo {
field field
} }
'); '
);
} }
/** /**
@ -50,7 +61,9 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/ */
public function testMultipleOperations() : void public function testMultipleOperations() : void
{ {
$this->expectPassesRule(new UniqueOperationNames, ' $this->expectPassesRule(
new UniqueOperationNames(),
'
query Foo { query Foo {
field field
} }
@ -58,7 +71,8 @@ class UniqueOperationNamesTest extends ValidatorTestCase
query Bar { query Bar {
field field
} }
'); '
);
} }
/** /**
@ -66,7 +80,9 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/ */
public function testMultipleOperationsOfDifferentTypes() : void public function testMultipleOperationsOfDifferentTypes() : void
{ {
$this->expectPassesRule(new UniqueOperationNames, ' $this->expectPassesRule(
new UniqueOperationNames(),
'
query Foo { query Foo {
field field
} }
@ -78,7 +94,8 @@ class UniqueOperationNamesTest extends ValidatorTestCase
subscription Baz { subscription Baz {
field field
} }
'); '
);
} }
/** /**
@ -86,14 +103,17 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/ */
public function testFragmentAndOperationNamedTheSame() : void public function testFragmentAndOperationNamedTheSame() : void
{ {
$this->expectPassesRule(new UniqueOperationNames, ' $this->expectPassesRule(
new UniqueOperationNames(),
'
query Foo { query Foo {
...Foo ...Foo
} }
fragment Foo on Type { fragment Foo on Type {
field field
} }
'); '
);
} }
/** /**
@ -101,50 +121,18 @@ class UniqueOperationNamesTest extends ValidatorTestCase
*/ */
public function testMultipleOperationsOfSameName() : void public function testMultipleOperationsOfSameName() : void
{ {
$this->expectFailsRule(new UniqueOperationNames, ' $this->expectFailsRule(
new UniqueOperationNames(),
'
query Foo { query Foo {
fieldA fieldA
} }
query Foo { query Foo {
fieldB fieldB
} }
', [ ',
$this->duplicateOp('Foo', 2, 13, 5, 13) [$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)
]);
} }
private function duplicateOp($opName, $l1, $c1, $l2, $c2) private function duplicateOp($opName, $l1, $c1, $l2, $c2)
@ -154,4 +142,42 @@ class UniqueOperationNamesTest extends ValidatorTestCase
[new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)] [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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,16 +11,18 @@ use GraphQL\Validator\Rules\UniqueVariableNames;
class UniqueVariableNamesTest extends ValidatorTestCase class UniqueVariableNamesTest extends ValidatorTestCase
{ {
// Validate: Unique variable names // Validate: Unique variable names
/** /**
* @see it('unique variable names') * @see it('unique variable names')
*/ */
public function testUniqueVariableNames() : void public function testUniqueVariableNames() : void
{ {
$this->expectPassesRule(new UniqueVariableNames(), ' $this->expectPassesRule(
new UniqueVariableNames(),
'
query A($x: Int, $y: String) { __typename } query A($x: Int, $y: String) { __typename }
query B($x: String, $y: Int) { __typename } query B($x: String, $y: Int) { __typename }
'); '
);
} }
/** /**
@ -25,16 +30,20 @@ class UniqueVariableNamesTest extends ValidatorTestCase
*/ */
public function testDuplicateVariableNames() : void public function testDuplicateVariableNames() : void
{ {
$this->expectFailsRule(new UniqueVariableNames, ' $this->expectFailsRule(
new UniqueVariableNames(),
'
query A($x: Int, $x: Int, $x: String) { __typename } query A($x: Int, $x: Int, $x: String) { __typename }
query B($x: String, $x: Int) { __typename } query B($x: String, $x: Int) { __typename }
query C($x: Int, $x: Int) { __typename } query C($x: Int, $x: Int) { __typename }
', [ ',
[
$this->duplicateVariable('x', 2, 16, 2, 25), $this->duplicateVariable('x', 2, 16, 2, 25),
$this->duplicateVariable('x', 2, 16, 2, 34), $this->duplicateVariable('x', 2, 16, 2, 34),
$this->duplicateVariable('x', 3, 16, 3, 28), $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) private function duplicateVariable($name, $l1, $c1, $l2, $c2)

View File

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

View File

@ -1,8 +1,10 @@
<?php <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\CustomScalarType; use GraphQL\Type\Definition\CustomScalarType;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\EnumType;
@ -11,11 +13,27 @@ use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType; use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Schema;
use GraphQL\Validator\DocumentValidator; use GraphQL\Validator\DocumentValidator;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use function array_map;
abstract class ValidatorTestCase extends TestCase 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 * @return Schema
*/ */
@ -28,8 +46,8 @@ abstract class ValidatorTestCase extends TestCase
'fields' => [ 'fields' => [
'name' => [ 'name' => [
'type' => Type::string(), 'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]] 'args' => ['surname' => ['type' => Type::boolean()]],
] ],
], ],
]); ]);
@ -38,8 +56,8 @@ abstract class ValidatorTestCase extends TestCase
'fields' => [ 'fields' => [
'name' => [ 'name' => [
'type' => Type::string(), 'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]] 'args' => ['surname' => ['type' => Type::boolean()]],
] ],
], ],
]); ]);
@ -49,10 +67,10 @@ abstract class ValidatorTestCase extends TestCase
return [ return [
'name' => [ 'name' => [
'type' => Type::string(), 'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]] 'args' => ['surname' => ['type' => Type::boolean()]],
] ],
]; ];
} },
]); ]);
$DogCommand = new EnumType([ $DogCommand = new EnumType([
@ -60,8 +78,8 @@ abstract class ValidatorTestCase extends TestCase
'values' => [ 'values' => [
'SIT' => ['value' => 0], 'SIT' => ['value' => 0],
'HEEL' => ['value' => 1], 'HEEL' => ['value' => 1],
'DOWN' => ['value' => 2] 'DOWN' => ['value' => 2],
] ],
]); ]);
$Dog = new ObjectType([ $Dog = new ObjectType([
@ -69,25 +87,25 @@ abstract class ValidatorTestCase extends TestCase
'fields' => [ 'fields' => [
'name' => [ 'name' => [
'type' => Type::string(), 'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]] 'args' => ['surname' => ['type' => Type::boolean()]],
], ],
'nickname' => ['type' => Type::string()], 'nickname' => ['type' => Type::string()],
'barkVolume' => ['type' => Type::int()], 'barkVolume' => ['type' => Type::int()],
'barks' => ['type' => Type::boolean()], 'barks' => ['type' => Type::boolean()],
'doesKnowCommand' => [ 'doesKnowCommand' => [
'type' => Type::boolean(), 'type' => Type::boolean(),
'args' => ['dogCommand' => ['type' => $DogCommand]] 'args' => ['dogCommand' => ['type' => $DogCommand]],
], ],
'isHousetrained' => [ 'isHousetrained' => [
'type' => Type::boolean(), 'type' => Type::boolean(),
'args' => ['atOtherHomes' => ['type' => Type::boolean(), 'defaultValue' => true]] 'args' => ['atOtherHomes' => ['type' => Type::boolean(), 'defaultValue' => true]],
], ],
'isAtLocation' => [ 'isAtLocation' => [
'type' => Type::boolean(), '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([ $Cat = new ObjectType([
@ -96,15 +114,15 @@ abstract class ValidatorTestCase extends TestCase
return [ return [
'name' => [ 'name' => [
'type' => Type::string(), 'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]] 'args' => ['surname' => ['type' => Type::boolean()]],
], ],
'nickname' => ['type' => Type::string()], 'nickname' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()], 'meows' => ['type' => Type::boolean()],
'meowVolume' => ['type' => Type::int()], 'meowVolume' => ['type' => Type::int()],
'furColor' => $FurColor 'furColor' => $FurColor,
]; ];
}, },
'interfaces' => [$Being, $Pet] 'interfaces' => [$Being, $Pet],
]); ]);
$CatOrDog = new UnionType([ $CatOrDog = new UnionType([
@ -115,8 +133,8 @@ abstract class ValidatorTestCase extends TestCase
$Intelligent = new InterfaceType([ $Intelligent = new InterfaceType([
'name' => 'Intelligent', 'name' => 'Intelligent',
'fields' => [ 'fields' => [
'iq' => ['type' => Type::int()] 'iq' => ['type' => Type::int()],
] ],
]); ]);
$Human = null; $Human = null;
@ -127,13 +145,13 @@ abstract class ValidatorTestCase extends TestCase
return [ return [
'name' => [ 'name' => [
'type' => Type::string(), 'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]] 'args' => ['surname' => ['type' => Type::boolean()]],
], ],
'pets' => ['type' => Type::listOf($Pet)], 'pets' => ['type' => Type::listOf($Pet)],
'relatives' => ['type' => Type::listOf($Human)], 'relatives' => ['type' => Type::listOf($Human)],
'iq' => ['type' => Type::int()] 'iq' => ['type' => Type::int()],
]; ];
} },
]); ]);
$Alien = new ObjectType([ $Alien = new ObjectType([
@ -143,10 +161,10 @@ abstract class ValidatorTestCase extends TestCase
'iq' => ['type' => Type::int()], 'iq' => ['type' => Type::int()],
'name' => [ 'name' => [
'type' => Type::string(), 'type' => Type::string(),
'args' => ['surname' => ['type' => Type::boolean()]] 'args' => ['surname' => ['type' => Type::boolean()]],
],
'numEyes' => ['type' => Type::int()],
], ],
'numEyes' => ['type' => Type::int()]
]
]); ]);
$DogOrHuman = new UnionType([ $DogOrHuman = new UnionType([
@ -177,8 +195,8 @@ abstract class ValidatorTestCase extends TestCase
'intField' => ['type' => Type::int()], 'intField' => ['type' => Type::int()],
'stringField' => ['type' => Type::string()], 'stringField' => ['type' => Type::string()],
'booleanField' => ['type' => Type::boolean()], 'booleanField' => ['type' => Type::boolean()],
'stringListField' => ['type' => Type::listOf(Type::string())] 'stringListField' => ['type' => Type::listOf(Type::string())],
] ],
]); ]);
$ComplicatedArgs = new ObjectType([ $ComplicatedArgs = new ObjectType([
@ -266,7 +284,7 @@ abstract class ValidatorTestCase extends TestCase
], ],
], ],
], ],
] ],
]); ]);
$invalidScalar = new CustomScalarType([ $invalidScalar = new CustomScalarType([
@ -300,7 +318,7 @@ abstract class ValidatorTestCase extends TestCase
'fields' => [ 'fields' => [
'human' => [ 'human' => [
'args' => ['id' => ['type' => Type::id()]], 'args' => ['id' => ['type' => Type::id()]],
'type' => $Human 'type' => $Human,
], ],
'alien' => ['type' => $Alien], 'alien' => ['type' => $Alien],
'dog' => ['type' => $Dog], 'dog' => ['type' => $Dog],
@ -312,7 +330,7 @@ abstract class ValidatorTestCase extends TestCase
'complicatedArgs' => ['type' => $ComplicatedArgs], 'complicatedArgs' => ['type' => $ComplicatedArgs],
'invalidArg' => [ 'invalidArg' => [
'args' => [ 'args' => [
'arg' => ['type' => $invalidScalar] 'arg' => ['type' => $invalidScalar],
], ],
'type' => Type::string(), 'type' => Type::string(),
], ],
@ -320,7 +338,7 @@ abstract class ValidatorTestCase extends TestCase
'args' => ['arg' => ['type' => $anyScalar]], 'args' => ['arg' => ['type' => $anyScalar]],
'type' => Type::string(), 'type' => Type::string(),
], ],
] ],
]); ]);
$testSchema = new Schema([ $testSchema = new Schema([
@ -402,19 +420,16 @@ abstract class ValidatorTestCase extends TestCase
]), ]),
], ],
]); ]);
return $testSchema; return $testSchema;
} }
function expectValid($schema, $rules, $queryString) protected function expectFailsRule($rule, $queryString, $errors)
{ {
$this->assertEquals( return $this->expectInvalid(self::getTestSchema(), [$rule], $queryString, $errors);
[],
DocumentValidator::validate($schema, Parser::parse($queryString), $rules),
'Should validate'
);
} }
function expectInvalid($schema, $rules, $queryString, $expectedErrors) protected function expectInvalid($schema, $rules, $queryString, $expectedErrors)
{ {
$errors = DocumentValidator::validate($schema, Parser::parse($queryString), $rules); $errors = DocumentValidator::validate($schema, Parser::parse($queryString), $rules);
@ -424,33 +439,23 @@ abstract class ValidatorTestCase extends TestCase
return $errors; return $errors;
} }
function expectPassesRule($rule, $queryString) protected function expectPassesRuleWithSchema($schema, $rule, $queryString) : void
{
$this->expectValid($this->getTestSchema(), [$rule], $queryString);
}
function expectFailsRule($rule, $queryString, $errors)
{
return $this->expectInvalid($this->getTestSchema(), [$rule], $queryString, $errors);
}
function expectPassesRuleWithSchema($schema, $rule, $queryString)
{ {
$this->expectValid($schema, [$rule], $queryString); $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); $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 <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -8,17 +11,19 @@ use GraphQL\Validator\Rules\VariablesAreInputTypes;
class VariablesAreInputTypesTest extends ValidatorTestCase class VariablesAreInputTypesTest extends ValidatorTestCase
{ {
// Validate: Variables are input types // Validate: Variables are input types
/** /**
* @see it('input types are valid') * @see it('input types are valid')
*/ */
public function testInputTypesAreValid() : void public function testInputTypesAreValid() : void
{ {
$this->expectPassesRule(new VariablesAreInputTypes(), ' $this->expectPassesRule(
new VariablesAreInputTypes(),
'
query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) { query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) {
field(a: $a, b: $b, c: $c) field(a: $a, b: $b, c: $c)
} }
'); '
);
} }
/** /**
@ -26,11 +31,14 @@ class VariablesAreInputTypesTest extends ValidatorTestCase
*/ */
public function testOutputTypesAreInvalid() : void public function testOutputTypesAreInvalid() : void
{ {
$this->expectFailsRule(new VariablesAreInputTypes, ' $this->expectFailsRule(
new VariablesAreInputTypes(),
'
query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) { query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) {
field(a: $a, b: $b, c: $c) field(a: $a, b: $b, c: $c)
} }
', [ ',
[
FormattedError::create( FormattedError::create(
VariablesAreInputTypes::nonInputTypeOnVarMessage('a', 'Dog'), VariablesAreInputTypes::nonInputTypeOnVarMessage('a', 'Dog'),
[new SourceLocation(2, 21)] [new SourceLocation(2, 21)]
@ -42,7 +50,7 @@ class VariablesAreInputTypesTest extends ValidatorTestCase
FormattedError::create( FormattedError::create(
VariablesAreInputTypes::nonInputTypeOnVarMessage('c', 'Pet'), VariablesAreInputTypes::nonInputTypeOnVarMessage('c', 'Pet'),
[new SourceLocation(2, 50)] [new SourceLocation(2, 50)]
) ),
] ]
); );
} }

View File

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator; namespace GraphQL\Tests\Validator;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
@ -7,6 +10,95 @@ use GraphQL\Validator\Rules\VariablesDefaultValueAllowed;
class VariablesDefaultValueAllowedTest extends ValidatorTestCase 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) private function defaultForRequiredVar($varName, $typeName, $guessTypeName, $line, $column)
{ {
return FormattedError::create( 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') * @see it('variables with invalid default null values')
*/ */
public function testNullIntoNullableType() : void public function testNullIntoNullableType() : void
{ {
$this->expectFailsRule(new VariablesDefaultValueAllowed(), ' $this->expectFailsRule(
new VariablesDefaultValueAllowed(),
'
query WithDefaultValues($a: Int! = null, $b: String! = null) { query WithDefaultValues($a: Int! = null, $b: String! = null) {
dog { name } dog { name }
} }
', [ ',
[
$this->defaultForRequiredVar('a', 'Int!', 'Int', 2, 42), $this->defaultForRequiredVar('a', 'Int!', 'Int', 2, 42),
$this->defaultForRequiredVar('b', 'String!', 'String', 2, 62), $this->defaultForRequiredVar('b', 'String!', 'String', 2, 62),
]); ]
);
} }
} }

View File

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