ArgumentsResolverTest.php 5.96 KB
Newer Older
1 2 3 4 5 6 7
<?php

/**
 * @file
 * Contains \Drupal\Tests\Component\Utility\ArgumentsResolverTest.
 */

8
namespace Drupal\Tests\Component\Utility;
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

use Drupal\Component\Utility\ArgumentsResolver;
use Drupal\Tests\UnitTestCase;

/**
 * @coversDefaultClass \Drupal\Component\Utility\ArgumentsResolver
 * @group Access
 */
class ArgumentsResolverTest extends UnitTestCase {

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();
  }

  /**
   * Tests the getArgument() method.
   *
   * @dataProvider providerTestGetArgument
   */
  public function testGetArgument($callable, $scalars, $objects, $wildcards, $expected) {
    $arguments = (new ArgumentsResolver($scalars, $objects, $wildcards))->getArguments($callable);
    $this->assertSame($expected, $arguments);
  }

  /**
   * Provides test data to testGetArgument().
   */
  public function providerTestGetArgument() {
    $data = [];

    // Test an optional parameter with no provided value.
    $data[] = [
      function($foo = 'foo') {}, [], [], [] , ['foo'],
    ];

    // Test an optional parameter with a provided value.
    $data[] = [
      function($foo = 'foo') {}, ['foo' => 'bar'], [], [], ['bar'],
    ];

    // Test with a provided value.
    $data[] = [
      function($foo) {}, ['foo' => 'bar'], [], [], ['bar'],
    ];

    // Test with an explicitly NULL value.
    $data[] = [
      function($foo) {}, [], ['foo' => NULL], [], [NULL],
    ];

    // Test with a raw value that overrides the provided upcast value, since
    // it is not typehinted.
    $scalars  = ['foo' => 'baz'];
    $objects = ['foo' => new \stdClass()];
    $data[] = [
      function($foo) {}, $scalars, $objects, [], ['baz'],
    ];

    return $data;
  }

  /**
   * Tests getArgument() with an object.
   */
  public function testGetArgumentObject() {
    $callable = function(\stdClass $object) {};

    $object = new \stdClass();
    $arguments = (new ArgumentsResolver([], ['object' => $object], []))->getArguments($callable);
    $this->assertSame([$object], $arguments);
  }

  /**
   * Tests getArgument() with a wildcard object for a parameter with a custom name.
   */
  public function testGetWildcardArgument() {
    $callable = function(\stdClass $custom_name) {};

    $object = new \stdClass();
    $arguments = (new ArgumentsResolver([], [], [$object]))->getArguments($callable);
    $this->assertSame([$object], $arguments);
  }

  /**
   * Tests getArgument() with a Route, Request, and Account object.
   */
  public function testGetArgumentOrder() {
    $a1 = $this->getMock('\Drupal\Tests\Component\Utility\TestInterface1');
    $a2 = $this->getMock('\Drupal\Tests\Component\Utility\TestClass');
    $a3 = $this->getMock('\Drupal\Tests\Component\Utility\TestInterface2');

    $objects = [
      't1' => $a1,
      'tc' => $a2,
    ];
    $wildcards = [$a3];
    $resolver = new ArgumentsResolver([], $objects, $wildcards);

    $callable = function(TestInterface1 $t1, TestClass $tc, TestInterface2 $t2) {};
    $arguments = $resolver->getArguments($callable);
    $this->assertSame([$a1, $a2, $a3], $arguments);

    // Test again, but with the arguments in a different order.
    $callable = function(TestInterface2 $t2, TestClass $tc, TestInterface1 $t1) {};
    $arguments = $resolver->getArguments($callable);
    $this->assertSame([$a3, $a2, $a1], $arguments);
  }

  /**
   * Tests getArgument() with a wildcard parameter with no typehint.
   *
   * Without the typehint, the wildcard object will not be passed to the callable.
   *
   * @expectedException \RuntimeException
   * @expectedExceptionMessage requires a value for the "$route" argument.
   */
  public function testGetWildcardArgumentNoTypehint() {
    $a = $this->getMock('\Drupal\Tests\Component\Utility\TestInterface1');
    $wildcards = [$a];
    $resolver = new ArgumentsResolver([], [], $wildcards);

    $callable = function($route) {};
    $arguments = $resolver->getArguments($callable);
    $this->assertNull($arguments);
  }

  /**
   * Tests getArgument() with a named parameter with no typehint and a value.
   *
   * Without the typehint, passing a value to a named parameter will still
   * receive the provided value.
   */
  public function testGetArgumentRouteNoTypehintAndValue() {
    $scalars = ['route' => 'foo'];
    $resolver = new ArgumentsResolver($scalars, [], []);

    $callable = function($route) {};
    $arguments = $resolver->getArguments($callable);
    $this->assertSame(['foo'], $arguments);
  }

  /**
   * Tests handleUnresolvedArgument() for a scalar argument.
   *
   * @expectedException \RuntimeException
   * @expectedExceptionMessage requires a value for the "$foo" argument.
   */
  public function testHandleNotUpcastedArgument() {
    $objects = ['foo' => 'bar'];
    $scalars = ['foo' => 'baz'];
    $resolver = new ArgumentsResolver($scalars, $objects, []);

    $callable = function(\stdClass $foo) {};
    $arguments = $resolver->getArguments($callable);
    $this->assertNull($arguments);
  }

  /**
   * Tests handleUnresolvedArgument() for missing arguments.
   *
   * @expectedException \RuntimeException
   * @expectedExceptionMessage requires a value for the "$foo" argument.
   *
   * @dataProvider providerTestHandleUnresolvedArgument
   */
  public function testHandleUnresolvedArgument($callable) {
    $resolver = new ArgumentsResolver([], [], []);
    $arguments = $resolver->getArguments($callable);
    $this->assertNull($arguments);
  }

  /**
   * Provides test data to testHandleUnresolvedArgument().
   */
  public function providerTestHandleUnresolvedArgument() {
    $data = [];
    $data[] = [function($foo) {}];
    $data[] = [[new TestClass(), 'access']];
190
    $data[] = ['Drupal\Tests\Component\Utility\test_access_arguments_resolver_access'];
191 192 193 194 195 196 197 198 199 200 201
    return $data;
  }

}

/**
 * Provides a test class.
 */
class TestClass {
  public function access($foo) {
  }
202

203 204 205 206 207 208 209 210 211 212 213 214 215 216
}

/**
 * Provides a test interface.
 */
interface TestInterface1 {
}

/**
 * Provides a different test interface.
 */
interface TestInterface2 {
}

217
function test_access_arguments_resolver_access($foo) {
218
}