graphql-php/tests/Validator/PossibleFragmentSpreadsTest.php

369 lines
10 KiB
PHP
Raw Normal View History

2015-07-15 20:05:46 +03:00
<?php
2018-09-02 14:08:49 +03:00
declare(strict_types=1);
2016-04-09 10:36:53 +03:00
namespace GraphQL\Tests\Validator;
2015-07-15 20:05:46 +03:00
use GraphQL\Error\FormattedError;
2015-07-15 20:05:46 +03:00
use GraphQL\Language\SourceLocation;
use GraphQL\Validator\Rules\PossibleFragmentSpreads;
2018-07-29 18:43:10 +03:00
class PossibleFragmentSpreadsTest extends ValidatorTestCase
2015-07-15 20:05:46 +03:00
{
// Validate: Possible fragment spreads
/**
* @see it('of the same object')
*/
public function testOfTheSameObject() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment objectWithinObject on Dog { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('of the same object with inline fragment')
*/
public function testOfTheSameObjectWithInlineFragment() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('object into an implemented interface')
*/
public function testObjectIntoAnImplementedInterface() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment objectWithinInterface on Pet { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('object into containing union')
*/
public function testObjectIntoContainingUnion() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment objectWithinUnion on CatOrDog { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('union into contained object')
*/
public function testUnionIntoContainedObject() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment unionWithinObject on Dog { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('union into overlapping interface')
*/
public function testUnionIntoOverlappingInterface() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment unionWithinInterface on Pet { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('union into overlapping union')
*/
public function testUnionIntoOverlappingUnion() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('interface into implemented object')
*/
public function testInterfaceIntoImplementedObject() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment interfaceWithinObject on Dog { ...petFragment }
fragment petFragment on Pet { name }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('interface into overlapping interface')
*/
public function testInterfaceIntoOverlappingInterface() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment interfaceWithinInterface on Pet { ...beingFragment }
fragment beingFragment on Being { name }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('interface into overlapping interface in inline fragment')
*/
public function testInterfaceIntoOverlappingInterfaceInInlineFragment() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment interfaceWithinInterface on Pet { ... on Being { name } }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('interface into overlapping union')
*/
public function testInterfaceIntoOverlappingUnion() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment interfaceWithinUnion on CatOrDog { ...petFragment }
fragment petFragment on Pet { name }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('ignores incorrect type (caught by FragmentsOnCompositeTypes)')
*/
public function testIgnoresIncorrectTypeCaughtByFragmentsOnCompositeTypes() : void
{
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
fragment petFragment on Pet { ...badInADifferentWay }
fragment badInADifferentWay on String { name }
2018-09-02 14:08:49 +03:00
'
);
}
/**
* @see it('different object into object')
*/
public function testDifferentObjectIntoObject() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidObjectWithinObject on Cat { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
',
[$this->error('dogFragment', 'Cat', 'Dog', 2, 51)]
);
}
2018-09-02 14:08:49 +03:00
private function error($fragName, $parentType, $fragType, $line, $column)
{
return FormattedError::create(
PossibleFragmentSpreads::typeIncompatibleSpreadMessage($fragName, $parentType, $fragType),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('different object into object in inline fragment')
*/
public function testDifferentObjectIntoObjectInInlineFragment() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidObjectWithinObjectAnon on Cat {
... on Dog { barkVolume }
}
',
[$this->errorAnon('Cat', 'Dog', 3, 9)]
);
}
2018-09-02 14:08:49 +03:00
private function errorAnon($parentType, $fragType, $line, $column)
{
return FormattedError::create(
PossibleFragmentSpreads::typeIncompatibleAnonSpreadMessage($parentType, $fragType),
[new SourceLocation($line, $column)]
);
}
/**
* @see it('object into not implementing interface')
*/
public function testObjectIntoNotImplementingInterface() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidObjectWithinInterface on Pet { ...humanFragment }
fragment humanFragment on Human { pets { name } }
',
[$this->error('humanFragment', 'Pet', 'Human', 2, 54)]
);
}
/**
* @see it('object into not containing union')
*/
public function testObjectIntoNotContainingUnion() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment }
fragment humanFragment on Human { pets { name } }
',
[$this->error('humanFragment', 'CatOrDog', 'Human', 2, 55)]
);
}
/**
* @see it('union into not contained object')
*/
public function testUnionIntoNotContainedObject() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidUnionWithinObject on Human { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
',
[$this->error('catOrDogFragment', 'Human', 'CatOrDog', 2, 52)]
);
}
/**
* @see it('union into non overlapping interface')
*/
public function testUnionIntoNonOverlappingInterface() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment }
fragment humanOrAlienFragment on HumanOrAlien { __typename }
',
[$this->error('humanOrAlienFragment', 'Pet', 'HumanOrAlien', 2, 53)]
);
}
/**
* @see it('union into non overlapping union')
*/
public function testUnionIntoNonOverlappingUnion() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment }
fragment humanOrAlienFragment on HumanOrAlien { __typename }
',
[$this->error('humanOrAlienFragment', 'CatOrDog', 'HumanOrAlien', 2, 54)]
);
}
/**
* @see it('interface into non implementing object')
*/
public function testInterfaceIntoNonImplementingObject() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment }
fragment intelligentFragment on Intelligent { iq }
',
[$this->error('intelligentFragment', 'Cat', 'Intelligent', 2, 54)]
);
}
/**
* @see it('interface into non overlapping interface')
*/
public function testInterfaceIntoNonOverlappingInterface() : void
2015-07-15 20:05:46 +03:00
{
// 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:
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidInterfaceWithinInterface on Pet {
...intelligentFragment
}
fragment intelligentFragment on Intelligent { iq }
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('interface into non overlapping interface in inline fragment')
*/
public function testInterfaceIntoNonOverlappingInterfaceInInlineFragment() : void
2015-07-15 20:05:46 +03:00
{
// 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:
2018-09-02 14:08:49 +03:00
$this->expectPassesRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidInterfaceWithinInterfaceAnon on Pet {
...on Intelligent { iq }
}
2018-09-02 14:08:49 +03:00
'
);
2015-07-15 20:05:46 +03:00
}
/**
* @see it('interface into non overlapping union')
*/
public function testInterfaceIntoNonOverlappingUnion() : void
2015-07-15 20:05:46 +03:00
{
2018-09-02 14:08:49 +03:00
$this->expectFailsRule(
new PossibleFragmentSpreads(),
'
2015-07-15 20:05:46 +03:00
fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment }
fragment petFragment on Pet { name }
',
[$this->error('petFragment', 'HumanOrAlien', 'Pet', 2, 62)]
);
}
}