WidgetLocatorTest.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice.
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 3.0.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\View\Widget;
  17. use Cake\TestSuite\TestCase;
  18. use Cake\View\StringTemplate;
  19. use Cake\View\View;
  20. use Cake\View\Widget\WidgetLocator;
  21. use RuntimeException;
  22. use stdClass;
  23. use TestApp\View\Widget\TestUsingViewWidget;
  24. /**
  25. * WidgetLocator test case
  26. */
  27. class WidgetLocatorTest extends TestCase
  28. {
  29. /**
  30. * @var \Cake\View\StringTemplate
  31. */
  32. protected $templates;
  33. /**
  34. * @var \Cake\View\View
  35. */
  36. protected $view;
  37. /**
  38. * setup method
  39. */
  40. public function setUp(): void
  41. {
  42. parent::setUp();
  43. $this->templates = new StringTemplate();
  44. $this->view = new View();
  45. }
  46. /**
  47. * Test adding new widgets.
  48. */
  49. public function testAddInConstructor(): void
  50. {
  51. $widgets = [
  52. 'text' => ['Cake\View\Widget\BasicWidget'],
  53. 'label' => ['Label'],
  54. ];
  55. $inputs = new WidgetLocator($this->templates, $this->view, $widgets);
  56. $result = $inputs->get('text');
  57. $this->assertInstanceOf('Cake\View\Widget\BasicWidget', $result);
  58. $result = $inputs->get('label');
  59. $this->assertInstanceOf('Cake\View\Widget\LabelWidget', $result);
  60. }
  61. /**
  62. * Test that view instance is properly passed to widget constructor.
  63. */
  64. public function testGeneratingWidgetUsingViewInstance(): void
  65. {
  66. $inputs = new WidgetLocator(
  67. $this->templates,
  68. $this->view,
  69. ['test' => [TestUsingViewWidget::class, '_view']]
  70. );
  71. /** @var \TestApp\View\Widget\TestUsingViewWidget $widget */
  72. $widget = $inputs->get('test');
  73. $this->assertInstanceOf(View::class, $widget->getView());
  74. }
  75. /**
  76. * Test loading widgets files in the app.
  77. */
  78. public function testAddWidgetsFromConfigInConstructor(): void
  79. {
  80. $widgets = [
  81. 'text' => ['Cake\View\Widget\BasicWidget'],
  82. 'test_widgets',
  83. ];
  84. $inputs = new WidgetLocator($this->templates, $this->view, $widgets);
  85. $this->assertInstanceOf('Cake\View\Widget\LabelWidget', $inputs->get('text'));
  86. }
  87. /**
  88. * Test loading templates files from a plugin
  89. */
  90. public function testAddPluginWidgetsFromConfigInConstructor(): void
  91. {
  92. $this->loadPlugins(['TestPlugin']);
  93. $widgets = [
  94. 'text' => ['Cake\View\Widget\BasicWidget'],
  95. 'TestPlugin.test_widgets',
  96. ];
  97. $inputs = new WidgetLocator($this->templates, $this->view, $widgets);
  98. $this->assertInstanceOf('Cake\View\Widget\LabelWidget', $inputs->get('text'));
  99. $this->clearPlugins();
  100. }
  101. /**
  102. * Test adding new widgets.
  103. */
  104. public function testAdd(): void
  105. {
  106. $inputs = new WidgetLocator($this->templates, $this->view);
  107. $inputs->add([
  108. 'text' => ['Cake\View\Widget\BasicWidget'],
  109. ]);
  110. $result = $inputs->get('text');
  111. $this->assertInstanceOf('Cake\View\Widget\WidgetInterface', $result);
  112. $inputs = new WidgetLocator($this->templates, $this->view);
  113. $inputs->add([
  114. 'hidden' => 'Cake\View\Widget\BasicWidget',
  115. ]);
  116. $result = $inputs->get('hidden');
  117. $this->assertInstanceOf('Cake\View\Widget\WidgetInterface', $result);
  118. }
  119. /**
  120. * Test adding an instance of an invalid type.
  121. */
  122. public function testAddInvalidType(): void
  123. {
  124. $this->expectException(RuntimeException::class);
  125. $this->expectExceptionMessage(
  126. 'Widget objects must implement `Cake\View\Widget\WidgetInterface`. Got `stdClass` instance instead.'
  127. );
  128. $inputs = new WidgetLocator($this->templates, $this->view);
  129. $inputs->add([
  130. 'text' => new stdClass(),
  131. ]);
  132. }
  133. /**
  134. * Test getting registered widgets.
  135. */
  136. public function testGet(): void
  137. {
  138. $inputs = new WidgetLocator($this->templates, $this->view);
  139. $inputs->add([
  140. 'text' => ['Cake\View\Widget\BasicWidget'],
  141. ]);
  142. $result = $inputs->get('text');
  143. $this->assertInstanceOf('Cake\View\Widget\BasicWidget', $result);
  144. $this->assertSame($result, $inputs->get('text'));
  145. }
  146. /**
  147. * Test getting fallback widgets.
  148. */
  149. public function testGetFallback(): void
  150. {
  151. $inputs = new WidgetLocator($this->templates, $this->view);
  152. $inputs->add([
  153. '_default' => ['Cake\View\Widget\BasicWidget'],
  154. ]);
  155. $result = $inputs->get('text');
  156. $this->assertInstanceOf('Cake\View\Widget\BasicWidget', $result);
  157. $result2 = $inputs->get('hidden');
  158. $this->assertSame($result, $result2);
  159. }
  160. /**
  161. * Test getting errors
  162. */
  163. public function testGetNoFallbackError(): void
  164. {
  165. $this->expectException(RuntimeException::class);
  166. $this->expectExceptionMessage('Unknown widget `foo`');
  167. $inputs = new WidgetLocator($this->templates, $this->view);
  168. $inputs->clear();
  169. $inputs->get('foo');
  170. }
  171. /**
  172. * Test getting resolve dependency
  173. */
  174. public function testGetResolveDependency(): void
  175. {
  176. $inputs = new WidgetLocator($this->templates, $this->view);
  177. $inputs->clear();
  178. $inputs->add([
  179. 'label' => ['Cake\View\Widget\LabelWidget'],
  180. 'multicheckbox' => ['Cake\View\Widget\MultiCheckboxWidget', 'label'],
  181. ]);
  182. $result = $inputs->get('multicheckbox');
  183. $this->assertInstanceOf('Cake\View\Widget\MultiCheckboxWidget', $result);
  184. }
  185. /**
  186. * Test getting resolve dependency missing class
  187. */
  188. public function testGetResolveDependencyMissingClass(): void
  189. {
  190. $this->expectException(RuntimeException::class);
  191. $this->expectExceptionMessage('Unable to locate widget class "TestApp\View\DerpWidget"');
  192. $inputs = new WidgetLocator($this->templates, $this->view);
  193. $inputs->add(['test' => ['TestApp\View\DerpWidget']]);
  194. $inputs->get('test');
  195. }
  196. /**
  197. * Test getting resolve dependency missing dependency
  198. */
  199. public function testGetResolveDependencyMissingDependency(): void
  200. {
  201. $this->expectException(RuntimeException::class);
  202. $this->expectExceptionMessage('Unknown widget `label`');
  203. $inputs = new WidgetLocator($this->templates, $this->view);
  204. $inputs->clear();
  205. $inputs->add(['multicheckbox' => ['Cake\View\Widget\MultiCheckboxWidget', 'label']]);
  206. $inputs->get('multicheckbox');
  207. }
  208. }