StaticDiscoveryDecoratorTest.php 7.9 KB

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