ViewBuilderTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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.1.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\View;
  17. use Cake\Event\EventManager;
  18. use Cake\Http\Response;
  19. use Cake\Http\ServerRequest;
  20. use Cake\TestSuite\TestCase;
  21. use Cake\View\Exception\MissingViewException;
  22. use Cake\View\ViewBuilder;
  23. /**
  24. * View builder test case.
  25. */
  26. class ViewBuilderTest extends TestCase
  27. {
  28. public function testSetVar(): void
  29. {
  30. $builder = new ViewBuilder();
  31. $builder->setVar('testing', 'value');
  32. $this->assertSame('value', $builder->getVar('testing'));
  33. }
  34. public function testSetVars(): void
  35. {
  36. $builder = new ViewBuilder();
  37. $data = ['test' => 'val', 'foo' => 'bar'];
  38. $builder->setVars($data);
  39. $this->assertEquals($data, $builder->getVars());
  40. $update = ['test' => 'updated'];
  41. $builder->setVars($update);
  42. $this->assertEquals(
  43. ['foo' => 'bar', 'test' => 'updated'],
  44. $builder->getVars()
  45. );
  46. $update = ['overwrite' => 'yes'];
  47. $builder->setVars($update, false);
  48. $this->assertEquals(
  49. ['overwrite' => 'yes'],
  50. $builder->getVars()
  51. );
  52. }
  53. public function testHasVar(): void
  54. {
  55. $builder = new ViewBuilder();
  56. $this->assertFalse($builder->hasVar('foo'));
  57. $builder->setVar('foo', 'value');
  58. $this->assertTrue($builder->hasVar('foo'));
  59. $builder->setVar('bar', null);
  60. $this->assertTrue($builder->hasVar('bar'));
  61. }
  62. /**
  63. * data provider for string properties.
  64. *
  65. * @return array
  66. */
  67. public function stringPropertyProvider(): array
  68. {
  69. return [
  70. ['layoutPath', 'Admin/'],
  71. ['templatePath', 'Admin/'],
  72. ['plugin', 'TestPlugin'],
  73. ['layout', 'admin'],
  74. ['theme', 'TestPlugin'],
  75. ['template', 'edit'],
  76. ['name', 'Articles'],
  77. ['className', 'Cake\View\JsonView'],
  78. ];
  79. }
  80. /**
  81. * data provider for boolean properties.
  82. * Format: [key, expectedDefault, newValue]
  83. *
  84. * @return array
  85. */
  86. public function boolPropertyProvider(): array
  87. {
  88. return [
  89. ['autoLayout', true, false],
  90. ];
  91. }
  92. /**
  93. * data provider for array properties.
  94. *
  95. * @return array
  96. */
  97. public function arrayPropertyProvider(): array
  98. {
  99. return [
  100. ['options', ['key' => 'value']],
  101. ];
  102. }
  103. /**
  104. * Test string property accessor/mutator methods.
  105. *
  106. * @dataProvider stringPropertyProvider
  107. */
  108. public function testStringProperties(string $property, string $value): void
  109. {
  110. $get = 'get' . ucfirst($property);
  111. $set = 'set' . ucfirst($property);
  112. $builder = new ViewBuilder();
  113. $this->assertNull($builder->{$get}(), 'Default value should be null');
  114. $this->assertSame($builder, $builder->{$set}($value), 'Setter returns this');
  115. $this->assertSame($value, $builder->{$get}(), 'Getter gets value.');
  116. }
  117. /**
  118. * Test string property accessor/mutator methods.
  119. *
  120. * @dataProvider boolPropertyProvider
  121. */
  122. public function testBoolProperties(string $property, bool $default, bool $value): void
  123. {
  124. $set = 'enable' . ucfirst($property);
  125. $get = 'is' . ucfirst($property) . 'Enabled';
  126. $builder = new ViewBuilder();
  127. $this->assertSame($default, $builder->{$get}(), 'Default value not as expected');
  128. $this->assertSame($builder, $builder->{$set}($value), 'Setter returns this');
  129. $this->assertSame($value, $builder->{$get}(), 'Getter gets value.');
  130. }
  131. /**
  132. * Test array property accessor/mutator methods.
  133. *
  134. * @dataProvider arrayPropertyProvider
  135. */
  136. public function testArrayProperties(string $property, array $value): void
  137. {
  138. $get = 'get' . ucfirst($property);
  139. $set = 'set' . ucfirst($property);
  140. $builder = new ViewBuilder();
  141. $this->assertSame([], $builder->{$get}(), 'Default value should be empty list');
  142. $this->assertSame($builder, $builder->{$set}($value), 'Setter returns this');
  143. $this->assertSame($value, $builder->{$get}(), 'Getter gets value.');
  144. }
  145. /**
  146. * Test array property accessor/mutator methods.
  147. *
  148. * @dataProvider arrayPropertyProvider
  149. */
  150. public function testArrayPropertyMerge(string $property, array $value): void
  151. {
  152. $get = 'get' . ucfirst($property);
  153. $set = 'set' . ucfirst($property);
  154. $builder = new ViewBuilder();
  155. $builder->{$set}($value);
  156. $builder->{$set}(['merged' => 'Merged'], true);
  157. $this->assertSame(['merged' => 'Merged'] + $value, $builder->{$get}(), 'Should merge');
  158. $builder->{$set}($value, false);
  159. $this->assertSame($value, $builder->{$get}(), 'Should replace');
  160. }
  161. /**
  162. * Tests that adding non-assoc and assoc merge properly.
  163. *
  164. * @return void
  165. */
  166. public function testAddHelpers(): void
  167. {
  168. $builder = new ViewBuilder();
  169. $builder->addHelper('Form');
  170. $builder->addHelpers(['Form' => ['config' => 'value']]);
  171. $helpers = $builder->getHelpers();
  172. $expected = [
  173. 'Form' => [
  174. 'config' => 'value',
  175. ],
  176. ];
  177. $this->assertSame($expected, $helpers);
  178. }
  179. /**
  180. * test building with all the options.
  181. */
  182. public function testBuildComplete(): void
  183. {
  184. $request = new ServerRequest();
  185. $response = new Response();
  186. $events = new EventManager();
  187. $builder = new ViewBuilder();
  188. $builder->setName('Articles')
  189. ->setClassName('Ajax')
  190. ->setTemplate('edit')
  191. ->setLayout('default')
  192. ->setTemplatePath('Articles/')
  193. ->setHelpers(['Form', 'Html'], false)
  194. ->setLayoutPath('Admin/')
  195. ->setTheme('TestTheme')
  196. ->setPlugin('TestPlugin')
  197. ->setVars(['foo' => 'bar', 'x' => 'old']);
  198. $view = $builder->build(
  199. $request,
  200. $response,
  201. $events
  202. );
  203. $this->assertInstanceOf('Cake\View\AjaxView', $view);
  204. $this->assertSame('edit', $view->getTemplate());
  205. $this->assertSame('default', $view->getLayout());
  206. $this->assertSame('Articles/', $view->getTemplatePath());
  207. $this->assertSame('Admin/', $view->getLayoutPath());
  208. $this->assertSame('TestPlugin', $view->getPlugin());
  209. $this->assertSame('TestTheme', $view->getTheme());
  210. $this->assertSame($request, $view->getRequest());
  211. $this->assertInstanceOf(Response::class, $view->getResponse());
  212. $this->assertSame($events, $view->getEventManager());
  213. $this->assertSame(['foo', 'x'], $view->getVars());
  214. $this->assertSame('bar', $view->get('foo'));
  215. $this->assertInstanceOf('Cake\View\Helper\HtmlHelper', $view->Html);
  216. $this->assertInstanceOf('Cake\View\Helper\FormHelper', $view->Form);
  217. }
  218. /**
  219. * Test that the default is AppView.
  220. */
  221. public function testBuildAppViewMissing(): void
  222. {
  223. static::setAppNamespace('Nope');
  224. $builder = new ViewBuilder();
  225. $view = $builder->build();
  226. $this->assertInstanceOf('Cake\View\View', $view);
  227. }
  228. /**
  229. * Test that the default is AppView.
  230. */
  231. public function testBuildAppViewPresent(): void
  232. {
  233. static::setAppNamespace();
  234. $builder = new ViewBuilder();
  235. $view = $builder->build();
  236. $this->assertInstanceOf('TestApp\View\AppView', $view);
  237. }
  238. /**
  239. * test missing view class
  240. */
  241. public function testBuildMissingViewClass(): void
  242. {
  243. $this->expectException(MissingViewException::class);
  244. $this->expectExceptionMessage('View class "Foo" is missing.');
  245. $builder = new ViewBuilder();
  246. $builder->setClassName('Foo');
  247. $builder->build();
  248. }
  249. /**
  250. * testJsonSerialize()
  251. */
  252. public function testJsonSerialize(): void
  253. {
  254. $builder = new ViewBuilder();
  255. $builder
  256. ->setTemplate('default')
  257. ->setLayout('test')
  258. ->setHelpers(['Html'], false)
  259. ->setClassName('JsonView');
  260. $result = json_decode(json_encode($builder), true);
  261. $expected = [
  262. '_template' => 'default',
  263. '_layout' => 'test',
  264. '_helpers' => ['Html'],
  265. '_className' => 'JsonView',
  266. '_autoLayout' => true,
  267. ];
  268. $this->assertEquals($expected, $result);
  269. $result = json_decode(json_encode(unserialize(serialize($builder))), true);
  270. $this->assertEquals($expected, $result);
  271. }
  272. /**
  273. * testCreateFromArray()
  274. */
  275. public function testCreateFromArray(): void
  276. {
  277. $builder = new ViewBuilder();
  278. $builder
  279. ->setTemplate('default')
  280. ->setLayout('test')
  281. ->setHelpers(['Html'], false)
  282. ->setClassName('JsonView');
  283. $result = json_encode($builder);
  284. $builder = new ViewBuilder();
  285. $builder->createFromArray(json_decode($result, true));
  286. $this->assertSame('default', $builder->getTemplate());
  287. $this->assertSame('test', $builder->getLayout());
  288. $this->assertEquals(['Html'], $builder->getHelpers());
  289. $this->assertSame('JsonView', $builder->getClassName());
  290. }
  291. /**
  292. * test setOptions() with 1 string param, merge true
  293. */
  294. public function testSetOptionsOne(): void
  295. {
  296. $builder = new ViewBuilder();
  297. $this->assertSame($builder, $builder->setOptions(['newOption']));
  298. $this->assertContains('newOption', $builder->getOptions());
  299. }
  300. /**
  301. * test setOptions() with 2 assoc strings in array, merge true.
  302. */
  303. public function testSetOptionsMultiple(): void
  304. {
  305. $builder = new ViewBuilder();
  306. $builder->setOptions(['key' => 'oldOption'], false);
  307. $option = ['anotherKey' => 'anotherOption', 'key' => 'newOption'];
  308. $builder->setOptions($option);
  309. $expects = ['key' => 'newOption', 'anotherKey' => 'anotherOption'];
  310. $result = $builder->getOptions();
  311. $this->assertEquals($expects, $result);
  312. }
  313. /**
  314. * test empty params reads _viewOptions.
  315. */
  316. public function testReadingViewOptions(): void
  317. {
  318. $builder = new ViewBuilder();
  319. $builder->setOptions(['one', 'two', 'three'], false);
  320. $this->assertEquals(['one', 'two', 'three'], $builder->getOptions());
  321. }
  322. /**
  323. * test setting $merge `false` overrides correct options.
  324. */
  325. public function testMergeFalseViewOptions(): void
  326. {
  327. $builder = new ViewBuilder();
  328. $builder->setOptions(['one', 'two', 'three'], false);
  329. $expected = ['four', 'five', 'six'];
  330. $builder->setOptions($expected, false);
  331. $this->assertEquals($expected, $builder->getOptions());
  332. }
  333. /**
  334. * test _viewOptions is undefined and $opts is null, an empty array is returned.
  335. */
  336. public function testUndefinedValidViewOptions(): void
  337. {
  338. $builder = new ViewBuilder();
  339. $builder->setOptions([], false);
  340. $result = $builder->getOptions();
  341. $this->assertIsArray($result);
  342. $this->assertEmpty($result);
  343. }
  344. public function testOptionSetGet(): void
  345. {
  346. $builder = new ViewBuilder();
  347. $result = $builder->setOption('foo', 'bar');
  348. $this->assertSame($builder, $result);
  349. $this->assertSame('bar', $builder->getOption('foo'));
  350. $builder->setOption('foo', 'overwrite');
  351. $this->assertSame('overwrite', $builder->getOption('foo'));
  352. $this->assertNull($builder->getOption('nonexistent'));
  353. }
  354. public function testDisableAutoLayout(): void
  355. {
  356. $builder = new ViewBuilder();
  357. $this->assertTrue($builder->isAutoLayoutEnabled());
  358. $builder->disableAutoLayout();
  359. $this->assertFalse($builder->isAutoLayoutEnabled());
  360. }
  361. public function testAddHelperChained(): void
  362. {
  363. $builder = new ViewBuilder();
  364. $builder->addHelper('Form')
  365. ->addHelper('Time')
  366. ->addHelper('Text');
  367. $helpers = $builder->getHelpers();
  368. $expected = [
  369. 'Form' => [],
  370. 'Time' => [],
  371. 'Text' => [],
  372. ];
  373. $this->assertSame($expected, $helpers);
  374. }
  375. public function testAddHelperOptions(): void
  376. {
  377. $builder = new ViewBuilder();
  378. $builder->addHelper('Form')
  379. ->addHelper('Text', ['foo' => 'bar']);
  380. $helpers = $builder->getHelpers();
  381. $this->assertSame(['foo' => 'bar'], $helpers['Text']);
  382. }
  383. }