View source  
  <?php
namespace Drupal\Tests\graphql\Kernel;
use GraphQL\Deferred;
use Drupal\graphql\GraphQL\Resolver\ResolverInterface;
class ResolverBuilderTest extends GraphQLTestBase {
  
  protected static $modules = [
    'graphql_resolver_builder_test',
  ];
  
  public function setUp() : void {
    parent::setUp();
    $schema = <<<GQL
      type Query {
        me: String
        tree(id: Int): Tree
      }
      type Tree {
        id(someArg: Int): Int
        name: String
        uri: String
        context: Context
      }
      type Context {
        myContext: String
      }
GQL;
    $this
      ->setUpSchema($schema);
  }
  
  public function testBuilderProducing($input, $expected) : void {
    $plugin = $this->builder
      ->produce($input, []);
    $this
      ->assertInstanceOf($expected, $plugin);
  }
  
  public function testBuilderProducingProvider() : array {
    return [
      [
        'entity_load',
        ResolverInterface::class,
      ],
      [
        'entity_id',
        ResolverInterface::class,
      ],
      [
        'uppercase',
        ResolverInterface::class,
      ],
    ];
  }
  
  public function testFromValue() : void {
    $this
      ->mockResolver('Query', 'me', $this->builder
      ->fromValue('some me'));
    $query = <<<GQL
      query {
        me
      }
GQL;
    $this
      ->assertResults($query, [], [
      'me' => 'some me',
    ]);
  }
  
