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); } // Execute: handles non-nullable types public function testNullsANullableFieldThatThrowsSynchronously() { $doc = ' query Q { sync } '; $ast = Parser::parse($doc); $expected = [ 'data' => [ 'sync' => null, ], 'errors' => [ new FormattedError( $this->syncError->message, [new SourceLocation(3, 9)] ) ] ]; $this->assertEquals($expected, Executor::execute($this->schema, $this->throwingData, $ast, 'Q', [])); } public function testNullsASynchronouslyReturnedObjectThatContainsANonNullableFieldThatThrowsSynchronously() { // nulls a synchronously returned object that contains a non-nullable field that throws synchronously $doc = ' query Q { nest { nonNullSync, } } '; $ast = Parser::parse($doc); $expected = [ 'data' => [ 'nest' => null ], 'errors' => [ new FormattedError($this->nonNullSyncError->message, [new SourceLocation(4, 11)]) ] ]; $this->assertEquals($expected, Executor::execute($this->schema, $this->throwingData, $ast, 'Q', [])); } public function testNullsAComplexTreeOfNullableFieldsThatThrow() { $doc = ' query Q { nest { sync nest { sync } } } '; $ast = Parser::parse($doc); $expected = [ 'data' => [ 'nest' => [ 'sync' => null, 'nest' => [ 'sync' => null, ] ] ], 'errors' => [ new FormattedError($this->syncError->message, [new SourceLocation(4, 11)]), new FormattedError($this->syncError->message, [new SourceLocation(6, 13)]), ] ]; $this->assertEquals($expected, Executor::execute($this->schema, $this->throwingData, $ast, 'Q', [])); } public function testNullsANullableFieldThatSynchronouslyReturnsNull() { $doc = ' query Q { sync } '; $ast = Parser::parse($doc); $expected = [ 'data' => [ 'sync' => null, ] ]; $this->assertEquals($expected, Executor::execute($this->schema, $this->nullingData, $ast, 'Q', [])); } public function test4() { // nulls a synchronously returned object that contains a non-nullable field that returns null synchronously $doc = ' query Q { nest { nonNullSync, } } '; $ast = Parser::parse($doc); $expected = [ 'data' => [ 'nest' => null ], 'errors' => [ new FormattedError('Cannot return null for non-nullable type.', [new SourceLocation(4, 11)]) ] ]; $this->assertEquals($expected, Executor::execute($this->schema, $this->nullingData, $ast, 'Q', [])); } public function test5() { // nulls a complex tree of nullable fields that return null $doc = ' query Q { nest { sync nest { sync nest { sync } } } } '; $ast = Parser::parse($doc); $expected = [ 'data' => [ 'nest' => [ 'sync' => null, 'nest' => [ 'sync' => null, 'nest' => [ 'sync' => null ] ], ], ] ]; $this->assertEquals($expected, Executor::execute($this->schema, $this->nullingData, $ast, 'Q', [])); } public function testNullsTheTopLevelIfSyncNonNullableFieldThrows() { $doc = ' query Q { nonNullSync } '; $expected = [ 'data' => null, 'errors' => [ new FormattedError($this->nonNullSyncError->message, [new SourceLocation(2, 17)]) ] ]; $this->assertEquals($expected, Executor::execute($this->schema, $this->throwingData, Parser::parse($doc))); } public function testNullsTheTopLevelIfSyncNonNullableFieldReturnsNull() { // nulls the top level if sync non-nullable field returns null $doc = ' query Q { nonNullSync } '; $expected = [ 'data' => null, 'errors' => [ new FormattedError('Cannot return null for non-nullable type.', [new SourceLocation(2, 17)]), ] ]; $this->assertEquals($expected, Executor::execute($this->schema, $this->nullingData, Parser::parse($doc))); } }