Chris@0: getArguments($callable); Chris@0: $this->assertSame($expected, $arguments); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Provides test data to testGetArgument(). Chris@0: */ Chris@0: public function providerTestGetArgument() { Chris@0: $data = []; Chris@0: Chris@0: // Test an optional parameter with no provided value. Chris@0: $data[] = [ Chris@0: function ($foo = 'foo') {}, [], [], [] , ['foo'], Chris@0: ]; Chris@0: Chris@0: // Test an optional parameter with a provided value. Chris@0: $data[] = [ Chris@0: function ($foo = 'foo') {}, ['foo' => 'bar'], [], [], ['bar'], Chris@0: ]; Chris@0: Chris@0: // Test with a provided value. Chris@0: $data[] = [ Chris@0: function ($foo) {}, ['foo' => 'bar'], [], [], ['bar'], Chris@0: ]; Chris@0: Chris@0: // Test with an explicitly NULL value. Chris@0: $data[] = [ Chris@0: function ($foo) {}, [], ['foo' => NULL], [], [NULL], Chris@0: ]; Chris@0: Chris@0: // Test with a raw value that overrides the provided upcast value, since Chris@0: // it is not typehinted. Chris@17: $scalars = ['foo' => 'baz']; Chris@0: $objects = ['foo' => new \stdClass()]; Chris@0: $data[] = [ Chris@0: function ($foo) {}, $scalars, $objects, [], ['baz'], Chris@0: ]; Chris@0: Chris@0: return $data; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests getArgument() with an object. Chris@0: */ Chris@0: public function testGetArgumentObject() { Chris@0: $callable = function (\stdClass $object) {}; Chris@0: Chris@0: $object = new \stdClass(); Chris@0: $arguments = (new ArgumentsResolver([], ['object' => $object], []))->getArguments($callable); Chris@0: $this->assertSame([$object], $arguments); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests getArgument() with a wildcard object for a parameter with a custom name. Chris@0: */ Chris@0: public function testGetWildcardArgument() { Chris@0: $callable = function (\stdClass $custom_name) {}; Chris@0: Chris@0: $object = new \stdClass(); Chris@0: $arguments = (new ArgumentsResolver([], [], [$object]))->getArguments($callable); Chris@0: $this->assertSame([$object], $arguments); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests getArgument() with a Route, Request, and Account object. Chris@0: */ Chris@0: public function testGetArgumentOrder() { Chris@14: $a1 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test1Interface')->getMock(); Chris@14: $a2 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\TestClass')->getMock(); Chris@14: $a3 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test2Interface')->getMock(); Chris@0: Chris@0: $objects = [ Chris@0: 't1' => $a1, Chris@0: 'tc' => $a2, Chris@0: ]; Chris@0: $wildcards = [$a3]; Chris@0: $resolver = new ArgumentsResolver([], $objects, $wildcards); Chris@0: Chris@0: $callable = function (Test1Interface $t1, TestClass $tc, Test2Interface $t2) {}; Chris@0: $arguments = $resolver->getArguments($callable); Chris@0: $this->assertSame([$a1, $a2, $a3], $arguments); Chris@0: Chris@0: // Test again, but with the arguments in a different order. Chris@0: $callable = function (Test2Interface $t2, TestClass $tc, Test1Interface $t1) {}; Chris@0: $arguments = $resolver->getArguments($callable); Chris@0: $this->assertSame([$a3, $a2, $a1], $arguments); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests getArgument() with a wildcard parameter with no typehint. Chris@0: * Chris@0: * Without the typehint, the wildcard object will not be passed to the callable. Chris@0: */ Chris@0: public function testGetWildcardArgumentNoTypehint() { Chris@14: $a = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test1Interface')->getMock(); Chris@0: $wildcards = [$a]; Chris@0: $resolver = new ArgumentsResolver([], [], $wildcards); Chris@0: Chris@0: $callable = function ($route) {}; Chris@14: if (method_exists($this, 'expectException')) { Chris@14: $this->expectException(\RuntimeException::class); Chris@14: $this->expectExceptionMessage('requires a value for the "$route" argument.'); Chris@14: } Chris@14: else { Chris@14: $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$route" argument.'); Chris@14: } Chris@0: $resolver->getArguments($callable); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests getArgument() with a named parameter with no typehint and a value. Chris@0: * Chris@0: * Without the typehint, passing a value to a named parameter will still Chris@0: * receive the provided value. Chris@0: */ Chris@0: public function testGetArgumentRouteNoTypehintAndValue() { Chris@0: $scalars = ['route' => 'foo']; Chris@0: $resolver = new ArgumentsResolver($scalars, [], []); Chris@0: Chris@0: $callable = function ($route) {}; Chris@0: $arguments = $resolver->getArguments($callable); Chris@0: $this->assertSame(['foo'], $arguments); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests handleUnresolvedArgument() for a scalar argument. Chris@0: */ Chris@0: public function testHandleNotUpcastedArgument() { Chris@0: $objects = ['foo' => 'bar']; Chris@0: $scalars = ['foo' => 'baz']; Chris@0: $resolver = new ArgumentsResolver($scalars, $objects, []); Chris@0: Chris@0: $callable = function (\stdClass $foo) {}; Chris@14: if (method_exists($this, 'expectException')) { Chris@14: $this->expectException(\RuntimeException::class); Chris@14: $this->expectExceptionMessage('requires a value for the "$foo" argument.'); Chris@14: } Chris@14: else { Chris@14: $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.'); Chris@14: } Chris@0: $resolver->getArguments($callable); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests handleUnresolvedArgument() for missing arguments. Chris@0: * Chris@0: * @dataProvider providerTestHandleUnresolvedArgument Chris@0: */ Chris@0: public function testHandleUnresolvedArgument($callable) { Chris@0: $resolver = new ArgumentsResolver([], [], []); Chris@14: if (method_exists($this, 'expectException')) { Chris@14: $this->expectException(\RuntimeException::class); Chris@14: $this->expectExceptionMessage('requires a value for the "$foo" argument.'); Chris@14: } Chris@14: else { Chris@14: $this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.'); Chris@14: } Chris@0: $resolver->getArguments($callable); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Provides test data to testHandleUnresolvedArgument(). Chris@0: */ Chris@0: public function providerTestHandleUnresolvedArgument() { Chris@0: $data = []; Chris@0: $data[] = [function ($foo) {}]; Chris@0: $data[] = [[new TestClass(), 'access']]; Chris@0: $data[] = ['Drupal\Tests\Component\Utility\test_access_arguments_resolver_access']; Chris@0: return $data; Chris@0: } Chris@0: Chris@0: } Chris@0: Chris@0: /** Chris@0: * Provides a test class. Chris@0: */ Chris@0: class TestClass { Chris@17: Chris@0: public function access($foo) { Chris@0: } Chris@0: Chris@0: } Chris@0: Chris@0: /** Chris@0: * Provides a test interface. Chris@0: */ Chris@0: interface Test1Interface { Chris@0: } Chris@0: Chris@0: /** Chris@0: * Provides a different test interface. Chris@0: */ Chris@0: interface Test2Interface { Chris@0: } Chris@0: Chris@0: function test_access_arguments_resolver_access($foo) { Chris@0: }