Updated to Drupal 8.5. Core Media not yet in use.
[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       if (method_exists($this, 'expectException')) {
104         $this->expectException('Drupal\Component\Plugin\Exception\PluginNotFoundException');
105       }
106       else {
107         $this->setExpectedException('Drupal\Component\Plugin\Exception\PluginNotFoundException');
108       }
109     }
110
111     // Exercise getDefinition(). It calls parent::getDefinition().
112     $this->assertEquals(
113       $expected,
114       $mock_decorator->getDefinition($base_plugin_id, $exception_on_invalid)
115     );
116   }
117
118   /**
119    * Data provider for testGetDefinitions().
120    *
121    * @return array
122    *   - bool Whether the test mock has a callback.
123    *   - array Plugin definitions.
124    */
125   public function providerGetDefinitions() {
126     return [
127       [TRUE, ['definition' => 'is_fake']],
128       [FALSE, ['definition' => 'array_of_stuff']],
129     ];
130   }
131
132   /**
133    * @covers ::getDefinitions
134    * @dataProvider providerGetDefinitions
135    */
136   public function testGetDefinitions($has_register_definitions, $definitions) {
137     // Mock our StaticDiscoveryDecorator.
138     $mock_decorator = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator')
139       ->disableOriginalConstructor()
140       ->setMethods(['registeredDefintionCallback'])
141       ->getMock();
142
143     // Set up the ::$registerDefinitions property.
144     $ref_register_definitions = new \ReflectionProperty($mock_decorator, 'registerDefinitions');
145     $ref_register_definitions->setAccessible(TRUE);
146     if ($has_register_definitions) {
147       // Set the callback object on the mocked decorator.
148       $ref_register_definitions->setValue(
149         $mock_decorator,
150         [$this->getRegisterDefinitionsCallback(), 'registerDefinitionsCallback']
151       );
152     }
153     else {
154       // There should be no registerDefinitions callback.
155       $ref_register_definitions->setValue($mock_decorator, NULL);
156     }
157
158     // Set up ::$definitions to an empty array.
159     $ref_definitions = new \ReflectionProperty($mock_decorator, 'definitions');
160     $ref_definitions->setAccessible(TRUE);
161     $ref_definitions->setValue($mock_decorator, []);
162
163     // Mock a decorated object.
164     $mock_decorated = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\DiscoveryInterface')
165       ->setMethods(['getDefinitions'])
166       ->getMockForAbstractClass();
167     // Our mocked method will return any arguments sent to it.
168     $mock_decorated->expects($this->once())
169       ->method('getDefinitions')
170       ->willReturn($definitions);
171
172     // Set up ::$decorated to our mocked decorated object.
173     $ref_decorated = new \ReflectionProperty($mock_decorator, 'decorated');
174     $ref_decorated->setAccessible(TRUE);
175     $ref_decorated->setValue($mock_decorator, $mock_decorated);
176
177     // Exercise getDefinitions(). It calls parent::getDefinitions() but in this
178     // case there will be no side-effects.
179     $this->assertEquals(
180       $definitions,
181       $mock_decorator->getDefinitions()
182     );
183   }
184
185   /**
186    * Data provider for testCall().
187    *
188    * @return array
189    *   - Method name.
190    *   - Array of arguments to pass to the method, with the expectation that our
191    *     mocked __call() will return them.
192    */
193   public function providerCall() {
194     return [
195       ['complexArguments', ['1', 2.0, 3, ['4' => 'five']]],
196       ['noArguments', []],
197     ];
198   }
199
200   /**
201    * @covers ::__call
202    * @dataProvider providerCall
203    */
204   public function testCall($method, $args) {
205     // Mock a decorated object.
206     $mock_decorated = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\DiscoveryInterface')
207       ->setMethods([$method])
208       ->getMockForAbstractClass();
209     // Our mocked method will return any arguments sent to it.
210     $mock_decorated->expects($this->once())
211       ->method($method)
212       ->willReturnCallback(
213         function () {
214           return \func_get_args();
215         }
216       );
217
218     // Create a mock decorator.
219     $mock_decorator = $this->getMockBuilder('Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator')
220       ->disableOriginalConstructor()
221       ->getMock();
222     // Poke the decorated object into our decorator.
223     $ref_decorated = new \ReflectionProperty($mock_decorator, 'decorated');
224     $ref_decorated->setAccessible(TRUE);
225     $ref_decorated->setValue($mock_decorator, $mock_decorated);
226
227     // Exercise __call.
228     $this->assertEquals(
229       $args,
230       \call_user_func_array([$mock_decorated, $method], $args)
231     );
232   }
233
234 }