a44721bd9b4e76d49f3981fcc6188cb35b08cf97
[yaffs-website] / web / core / tests / Drupal / Tests / Component / Plugin / Discovery / StaticDiscoveryDecoratorTest.php
1 <?php
2
3 namespace Drupal\Tests\Component\Plugin\Discovery;
4
5 use PHPUnit\Framework\TestCase;
6
7 /**
8  * @group Plugin
9  * @coversDefaultClass \Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator
10  */
11 class StaticDiscoveryDecoratorTest extends TestCase {
12
13   /**
14    * Helper method to provide a mocked callback object with expectations.
15    *
16    * If there should be a registered definition, then we have to place a
17    * \Callable in the mock object. The return value of this callback is
18    * never used.
19    *
20    * @return \PHPUnit_Framework_MockObject_MockObject
21    *   Mocked object with expectation of registerDefinitionsCallback() being
22    *   called once.
23    */
24   public function getRegisterDefinitionsCallback() {
25     $mock_callable = $this->getMockBuilder('\stdClass')
26       ->setMethods(['registerDefinitionsCallback'])
27       ->getMock();
28     // Set expectations for the callback method.
29     $mock_callable->expects($this->once())
30       ->method('registerDefinitionsCallback');
31     return $mock_callable;
32   }
33
34   /**
35    * Data provider for testGetDefinitions().
36    *
37    * @return array
38    *   - Expected plugin definition.
39    *   - Whether we require the method to register definitions through a
40    *     callback.
41    *   - Whether to throw an exception if the definition is invalid.
42    *   - A plugin definition.
43    *   - Base plugin ID.
44    */
45   public function providerGetDefinition() {
46     return [
47       ['is_defined', TRUE, FALSE, ['plugin-definition' => 'is_defined'], 'plugin-definition'],
48       // Make sure we don't call the decorated method if we shouldn't.
49       ['is_defined', FALSE, FALSE, ['plugin-definition' => 'is_defined'], 'plugin-definition'],
50       // Return NULL for bad plugin id.
51       [NULL, FALSE, FALSE, ['plugin-definition' => 'is_defined'], 'BAD-plugin-definition'],
52       // Generate an exception.
53       [NULL, FALSE, TRUE, ['plugin-definition' => 'is_defined'], 'BAD-plugin-definition'],
54     ];
55   }
56
57   /**
58    * @covers ::getDefinition
59    * @dataProvider providerGetDefinition
60    */
61   public function testGetDefinition($expected, $has_register_definitions, $exception_on_invalid, $definitions, $base_plugin_id) {
62     // Mock our StaticDiscoveryDecorator.
63     $mock_decorator = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator')
64       ->disableOriginalConstructor()
65       ->setMethods(['registeredDefintionCallback'])
66       ->getMock();
67
68     // Set up the ::$registerDefinitions property.
69     $ref_register_definitions = new \ReflectionProperty($mock_decorator, 'registerDefinitions');
70     $ref_register_definitions->setAccessible(TRUE);
71     if ($has_register_definitions) {
72       // Set the callback object on the mocked decorator.
73       $ref_register_definitions->setValue(
74         $mock_decorator,
75         [$this->getRegisterDefinitionsCallback(), 'registerDefinitionsCallback']
76       );
77     }
78     else {
79       // There should be no registerDefinitions callback.
80       $ref_register_definitions->setValue($mock_decorator, NULL);
81     }
82
83     // Set up ::$definitions to an empty array.
84     $ref_definitions = new \ReflectionProperty($mock_decorator, 'definitions');
85     $ref_definitions->setAccessible(TRUE);
86     $ref_definitions->setValue($mock_decorator, []);
87
88     // Mock a decorated object.
89     $mock_decorated = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\DiscoveryInterface')
90       ->setMethods(['getDefinitions'])
91       ->getMockForAbstractClass();
92     // Return our definitions from getDefinitions().
93     $mock_decorated->expects($this->once())
94       ->method('getDefinitions')
95       ->willReturn($definitions);
96
97     // Set up ::$decorated to our mocked decorated object.
98     $ref_decorated = new \ReflectionProperty($mock_decorator, 'decorated');
99     $ref_decorated->setAccessible(TRUE);
100     $ref_decorated->setValue($mock_decorator, $mock_decorated);
101
102     if ($exception_on_invalid) {
103       $this->setExpectedException('Drupal\Component\Plugin\Exception\PluginNotFoundException');
104     }
105
106     // Exercise getDefinition(). It calls parent::getDefinition().
107     $this->assertEquals(
108       $expected,
109       $mock_decorator->getDefinition($base_plugin_id, $exception_on_invalid)
110     );
111   }
112
113   /**
114    * Data provider for testGetDefinitions().
115    *
116    * @return array
117    *   - bool Whether the test mock has a callback.
118    *   - array Plugin definitions.
119    */
120   public function providerGetDefinitions() {
121     return [
122       [TRUE, ['definition' => 'is_fake']],
123       [FALSE, ['definition' => 'array_of_stuff']],
124     ];
125   }
126
127   /**
128    * @covers ::getDefinitions
129    * @dataProvider providerGetDefinitions
130    */
131   public function testGetDefinitions($has_register_definitions, $definitions) {
132     // Mock our StaticDiscoveryDecorator.
133     $mock_decorator = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator')
134       ->disableOriginalConstructor()
135       ->setMethods(['registeredDefintionCallback'])
136       ->getMock();
137
138     // Set up the ::$registerDefinitions property.
139     $ref_register_definitions = new \ReflectionProperty($mock_decorator, 'registerDefinitions');
140     $ref_register_definitions->setAccessible(TRUE);
141     if ($has_register_definitions) {
142       // Set the callback object on the mocked decorator.
143       $ref_register_definitions->setValue(
144         $mock_decorator,
145         [$this->getRegisterDefinitionsCallback(), 'registerDefinitionsCallback']
146       );
147     }
148     else {
149       // There should be no registerDefinitions callback.
150       $ref_register_definitions->setValue($mock_decorator, NULL);
151     }
152
153     // Set up ::$definitions to an empty array.
154     $ref_definitions = new \ReflectionProperty($mock_decorator, 'definitions');
155     $ref_definitions->setAccessible(TRUE);
156     $ref_definitions->setValue($mock_decorator, []);
157
158     // Mock a decorated object.
159     $mock_decorated = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\DiscoveryInterface')
160       ->setMethods(['getDefinitions'])
161       ->getMockForAbstractClass();
162     // Our mocked method will return any arguments sent to it.
163     $mock_decorated->expects($this->once())
164       ->method('getDefinitions')
165       ->willReturn($definitions);
166
167     // Set up ::$decorated to our mocked decorated object.
168     $ref_decorated = new \ReflectionProperty($mock_decorator, 'decorated');
169     $ref_decorated->setAccessible(TRUE);
170     $ref_decorated->setValue($mock_decorator, $mock_decorated);
171
172     // Exercise getDefinitions(). It calls parent::getDefinitions() but in this
173     // case there will be no side-effects.
174     $this->assertEquals(
175       $definitions,
176       $mock_decorator->getDefinitions()
177     );
178   }
179
180   /**
181    * Data provider for testCall().
182    *
183    * @return array
184    *   - Method name.
185    *   - Array of arguments to pass to the method, with the expectation that our
186    *     mocked __call() will return them.
187    */
188   public function providerCall() {
189     return [
190       ['complexArguments', ['1', 2.0, 3, ['4' => 'five']]],
191       ['noArguments', []],
192     ];
193   }
194
195   /**
196    * @covers ::__call
197    * @dataProvider providerCall
198    */
199   public function testCall($method, $args) {
200     // Mock a decorated object.
201     $mock_decorated = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\DiscoveryInterface')
202       ->setMethods([$method])
203       ->getMockForAbstractClass();
204     // Our mocked method will return any arguments sent to it.
205     $mock_decorated->expects($this->once())
206       ->method($method)
207       ->willReturnCallback(
208         function () {
209           return \func_get_args();
210         }
211       );
212
213     // Create a mock decorator.
214     $mock_decorator = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator')
215       ->disableOriginalConstructor()
216       ->getMock();
217     // Poke the decorated object into our decorator.
218     $ref_decorated = new \ReflectionProperty($mock_decorator, 'decorated');
219     $ref_decorated->setAccessible(TRUE);
220     $ref_decorated->setValue($mock_decorator, $mock_decorated);
221
222     // Exercise __call.
223     $this->assertEquals(
224       $args,
225       \call_user_func_array([$mock_decorated, $method], $args)
226     );
227   }
228
229 }