ViewBuilderTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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. $this->deprecated(function () use ($get, $set, $value) {
  141. $builder = new ViewBuilder();
  142. $this->assertSame([], $builder->{$get}(), 'Default value should be empty list');
  143. $this->assertSame($builder, $builder->{$set}($value), 'Setter returns this');
  144. $this->assertSame($value, $builder->{$get}(), 'Getter gets value.');
  145. });
  146. }
  147. /**
  148. * Test array property accessor/mutator methods.
  149. *
  150. * @dataProvider arrayPropertyProvider
  151. */
  152. public function testArrayPropertyMerge(string $property, array $value): void
  153. {
  154. $get = 'get' . ucfirst($property);
  155. $set = 'set' . ucfirst($property);
  156. $this->deprecated(function () use ($get, $set, $value) {
  157. $builder = new ViewBuilder();
  158. $builder->{$set}($value);
  159. $builder->{$set}(['merged' => 'Merged'], true);
  160. $this->assertSame(['merged' => 'Merged'] + $value, $builder->{$get}(), 'Should merge');
  161. $builder->{$set}($value, false);
  162. $this->assertSame($value, $builder->{$get}(), 'Should replace');
  163. });
  164. }
  165. /**
  166. * Tests that adding non-assoc and assoc merge properly.
  167. *
  168. * @return void
  169. */
  170. public function testAddHelpers(): void
  171. {
  172. $builder = new ViewBuilder();
  173. $builder->addHelper('Form');
  174. $builder->addHelpers(['Form' => ['config' => 'value']]);
  175. $helpers = $builder->getHelpers();
  176. $expected = [
  177. 'Form' => [
  178. 'config' => 'value',
  179. ],
  180. ];
  181. $this->assertSame($expected, $helpers);
  182. }
  183. /**
  184. * test building with all the options.
  185. */
  186. public function testBuildComplete(): void
  187. {
  188. $request = new ServerRequest();
  189. $response = new Response();
  190. $events = new EventManager();
  191. $builder = new ViewBuilder();
  192. $builder->setName('Articles')
  193. ->setClassName('Ajax')
  194. ->setTemplate('edit')
  195. ->setLayout('default')
  196. ->setTemplatePath('Articles/')
  197. ->setHelpers(['Form', 'Html'], false)
  198. ->setLayoutPath('Admin/')
  199. ->setTheme('TestTheme')
  200. ->setPlugin('TestPlugin')
  201. ->setVars(['foo' => 'bar', 'x' => 'old']);
  202. $view = $builder->build(
  203. $request,
  204. $response,
  205. $events
  206. );
  207. $this->assertInstanceOf('Cake\View\AjaxView', $view);
  208. $this->assertSame('edit', $view->getTemplate());
  209. $this->assertSame('default', $view->getLayout());
  210. $this->assertSame('Articles/', $view->getTemplatePath());
  211. $this->assertSame('Admin/', $view->getLayoutPath());
  212. $this->assertSame('TestPlugin', $view->getPlugin());
  213. $this->assertSame('TestTheme', $view->getTheme());
  214. $this->assertSame($request, $view->getRequest());
  215. $this->assertInstanceOf(Response::class, $view->getResponse());
  216. $this->assertSame($events, $view->getEventManager());
  217. $this->assertSame(['foo', 'x'], $view->getVars());
  218. $this->assertSame('bar', $view->get('foo'));
  219. $this->assertInstanceOf('Cake\View\Helper\HtmlHelper', $view->Html);
  220. $this->assertInstanceOf('Cake\View\Helper\FormHelper', $view->Form);
  221. }
  222. /**
  223. * Test that the default is AppView.
  224. */
  225. public function testBuildAppViewMissing(): void
  226. {
  227. static::setAppNamespace('Nope');
  228. $builder = new ViewBuilder();
  229. $view = $builder->build();
  230. $this->assertInstanceOf('Cake\View\View', $view);
  231. }
  232. /**
  233. * Test that the default is AppView.
  234. */
  235. public function testBuildAppViewPresent(): void
  236. {
  237. static::setAppNamespace();
  238. $builder = new ViewBuilder();
  239. $view = $builder->build();
  240. $this->assertInstanceOf('TestApp\View\AppView', $view);
  241. }
  242. /**
  243. * test missing view class
  244. */
  245. public function testBuildMissingViewClass(): void
  246. {
  247. $this->expectException(MissingViewException::class);
  248. $this->expectExceptionMessage('View class "Foo" is missing.');
  249. $builder = new ViewBuilder();
  250. $builder->setClassName('Foo');
  251. $builder->build();
  252. }
  253. /**
  254. * testJsonSerialize()
  255. */
  256. public function testJsonSerialize(): void
  257. {
  258. $builder = new ViewBuilder();
  259. $builder
  260. ->setTemplate('default')
  261. ->setLayout('test')
  262. ->setHelpers(['Html'], false)
  263. ->setClassName('JsonView');
  264. $result = json_decode(json_encode($builder), true);
  265. $expected = [
  266. '_template' => 'default',
  267. '_layout' => 'test',
  268. '_helpers' => ['Html'],
  269. '_className' => 'JsonView',
  270. '_autoLayout' => true,
  271. ];
  272. $this->assertEquals($expected, $result);
  273. $result = json_decode(json_encode(unserialize(serialize($builder))), true);
  274. $this->assertEquals($expected, $result);
  275. }
  276. /**
  277. * testCreateFromArray()
  278. */
  279. public function testCreateFromArray(): void
  280. {
  281. $builder = new ViewBuilder();
  282. $builder
  283. ->setTemplate('default')
  284. ->setLayout('test')
  285. ->setHelpers(['Html'], false)
  286. ->setClassName('JsonView');
  287. $result = json_encode($builder);
  288. $builder = new ViewBuilder();
  289. $builder->createFromArray(json_decode($result, true));
  290. $this->assertSame('default', $builder->getTemplate());
  291. $this->assertSame('test', $builder->getLayout());
  292. $this->assertEquals(['Html'], $builder->getHelpers());
  293. $this->assertSame('JsonView', $builder->getClassName());
  294. }
  295. /**
  296. * test setOptions() with 1 string param, merge true
  297. */
  298. public function testSetOptionsOne(): void
  299. {
  300. $builder = new ViewBuilder();
  301. $this->assertSame($builder, $builder->setOptions(['newOption']));
  302. $this->assertContains('newOption', $builder->getOptions());
  303. }
  304. /**
  305. * test setOptions() with 2 assoc strings in array, merge true.
  306. */
  307. public function testSetOptionsMultiple(): void
  308. {
  309. $builder = new ViewBuilder();
  310. $builder->setOptions(['key' => 'oldOption'], false);
  311. $option = ['anotherKey' => 'anotherOption', 'key' => 'newOption'];
  312. $builder->setOptions($option);
  313. $expects = ['key' => 'newOption', 'anotherKey' => 'anotherOption'];
  314. $result = $builder->getOptions();
  315. $this->assertEquals($expects, $result);
  316. }
  317. /**
  318. * test empty params reads _viewOptions.
  319. */
  320. public function testReadingViewOptions(): void
  321. {
  322. $builder = new ViewBuilder();
  323. $builder->setOptions(['one', 'two', 'three'], false);
  324. $this->assertEquals(['one', 'two', 'three'], $builder->getOptions());
  325. }
  326. /**
  327. * test setting $merge `false` overrides correct options.
  328. */
  329. public function testMergeFalseViewOptions(): void
  330. {
  331. $builder = new ViewBuilder();
  332. $builder->setOptions(['one', 'two', 'three'], false);
  333. $expected = ['four', 'five', 'six'];
  334. $builder->setOptions($expected, false);
  335. $this->assertEquals($expected, $builder->getOptions());
  336. }
  337. /**
  338. * test _viewOptions is undefined and $opts is null, an empty array is returned.
  339. */
  340. public function testUndefinedValidViewOptions(): void
  341. {
  342. $builder = new ViewBuilder();
  343. $builder->setOptions([], false);
  344. $result = $builder->getOptions();
  345. $this->assertIsArray($result);
  346. $this->assertEmpty($result);
  347. }
  348. public function testOptionSetGet(): void
  349. {
  350. $builder = new ViewBuilder();
  351. $result = $builder->setOption('foo', 'bar');
  352. $this->assertSame($builder, $result);
  353. $this->assertSame('bar', $builder->getOption('foo'));
  354. $builder->setOption('foo', 'overwrite');
  355. $this->assertSame('overwrite', $builder->getOption('foo'));
  356. $this->assertNull($builder->getOption('nonexistent'));
  357. }
  358. public function testDisableAutoLayout(): void
  359. {
  360. $builder = new ViewBuilder();
  361. $this->assertTrue($builder->isAutoLayoutEnabled());
  362. $builder->disableAutoLayout();
  363. $this->assertFalse($builder->isAutoLayoutEnabled());
  364. }
  365. public function testAddHelperChained(): void
  366. {
  367. $builder = new ViewBuilder();
  368. $builder->addHelper('Form')
  369. ->addHelper('Time')
  370. ->addHelper('Text');
  371. $helpers = $builder->getHelpers();
  372. $expected = [
  373. 'Form' => [],
  374. 'Time' => [],
  375. 'Text' => [],
  376. ];
  377. $this->assertSame($expected, $helpers);
  378. }
  379. public function testAddHelperOptions(): void
  380. {
  381. $builder = new ViewBuilder();
  382. $builder->addHelper('Form')
  383. ->addHelper('Text', ['foo' => 'bar']);
  384. $helpers = $builder->getHelpers();
  385. $this->assertSame(['foo' => 'bar'], $helpers['Text']);
  386. }
  387. }