  public function testFromParent() : void {
    $this
      ->mockResolver('Query', 'tree', $this->builder
      ->fromValue('Some string value'));
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->fromParent());
    $query = <<<GQL
      query {
        tree {
          name
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => 'Some string value',
      ],
    ]);
  }
  
  public function testFromArgument() : void {
    $this
      ->mockResolver('Query', 'tree', $this->builder
      ->fromValue([
      'name' => 'some tree',
      'id' => 5,
    ]));
    $this
      ->mockResolver('Tree', 'id', $this->builder
      ->fromArgument('someArg'));
    $query = <<<GQL
      query {
        tree(id: 5) {
          id(someArg: 234)
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'id' => 234,
      ],
    ]);
  }
  
  public function testFromPath() : void {
    $manager = $this->container
      ->get('typed_data_manager');
    $tree_definition = $manager
      ->createDataDefinition('tree');
    
    $right = $manager
      ->create($tree_definition);
    $right
      ->set('value', 'Front page');
    
    $tree = $manager
      ->create($tree_definition);
    $tree
      ->set('left', [
      'value' => '<front>',
      'right' => $right,
    ]);
    $this
      ->mockResolver('Query', 'tree', $this->builder
      ->fromValue($tree));
    $this
      ->mockResolver('Tree', 'uri', $this->builder
      ->fromPath('tree', 'left.value'));
    $query = <<<GQL
      query {
        tree {
          uri
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'uri' => '<front>',
      ],
    ]);
  }
  
  public function testCompose() : void {
    $this
      ->mockResolver('Query', 'tree', $this->builder
      ->fromValue([
      'name' => 'some tree',
      'id' => 5,
    ]));
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->compose($this->builder
      ->fromValue('Some tree name'), $this->builder
      ->produce('uppercase')
      ->map('string', $this->builder
      ->fromParent())));
    $query = <<<GQL
      query {
        tree {
          name
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => 'SOME TREE NAME',
      ],
    ]);
  }
  
  public function testComposeNullValue() : void {
    $this
      ->mockResolver('Query', 'tree', $this->builder
      ->fromValue([
      'name' => 'some tree',
      'id' => 5,
    ]));
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->compose($this->builder
      ->fromValue(NULL), $this->builder
      ->produce('uppercase')
      ->map('string', $this->builder
      ->fromParent())));
    $query = <<<GQL
      query {
        tree {
          name
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => NULL,
      ],
    ]);
  }
  
  public function testFromContext() : void {
    $this
      ->mockResolver('Query', 'tree', $this->builder
      ->fromValue('some value'));
    $this
      ->mockResolver('Tree', 'context', $this->builder
      ->compose($this->builder
      ->context('my context', $this->builder
      ->fromValue('my context value')), $this->builder
      ->fromValue('some language value')));
    $this
      ->mockResolver('Context', 'myContext', $this->builder
      ->fromContext('my context'));
    $query = <<<GQL
      query {
        tree {
          context {
            myContext
          }
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'context' => [
          'myContext' => 'my context value',
        ],
      ],
    ]);
  }
  
  public function testSimpleCond() : void {
    $this
      ->mockResolver('Query', 'tree', $this->builder
      ->fromValue([
      'name' => 'some tree',
      'id' => 5,
    ]));
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->cond([
      [
        $this->builder
          ->fromValue(FALSE),
        $this->builder
          ->fromValue('This should not be in the result.'),
      ],
      [
        $this->builder
          ->fromValue(TRUE),
        $this->builder
          ->fromValue('But this should.'),
      ],
      [
        $this->builder
          ->fromValue(TRUE),
        $this->builder
          ->fromValue('And this not, event though its true.'),
      ],
    ]));
    $query = <<<GQL
      query {
        tree {
          name
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => 'But this should.',
      ],
    ]);
  }
  
  public function testDeferredCond() : void {
    $this
      ->mockResolver('Query', 'tree', $this->builder
      ->fromValue([
      'name' => 'some tree',
      'id' => 5,
    ]));
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->cond([
      [
        $this->builder
          ->fromValue(FALSE),
        $this->builder
          ->fromValue('This should not be in the result.'),
      ],
      [
        function () {
          return new Deferred(function () {
            return TRUE;
          });
        },
        $this->builder
          ->fromValue('But this should.'),
      ],
      [
        $this->builder
          ->fromValue(TRUE),
        $this->builder
          ->fromValue('And this not, event though its true.'),
      ],
    ]));
    $query = <<<GQL
      query {
        tree {
          name
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => 'But this should.',
      ],
    ]);
  }
  
  public function testParentCond() : void {
    $this
      ->mockResolver('Query', 'tree', [
      'name' => 'some tree',
      'id' => 5,
    ]);
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->cond([
      [
        $this->builder
          ->fromValue(FALSE),
        $this->builder
          ->fromValue('This should not be in the result.'),
      ],
      [
        $this->builder
          ->fromParent(),
        $this->builder
          ->fromValue('But this should.'),
      ],
      [
        $this->builder
          ->fromValue(TRUE),
        $this->builder
          ->fromValue('And this not, event though its true.'),
      ],
    ]));
    $query = <<<GQL
      query {
        tree {
          name
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => 'But this should.',
      ],
    ]);
  }
  
  public function testSimpleDefaultValue() : void {
    $this
      ->mockResolver('Query', 'tree', [
      'name' => 'some tree',
      'id' => 5,
    ]);
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->defaultValue($this->builder
      ->fromValue(NULL), $this->builder
      ->fromValue('bar')));
    $this
      ->mockResolver('Tree', 'uri', $this->builder
      ->defaultValue($this->builder
      ->fromValue('baz'), $this->builder
      ->fromValue('bar')));
    $query = <<<GQL
      query {
        tree(id: 1) {
          name
          uri
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => 'bar',
        'uri' => 'baz',
      ],
    ]);
  }
  
  public function testCompositeDefaultValue() : void {
    $this
      ->mockResolver('Query', 'tree', [
      'name' => 'some tree',
      'id' => 5,
    ]);
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->defaultValue($this->builder
      ->compose($this->builder
      ->fromValue('baz'), $this->builder
      ->fromValue(NULL)), $this->builder
      ->fromValue('bar')));
    $this
      ->mockResolver('Tree', 'uri', $this->builder
      ->defaultValue($this->builder
      ->compose($this->builder
      ->fromValue(TRUE), $this->builder
      ->fromValue('baz')), $this->builder
      ->fromValue('bar')));
    $query = <<<GQL
      query {
        tree(id: 1) {
          name
          uri
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => 'bar',
        'uri' => 'baz',
      ],
    ]);
  }
  
  public function testDeferredDefaultValue() : void {
    $this
      ->mockResolver('Query', 'tree', [
      'name' => 'some tree',
      'id' => 5,
    ]);
    $this
      ->mockResolver('Tree', 'name', $this->builder
      ->defaultValue($this->builder
      ->callback(function () {
      return new Deferred(function () {
        return NULL;
      });
    }), $this->builder
      ->callback(function () {
      return new Deferred(function () {
        return 'bar';
      });
    })));
    $this
      ->mockResolver('Tree', 'uri', $this->builder
      ->defaultValue($this->builder
      ->callback(function () {
      return new Deferred(function () {
        return 'baz';
      });
    }), $this->builder
      ->callback(function () {
      return new Deferred(function () {
        return 'bar';
      });
    })));
    $query = <<<GQL
      query {
        tree(id: 1) {
          name
          uri
        }
      }
GQL;
    $this
      ->assertResults($query, [], [
      'tree' => [
        'name' => 'bar',
        'uri' => 'baz',
      ],
    ]);
  }
}