mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-22 12:56:05 +03:00
commit
bfff27ef34
@ -1,62 +1,31 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace GraphQL\Tests;
|
namespace GraphQL\Tests;
|
||||||
|
|
||||||
|
use function array_map;
|
||||||
|
|
||||||
class StarWarsData
|
class StarWarsData
|
||||||
{
|
{
|
||||||
private static function luke()
|
/**
|
||||||
|
* Helper function to get a character by ID.
|
||||||
|
*/
|
||||||
|
public static function getCharacter($id)
|
||||||
{
|
{
|
||||||
return [
|
$humans = self::humans();
|
||||||
'id' => '1000',
|
$droids = self::droids();
|
||||||
'name' => 'Luke Skywalker',
|
if (isset($humans[$id])) {
|
||||||
'friends' => ['1002', '1003', '2000', '2001'],
|
return $humans[$id];
|
||||||
'appearsIn' => [4, 5, 6],
|
}
|
||||||
'homePlanet' => 'Tatooine',
|
if (isset($droids[$id])) {
|
||||||
];
|
return $droids[$id];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function vader()
|
public static function humans()
|
||||||
{
|
|
||||||
return [
|
|
||||||
'id' => '1001',
|
|
||||||
'name' => 'Darth Vader',
|
|
||||||
'friends' => ['1004'],
|
|
||||||
'appearsIn' => [4, 5, 6],
|
|
||||||
'homePlanet' => 'Tatooine',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function han()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'id' => '1002',
|
|
||||||
'name' => 'Han Solo',
|
|
||||||
'friends' => ['1000', '1003', '2001'],
|
|
||||||
'appearsIn' => [4, 5, 6],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function leia()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'id' => '1003',
|
|
||||||
'name' => 'Leia Organa',
|
|
||||||
'friends' => ['1000', '1002', '2000', '2001'],
|
|
||||||
'appearsIn' => [4, 5, 6],
|
|
||||||
'homePlanet' => 'Alderaan',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function tarkin()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'id' => '1004',
|
|
||||||
'name' => 'Wilhuff Tarkin',
|
|
||||||
'friends' => ['1001'],
|
|
||||||
'appearsIn' => [4],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static function humans()
|
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'1000' => self::luke(),
|
'1000' => self::luke(),
|
||||||
@ -67,13 +36,74 @@ class StarWarsData
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function luke()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => '1000',
|
||||||
|
'name' => 'Luke Skywalker',
|
||||||
|
'friends' => ['1002', '1003', '2000', '2001'],
|
||||||
|
'appearsIn' => [4, 5, 6],
|
||||||
|
'homePlanet' => 'Tatooine',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function vader()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => '1001',
|
||||||
|
'name' => 'Darth Vader',
|
||||||
|
'friends' => ['1004'],
|
||||||
|
'appearsIn' => [4, 5, 6],
|
||||||
|
'homePlanet' => 'Tatooine',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function han()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => '1002',
|
||||||
|
'name' => 'Han Solo',
|
||||||
|
'friends' => ['1000', '1003', '2001'],
|
||||||
|
'appearsIn' => [4, 5, 6],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function leia()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => '1003',
|
||||||
|
'name' => 'Leia Organa',
|
||||||
|
'friends' => ['1000', '1002', '2000', '2001'],
|
||||||
|
'appearsIn' => [4, 5, 6],
|
||||||
|
'homePlanet' => 'Alderaan',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function tarkin()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => '1004',
|
||||||
|
'name' => 'Wilhuff Tarkin',
|
||||||
|
'friends' => ['1001'],
|
||||||
|
'appearsIn' => [4],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function droids()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'2000' => self::threepio(),
|
||||||
|
'2001' => self::artoo(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
private static function threepio()
|
private static function threepio()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => '2000',
|
'id' => '2000',
|
||||||
'name' => 'C-3PO',
|
'name' => 'C-3PO',
|
||||||
'friends' => ['1000', '1002', '1003', '2001'],
|
'friends' => ['1000', '1002', '1003', '2001'],
|
||||||
'appearsIn' => [4, 5, 6],
|
'appearsIn' => [4, 5, 6],
|
||||||
'primaryFunction' => 'Protocol',
|
'primaryFunction' => 'Protocol',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -82,60 +112,37 @@ class StarWarsData
|
|||||||
* We export artoo directly because the schema returns him
|
* We export artoo directly because the schema returns him
|
||||||
* from a root field, and hence needs to reference him.
|
* from a root field, and hence needs to reference him.
|
||||||
*/
|
*/
|
||||||
static function artoo()
|
private static function artoo()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|
||||||
'id' => '2001',
|
'id' => '2001',
|
||||||
'name' => 'R2-D2',
|
'name' => 'R2-D2',
|
||||||
'friends' => ['1000', '1002', '1003'],
|
'friends' => ['1000', '1002', '1003'],
|
||||||
'appearsIn' => [4, 5, 6],
|
'appearsIn' => [4, 5, 6],
|
||||||
'primaryFunction' => 'Astromech',
|
'primaryFunction' => 'Astromech',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
static function droids()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'2000' => self::threepio(),
|
|
||||||
'2001' => self::artoo(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to get a character by ID.
|
|
||||||
*/
|
|
||||||
static function getCharacter($id)
|
|
||||||
{
|
|
||||||
$humans = self::humans();
|
|
||||||
$droids = self::droids();
|
|
||||||
if (isset($humans[$id])) {
|
|
||||||
return $humans[$id];
|
|
||||||
}
|
|
||||||
if (isset($droids[$id])) {
|
|
||||||
return $droids[$id];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows us to query for a character's friends.
|
* Allows us to query for a character's friends.
|
||||||
*/
|
*/
|
||||||
static function getFriends($character)
|
public static function getFriends($character)
|
||||||
{
|
{
|
||||||
return array_map([__CLASS__, 'getCharacter'], $character['friends']);
|
return array_map([__CLASS__, 'getCharacter'], $character['friends']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $episode
|
* @param int $episode
|
||||||
* @return array
|
* @return mixed[]
|
||||||
*/
|
*/
|
||||||
static function getHero($episode)
|
public static function getHero($episode)
|
||||||
{
|
{
|
||||||
if ($episode === 5) {
|
if ($episode === 5) {
|
||||||
// Luke is the hero of Episode V.
|
// Luke is the hero of Episode V.
|
||||||
return self::luke();
|
return self::luke();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Artoo is the hero otherwise.
|
// Artoo is the hero otherwise.
|
||||||
return self::artoo();
|
return self::artoo();
|
||||||
}
|
}
|
||||||
@ -144,19 +151,21 @@ class StarWarsData
|
|||||||
* @param $id
|
* @param $id
|
||||||
* @return mixed|null
|
* @return mixed|null
|
||||||
*/
|
*/
|
||||||
static function getHuman($id)
|
public static function getHuman($id)
|
||||||
{
|
{
|
||||||
$humans = self::humans();
|
$humans = self::humans();
|
||||||
return isset($humans[$id]) ? $humans[$id] : null;
|
|
||||||
|
return $humans[$id] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $id
|
* @param $id
|
||||||
* @return mixed|null
|
* @return mixed|null
|
||||||
*/
|
*/
|
||||||
static function getDroid($id)
|
public static function getDroid($id)
|
||||||
{
|
{
|
||||||
$droids = self::droids();
|
$droids = self::droids();
|
||||||
return isset($droids[$id]) ? $droids[$id] : null;
|
|
||||||
|
return $droids[$id] ?? null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace GraphQL\Tests;
|
namespace GraphQL\Tests;
|
||||||
|
|
||||||
use GraphQL\GraphQL;
|
use GraphQL\GraphQL;
|
||||||
@ -14,7 +17,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsQueryingTheSchemaForTypes() : void
|
public function testAllowsQueryingTheSchemaForTypes() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query IntrospectionTypeQuery {
|
query IntrospectionTypeQuery {
|
||||||
__schema {
|
__schema {
|
||||||
types {
|
types {
|
||||||
@ -44,18 +47,26 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
['name' => '__EnumValue'],
|
['name' => '__EnumValue'],
|
||||||
['name' => '__Directive'],
|
['name' => '__Directive'],
|
||||||
['name' => '__DirectiveLocation'],
|
['name' => '__DirectiveLocation'],
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to test a query and the expected response.
|
||||||
|
*/
|
||||||
|
private function assertValidQuery($query, $expected) : void
|
||||||
|
{
|
||||||
|
$this->assertEquals(['data' => $expected], GraphQL::executeQuery(StarWarsSchema::build(), $query)->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Allows querying the schema for query type')
|
* @see it('Allows querying the schema for query type')
|
||||||
*/
|
*/
|
||||||
public function testAllowsQueryingTheSchemaForQueryType() : void
|
public function testAllowsQueryingTheSchemaForQueryType() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query IntrospectionQueryTypeQuery {
|
query IntrospectionQueryTypeQuery {
|
||||||
__schema {
|
__schema {
|
||||||
queryType {
|
queryType {
|
||||||
@ -66,10 +77,8 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'__schema' => [
|
'__schema' => [
|
||||||
'queryType' => [
|
'queryType' => ['name' => 'Query'],
|
||||||
'name' => 'Query'
|
],
|
||||||
],
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -79,7 +88,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsQueryingTheSchemaForASpecificType() : void
|
public function testAllowsQueryingTheSchemaForASpecificType() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query IntrospectionDroidTypeQuery {
|
query IntrospectionDroidTypeQuery {
|
||||||
__type(name: "Droid") {
|
__type(name: "Droid") {
|
||||||
name
|
name
|
||||||
@ -87,9 +96,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
}
|
}
|
||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'__type' => [
|
'__type' => ['name' => 'Droid'],
|
||||||
'name' => 'Droid'
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -99,7 +106,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsQueryingForAnObjectKind() : void
|
public function testAllowsQueryingForAnObjectKind() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query IntrospectionDroidKindQuery {
|
query IntrospectionDroidKindQuery {
|
||||||
__type(name: "Droid") {
|
__type(name: "Droid") {
|
||||||
name
|
name
|
||||||
@ -110,8 +117,8 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
$expected = [
|
$expected = [
|
||||||
'__type' => [
|
'__type' => [
|
||||||
'name' => 'Droid',
|
'name' => 'Droid',
|
||||||
'kind' => 'OBJECT'
|
'kind' => 'OBJECT',
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -121,7 +128,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsQueryingForInterfaceKind() : void
|
public function testAllowsQueryingForInterfaceKind() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query IntrospectionCharacterKindQuery {
|
query IntrospectionCharacterKindQuery {
|
||||||
__type(name: "Character") {
|
__type(name: "Character") {
|
||||||
name
|
name
|
||||||
@ -132,8 +139,8 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
$expected = [
|
$expected = [
|
||||||
'__type' => [
|
'__type' => [
|
||||||
'name' => 'Character',
|
'name' => 'Character',
|
||||||
'kind' => 'INTERFACE'
|
'kind' => 'INTERFACE',
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -143,7 +150,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsQueryingForObjectFields() : void
|
public function testAllowsQueryingForObjectFields() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query IntrospectionDroidFieldsQuery {
|
query IntrospectionDroidFieldsQuery {
|
||||||
__type(name: "Droid") {
|
__type(name: "Droid") {
|
||||||
name
|
name
|
||||||
@ -159,52 +166,52 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'__type' => [
|
'__type' => [
|
||||||
'name' => 'Droid',
|
'name' => 'Droid',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
[
|
[
|
||||||
'name' => 'id',
|
'name' => 'id',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => null,
|
'name' => null,
|
||||||
'kind' => 'NON_NULL'
|
'kind' => 'NON_NULL',
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'name',
|
'name' => 'name',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
'kind' => 'SCALAR'
|
'kind' => 'SCALAR',
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'friends',
|
'name' => 'friends',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => null,
|
'name' => null,
|
||||||
'kind' => 'LIST'
|
'kind' => 'LIST',
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'appearsIn',
|
'name' => 'appearsIn',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => null,
|
'name' => null,
|
||||||
'kind' => 'LIST'
|
'kind' => 'LIST',
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'secretBackstory',
|
'name' => 'secretBackstory',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
'kind' => 'SCALAR'
|
'kind' => 'SCALAR',
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'primaryFunction',
|
'name' => 'primaryFunction',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
'kind' => 'SCALAR'
|
'kind' => 'SCALAR',
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -214,7 +221,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsQueryingTheSchemaForNestedObjectFields() : void
|
public function testAllowsQueryingTheSchemaForNestedObjectFields() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query IntrospectionDroidNestedFieldsQuery {
|
query IntrospectionDroidNestedFieldsQuery {
|
||||||
__type(name: "Droid") {
|
__type(name: "Droid") {
|
||||||
name
|
name
|
||||||
@ -234,67 +241,67 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'__type' => [
|
'__type' => [
|
||||||
'name' => 'Droid',
|
'name' => 'Droid',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
[
|
[
|
||||||
'name' => 'id',
|
'name' => 'id',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => null,
|
'name' => null,
|
||||||
'kind' => 'NON_NULL',
|
'kind' => 'NON_NULL',
|
||||||
'ofType' => [
|
'ofType' => [
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
'kind' => 'SCALAR'
|
'kind' => 'SCALAR',
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'name',
|
'name' => 'name',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
'kind' => 'SCALAR',
|
'kind' => 'SCALAR',
|
||||||
'ofType' => null
|
'ofType' => null,
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'friends',
|
'name' => 'friends',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => null,
|
'name' => null,
|
||||||
'kind' => 'LIST',
|
'kind' => 'LIST',
|
||||||
'ofType' => [
|
'ofType' => [
|
||||||
'name' => 'Character',
|
'name' => 'Character',
|
||||||
'kind' => 'INTERFACE'
|
'kind' => 'INTERFACE',
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'appearsIn',
|
'name' => 'appearsIn',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => null,
|
'name' => null,
|
||||||
'kind' => 'LIST',
|
'kind' => 'LIST',
|
||||||
'ofType' => [
|
'ofType' => [
|
||||||
'name' => 'Episode',
|
'name' => 'Episode',
|
||||||
'kind' => 'ENUM'
|
'kind' => 'ENUM',
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'secretBackstory',
|
'name' => 'secretBackstory',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
'kind' => 'SCALAR',
|
'kind' => 'SCALAR',
|
||||||
'ofType' => null
|
'ofType' => null,
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'primaryFunction',
|
'name' => 'primaryFunction',
|
||||||
'type' => [
|
'type' => [
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
'kind' => 'SCALAR',
|
'kind' => 'SCALAR',
|
||||||
'ofType' => null
|
'ofType' => null,
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -329,7 +336,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
}
|
}
|
||||||
';
|
';
|
||||||
|
|
||||||
$expected = array(
|
$expected = [
|
||||||
'__schema' => [
|
'__schema' => [
|
||||||
'queryType' => [
|
'queryType' => [
|
||||||
'fields' => [
|
'fields' => [
|
||||||
@ -337,13 +344,13 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
'name' => 'hero',
|
'name' => 'hero',
|
||||||
'args' => [
|
'args' => [
|
||||||
[
|
[
|
||||||
'defaultValue' => NULL,
|
'defaultValue' => null,
|
||||||
'description' => 'If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode.',
|
'description' => 'If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode.',
|
||||||
'name' => 'episode',
|
'name' => 'episode',
|
||||||
'type' => [
|
'type' => [
|
||||||
'kind' => 'ENUM',
|
'kind' => 'ENUM',
|
||||||
'name' => 'Episode',
|
'name' => 'Episode',
|
||||||
'ofType' => NULL,
|
'ofType' => null,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -352,17 +359,17 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
'name' => 'human',
|
'name' => 'human',
|
||||||
'args' => [
|
'args' => [
|
||||||
[
|
[
|
||||||
'name' => 'id',
|
'name' => 'id',
|
||||||
'description' => 'id of the human',
|
'description' => 'id of the human',
|
||||||
'type' => [
|
'type' => [
|
||||||
'kind' => 'NON_NULL',
|
'kind' => 'NON_NULL',
|
||||||
'name' => NULL,
|
'name' => null,
|
||||||
'ofType' => [
|
'ofType' => [
|
||||||
'kind' => 'SCALAR',
|
'kind' => 'SCALAR',
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'defaultValue' => NULL,
|
'defaultValue' => null,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -370,25 +377,25 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
'name' => 'droid',
|
'name' => 'droid',
|
||||||
'args' => [
|
'args' => [
|
||||||
[
|
[
|
||||||
'name' => 'id',
|
'name' => 'id',
|
||||||
'description' => 'id of the droid',
|
'description' => 'id of the droid',
|
||||||
'type' => [
|
'type' => [
|
||||||
'kind' => 'NON_NULL',
|
'kind' => 'NON_NULL',
|
||||||
'name' => NULL,
|
'name' => null,
|
||||||
'ofType' =>
|
'ofType' =>
|
||||||
[
|
[
|
||||||
'kind' => 'SCALAR',
|
'kind' => 'SCALAR',
|
||||||
'name' => 'String',
|
'name' => 'String',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'defaultValue' => NULL,
|
'defaultValue' => null,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
);
|
];
|
||||||
|
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -398,7 +405,7 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsQueryingTheSchemaForDocumentation() : void
|
public function testAllowsQueryingTheSchemaForDocumentation() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query IntrospectionDroidDescriptionQuery {
|
query IntrospectionDroidDescriptionQuery {
|
||||||
__type(name: "Droid") {
|
__type(name: "Droid") {
|
||||||
name
|
name
|
||||||
@ -408,18 +415,10 @@ class StarWarsIntrospectionTest extends TestCase
|
|||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'__type' => [
|
'__type' => [
|
||||||
'name' => 'Droid',
|
'name' => 'Droid',
|
||||||
'description' => 'A mechanical creature in the Star Wars universe.'
|
'description' => 'A mechanical creature in the Star Wars universe.',
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to test a query and the expected response.
|
|
||||||
*/
|
|
||||||
private function assertValidQuery($query, $expected)
|
|
||||||
{
|
|
||||||
$this->assertEquals(['data' => $expected], GraphQL::executeQuery(StarWarsSchema::build(), $query)->toArray());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Tests;
|
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace GraphQL\Tests;
|
||||||
|
|
||||||
use GraphQL\GraphQL;
|
use GraphQL\GraphQL;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class StarWarsQueryTest extends TestCase
|
class StarWarsQueryTest extends TestCase
|
||||||
{
|
{
|
||||||
// Star Wars Query Tests
|
|
||||||
// Basic Queries
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Correctly identifies R2-D2 as the hero of the Star Wars Saga')
|
* @see it('Correctly identifies R2-D2 as the hero of the Star Wars Saga')
|
||||||
*/
|
*/
|
||||||
public function testCorrectlyIdentifiesR2D2AsTheHeroOfTheStarWarsSaga() : void
|
public function testCorrectlyIdentifiesR2D2AsTheHeroOfTheStarWarsSaga() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query HeroNameQuery {
|
query HeroNameQuery {
|
||||||
hero {
|
hero {
|
||||||
name
|
name
|
||||||
@ -23,19 +22,30 @@ class StarWarsQueryTest extends TestCase
|
|||||||
}
|
}
|
||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'hero' => [
|
'hero' => ['name' => 'R2-D2'],
|
||||||
'name' => 'R2-D2'
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to test a query and the expected response.
|
||||||
|
*/
|
||||||
|
private function assertValidQuery($query, $expected) : void
|
||||||
|
{
|
||||||
|
$this->assertEquals(
|
||||||
|
['data' => $expected],
|
||||||
|
GraphQL::executeQuery(StarWarsSchema::build(), $query)->toArray()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describe: Nested Queries
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Allows us to query for the ID and friends of R2-D2')
|
* @see it('Allows us to query for the ID and friends of R2-D2')
|
||||||
*/
|
*/
|
||||||
public function testAllowsUsToQueryForTheIDAndFriendsOfR2D2() : void
|
public function testAllowsUsToQueryForTheIDAndFriendsOfR2D2() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query HeroNameAndFriendsQuery {
|
query HeroNameAndFriendsQuery {
|
||||||
hero {
|
hero {
|
||||||
id
|
id
|
||||||
@ -48,32 +58,26 @@ class StarWarsQueryTest extends TestCase
|
|||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'hero' => [
|
'hero' => [
|
||||||
'id' => '2001',
|
'id' => '2001',
|
||||||
'name' => 'R2-D2',
|
'name' => 'R2-D2',
|
||||||
'friends' => [
|
'friends' => [
|
||||||
[
|
['name' => 'Luke Skywalker'],
|
||||||
'name' => 'Luke Skywalker',
|
['name' => 'Han Solo'],
|
||||||
],
|
['name' => 'Leia Organa'],
|
||||||
[
|
],
|
||||||
'name' => 'Han Solo',
|
],
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Leia Organa',
|
|
||||||
],
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe: Nested Queries
|
// Describe: Using IDs and query parameters to refetch objects
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Allows us to query for the friends of friends of R2-D2')
|
* @see it('Allows us to query for the friends of friends of R2-D2')
|
||||||
*/
|
*/
|
||||||
public function testAllowsUsToQueryForTheFriendsOfFriendsOfR2D2() : void
|
public function testAllowsUsToQueryForTheFriendsOfFriendsOfR2D2() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query NestedQuery {
|
query NestedQuery {
|
||||||
hero {
|
hero {
|
||||||
name
|
name
|
||||||
@ -89,52 +93,50 @@ class StarWarsQueryTest extends TestCase
|
|||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'hero' => [
|
'hero' => [
|
||||||
'name' => 'R2-D2',
|
'name' => 'R2-D2',
|
||||||
'friends' => [
|
'friends' => [
|
||||||
[
|
[
|
||||||
'name' => 'Luke Skywalker',
|
'name' => 'Luke Skywalker',
|
||||||
'appearsIn' => ['NEWHOPE', 'EMPIRE', 'JEDI',],
|
'appearsIn' => ['NEWHOPE', 'EMPIRE', 'JEDI'],
|
||||||
'friends' => [
|
'friends' => [
|
||||||
['name' => 'Han Solo',],
|
['name' => 'Han Solo'],
|
||||||
['name' => 'Leia Organa',],
|
['name' => 'Leia Organa'],
|
||||||
['name' => 'C-3PO',],
|
['name' => 'C-3PO'],
|
||||||
['name' => 'R2-D2',],
|
['name' => 'R2-D2'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'Han Solo',
|
'name' => 'Han Solo',
|
||||||
'appearsIn' => ['NEWHOPE', 'EMPIRE', 'JEDI'],
|
'appearsIn' => ['NEWHOPE', 'EMPIRE', 'JEDI'],
|
||||||
'friends' => [
|
'friends' => [
|
||||||
['name' => 'Luke Skywalker',],
|
['name' => 'Luke Skywalker'],
|
||||||
['name' => 'Leia Organa'],
|
['name' => 'Leia Organa'],
|
||||||
['name' => 'R2-D2',],
|
['name' => 'R2-D2'],
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'Leia Organa',
|
'name' => 'Leia Organa',
|
||||||
'appearsIn' => ['NEWHOPE', 'EMPIRE', 'JEDI'],
|
'appearsIn' => ['NEWHOPE', 'EMPIRE', 'JEDI'],
|
||||||
'friends' =>
|
'friends' =>
|
||||||
[
|
[
|
||||||
['name' => 'Luke Skywalker',],
|
['name' => 'Luke Skywalker'],
|
||||||
['name' => 'Han Solo',],
|
['name' => 'Han Solo'],
|
||||||
['name' => 'C-3PO',],
|
['name' => 'C-3PO'],
|
||||||
['name' => 'R2-D2',],
|
['name' => 'R2-D2'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe: Using IDs and query parameters to refetch objects
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Using IDs and query parameters to refetch objects')
|
* @see it('Using IDs and query parameters to refetch objects')
|
||||||
*/
|
*/
|
||||||
public function testAllowsUsToQueryForLukeSkywalkerDirectlyUsingHisID() : void
|
public function testAllowsUsToQueryForLukeSkywalkerDirectlyUsingHisID() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query FetchLukeQuery {
|
query FetchLukeQuery {
|
||||||
human(id: "1000") {
|
human(id: "1000") {
|
||||||
name
|
name
|
||||||
@ -142,9 +144,7 @@ class StarWarsQueryTest extends TestCase
|
|||||||
}
|
}
|
||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'human' => [
|
'human' => ['name' => 'Luke Skywalker'],
|
||||||
'name' => 'Luke Skywalker'
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
@ -155,44 +155,49 @@ class StarWarsQueryTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGenericQueryToGetLukeSkywalkerById() : void
|
public function testGenericQueryToGetLukeSkywalkerById() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query FetchSomeIDQuery($someId: String!) {
|
query FetchSomeIDQuery($someId: String!) {
|
||||||
human(id: $someId) {
|
human(id: $someId) {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
';
|
';
|
||||||
$params = [
|
$params = ['someId' => '1000'];
|
||||||
'someId' => '1000'
|
|
||||||
];
|
|
||||||
$expected = [
|
$expected = [
|
||||||
'human' => [
|
'human' => ['name' => 'Luke Skywalker'],
|
||||||
'name' => 'Luke Skywalker'
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->assertValidQueryWithParams($query, $params, $expected);
|
$this->assertValidQueryWithParams($query, $params, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to test a query with params and the expected response.
|
||||||
|
*/
|
||||||
|
private function assertValidQueryWithParams($query, $params, $expected)
|
||||||
|
{
|
||||||
|
$this->assertEquals(
|
||||||
|
['data' => $expected],
|
||||||
|
GraphQL::executeQuery(StarWarsSchema::build(), $query, null, null, $params)->toArray()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using aliases to change the key in the response
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Allows us to create a generic query, then use it to fetch Han Solo using his ID')
|
* @see it('Allows us to create a generic query, then use it to fetch Han Solo using his ID')
|
||||||
*/
|
*/
|
||||||
public function testGenericQueryToGetHanSoloById() : void
|
public function testGenericQueryToGetHanSoloById() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query FetchSomeIDQuery($someId: String!) {
|
query FetchSomeIDQuery($someId: String!) {
|
||||||
human(id: $someId) {
|
human(id: $someId) {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
';
|
';
|
||||||
$params = [
|
$params = ['someId' => '1002'];
|
||||||
'someId' => '1002'
|
|
||||||
];
|
|
||||||
$expected = [
|
$expected = [
|
||||||
'human' => [
|
'human' => ['name' => 'Han Solo'],
|
||||||
'name' => 'Han Solo'
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
$this->assertValidQueryWithParams($query, $params, $expected);
|
$this->assertValidQueryWithParams($query, $params, $expected);
|
||||||
}
|
}
|
||||||
@ -202,30 +207,26 @@ class StarWarsQueryTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGenericQueryWithInvalidId() : void
|
public function testGenericQueryWithInvalidId() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query humanQuery($id: String!) {
|
query humanQuery($id: String!) {
|
||||||
human(id: $id) {
|
human(id: $id) {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
';
|
';
|
||||||
$params = [
|
$params = ['id' => 'not a valid id'];
|
||||||
'id' => 'not a valid id'
|
$expected = ['human' => null];
|
||||||
];
|
|
||||||
$expected = [
|
|
||||||
'human' => null
|
|
||||||
];
|
|
||||||
$this->assertValidQueryWithParams($query, $params, $expected);
|
$this->assertValidQueryWithParams($query, $params, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using aliases to change the key in the response
|
// Uses fragments to express more complex queries
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Allows us to query for Luke, changing his key with an alias')
|
* @see it('Allows us to query for Luke, changing his key with an alias')
|
||||||
*/
|
*/
|
||||||
function testLukeKeyAlias()
|
public function testLukeKeyAlias() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query FetchLukeAliased {
|
query FetchLukeAliased {
|
||||||
luke: human(id: "1000") {
|
luke: human(id: "1000") {
|
||||||
name
|
name
|
||||||
@ -233,9 +234,7 @@ class StarWarsQueryTest extends TestCase
|
|||||||
}
|
}
|
||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'luke' => [
|
'luke' => ['name' => 'Luke Skywalker'],
|
||||||
'name' => 'Luke Skywalker'
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -243,9 +242,9 @@ class StarWarsQueryTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @see it('Allows us to query for both Luke and Leia, using two root fields and an alias')
|
* @see it('Allows us to query for both Luke and Leia, using two root fields and an alias')
|
||||||
*/
|
*/
|
||||||
function testTwoRootKeysAsAnAlias()
|
public function testTwoRootKeysAsAnAlias() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query FetchLukeAndLeiaAliased {
|
query FetchLukeAndLeiaAliased {
|
||||||
luke: human(id: "1000") {
|
luke: human(id: "1000") {
|
||||||
name
|
name
|
||||||
@ -256,24 +255,18 @@ class StarWarsQueryTest extends TestCase
|
|||||||
}
|
}
|
||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'luke' => [
|
'luke' => ['name' => 'Luke Skywalker'],
|
||||||
'name' => 'Luke Skywalker'
|
'leia' => ['name' => 'Leia Organa'],
|
||||||
],
|
|
||||||
'leia' => [
|
|
||||||
'name' => 'Leia Organa'
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uses fragments to express more complex queries
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Allows us to query using duplicated content')
|
* @see it('Allows us to query using duplicated content')
|
||||||
*/
|
*/
|
||||||
function testQueryUsingDuplicatedContent()
|
public function testQueryUsingDuplicatedContent() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query DuplicateFields {
|
query DuplicateFields {
|
||||||
luke: human(id: "1000") {
|
luke: human(id: "1000") {
|
||||||
name
|
name
|
||||||
@ -287,13 +280,13 @@ class StarWarsQueryTest extends TestCase
|
|||||||
';
|
';
|
||||||
$expected = [
|
$expected = [
|
||||||
'luke' => [
|
'luke' => [
|
||||||
'name' => 'Luke Skywalker',
|
'name' => 'Luke Skywalker',
|
||||||
'homePlanet' => 'Tatooine'
|
'homePlanet' => 'Tatooine',
|
||||||
],
|
],
|
||||||
'leia' => [
|
'leia' => [
|
||||||
'name' => 'Leia Organa',
|
'name' => 'Leia Organa',
|
||||||
'homePlanet' => 'Alderaan'
|
'homePlanet' => 'Alderaan',
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -301,7 +294,7 @@ class StarWarsQueryTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @see it('Allows us to use a fragment to avoid duplicating content')
|
* @see it('Allows us to use a fragment to avoid duplicating content')
|
||||||
*/
|
*/
|
||||||
function testUsingFragment()
|
public function testUsingFragment() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query UseFragment {
|
query UseFragment {
|
||||||
@ -321,13 +314,13 @@ class StarWarsQueryTest extends TestCase
|
|||||||
|
|
||||||
$expected = [
|
$expected = [
|
||||||
'luke' => [
|
'luke' => [
|
||||||
'name' => 'Luke Skywalker',
|
'name' => 'Luke Skywalker',
|
||||||
'homePlanet' => 'Tatooine'
|
'homePlanet' => 'Tatooine',
|
||||||
],
|
],
|
||||||
'leia' => [
|
'leia' => [
|
||||||
'name' => 'Leia Organa',
|
'name' => 'Leia Organa',
|
||||||
'homePlanet' => 'Alderaan'
|
'homePlanet' => 'Alderaan',
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
@ -337,7 +330,7 @@ class StarWarsQueryTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testVerifyThatR2D2IsADroid() : void
|
public function testVerifyThatR2D2IsADroid() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query CheckTypeOfR2 {
|
query CheckTypeOfR2 {
|
||||||
hero {
|
hero {
|
||||||
__typename
|
__typename
|
||||||
@ -348,7 +341,7 @@ class StarWarsQueryTest extends TestCase
|
|||||||
$expected = [
|
$expected = [
|
||||||
'hero' => [
|
'hero' => [
|
||||||
'__typename' => 'Droid',
|
'__typename' => 'Droid',
|
||||||
'name' => 'R2-D2'
|
'name' => 'R2-D2',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
@ -371,32 +364,10 @@ class StarWarsQueryTest extends TestCase
|
|||||||
$expected = [
|
$expected = [
|
||||||
'hero' => [
|
'hero' => [
|
||||||
'__typename' => 'Human',
|
'__typename' => 'Human',
|
||||||
'name' => 'Luke Skywalker'
|
'name' => 'Luke Skywalker',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->assertValidQuery($query, $expected);
|
$this->assertValidQuery($query, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to test a query and the expected response.
|
|
||||||
*/
|
|
||||||
private function assertValidQuery($query, $expected)
|
|
||||||
{
|
|
||||||
$this->assertEquals(
|
|
||||||
['data' => $expected],
|
|
||||||
GraphQL::executeQuery(StarWarsSchema::build(), $query)->toArray()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to test a query with params and the expected response.
|
|
||||||
*/
|
|
||||||
private function assertValidQueryWithParams($query, $params, $expected)
|
|
||||||
{
|
|
||||||
$this->assertEquals(
|
|
||||||
['data' => $expected],
|
|
||||||
GraphQL::executeQuery(StarWarsSchema::build(), $query, null, null, $params)->toArray()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace GraphQL\Tests;
|
namespace GraphQL\Tests;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,13 +14,16 @@ namespace GraphQL\Tests;
|
|||||||
* NOTE: This may contain spoilers for the original Star
|
* NOTE: This may contain spoilers for the original Star
|
||||||
* Wars trilogy.
|
* Wars trilogy.
|
||||||
*/
|
*/
|
||||||
use GraphQL\Type\Schema;
|
|
||||||
use GraphQL\Type\Definition\EnumType;
|
use GraphQL\Type\Definition\EnumType;
|
||||||
use GraphQL\Type\Definition\InterfaceType;
|
use GraphQL\Type\Definition\InterfaceType;
|
||||||
use GraphQL\Type\Definition\NonNull;
|
use GraphQL\Type\Definition\NonNull;
|
||||||
use GraphQL\Type\Definition\ObjectType;
|
use GraphQL\Type\Definition\ObjectType;
|
||||||
use GraphQL\Type\Definition\ResolveInfo;
|
use GraphQL\Type\Definition\ResolveInfo;
|
||||||
use GraphQL\Type\Definition\Type;
|
use GraphQL\Type\Definition\Type;
|
||||||
|
use GraphQL\Type\Schema;
|
||||||
|
use function array_intersect_key;
|
||||||
|
use function array_map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using our shorthand to describe type systems, the type system for our
|
* Using our shorthand to describe type systems, the type system for our
|
||||||
@ -56,10 +62,9 @@ use GraphQL\Type\Definition\Type;
|
|||||||
*
|
*
|
||||||
* We begin by setting up our schema.
|
* We begin by setting up our schema.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StarWarsSchema
|
class StarWarsSchema
|
||||||
{
|
{
|
||||||
public static function build()
|
public static function build() : Schema
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The original trilogy consists of three movies.
|
* The original trilogy consists of three movies.
|
||||||
@ -68,22 +73,22 @@ class StarWarsSchema
|
|||||||
* enum Episode { NEWHOPE, EMPIRE, JEDI }
|
* enum Episode { NEWHOPE, EMPIRE, JEDI }
|
||||||
*/
|
*/
|
||||||
$episodeEnum = new EnumType([
|
$episodeEnum = new EnumType([
|
||||||
'name' => 'Episode',
|
'name' => 'Episode',
|
||||||
'description' => 'One of the films in the Star Wars Trilogy',
|
'description' => 'One of the films in the Star Wars Trilogy',
|
||||||
'values' => [
|
'values' => [
|
||||||
'NEWHOPE' => [
|
'NEWHOPE' => [
|
||||||
'value' => 4,
|
'value' => 4,
|
||||||
'description' => 'Released in 1977.'
|
'description' => 'Released in 1977.',
|
||||||
],
|
],
|
||||||
'EMPIRE' => [
|
'EMPIRE' => [
|
||||||
'value' => 5,
|
'value' => 5,
|
||||||
'description' => 'Released in 1980.'
|
'description' => 'Released in 1980.',
|
||||||
],
|
],
|
||||||
'JEDI' => [
|
'JEDI' => [
|
||||||
'value' => 6,
|
'value' => 6,
|
||||||
'description' => 'Released in 1983.'
|
'description' => 'Released in 1983.',
|
||||||
],
|
],
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$humanType = null;
|
$humanType = null;
|
||||||
@ -101,28 +106,28 @@ class StarWarsSchema
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
$characterInterface = new InterfaceType([
|
$characterInterface = new InterfaceType([
|
||||||
'name' => 'Character',
|
'name' => 'Character',
|
||||||
'description' => 'A character in the Star Wars Trilogy',
|
'description' => 'A character in the Star Wars Trilogy',
|
||||||
'fields' => function() use (&$characterInterface, $episodeEnum) {
|
'fields' => function () use (&$characterInterface, $episodeEnum) {
|
||||||
return [
|
return [
|
||||||
'id' => [
|
'id' => [
|
||||||
'type' => Type::nonNull(Type::string()),
|
'type' => Type::nonNull(Type::string()),
|
||||||
'description' => 'The id of the character.',
|
'description' => 'The id of the character.',
|
||||||
],
|
],
|
||||||
'name' => [
|
'name' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'description' => 'The name of the character.'
|
'description' => 'The name of the character.',
|
||||||
],
|
],
|
||||||
'friends' => [
|
'friends' => [
|
||||||
'type' => Type::listOf($characterInterface),
|
'type' => Type::listOf($characterInterface),
|
||||||
'description' => 'The friends of the character, or an empty list if they have none.',
|
'description' => 'The friends of the character, or an empty list if they have none.',
|
||||||
],
|
],
|
||||||
'appearsIn' => [
|
'appearsIn' => [
|
||||||
'type' => Type::listOf($episodeEnum),
|
'type' => Type::listOf($episodeEnum),
|
||||||
'description' => 'Which movies they appear in.'
|
'description' => 'Which movies they appear in.',
|
||||||
],
|
],
|
||||||
'secretBackstory' => [
|
'secretBackstory' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'description' => 'All secrets about their past.',
|
'description' => 'All secrets about their past.',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
@ -145,26 +150,26 @@ class StarWarsSchema
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
$humanType = new ObjectType([
|
$humanType = new ObjectType([
|
||||||
'name' => 'Human',
|
'name' => 'Human',
|
||||||
'description' => 'A humanoid creature in the Star Wars universe.',
|
'description' => 'A humanoid creature in the Star Wars universe.',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'id' => [
|
'id' => [
|
||||||
'type' => new NonNull(Type::string()),
|
'type' => new NonNull(Type::string()),
|
||||||
'description' => 'The id of the human.',
|
'description' => 'The id of the human.',
|
||||||
],
|
],
|
||||||
'name' => [
|
'name' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'description' => 'The name of the human.',
|
'description' => 'The name of the human.',
|
||||||
],
|
],
|
||||||
'friends' => [
|
'friends' => [
|
||||||
'type' => Type::listOf($characterInterface),
|
'type' => Type::listOf($characterInterface),
|
||||||
'description' => 'The friends of the human, or an empty list if they have none.',
|
'description' => 'The friends of the human, or an empty list if they have none.',
|
||||||
'resolve' => function ($human, $args, $context, ResolveInfo $info) {
|
'resolve' => function ($human, $args, $context, ResolveInfo $info) {
|
||||||
$fieldSelection = $info->getFieldSelection();
|
$fieldSelection = $info->getFieldSelection();
|
||||||
$fieldSelection['id'] = true;
|
$fieldSelection['id'] = true;
|
||||||
|
|
||||||
$friends = array_map(
|
$friends = array_map(
|
||||||
function($friend) use ($fieldSelection) {
|
function ($friend) use ($fieldSelection) {
|
||||||
return array_intersect_key($friend, $fieldSelection);
|
return array_intersect_key($friend, $fieldSelection);
|
||||||
},
|
},
|
||||||
StarWarsData::getFriends($human)
|
StarWarsData::getFriends($human)
|
||||||
@ -173,24 +178,24 @@ class StarWarsSchema
|
|||||||
return $friends;
|
return $friends;
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'appearsIn' => [
|
'appearsIn' => [
|
||||||
'type' => Type::listOf($episodeEnum),
|
'type' => Type::listOf($episodeEnum),
|
||||||
'description' => 'Which movies they appear in.'
|
'description' => 'Which movies they appear in.',
|
||||||
],
|
],
|
||||||
'homePlanet' => [
|
'homePlanet' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'description' => 'The home planet of the human, or null if unknown.'
|
'description' => 'The home planet of the human, or null if unknown.',
|
||||||
],
|
],
|
||||||
'secretBackstory' => [
|
'secretBackstory' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'description' => 'Where are they from and how they came to be who they are.',
|
'description' => 'Where are they from and how they came to be who they are.',
|
||||||
'resolve' => function() {
|
'resolve' => function () {
|
||||||
// This is to demonstrate error reporting
|
// This is to demonstrate error reporting
|
||||||
throw new \Exception('secretBackstory is secret.');
|
throw new \Exception('secretBackstory is secret.');
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'interfaces' => [$characterInterface]
|
'interfaces' => [$characterInterface],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -207,42 +212,42 @@ class StarWarsSchema
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
$droidType = new ObjectType([
|
$droidType = new ObjectType([
|
||||||
'name' => 'Droid',
|
'name' => 'Droid',
|
||||||
'description' => 'A mechanical creature in the Star Wars universe.',
|
'description' => 'A mechanical creature in the Star Wars universe.',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'id' => [
|
'id' => [
|
||||||
'type' => Type::nonNull(Type::string()),
|
'type' => Type::nonNull(Type::string()),
|
||||||
'description' => 'The id of the droid.',
|
'description' => 'The id of the droid.',
|
||||||
],
|
],
|
||||||
'name' => [
|
'name' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'description' => 'The name of the droid.'
|
'description' => 'The name of the droid.',
|
||||||
],
|
],
|
||||||
'friends' => [
|
'friends' => [
|
||||||
'type' => Type::listOf($characterInterface),
|
'type' => Type::listOf($characterInterface),
|
||||||
'description' => 'The friends of the droid, or an empty list if they have none.',
|
'description' => 'The friends of the droid, or an empty list if they have none.',
|
||||||
'resolve' => function ($droid) {
|
'resolve' => function ($droid) {
|
||||||
return StarWarsData::getFriends($droid);
|
return StarWarsData::getFriends($droid);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'appearsIn' => [
|
'appearsIn' => [
|
||||||
'type' => Type::listOf($episodeEnum),
|
'type' => Type::listOf($episodeEnum),
|
||||||
'description' => 'Which movies they appear in.'
|
'description' => 'Which movies they appear in.',
|
||||||
],
|
],
|
||||||
'secretBackstory' => [
|
'secretBackstory' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'description' => 'Construction date and the name of the designer.',
|
'description' => 'Construction date and the name of the designer.',
|
||||||
'resolve' => function() {
|
'resolve' => function () {
|
||||||
// This is to demonstrate error reporting
|
// This is to demonstrate error reporting
|
||||||
throw new \Exception('secretBackstory is secret.');
|
throw new \Exception('secretBackstory is secret.');
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'primaryFunction' => [
|
'primaryFunction' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'description' => 'The primary function of the droid.'
|
'description' => 'The primary function of the droid.',
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
'interfaces' => [$characterInterface]
|
'interfaces' => [$characterInterface],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -260,49 +265,51 @@ class StarWarsSchema
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
$queryType = new ObjectType([
|
$queryType = new ObjectType([
|
||||||
'name' => 'Query',
|
'name' => 'Query',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'hero' => [
|
'hero' => [
|
||||||
'type' => $characterInterface,
|
'type' => $characterInterface,
|
||||||
'args' => [
|
'args' => [
|
||||||
'episode' => [
|
'episode' => [
|
||||||
'description' => 'If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode.',
|
'description' => 'If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode.',
|
||||||
'type' => $episodeEnum
|
'type' => $episodeEnum,
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
'resolve' => function ($root, $args) {
|
'resolve' => function ($root, $args) {
|
||||||
return StarWarsData::getHero(isset($args['episode']) ? $args['episode'] : null);
|
return StarWarsData::getHero($args['episode'] ?? null);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'human' => [
|
'human' => [
|
||||||
'type' => $humanType,
|
'type' => $humanType,
|
||||||
'args' => [
|
'args' => [
|
||||||
'id' => [
|
'id' => [
|
||||||
'name' => 'id',
|
'name' => 'id',
|
||||||
'description' => 'id of the human',
|
'description' => 'id of the human',
|
||||||
'type' => Type::nonNull(Type::string())
|
'type' => Type::nonNull(Type::string()),
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
'resolve' => function ($root, $args) {
|
'resolve' => function ($root, $args) {
|
||||||
$humans = StarWarsData::humans();
|
$humans = StarWarsData::humans();
|
||||||
return isset($humans[$args['id']]) ? $humans[$args['id']] : null;
|
|
||||||
}
|
return $humans[$args['id']] ?? null;
|
||||||
|
},
|
||||||
],
|
],
|
||||||
'droid' => [
|
'droid' => [
|
||||||
'type' => $droidType,
|
'type' => $droidType,
|
||||||
'args' => [
|
'args' => [
|
||||||
'id' => [
|
'id' => [
|
||||||
'name' => 'id',
|
'name' => 'id',
|
||||||
'description' => 'id of the droid',
|
'description' => 'id of the droid',
|
||||||
'type' => Type::nonNull(Type::string())
|
'type' => Type::nonNull(Type::string()),
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
'resolve' => function ($root, $args) {
|
'resolve' => function ($root, $args) {
|
||||||
$droids = StarWarsData::droids();
|
$droids = StarWarsData::droids();
|
||||||
return isset($droids[$args['id']]) ? $droids[$args['id']] : null;
|
|
||||||
}
|
return $droids[$args['id']] ?? null;
|
||||||
]
|
},
|
||||||
]
|
],
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return new Schema(['query' => $queryType]);
|
return new Schema(['query' => $queryType]);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace GraphQL\Tests;
|
namespace GraphQL\Tests;
|
||||||
|
|
||||||
use GraphQL\Language\Parser;
|
use GraphQL\Language\Parser;
|
||||||
@ -15,7 +18,7 @@ class StarWarsValidationTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testValidatesAComplexButValidQuery() : void
|
public function testValidatesAComplexButValidQuery() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query NestedQueryWithFragment {
|
query NestedQueryWithFragment {
|
||||||
hero {
|
hero {
|
||||||
...NameAndAppearances
|
...NameAndAppearances
|
||||||
@ -37,12 +40,22 @@ class StarWarsValidationTest extends TestCase
|
|||||||
$this->assertEquals(true, empty($errors));
|
$this->assertEquals(true, empty($errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to test a query and the expected response.
|
||||||
|
*/
|
||||||
|
private function validationErrors($query)
|
||||||
|
{
|
||||||
|
$ast = Parser::parse($query);
|
||||||
|
|
||||||
|
return DocumentValidator::validate(StarWarsSchema::build(), $ast);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('Notes that non-existent fields are invalid')
|
* @see it('Notes that non-existent fields are invalid')
|
||||||
*/
|
*/
|
||||||
public function testThatNonExistentFieldsAreInvalid() : void
|
public function testThatNonExistentFieldsAreInvalid() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query HeroSpaceshipQuery {
|
query HeroSpaceshipQuery {
|
||||||
hero {
|
hero {
|
||||||
favoriteSpaceship
|
favoriteSpaceship
|
||||||
@ -73,7 +86,7 @@ class StarWarsValidationTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testDisallowsFieldsOnScalars() : void
|
public function testDisallowsFieldsOnScalars() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query HeroFieldsOnScalarQuery {
|
query HeroFieldsOnScalarQuery {
|
||||||
hero {
|
hero {
|
||||||
name {
|
name {
|
||||||
@ -91,7 +104,7 @@ class StarWarsValidationTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testDisallowsObjectFieldsOnInterfaces() : void
|
public function testDisallowsObjectFieldsOnInterfaces() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query DroidFieldOnCharacter {
|
query DroidFieldOnCharacter {
|
||||||
hero {
|
hero {
|
||||||
name
|
name
|
||||||
@ -108,7 +121,7 @@ class StarWarsValidationTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsObjectFieldsInFragments() : void
|
public function testAllowsObjectFieldsInFragments() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query DroidFieldInFragment {
|
query DroidFieldInFragment {
|
||||||
hero {
|
hero {
|
||||||
name
|
name
|
||||||
@ -129,7 +142,7 @@ class StarWarsValidationTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAllowsObjectFieldsInInlineFragments() : void
|
public function testAllowsObjectFieldsInInlineFragments() : void
|
||||||
{
|
{
|
||||||
$query = '
|
$query = '
|
||||||
query DroidFieldInFragment {
|
query DroidFieldInFragment {
|
||||||
hero {
|
hero {
|
||||||
name
|
name
|
||||||
@ -142,13 +155,4 @@ class StarWarsValidationTest extends TestCase
|
|||||||
$errors = $this->validationErrors($query);
|
$errors = $this->validationErrors($query);
|
||||||
$this->assertEquals(true, empty($errors));
|
$this->assertEquals(true, empty($errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to test a query and the expected response.
|
|
||||||
*/
|
|
||||||
private function validationErrors($query)
|
|
||||||
{
|
|
||||||
$ast = Parser::parse($query);
|
|
||||||
return DocumentValidator::validate(StarWarsSchema::build(), $ast);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace GraphQL\Tests;
|
namespace GraphQL\Tests;
|
||||||
|
|
||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
@ -8,7 +11,7 @@ class UtilsTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testAssignThrowsExceptionOnMissingRequiredKey() : void
|
public function testAssignThrowsExceptionOnMissingRequiredKey() : void
|
||||||
{
|
{
|
||||||
$object = new \stdClass();
|
$object = new \stdClass();
|
||||||
$object->requiredKey = 'value';
|
$object->requiredKey = 'value';
|
||||||
|
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
Loading…
Reference in New Issue
Block a user