Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / core / tests / Drupal / Tests / Component / Utility / ArgumentsResolverTest.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Tests\Component\Utility\ArgumentsResolverTest.
6  */
7
8 namespace Drupal\Tests\Component\Utility;
9
10 use Drupal\Component\Utility\ArgumentsResolver;
11 use PHPUnit\Framework\TestCase;
12
13 /**
14  * @coversDefaultClass \Drupal\Component\Utility\ArgumentsResolver
15  * @group Access
16  */
17 class ArgumentsResolverTest extends TestCase {
18
19   /**
20    * {@inheritdoc}
21    */
22   protected function setUp() {
23     parent::setUp();
24   }
25
26   /**
27    * Tests the getArgument() method.
28    *
29    * @dataProvider providerTestGetArgument
30    */
31   public function testGetArgument($callable, $scalars, $objects, $wildcards, $expected) {
32     $arguments = (new ArgumentsResolver($scalars, $objects, $wildcards))->getArguments($callable);
33     $this->assertSame($expected, $arguments);
34   }
35
36   /**
37    * Provides test data to testGetArgument().
38    */
39   public function providerTestGetArgument() {
40     $data = [];
41
42     // Test an optional parameter with no provided value.
43     $data[] = [
44       function ($foo = 'foo') {}, [], [], [] , ['foo'],
45     ];
46
47     // Test an optional parameter with a provided value.
48     $data[] = [
49       function ($foo = 'foo') {}, ['foo' => 'bar'], [], [], ['bar'],
50     ];
51
52     // Test with a provided value.
53     $data[] = [
54       function ($foo) {}, ['foo' => 'bar'], [], [], ['bar'],
55     ];
56
57     // Test with an explicitly NULL value.
58     $data[] = [
59       function ($foo) {}, [], ['foo' => NULL], [], [NULL],
60     ];
61
62     // Test with a raw value that overrides the provided upcast value, since
63     // it is not typehinted.
64     $scalars  = ['foo' => 'baz'];
65     $objects = ['foo' => new \stdClass()];
66     $data[] = [
67       function ($foo) {}, $scalars, $objects, [], ['baz'],
68     ];
69
70     return $data;
71   }
72
73   /**
74    * Tests getArgument() with an object.
75    */
76   public function testGetArgumentObject() {
77     $callable = function (\stdClass $object) {};
78
79     $object = new \stdClass();
80     $arguments = (new ArgumentsResolver([], ['object' => $object], []))->getArguments($callable);
81     $this->assertSame([$object], $arguments);
82   }
83
84   /**
85    * Tests getArgument() with a wildcard object for a parameter with a custom name.
86    */
87   public function testGetWildcardArgument() {
88     $callable = function (\stdClass $custom_name) {};
89
90     $object = new \stdClass();
91     $arguments = (new ArgumentsResolver([], [], [$object]))->getArguments($callable);
92     $this->assertSame([$object], $arguments);
93   }
94
95   /**
96    * Tests getArgument() with a Route, Request, and Account object.
97    */
98   public function testGetArgumentOrder() {
99     $a1 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test1Interface')->getMock();
100     $a2 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\TestClass')->getMock();
101     $a3 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test2Interface')->getMock();
102
103     $objects = [
104       't1' => $a1,
105       'tc' => $a2,
106     ];
107     $wildcards = [$a3];
108     $resolver = new ArgumentsResolver([], $objects, $wildcards);
109
110     $callable = function (Test1Interface $t1, TestClass $tc, Test2Interface $t2) {};
111     $arguments = $resolver->getArguments($callable);
112     $this->assertSame([$a1, $a2, $a3], $arguments);
113
114     // Test again, but with the arguments in a different order.
115     $callable = function (Test2Interface $t2, TestClass $tc, Test1Interface $t1) {};
116     $arguments = $resolver->getArguments($callable);
117     $this->assertSame([$a3, $a2, $a1], $arguments);
118   }
119
120   /**
121    * Tests getArgument() with a wildcard parameter with no typehint.
122    *
123    * Without the typehint, the wildcard object will not be passed to the callable.
124    */
125   public function testGetWildcardArgumentNoTypehint() {
126     $a = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test1Interface')->getMock();
127     $wildcards = [$a];
128     $resolver = new ArgumentsResolver([], [], $wildcards);
129
130     $callable = function ($route) {};
131     if (method_exists($this, 'expectException')) {
132       $this->expectException(\RuntimeException::class);
133       $this->expectExceptionMessage('requires a value for the "$route" argument.');
134     }
135     else {
136       $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$route" argument.');
137     }
138     $resolver->getArguments($callable);
139   }
140
141   /**
142    * Tests getArgument() with a named parameter with no typehint and a value.
143    *
144    * Without the typehint, passing a value to a named parameter will still
145    * receive the provided value.
146    */
147   public function testGetArgumentRouteNoTypehintAndValue() {
148     $scalars = ['route' => 'foo'];
149     $resolver = new ArgumentsResolver($scalars, [], []);
150
151     $callable = function ($route) {};
152     $arguments = $resolver->getArguments($callable);
153     $this->assertSame(['foo'], $arguments);
154   }
155
156   /**
157    * Tests handleUnresolvedArgument() for a scalar argument.
158    */
159   public function testHandleNotUpcastedArgument() {
160     $objects = ['foo' => 'bar'];
161     $scalars = ['foo' => 'baz'];
162     $resolver = new ArgumentsResolver($scalars, $objects, []);
163
164     $callable = function (\stdClass $foo) {};
165     if (method_exists($this, 'expectException')) {
166       $this->expectException(\RuntimeException::class);
167       $this->expectExceptionMessage('requires a value for the "$foo" argument.');
168     }
169     else {
170       $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.');
171     }
172     $resolver->getArguments($callable);
173   }
174
175   /**
176    * Tests handleUnresolvedArgument() for missing arguments.
177    *
178    * @dataProvider providerTestHandleUnresolvedArgument
179    */
180   public function testHandleUnresolvedArgument($callable) {
181     $resolver = new ArgumentsResolver([], [], []);
182     if (method_exists($this, 'expectException')) {
183       $this->expectException(\RuntimeException::class);
184       $this->expectExceptionMessage('requires a value for the "$foo" argument.');
185     }
186     else {
187       $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.');
188     }
189     $resolver->getArguments($callable);
190   }
191
192   /**
193    * Provides test data to testHandleUnresolvedArgument().
194    */
195   public function providerTestHandleUnresolvedArgument() {
196     $data = [];
197     $data[] = [function ($foo) {}];
198     $data[] = [[new TestClass(), 'access']];
199     $data[] = ['Drupal\Tests\Component\Utility\test_access_arguments_resolver_access'];
200     return $data;
201   }
202
203 }
204
205 /**
206  * Provides a test class.
207  */
208 class TestClass {
209   public function access($foo) {
210   }
211
212 }
213
214 /**
215  * Provides a test interface.
216  */
217 interface Test1Interface {
218 }
219
220 /**
221  * Provides a different test interface.
222  */
223 interface Test2Interface {
224 }
225
226 function test_access_arguments_resolver_access($foo) {
227 }