public function setUp() { $NamedType = new InterfaceType(['name' => 'Named', 'fields' => ['name' => ['type' => Type::string()]]]); $DogType = new ObjectType(['name' => 'Dog', 'interfaces' => [$NamedType], 'fields' => ['name' => ['type' => Type::string()], 'barks' => ['type' => Type::boolean()]], 'isTypeOf' => function ($value) { return $value instanceof Dog; }]); $CatType = new ObjectType(['name' => 'Cat', 'interfaces' => [$NamedType], 'fields' => ['name' => ['type' => Type::string()], 'meows' => ['type' => Type::boolean()]], 'isTypeOf' => function ($value) { return $value instanceof Cat; }]); $PetType = new UnionType(['name' => 'Pet', 'types' => [$DogType, $CatType], 'resolveType' => function ($value) use($DogType, $CatType) { if ($value instanceof Dog) { return $DogType; } if ($value instanceof Cat) { return $CatType; } }]); $PersonType = new ObjectType(['name' => 'Person', 'interfaces' => [$NamedType], 'fields' => ['name' => ['type' => Type::string()], 'pets' => ['type' => Type::listOf($PetType)], 'friends' => ['type' => Type::listOf($NamedType)]], 'isTypeOf' => function ($value) { return $value instanceof Person; }]); $this->schema = new Schema($PersonType); $this->garfield = new Cat('Garfield', false); $this->odie = new Dog('Odie', true); $this->liz = new Person('Liz'); $this->john = new Person('John', [$this->garfield, $this->odie], [$this->liz, $this->odie]); }
/** * @return Schema */ protected function getDefaultSchema() { $Being = new InterfaceType(['name' => 'Being', 'fields' => ['name' => ['type' => Type::string()]]]); $Pet = new InterfaceType(['name' => 'Pet', 'fields' => ['name' => ['type' => Type::string()]]]); $DogCommand = new EnumType(['name' => 'DogCommand', 'values' => ['SIT' => ['value' => 0], 'HEEL' => ['value' => 1], 'DOWN' => ['value' => 3]]]); $Dog = new ObjectType(['name' => 'Dog', 'fields' => ['name' => ['type' => Type::string()], 'nickname' => ['type' => Type::string()], 'barkVolume' => ['type' => Type::int()], 'barks' => ['type' => Type::boolean()], 'doesKnowCommand' => ['type' => Type::boolean(), 'args' => ['dogCommand' => ['type' => $DogCommand]]], 'isHousetrained' => ['type' => Type::boolean(), 'args' => ['atOtherHomes' => ['type' => Type::boolean(), 'defaultValue' => true]]], 'isAtLocation' => ['type' => Type::boolean(), 'args' => ['x' => ['type' => Type::int()], 'y' => ['type' => Type::int()]]]], 'interfaces' => [$Being, $Pet]]); $FurColor = new EnumType(['name' => 'FurColor', 'values' => ['BROWN' => ['value' => 0], 'BLACK' => ['value' => 1], 'TAN' => ['value' => 2], 'SPOTTED' => ['value' => 3]]]); $Cat = new ObjectType(['name' => 'Cat', 'fields' => ['name' => ['type' => Type::string()], 'nickname' => ['type' => Type::string()], 'meows' => ['type' => Type::boolean()], 'meowVolume' => ['type' => Type::int()], 'furColor' => ['type' => $FurColor]], 'interfaces' => [$Being, $Pet]]); $CatOrDog = new UnionType(['name' => 'CatOrDog', 'types' => [$Dog, $Cat], 'resolveType' => function ($value) { // not used for validation return null; }]); $Intelligent = new InterfaceType(['name' => 'Intelligent', 'fields' => ['iq' => ['type' => Type::int()]]]); $Human = $this->humanType = new ObjectType(['name' => 'Human', 'interfaces' => [$Being, $Intelligent], 'fields' => ['name' => ['args' => ['surname' => ['type' => Type::boolean()]], 'type' => Type::string()], 'pets' => ['type' => Type::listOf($Pet)], 'relatives' => ['type' => function () { return Type::listOf($this->humanType); }]]]); $Alien = new ObjectType(['name' => 'Alien', 'interfaces' => [$Being, $Intelligent], 'fields' => ['iq' => ['type' => Type::int()], 'numEyes' => ['type' => Type::int()]]]); $DogOrHuman = new UnionType(['name' => 'DogOrHuman', 'types' => [$Dog, $Human], 'resolveType' => function () { // not used for validation return null; }]); $HumanOrAlien = new UnionType(['name' => 'HumanOrAlien', 'types' => [$Human, $Alien], 'resolveType' => function () { // not used for validation return null; }]); $ComplexInput = new InputObjectType(['name' => 'ComplexInput', 'fields' => ['requiredField' => ['type' => Type::nonNull(Type::boolean())], 'intField' => ['type' => Type::int()], 'stringField' => ['type' => Type::string()], 'booleanField' => ['type' => Type::boolean()], 'stringListField' => ['type' => Type::listOf(Type::string())]]]); $ComplicatedArgs = new ObjectType(['name' => 'ComplicatedArgs', 'fields' => ['intArgField' => ['type' => Type::string(), 'args' => ['intArg' => ['type' => Type::int()]]], 'nonNullIntArgField' => ['type' => Type::string(), 'args' => ['nonNullIntArg' => ['type' => Type::nonNull(Type::int())]]], 'stringArgField' => ['type' => Type::string(), 'args' => ['stringArg' => ['type' => Type::string()]]], 'booleanArgField' => ['type' => Type::string(), 'args' => ['booleanArg' => ['type' => Type::boolean()]]], 'enumArgField' => ['type' => Type::string(), 'args' => ['enumArg' => ['type' => $FurColor]]], 'floatArgField' => ['type' => Type::string(), 'args' => ['floatArg' => ['type' => Type::float()]]], 'idArgField' => ['type' => Type::string(), 'args' => ['idArg' => ['type' => Type::id()]]], 'stringListArgField' => ['type' => Type::string(), 'args' => ['stringListArg' => ['type' => Type::listOf(Type::string())]]], 'complexArgField' => ['type' => Type::string(), 'args' => ['complexArg' => ['type' => $ComplexInput]]], 'multipleReqs' => ['type' => Type::string(), 'args' => ['req1' => ['type' => Type::nonNull(Type::int())], 'req2' => ['type' => Type::nonNull(Type::int())]]], 'multipleOpts' => ['type' => Type::string(), 'args' => ['opt1' => ['type' => Type::int(), 'defaultValue' => 0], 'opt2' => ['type' => Type::int(), 'defaultValue' => 0]]], 'multipleOptAndReq' => ['type' => Type::string(), 'args' => ['req1' => ['type' => Type::nonNull(Type::int())], 'req2' => ['type' => Type::nonNull(Type::int())], 'opt1' => ['type' => Type::int(), 'defaultValue' => 0], 'opt2' => ['type' => Type::int(), 'defaultValue' => 0]]]]]); $queryRoot = new ObjectType(['name' => 'QueryRoot', 'fields' => ['human' => ['args' => ['id' => ['type' => Type::id()]], 'type' => $Human], 'alien' => ['type' => $Alien], 'dog' => ['type' => $Dog], 'cat' => ['type' => $Cat], 'pet' => ['type' => $Pet], 'catOrDog' => ['type' => $CatOrDog], 'dogOrHuman' => ['type' => $DogOrHuman], 'humanOrAlien' => ['type' => $HumanOrAlien], 'complicatedArgs' => ['type' => $ComplicatedArgs]]]); $defaultSchema = new Schema($queryRoot); return $defaultSchema; }
public function testDefinesAQueryOnlySchema() { $blogSchema = new Schema($this->blogQuery); $this->assertSame($blogSchema->getQueryType(), $this->blogQuery); $articleField = $this->blogQuery->getField('article'); $this->assertSame($articleField->getType(), $this->blogArticle); $this->assertSame($articleField->getType()->name, 'Article'); $this->assertSame($articleField->name, 'article'); /** @var ObjectType $articleFieldType */ $articleFieldType = $articleField->getType(); $titleField = $articleFieldType->getField('title'); $this->assertInstanceOf('GraphQL\\Type\\Definition\\FieldDefinition', $titleField); $this->assertSame('title', $titleField->name); $this->assertSame(Type::string(), $titleField->getType()); $authorField = $articleFieldType->getField('author'); $this->assertInstanceOf('GraphQL\\Type\\Definition\\FieldDefinition', $authorField); /** @var ObjectType $authorFieldType */ $authorFieldType = $authorField->getType(); $this->assertSame($this->blogAuthor, $authorFieldType); $recentArticleField = $authorFieldType->getField('recentArticle'); $this->assertInstanceOf('GraphQL\\Type\\Definition\\FieldDefinition', $recentArticleField); $this->assertSame($this->blogArticle, $recentArticleField->getType()); $feedField = $this->blogQuery->getField('feed'); $this->assertInstanceOf('GraphQL\\Type\\Definition\\FieldDefinition', $feedField); /** @var ListOfType $feedFieldType */ $feedFieldType = $feedField->getType(); $this->assertInstanceOf('GraphQL\\Type\\Definition\\ListOfType', $feedFieldType); $this->assertSame($this->blogArticle, $feedFieldType->getWrappedType()); }
public function setup() { $this->allUsers = [['name' => 'Dan', 'friends' => [1, 2, 3, 4]], ['name' => 'Nick', 'friends' => [0, 2, 3, 4]], ['name' => 'Lee', 'friends' => [0, 1, 3, 4]], ['name' => 'Joe', 'friends' => [0, 1, 2, 4]], ['name' => 'Tim', 'friends' => [0, 1, 2, 3]]]; $this->userType = new ObjectType(['name' => 'User', 'fields' => function () { return ['name' => ['type' => Type::string()], 'friends' => ['type' => $this->friendConnection, 'args' => Connection::connectionArgs(), 'resolve' => function ($user, $args) { return ArrayConnection::connectionFromArray($user['friends'], $args); }], 'friendsForward' => ['type' => $this->userConnection, 'args' => Connection::forwardConnectionArgs(), 'resolve' => function ($user, $args) { return ArrayConnection::connectionFromArray($user['friends'], $args); }], 'friendsBackward' => ['type' => $this->userConnection, 'args' => Connection::backwardConnectionArgs(), 'resolve' => function ($user, $args) { return ArrayConnection::connectionFromArray($user['friends'], $args); }]]; }]); $this->friendEdge = Connection::createEdgeType(['name' => 'Friend', 'nodeType' => $this->userType, 'resolveNode' => function ($edge) { return $this->allUsers[$edge['node']]; }, 'edgeFields' => function () { return ['friendshipTime' => ['type' => Type::string(), 'resolve' => function () { return 'Yesterday'; }]]; }]); $this->friendConnection = Connection::createConnectionType(['name' => 'Friend', 'nodeType' => $this->userType, 'edgeType' => $this->friendEdge, 'connectionFields' => function () { return ['totalCount' => ['type' => Type::int(), 'resolve' => function () { return count($this->allUsers) - 1; }]]; }]); $this->userEdge = Connection::createEdgeType(['nodeType' => $this->userType, 'resolveNode' => function ($edge) { return $this->allUsers[$edge['node']]; }]); $this->userConnection = Connection::createConnectionType(['nodeType' => $this->userType, 'edgeType' => $this->userEdge]); $this->queryType = new ObjectType(['name' => 'Query', 'fields' => function () { return ['user' => ['type' => $this->userType, 'resolve' => function () { return $this->allUsers[0]; }]]; }]); $this->schema = new Schema(['query' => $this->queryType]); }
public function testFieldSelection() { $image = new ObjectType(['name' => 'Image', 'fields' => ['url' => ['type' => Type::string()], 'width' => ['type' => Type::int()], 'height' => ['type' => Type::int()]]]); $article = null; $author = new ObjectType(['name' => 'Author', 'fields' => function () use($image, &$article) { return ['id' => ['type' => Type::string()], 'name' => ['type' => Type::string()], 'pic' => ['type' => $image, 'args' => ['width' => ['type' => Type::int()], 'height' => ['type' => Type::int()]]], 'recentArticle' => ['type' => $article]]; }]); $reply = new ObjectType(['name' => 'Reply', 'fields' => ['author' => ['type' => $author], 'body' => ['type' => Type::string()]]]); $article = new ObjectType(['name' => 'Article', 'fields' => ['id' => ['type' => Type::string()], 'isPublished' => ['type' => Type::boolean()], 'author' => ['type' => $author], 'title' => ['type' => Type::string()], 'body' => ['type' => Type::string()], 'image' => ['type' => $image], 'replies' => ['type' => Type::listOf($reply)]]]); $doc = ' query Test { article { author { name pic { url width } } image { width height } replies { body author { id name pic { url width } recentArticle { id title body } } } } } '; $expectedDefaultSelection = ['author' => true, 'image' => true, 'replies' => true]; $expectedDeepSelection = ['author' => ['name' => true, 'pic' => ['url' => true, 'width' => true]], 'image' => ['width' => true, 'height' => true], 'replies' => ['body' => true, 'author' => ['id' => true, 'name' => true, 'pic' => ['url' => true, 'width' => true], 'recentArticle' => ['id' => true, 'title' => true, 'body' => true]]]]; $hasCalled = false; $actualDefaultSelection = null; $actualDeepSelection = null; $blogQuery = new ObjectType(['name' => 'Query', 'fields' => ['article' => ['type' => $article, 'resolve' => function ($value, $args, $context, ResolveInfo $info) use(&$hasCalled, &$actualDefaultSelection, &$actualDeepSelection) { $hasCalled = true; $actualDefaultSelection = $info->getFieldSelection(); $actualDeepSelection = $info->getFieldSelection(5); return null; }]]]); $schema = new Schema(['query' => $blogQuery]); $result = GraphQL::execute($schema, $doc); $this->assertTrue($hasCalled); $this->assertEquals(['data' => ['article' => null]], $result); $this->assertEquals($expectedDefaultSelection, $actualDefaultSelection); $this->assertEquals($expectedDeepSelection, $actualDeepSelection); }
/** * @param string $name * @return Type */ public function resolveType($name) { if (preg_match('#^(.+)\\!$#', $name, $regs)) { return Type::nonNull($this->resolveType($regs[1])); } if (preg_match('#^\\[(.+)\\]$#', $name, $regs)) { return Type::listOf($this->resolveType($regs[1])); } switch ($name) { case Type::INT: return Type::int(); case Type::STRING: return Type::string(); case Type::BOOLEAN: return Type::boolean(); case Type::FLOAT: return Type::float(); case Type::ID: return Type::id(); default: if (!isset($this->types[$name])) { throw new \InvalidArgumentException(sprintf('Type "%s" is not defined', $name)); } return $this->types[$name]; } }
public function setUp() { $this->syncError = new Error('sync'); $this->nonNullSyncError = new Error('nonNullSync'); $this->throwingData = ['sync' => function () { throw $this->syncError; }, 'nonNullSync' => function () { throw $this->nonNullSyncError; }, 'nest' => function () { return $this->throwingData; }, 'nonNullNest' => function () { return $this->throwingData; }]; $this->nullingData = ['sync' => function () { return null; }, 'nonNullSync' => function () { return null; }, 'nest' => function () { return $this->nullingData; }, 'nonNullNest' => function () { return $this->nullingData; }]; $dataType = new ObjectType(['name' => 'DataType', 'fields' => ['sync' => ['type' => Type::string()], 'nonNullSync' => ['type' => Type::nonNull(Type::string())], 'nest' => ['type' => function () use(&$dataType) { return $dataType; }], 'nonNullNest' => ['type' => function () use(&$dataType) { return Type::nonNull($dataType); }]]]); $this->schema = new Schema($dataType); }
public static function buildDogType() { if (null !== self::$dogType) { return self::$dogType; } self::$dogType = new ObjectType(['name' => 'Dog', 'fields' => ['name' => ['type' => Type::nonNull(Type::string())], 'master' => ['type' => self::buildHumanType()]]]); return self::$dogType; }
/** * Type fields. * * @return array */ public function fields() { return ['name' => ['type' => Type::string(), 'description' => 'Name of the user.'], 'email' => ['type' => Type::string(), 'description' => 'Email of the user.'], 'tasks' => GraphQL::connection('task')->args(['order' => ['type' => Type::string(), 'description' => 'Sort order of tasks.']])->resolve(function ($parent, array $args) { return $parent->tasks->transform(function ($task) { return array_merge($task->toArray(), ['title' => 'foo']); }); })->field()]; }
/** * Returns the test ObjectType * @return ObjectType */ protected function getTestObjectType() { if (!$this->testObject) { $this->testObject = new ObjectType(['name' => 'TestObject', 'fields' => ['name' => ['type' => Type::string(), 'resolve' => function () { return 'testname'; }]], 'interfaces' => [$this->getLazyInterfaceType()]]); } return $this->testObject; }
public function testCoercesOutputStrings() { $stringType = Type::string(); $this->assertSame('string', $stringType->coerce('string')); $this->assertSame('1', $stringType->coerce(1)); $this->assertSame('-1.1', $stringType->coerce(-1.1)); $this->assertSame('true', $stringType->coerce(true)); $this->assertSame('false', $stringType->coerce(false)); }
public function __construct() { $config = ['name' => 'Query', 'fields' => ['user' => ['type' => Types::user(), 'description' => 'Returns user by id (in range of 1-5)', 'args' => ['id' => Types::nonNull(Types::id())]], 'viewer' => ['type' => Types::user(), 'description' => 'Represents currently logged-in user (for the sake of example - simply returns user with id == 1)'], 'stories' => ['type' => Types::listOf(Types::story()), 'description' => 'Returns subset of stories posted for this blog', 'args' => ['after' => ['type' => Types::id(), 'description' => 'Fetch stories listed after the story with this ID'], 'limit' => ['type' => Types::int(), 'description' => 'Number of stories to be returned', 'defaultValue' => 10]]], 'lastStoryPosted' => ['type' => Types::story(), 'description' => 'Returns last story posted for this blog'], 'deprecatedField' => ['type' => Types::string(), 'deprecationReason' => 'This field is deprecated!'], 'fieldWithException' => ['type' => Types::string(), 'resolve' => function () { throw new \Exception("Exception message thrown in field resolver"); }], 'hello' => Type::string()], 'resolveField' => function ($val, $args, $context, ResolveInfo $info) { return $this->{$info->fieldName}($val, $args, $context, $info); }]; parent::__construct($config); }
public function setUp() { $ColorType = new EnumType(['name' => 'Color', 'values' => ['RED' => ['value' => 0], 'GREEN' => ['value' => 1], 'BLUE' => ['value' => 2]]]); $simpleEnum = new EnumType(['name' => 'SimpleEnum', 'values' => ['ONE', 'TWO', 'THREE']]); $Complex1 = ['someRandomFunction' => function () { }]; $Complex2 = new \ArrayObject(['someRandomValue' => 123]); $ComplexEnum = new EnumType(['name' => 'Complex', 'values' => ['ONE' => ['value' => $Complex1], 'TWO' => ['value' => $Complex2]]]); $QueryType = new ObjectType(['name' => 'Query', 'fields' => ['colorEnum' => ['type' => $ColorType, 'args' => ['fromEnum' => ['type' => $ColorType], 'fromInt' => ['type' => Type::int()], 'fromString' => ['type' => Type::string()]], 'resolve' => function ($value, $args) { if (isset($args['fromInt'])) { return $args['fromInt']; } if (isset($args['fromString'])) { return $args['fromString']; } if (isset($args['fromEnum'])) { return $args['fromEnum']; } }], 'simpleEnum' => ['type' => $simpleEnum, 'args' => ['fromName' => ['type' => Type::string()], 'fromValue' => ['type' => Type::string()]], 'resolve' => function ($value, $args) { if (isset($args['fromName'])) { return $args['fromName']; } if (isset($args['fromValue'])) { return $args['fromValue']; } }], 'colorInt' => ['type' => Type::int(), 'args' => ['fromEnum' => ['type' => $ColorType], 'fromInt' => ['type' => Type::int()]], 'resolve' => function ($value, $args) { if (isset($args['fromInt'])) { return $args['fromInt']; } if (isset($args['fromEnum'])) { return $args['fromEnum']; } }], 'complexEnum' => ['type' => $ComplexEnum, 'args' => ['fromEnum' => ['type' => $ComplexEnum, 'defaultValue' => $Complex1], 'provideGoodValue' => ['type' => Type::boolean()], 'provideBadValue' => ['type' => Type::boolean()]], 'resolve' => function ($value, $args) use($Complex1, $Complex2) { if (!empty($args['provideGoodValue'])) { // Note: this is one of the references of the internal values which // ComplexEnum allows. return $Complex2; } if (!empty($args['provideBadValue'])) { // Note: similar shape, but not the same *reference* // as Complex2 above. Enum internal values require === equality. return new \ArrayObject(['someRandomValue' => 123]); } return $args['fromEnum']; }]]]); $MutationType = new ObjectType(['name' => 'Mutation', 'fields' => ['favoriteEnum' => ['type' => $ColorType, 'args' => ['color' => ['type' => $ColorType]], 'resolve' => function ($value, $args) { return isset($args['color']) ? $args['color'] : null; }]]]); $SubscriptionType = new ObjectType(['name' => 'Subscription', 'fields' => ['subscribeToEnum' => ['type' => $ColorType, 'args' => ['color' => ['type' => $ColorType]], 'resolve' => function ($value, $args) { return isset($args['color']) ? $args['color'] : null; }]]]); $this->Complex1 = $Complex1; $this->Complex2 = $Complex2; $this->ComplexEnum = $ComplexEnum; $this->schema = new Schema(['query' => $QueryType, 'mutation' => $MutationType, 'subscription' => $SubscriptionType]); }
/** * @it uses provided resolve function */ public function testUsesProvidedResolveFunction() { $schema = $this->buildSchema(['type' => Type::string(), 'args' => ['aStr' => ['type' => Type::string()], 'aInt' => ['type' => Type::int()]], 'resolve' => function ($source, $args) { return json_encode([$source, $args]); }]); $this->assertEquals(['data' => ['test' => '[null,[]]']], GraphQL::execute($schema, '{ test }')); $this->assertEquals(['data' => ['test' => '["Source!",[]]']], GraphQL::execute($schema, '{ test }', 'Source!')); $this->assertEquals(['data' => ['test' => '["Source!",{"aStr":"String!"}]']], GraphQL::execute($schema, '{ test(aStr: "String!") }', 'Source!')); $this->assertEquals(['data' => ['test' => '["Source!",{"aStr":"String!","aInt":-123}]']], GraphQL::execute($schema, '{ test(aInt: -123, aStr: "String!") }', 'Source!')); }
/** * @it does not convert when input coercion rules reject a value */ public function testDoesNotConvertWhenInputCoercionRulesRejectAValue() { $undefined = Utils::undefined(); $this->runTestCase(Type::boolean(), '123', $undefined); $this->runTestCase(Type::int(), '123.456', $undefined); $this->runTestCase(Type::int(), 'true', $undefined); $this->runTestCase(Type::int(), '"123"', $undefined); $this->runTestCase(Type::float(), '"123"', $undefined); $this->runTestCase(Type::string(), '123', $undefined); $this->runTestCase(Type::string(), 'true', $undefined); $this->runTestCase(Type::id(), '123.456', $undefined); }
protected static function getSchema() { $userType = new ObjectType(['name' => 'User', 'fields' => function () { return ['username' => ['type' => Type::string()], 'url' => ['type' => Type::string()]]; }]); $queryType = new ObjectType(['name' => 'Query', 'fields' => function () use($userType) { return ['usernames' => Plural::pluralIdentifyingRootField(['argName' => 'usernames', 'description' => 'Map from a username to the user', 'inputType' => Type::string(), 'outputType' => $userType, 'resolveSingleInput' => function ($userName, $context, $info) { return ['username' => $userName, 'url' => 'www.facebook.com/' . $userName . '?lang=' . $info->rootValue['lang']]; }])]; }]); return new Schema(['query' => $queryType]); }
public function testExecutesUsingASchema() { $BlogArticle = null; $BlogImage = new ObjectType(['name' => 'Image', 'fields' => ['url' => ['type' => Type::string()], 'width' => ['type' => Type::int()], 'height' => ['type' => Type::int()]]]); $BlogAuthor = new ObjectType(['name' => 'Author', 'fields' => ['id' => ['type' => Type::string()], 'name' => ['type' => Type::string()], 'pic' => ['args' => ['width' => ['type' => Type::int()], 'height' => ['type' => Type::int()]], 'type' => $BlogImage, 'resolve' => function ($obj, $args) { return $obj['pic']($args['width'], $args['height']); }], 'recentArticle' => ['type' => function () use(&$BlogArticle) { return $BlogArticle; }]]]); $BlogArticle = new ObjectType(['name' => 'Article', 'fields' => ['id' => ['type' => Type::nonNull(Type::string())], 'isPublished' => ['type' => Type::boolean()], 'author' => ['type' => $BlogAuthor], 'title' => ['type' => Type::string()], 'body' => ['type' => Type::string()], 'keywords' => ['type' => Type::listOf(Type::string())]]]); $BlogQuery = new ObjectType(['name' => 'Query', 'fields' => ['article' => ['type' => $BlogArticle, 'args' => ['id' => ['type' => Type::id()]], 'resolve' => function ($_, $args) { return $this->article($args['id']); }], 'feed' => ['type' => Type::listOf($BlogArticle), 'resolve' => function () { return [$this->article(1), $this->article(2), $this->article(3), $this->article(4), $this->article(5), $this->article(6), $this->article(7), $this->article(8), $this->article(9), $this->article(10)]; }]]]); $BlogSchema = new Schema($BlogQuery); $request = ' { feed { id, title }, article(id: "1") { ...articleFields, author { id, name, pic(width: 640, height: 480) { url, width, height }, recentArticle { ...articleFields, keywords } } } } fragment articleFields on Article { id, isPublished, title, body, hidden, notdefined } '; $expected = ['data' => ['feed' => [['id' => '1', 'title' => 'My Article 1'], ['id' => '2', 'title' => 'My Article 2'], ['id' => '3', 'title' => 'My Article 3'], ['id' => '4', 'title' => 'My Article 4'], ['id' => '5', 'title' => 'My Article 5'], ['id' => '6', 'title' => 'My Article 6'], ['id' => '7', 'title' => 'My Article 7'], ['id' => '8', 'title' => 'My Article 8'], ['id' => '9', 'title' => 'My Article 9'], ['id' => '10', 'title' => 'My Article 10']], 'article' => ['id' => '1', 'isPublished' => true, 'title' => 'My Article 1', 'body' => 'This is a post', 'author' => ['id' => '123', 'name' => 'John Smith', 'pic' => ['url' => 'cdn://123', 'width' => 640, 'height' => 480], 'recentArticle' => ['id' => '1', 'isPublished' => true, 'title' => 'My Article 1', 'body' => 'This is a post', 'keywords' => ['foo', 'bar', '1', 'true', null]]]]]]; $this->assertEquals($expected, Executor::execute($BlogSchema, Parser::parse($request))->toArray()); }
/** * Fields that exist on every connection. * * @return array */ public function fields() { return ['node' => ['type' => $this->type, 'description' => 'The item at the end of the edge.', 'resolve' => function ($edge) { return $edge; }], 'cursor' => ['type' => Type::nonNull(Type::string()), 'description' => 'A cursor for use in pagination.', 'resolve' => function ($edge) { if (is_array($edge) && isset($edge['relayCursor'])) { return $edge['relayCursor']; } elseif (is_array($edge->attributes)) { return $edge->attributes['relayCursor']; } return $edge->relayCursor; }]]; }
function getConfig($config) { return array_replace_recursive(['description' => 'Items in a navigation menu', 'fields' => ['id' => ['type' => Type::string(), 'description' => 'Unique id for menu item', 'resolve' => function ($item) { return $item->object_id; }], 'caption' => ['type' => Type::string(), 'description' => 'File caption', 'resolve' => function ($item) { return $item->caption; }], 'title' => ['type' => Type::string(), 'description' => 'File title', 'resolve' => function ($item) { return $item->title; }], 'target' => ['type' => Type::string(), 'description' => 'Link target', 'resolve' => function ($item) { return $item->target; }], 'url' => ['type' => Type::string(), 'description' => 'Menu url', 'resolve' => function ($item) { return $item->url; }], 'description' => ['type' => Type::string(), 'description' => 'Link description', 'resolve' => function ($item) { return $item->description; }], 'classes' => ['type' => new ListOfType(Type::string()), 'description' => 'CSS class names for this item', 'resolve' => function ($item) { return $item->classes; }]]], $config); }
/** * Fields available on PageInfo. * * @return array */ public function fields() { return ['hasNextPage' => ['type' => Type::nonNull(Type::boolean()), 'description' => 'When paginating forwards, are there more items?', 'resolve' => function ($collection) { if ($collection instanceof LengthAwarePaginator) { return $collection->hasMorePages(); } return false; }], 'hasPreviousPage' => ['type' => Type::nonNull(Type::boolean()), 'description' => 'When paginating backwards, are there more items?', 'resolve' => function ($collection) { if ($collection instanceof LengthAwarePaginator) { return $collection->currentPage() > 1; } return false; }], 'startCursor' => ['type' => Type::string(), 'description' => 'When paginating backwards, the cursor to continue.', 'resolve' => function ($collection) { if ($collection instanceof LengthAwarePaginator) { return $this->encodeGlobalId('arrayconnection', $collection->firstItem() * $collection->currentPage()); } return null; }], 'endCursor' => ['type' => Type::string(), 'description' => 'When paginating forwards, the cursor to continue.', 'resolve' => function ($collection) { if ($collection instanceof LengthAwarePaginator) { return $this->encodeGlobalId('arrayconnection', $collection->lastItem() * $collection->currentPage()); } return null; }], 'total' => ['type' => Type::int(), 'description' => 'Total number of node in connection.', 'resolve' => function ($collection) { if ($collection instanceof LengthAwarePaginator) { return $collection->total(); } return null; }], 'count' => ['type' => Type::int(), 'description' => 'Count of nodes in current request.', 'resolve' => function ($collection) { if ($collection instanceof LengthAwarePaginator) { return $collection->count(); } return null; }], 'currentPage' => ['type' => Type::int(), 'description' => 'Current page of request.', 'resolve' => function ($collection) { if ($collection instanceof LengthAwarePaginator) { return $collection->currentPage(); } return null; }], 'lastPage' => ['type' => Type::int(), 'description' => 'Last page in connection.', 'resolve' => function ($collection) { if ($collection instanceof LengthAwarePaginator) { return $collection->lastPage(); } return null; }]]; }
function getConfig($config) { return array_replace_recursive(['description' => 'An image from the ACF plugin', 'fields' => ['caption' => ['description' => 'Image caption'], 'title' => ['description' => 'Image title'], 'url' => ['description' => 'Image path', 'args' => ['size' => ['description' => 'size of the image', 'type' => Type::string()]], 'resolve' => function ($field, $args) { $args += ['size' => 'medium']; $size = $args['size']; if ($size == 'full') { return $field['url']; } return $field['sizes'][$size]; }], 'width' => ['type' => Type::int(), 'description' => 'Image width', 'args' => ['size' => ['description' => 'size of the image', 'type' => Type::string()]], 'resolve' => function ($field) { $args += ['size' => 'medium']; $size = $args['size']; return $field['sizes'][$size . '-width']; }], 'height' => ['type' => Type::int(), 'description' => 'Image width', 'args' => ['size' => ['description' => 'size of the image', 'type' => Type::string()]], 'resolve' => function ($post) { $args += ['size' => 'medium']; $size = $args['size']; return $field['sizes'][$size . '-height']; }]]], parent::getConfig($config)); }
public function setup() { $this->simpleMutation = Mutation::mutationWithClientMutationId(['name' => 'SimpleMutation', 'inputFields' => [], 'outputFields' => ['result' => ['type' => Type::int()]], 'mutateAndGetPayload' => function () { return ['result' => 1]; }]); $this->simpleMutationWithThunkFields = Mutation::mutationWithClientMutationId(['name' => 'SimpleMutationWithThunkFields', 'inputFields' => function () { return ['inputData' => ['type' => Type::int()]]; }, 'outputFields' => function () { return ['result' => ['type' => Type::int()]]; }, 'mutateAndGetPayload' => function ($inputData) { return ['result' => $inputData['inputData']]; }]); $userType = new ObjectType(['name' => 'User', 'fields' => ['name' => ['type' => Type::string()]]]); $this->edgeMutation = Mutation::mutationWithClientMutationId(['name' => 'EdgeMutation', 'inputFields' => [], 'outputFields' => ['result' => ['type' => Connection::createEdgeType(['nodeType' => $userType])]], 'mutateAndGetPayload' => function () { return ['result' => ['node' => ['name' => 'Robert'], 'cursor' => 'SWxvdmVHcmFwaFFM']]; }]); $this->mutation = new ObjectType(['name' => 'Mutation', 'fields' => ['simpleMutation' => $this->simpleMutation, 'simpleMutationWithThunkFields' => $this->simpleMutationWithThunkFields, 'edgeMutation' => $this->edgeMutation]]); $this->schema = new Schema(['mutation' => $this->mutation, 'query' => $this->mutation]); }
/** * Returns a GraphQLFieldConfig for the mutation described by the * provided MutationConfig. * * A description of a mutation consumable by mutationWithClientMutationId * to create a GraphQLFieldConfig for that mutation. * * The inputFields and outputFields should not include `clientMutationId`, * as this will be provided automatically. * * An input object will be created containing the input fields, and an * object will be created containing the output fields. * * mutateAndGetPayload will receieve an Object with a key for each * input field, and it should return an Object with a key for each * output field. It may return synchronously, or return a Promise. * * type MutationConfig = { * name: string, * inputFields: InputObjectConfigFieldMap, * outputFields: GraphQLFieldConfigMap, * mutateAndGetPayload: mutationFn, * } */ public static function mutationWithClientMutationId(array $config) { $name = self::getArrayValue($config, 'name'); $inputFields = self::getArrayValue($config, 'inputFields'); $outputFields = self::getArrayValue($config, 'outputFields'); $mutateAndGetPayload = self::getArrayValue($config, 'mutateAndGetPayload'); $augmentedInputFields = function () use($inputFields) { $inputFieldsResolved = self::resolveMaybeThunk($inputFields); return array_merge($inputFieldsResolved !== null ? $inputFieldsResolved : [], ['clientMutationId' => ['type' => Type::nonNull(Type::string())]]); }; $augmentedOutputFields = function () use($outputFields) { $outputFieldsResolved = self::resolveMaybeThunk($outputFields); return array_merge($outputFieldsResolved !== null ? $outputFieldsResolved : [], ['clientMutationId' => ['type' => Type::nonNull(Type::string())]]); }; $outputType = new ObjectType(['name' => $name . 'Payload', 'fields' => $augmentedOutputFields]); $inputType = new InputObjectType(['name' => $name . 'Input', 'fields' => $augmentedInputFields]); return ['type' => $outputType, 'args' => ['input' => ['type' => Type::nonNull($inputType)]], 'resolve' => function ($query, $args, $context, ResolveInfo $info) use($mutateAndGetPayload) { $payload = call_user_func($mutateAndGetPayload, $args['input'], $context, $info); $payload['clientMutationId'] = $args['input']['clientMutationId']; return $payload; }]; }
/** * Returns node definitions * * @return array */ protected function getNodeDefinitions() { if (!self::$nodeDefinition) { self::$nodeDefinition = Node::nodeDefinitions(function ($id, $context, ResolveInfo $info) { $userData = $this->getUserData(); if (array_key_exists($id, $userData)) { return $userData[$id]; } else { $photoData = $this->getPhotoData(); if (array_key_exists($id, $photoData)) { return $photoData[$id]; } } }, function ($obj) { if (array_key_exists($obj['id'], $this->getUserData())) { return self::$userType; } else { return self::$photoType; } }); self::$userType = new ObjectType(['name' => 'User', 'fields' => ['id' => ['type' => Type::nonNull(Type::id())], 'name' => ['type' => Type::string()]], 'interfaces' => [self::$nodeDefinition['nodeInterface']]]); self::$photoType = new ObjectType(['name' => 'Photo', 'fields' => ['id' => ['type' => Type::nonNull(Type::id())], 'width' => ['type' => Type::int()]], 'interfaces' => [self::$nodeDefinition['nodeInterface']]]); } return self::$nodeDefinition; }
/** * Type fields. * * @return array */ public function fields() { return ['name' => ['type' => Type::string(), 'description' => 'Name of company.'], 'users' => GraphQL::connection(new UserConnection())->field()]; }
/** * @it fails as expected on the __type root field without an arg */ public function testFailsAsExpectedOnThe__typeRootFieldWithoutAnArg() { $TestType = new ObjectType(['name' => 'TestType', 'fields' => ['testField' => ['type' => Type::string()]]]); $schema = new Schema(['query' => $TestType]); $request = ' { __type { name } } '; $expected = ['errors' => [FormattedError::create(ProvidedNonNullArguments::missingFieldArgMessage('__type', 'name', 'String!'), [new SourceLocation(3, 9)])]]; $this->assertEquals($expected, GraphQL::execute($schema, $request)); }
/** * Generate EdgeType. * * @param string $name * @param mixed $type * @param Closure $resolveCursor * @return ObjectType */ protected function edgeType($name, $type, Closure $resolveCursor = null) { if ($type instanceof ListOfType) { $type = $type->getWrappedType(); } return new ObjectType(['name' => ucfirst($name) . 'Edge', 'fields' => ['node' => ['type' => $type, 'description' => 'The item at the end of the edge.', 'resolve' => function ($edge, array $args, ResolveInfo $info) { return $edge; }], 'cursor' => ['type' => Type::nonNull(Type::string()), 'description' => 'A cursor for use in pagination.', 'resolve' => function ($edge, array $args, ResolveInfo $info) use($resolveCursor) { if ($resolveCursor) { return $resolveCursor($edge, $args, $info); } return $this->resolveCursor($edge); }]]]); }
static function build() { $typeEnum = new EnumType(["name" => "Type", "description" => "The type of entity", "values" => ["user" => ["value" => "user"], "group" => ["value" => "group"], "object" => ["value" => "object"]]]); $statusEnum = new EnumType(["name" => "Status", "description" => "The status of the entity", "values" => ["ok" => ["value" => "ok"], "access_denied" => ["value" => "access_denied"], "not_found" => ["value" => "not_found"]]]); $voteDirectionEnum = new EnumType(["name" => "VoteType", "description" => "The type of vote", "values" => ["up" => ["value" => "up"], "down" => ["value" => "down"]]]); $entityInterface = new InterfaceType(["name" => "Entity", "fields" => ["guid" => ["type" => Type::nonNull(Type::string())], "status" => ["type" => Type::nonNull($statusEnum)]], "resolveType" => function ($object) use(&$userType, &$objectType, &$groupType) { switch ($object["type"]) { case "user": return $userType; case "object": return $objectType; case "group": return $groupType; } }]); $accessIdType = new ObjectType(["name" => "AccessId", "fields" => ["id" => ["type" => Type::nonNull(Type::int())], "description" => ["type" => Type::nonNull(Type::string())]]]); $userType = new ObjectType(["name" => "User", "interfaces" => [$entityInterface], "fields" => ["guid" => ["type" => Type::nonNull(Type::string())], "status" => ["type" => Type::nonNull($statusEnum)], "name" => ["type" => Type::string()], "icon" => ["type" => Type::string()], "url" => ["type" => Type::string()]]]); $groupType = new ObjectType(["name" => "Group", "interfaces" => [$entityInterface], "fields" => ["guid" => ["type" => Type::nonNull(Type::string())], "status" => ["type" => Type::nonNull($statusEnum)], "name" => ["type" => Type::string()], "icon" => ["type" => Type::string()], "canEdit" => ["type" => Type::boolean()], "isClosed" => ["type" => Type::boolean()], "canJoin" => ["type" => Type::boolean()], "defaultAccessId" => ["type" => Type::int()]]]); $objectType = new ObjectType(["name" => "Object", "interfaces" => [$entityInterface], "fields" => ["guid" => ["type" => Type::nonNull(Type::string())], "status" => ["type" => Type::nonNull($statusEnum)], "title" => ["type" => Type::string()], "subtype" => ["type" => Type::string()], "description" => ["type" => Type::string()], "url" => ["type" => Type::string()], "tags" => ["type" => Type::listOf(Type::string())], "timeCreated" => ["type" => Type::string()], "timeUpdated" => ["type" => Type::string()], "canEdit" => ["type" => Type::boolean()], "canComment" => ["type" => Type::boolean()], "accessId" => ["type" => Type::int()], "isBookmarked" => ["type" => Type::boolean(), "resolve" => function ($object) { return Resolver::isBookmarked($object); }], "votes" => ["type" => Type::int(), "resolve" => function ($object) { return Resolver::countVotes($object); }], "owner" => ["type" => $userType, "resolve" => function ($object) { return Resolver::getUser($object["ownerGuid"]); }], "comments" => ["type" => function () use(&$objectType) { return Type::listOf($objectType); }, "resolve" => function ($object) { return Resolver::getComments($object); }]]]); $searchListType = new ObjectType(["name" => "Search", "fields" => ["total" => ["type" => Type::nonNull(Type::int())], "results" => ["type" => Type::listOf($entityInterface)]]]); $entityListType = new ObjectType(["name" => "EntityList", "fields" => ["total" => ["type" => Type::nonNull(Type::int())], "canWrite" => ["type" => Type::nonNull(Type::boolean())], "entities" => ["type" => Type::listOf($entityInterface)]]]); $viewerType = new ObjectType(["name" => "Viewer", "description" => "The current site viewer", "fields" => ["guid" => ["type" => Type::nonNull(Type::string())], "loggedIn" => ["type" => Type::nonNull(Type::boolean())], "username" => ["type" => Type::string()], "name" => ["type" => Type::string()], "icon" => ["type" => Type::string()], "url" => ["type" => Type::string()], "bookmarks" => ["type" => $entityListType, "args" => ["offset" => ["type" => Type::int()], "limit" => ["type" => Type::int()]], "resolve" => "Pleio\\Resolver::getBookmarks"]]]); $menuItemType = new ObjectType(["name" => "MenuItem", "fields" => ["guid" => ["type" => Type::nonNull(Type::string())], "title" => ["type" => Type::nonNull(Type::string())], "link" => ["type" => Type::nonNull(Type::string())], "js" => ["type" => Type::nonNull(Type::boolean())]]]); $siteType = new ObjectType(["name" => "Site", "description" => "The current site", "fields" => ["id" => ["type" => Type::nonNull(Type::string())], "title" => ["type" => Type::nonNull(Type::string())], "menu" => ["type" => Type::listOf($menuItemType)], "accessIds" => ["type" => Type::listOf($accessIdType)], "defaultAccessId" => ["type" => Type::nonNull(Type::int())]]]); $queryType = new ObjectType(["name" => "Query", "fields" => ["viewer" => ["type" => $viewerType, "resolve" => "Pleio\\Resolver::getViewer"], "entity" => ["type" => $entityInterface, "args" => ["guid" => ["type" => Type::nonNull(Type::string())]], "resolve" => "Pleio\\Resolver::getEntity"], "search" => ["type" => $searchListType, "args" => ["q" => ["type" => Type::nonNull(Type::string())], "offset" => ["type" => Type::int()], "limit" => ["type" => Type::int()]], "resolve" => "Pleio\\Resolver::search"], "entities" => ["type" => $entityListType, "args" => ["offset" => ["type" => Type::int()], "limit" => ["type" => Type::int()], "type" => ["type" => $typeEnum], "subtype" => ["type" => Type::string()], "containerGuid" => ["type" => Type::int()], "tags" => ["type" => Type::listOf(Type::string())]], "resolve" => "Pleio\\Resolver::getEntities"], "site" => ["type" => $siteType, "resolve" => "Pleio\\Resolver::getSite"]]]); $loginMutation = Relay::mutationWithClientMutationId(["name" => "login", "inputFields" => ["username" => ["type" => Type::nonNull(Type::string())], "password" => ["type" => Type::nonNull(Type::string())], "rememberMe" => ["type" => Type::boolean()]], "outputFields" => ["viewer" => ["type" => $viewerType, "resolve" => "Pleio\\Resolver::getViewer"]], "mutateAndGetPayload" => "Pleio\\Mutations::login"]); $logoutMutation = Relay::mutationWithClientMutationId(["name" => "logout", "inputFields" => [], "outputFields" => ["viewer" => ["type" => $viewerType, "resolve" => "Pleio\\Resolver::getViewer"]], "mutateAndGetPayload" => "Pleio\\Mutations::logout"]); $registerMutation = Relay::mutationWithClientMutationId(["name" => "register", "inputFields" => ["name" => ["type" => Type::nonNull(Type::string())], "email" => ["type" => Type::nonNull(Type::string())], "password" => ["type" => Type::nonNull(Type::string())], "newsletter" => ["type" => Type::boolean()], "terms" => ["type" => Type::boolean()]], "outputFields" => ["viewer" => ["type" => $viewerType, "resolve" => "Pleio\\Resolver::getViewer"]], "mutateAndGetPayload" => "Pleio\\Mutations::register"]); $forgotPasswordMutation = Relay::mutationWithClientMutationId(["name" => "forgotPassword", "inputFields" => ["username" => ["type" => Type::nonNull(Type::string())]], "outputFields" => ["status" => ["type" => Type::nonNull($statusEnum), "resolve" => function ($return) { return $return["status"]; }]], "mutateAndGetPayload" => "Pleio\\Mutations::forgotPassword"]); $forgotPasswordConfirmMutation = Relay::mutationWithClientMutationId(["name" => "forgotPasswordConfirm", "inputFields" => ["userGuid" => ["type" => Type::nonNull(Type::string())], "code" => ["type" => Type::nonNull(Type::string())]], "outputFields" => ["status" => ["type" => Type::nonNull($statusEnum), "resolve" => function ($return) { return $return["status"]; }]], "mutateAndGetPayload" => "Pleio\\Mutations::forgotPasswordConfirm"]); $subscribeNewsletterMutation = Relay::mutationWithClientMutationId(["name" => "subscribeNewsletter", "inputFields" => ["email" => ["type" => Type::nonNull(Type::string())]], "outputFields" => ["viewer" => ["type" => $viewerType, "resolve" => "Pleio\\Resolver::getViewer"]], "mutateAndGetPayload" => "Pleio\\Mutations::subscribeNewsletter"]); $addEntityMutation = Relay::mutationWithClientMutationId(["name" => "addEntity", "inputFields" => ["type" => ["type" => Type::nonNull($typeEnum)], "subtype" => ["type" => Type::nonNull(Type::string())], "title" => ["type" => Type::string()], "description" => ["type" => Type::nonNull(Type::string())], "containerGuid" => ["type" => Type::int()], "accessId" => ["type" => Type::int()], "tags" => ["type" => Type::listOf(Type::string())]], "outputFields" => ["entity" => ["type" => $entityInterface, "resolve" => function ($entity) { return Resolver::getEntity(null, $entity, null); }]], "mutateAndGetPayload" => "Pleio\\Mutations::addEntity"]); $editEntityMutation = Relay::mutationWithClientMutationId(["name" => "editEntity", "inputFields" => ["guid" => ["type" => Type::nonNull(Type::string())], "title" => ["type" => Type::string()], "description" => ["type" => Type::nonNull(Type::string())], "accessId" => ["type" => Type::int()], "tags" => ["type" => Type::listOf(Type::string())]], "outputFields" => ["entity" => ["type" => $entityInterface, "resolve" => function ($entity) { return Resolver::getEntity(null, $entity, null); }]], "mutateAndGetPayload" => "Pleio\\Mutations::editEntity"]); $deleteEntityMutation = Relay::mutationWithClientMutationId(["name" => "deleteEntity", "inputFields" => ["guid" => ["type" => Type::nonNull(Type::string())]], "outputFields" => ["entity" => ["type" => $entityInterface, "resolve" => function ($entity) { return Resolver::getEntity(null, $entity, null); }]], "mutateAndGetPayload" => "Pleio\\Mutations::deleteEntity"]); $bookmarkMutation = Relay::mutationWithClientMutationId(["name" => "bookmark", "inputFields" => ["guid" => ["type" => Type::nonNull(Type::string()), "description" => "The guid of the entity to bookmark."], "isAdding" => ["type" => Type::nonNull(Type::boolean()), "description" => "True when adding, false when removing."]], "outputFields" => ["object" => ["type" => Type::nonNull($objectType), "resolve" => function ($entity) { return Resolver::getEntity(null, $entity, null); }]], "mutateAndGetPayload" => "Pleio\\Mutations::bookmark"]); $voteMutation = Relay::mutationWithClientMutationId(["name" => "vote", "inputFields" => ["guid" => ["type" => Type::nonNull(Type::string()), "description" => "The guid of the entity to bookmark."], "direction" => ["type" => Type::nonNull($voteDirectionEnum)]], "outputFields" => ["object" => ["type" => Type::nonNull($objectType), "resolve" => function ($entity) { return Resolver::getEntity(null, $entity, null); }]], "mutateAndGetPayload" => "Pleio\\Mutations::vote"]); $mutationType = new ObjectType(["name" => "Mutation", "fields" => ["login" => $loginMutation, "logout" => $logoutMutation, "register" => $registerMutation, "forgotPassword" => $forgotPasswordMutation, "forgotPasswordConfirm" => $forgotPasswordConfirmMutation, "addEntity" => $addEntityMutation, "editEntity" => $editEntityMutation, "deleteEntity" => $deleteEntityMutation, "subscribeNewsletter" => $subscribeNewsletterMutation, "bookmark" => $bookmarkMutation, "vote" => $voteMutation]]); $schema = new Schema($queryType, $mutationType); return $schema; }
private static function getSchema() { return self::$schema ?: (self::$schema = new Schema(new ObjectType(['name' => 'TestType', 'fields' => ['a' => ['type' => Type::string()], 'b' => ['type' => Type::string()]]]))); }
public function testSubstitutesArgumentWithDefaultValue() { $schema = new Schema(['query' => new ObjectType(['name' => 'Type', 'fields' => ['field' => ['type' => Type::string(), 'resolve' => function ($data, $args) { return $args ? json_encode($args) : ''; }, 'args' => ['a' => ['type' => Type::boolean(), 'defaultValue' => 1], 'b' => ['type' => Type::boolean(), 'defaultValue' => null], 'c' => ['type' => Type::boolean(), 'defaultValue' => 0], 'd' => ['type' => Type::int(), 'defaultValue' => false], 'e' => ['type' => Type::int(), 'defaultValue' => '0'], 'f' => ['type' => Type::int(), 'defaultValue' => 'some-string'], 'g' => ['type' => Type::boolean()], 'h' => ['type' => new InputObjectType(['name' => 'ComplexType', 'fields' => ['a' => ['type' => Type::int()], 'b' => ['type' => Type::string()]]]), 'defaultValue' => ['a' => 1, 'b' => 'test']]]]]])]); $query = Parser::parse('{ field }'); $result = Executor::execute($schema, $query); $expected = ['data' => ['field' => '{"a":1,"b":null,"c":0,"d":false,"e":"0","f":"some-string","h":{"a":1,"b":"test"}}']]; $this->assertEquals($expected, $result->toArray()); }