BreadcrumbsHelperTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 3.3.6
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\View\Helper;
  16. use Cake\TestSuite\TestCase;
  17. use Cake\View\Helper\BreadcrumbsHelper;
  18. use Cake\View\View;
  19. class BreadcrumbsHelperTest extends TestCase
  20. {
  21. /**
  22. * Instance of the BreadcrumbsHelper
  23. *
  24. * @var BreadcrumbsHelper
  25. */
  26. public $breadcrumbs;
  27. /**
  28. * setUp method
  29. *
  30. * @return void
  31. */
  32. public function setUp()
  33. {
  34. parent::setUp();
  35. $view = new View();
  36. $this->breadcrumbs = new BreadcrumbsHelper($view);
  37. }
  38. /**
  39. * Test adding crumbs to the trail using add()
  40. *
  41. * @return void
  42. */
  43. public function testAdd()
  44. {
  45. $this->breadcrumbs
  46. ->add('Home', '/', ['class' => 'first'])
  47. ->add('Some text', ['controller' => 'Some', 'action' => 'text']);
  48. $result = $this->breadcrumbs->getCrumbs();
  49. $expected = [
  50. [
  51. 'title' => 'Home',
  52. 'url' => '/',
  53. 'options' => [
  54. 'class' => 'first',
  55. ],
  56. ],
  57. [
  58. 'title' => 'Some text',
  59. 'url' => [
  60. 'controller' => 'Some',
  61. 'action' => 'text',
  62. ],
  63. 'options' => [],
  64. ],
  65. ];
  66. $this->assertEquals($expected, $result);
  67. }
  68. /**
  69. * Test adding multiple crumbs at once to the trail using add()
  70. *
  71. * @return void
  72. */
  73. public function testAddMultiple()
  74. {
  75. $this->breadcrumbs
  76. ->add([
  77. [
  78. 'title' => 'Home',
  79. 'url' => '/',
  80. 'options' => ['class' => 'first'],
  81. ],
  82. [
  83. 'title' => 'Some text',
  84. 'url' => ['controller' => 'Some', 'action' => 'text'],
  85. ],
  86. [
  87. 'title' => 'Final',
  88. ],
  89. ]);
  90. $result = $this->breadcrumbs->getCrumbs();
  91. $expected = [
  92. [
  93. 'title' => 'Home',
  94. 'url' => '/',
  95. 'options' => [
  96. 'class' => 'first',
  97. ],
  98. ],
  99. [
  100. 'title' => 'Some text',
  101. 'url' => [
  102. 'controller' => 'Some',
  103. 'action' => 'text',
  104. ],
  105. 'options' => [],
  106. ],
  107. [
  108. 'title' => 'Final',
  109. 'url' => null,
  110. 'options' => [],
  111. ],
  112. ];
  113. $this->assertEquals($expected, $result);
  114. }
  115. /**
  116. * Test adding crumbs to the trail using prepend()
  117. *
  118. * @return void
  119. */
  120. public function testPrepend()
  121. {
  122. $this->breadcrumbs
  123. ->add('Home', '/', ['class' => 'first'])
  124. ->prepend('Some text', ['controller' => 'Some', 'action' => 'text'])
  125. ->prepend('The root', '/root', ['data-name' => 'some-name']);
  126. $result = $this->breadcrumbs->getCrumbs();
  127. $expected = [
  128. [
  129. 'title' => 'The root',
  130. 'url' => '/root',
  131. 'options' => ['data-name' => 'some-name'],
  132. ],
  133. [
  134. 'title' => 'Some text',
  135. 'url' => [
  136. 'controller' => 'Some',
  137. 'action' => 'text',
  138. ],
  139. 'options' => [],
  140. ],
  141. [
  142. 'title' => 'Home',
  143. 'url' => '/',
  144. 'options' => [
  145. 'class' => 'first',
  146. ],
  147. ],
  148. ];
  149. $this->assertEquals($expected, $result);
  150. }
  151. /**
  152. * Test adding crumbs to the trail using prepend()
  153. *
  154. * @return void
  155. */
  156. public function testPrependMultiple()
  157. {
  158. $this->breadcrumbs
  159. ->add('Home', '/', ['class' => 'first'])
  160. ->prepend([
  161. ['title' => 'Some text', 'url' => ['controller' => 'Some', 'action' => 'text']],
  162. ['title' => 'The root', 'url' => '/root', 'options' => ['data-name' => 'some-name']],
  163. ]);
  164. $result = $this->breadcrumbs->getCrumbs();
  165. $expected = [
  166. [
  167. 'title' => 'Some text',
  168. 'url' => [
  169. 'controller' => 'Some',
  170. 'action' => 'text',
  171. ],
  172. 'options' => [],
  173. ],
  174. [
  175. 'title' => 'The root',
  176. 'url' => '/root',
  177. 'options' => ['data-name' => 'some-name'],
  178. ],
  179. [
  180. 'title' => 'Home',
  181. 'url' => '/',
  182. 'options' => [
  183. 'class' => 'first',
  184. ],
  185. ],
  186. ];
  187. $this->assertEquals($expected, $result);
  188. }
  189. /**
  190. * Test ability to empty crumbs list.
  191. *
  192. * @return void
  193. */
  194. public function testReset()
  195. {
  196. $this->breadcrumbs->add('Home', '/');
  197. $this->breadcrumbs->add('Products', '/products');
  198. $crumbs = $this->breadcrumbs->getCrumbs();
  199. $this->assertEquals(count($crumbs), 2);
  200. $this->breadcrumbs->reset();
  201. $actual = $this->breadcrumbs->getCrumbs();
  202. $this->assertEquals($actual, []);
  203. }
  204. /**
  205. * Test adding crumbs to a specific index
  206. *
  207. * @return void
  208. */
  209. public function testInsertAt()
  210. {
  211. $this->breadcrumbs
  212. ->add('Home', '/', ['class' => 'first'])
  213. ->prepend('Some text', ['controller' => 'Some', 'action' => 'text'])
  214. ->insertAt(1, 'Insert At', ['controller' => 'Insert', 'action' => 'at'])
  215. ->insertAt(1, 'Insert At Again', ['controller' => 'Insert', 'action' => 'at_again']);
  216. $result = $this->breadcrumbs->getCrumbs();
  217. $expected = [
  218. [
  219. 'title' => 'Some text',
  220. 'url' => [
  221. 'controller' => 'Some',
  222. 'action' => 'text',
  223. ],
  224. 'options' => [],
  225. ],
  226. [
  227. 'title' => 'Insert At Again',
  228. 'url' => [
  229. 'controller' => 'Insert',
  230. 'action' => 'at_again',
  231. ],
  232. 'options' => [],
  233. ],
  234. [
  235. 'title' => 'Insert At',
  236. 'url' => [
  237. 'controller' => 'Insert',
  238. 'action' => 'at',
  239. ],
  240. 'options' => [],
  241. ],
  242. [
  243. 'title' => 'Home',
  244. 'url' => '/',
  245. 'options' => [
  246. 'class' => 'first',
  247. ],
  248. ],
  249. ];
  250. $this->assertEquals($expected, $result);
  251. }
  252. /**
  253. * Test adding crumbs to a specific index
  254. */
  255. public function testInsertAtIndexOutOfBounds()
  256. {
  257. $this->expectException(\LogicException::class);
  258. $this->breadcrumbs
  259. ->add('Home', '/', ['class' => 'first'])
  260. ->insertAt(2, 'Insert At Again', ['controller' => 'Insert', 'action' => 'at_again']);
  261. }
  262. /**
  263. * Test adding crumbs before a specific one
  264. *
  265. * @return void
  266. */
  267. public function testInsertBefore()
  268. {
  269. $this->breadcrumbs
  270. ->add('Home', '/', ['class' => 'first'])
  271. ->prepend('Some text', ['controller' => 'Some', 'action' => 'text'])
  272. ->prepend('The root', '/root', ['data-name' => 'some-name'])
  273. ->insertBefore('The root', 'The super root');
  274. $result = $this->breadcrumbs->getCrumbs();
  275. $expected = [
  276. [
  277. 'title' => 'The super root',
  278. 'url' => null,
  279. 'options' => [],
  280. ],
  281. [
  282. 'title' => 'The root',
  283. 'url' => '/root',
  284. 'options' => ['data-name' => 'some-name'],
  285. ],
  286. [
  287. 'title' => 'Some text',
  288. 'url' => [
  289. 'controller' => 'Some',
  290. 'action' => 'text',
  291. ],
  292. 'options' => [],
  293. ],
  294. [
  295. 'title' => 'Home',
  296. 'url' => '/',
  297. 'options' => [
  298. 'class' => 'first',
  299. ],
  300. ],
  301. ];
  302. $this->assertEquals($expected, $result);
  303. }
  304. /**
  305. * Test adding crumbs after a specific one
  306. *
  307. * @return void
  308. */
  309. public function testInsertAfter()
  310. {
  311. $this->breadcrumbs
  312. ->add('Home', '/', ['class' => 'first'])
  313. ->prepend('Some text', ['controller' => 'Some', 'action' => 'text'])
  314. ->prepend('The root', '/root', ['data-name' => 'some-name'])
  315. ->insertAfter('The root', 'The less super root');
  316. $result = $this->breadcrumbs->getCrumbs();
  317. $expected = [
  318. [
  319. 'title' => 'The root',
  320. 'url' => '/root',
  321. 'options' => ['data-name' => 'some-name'],
  322. ],
  323. [
  324. 'title' => 'The less super root',
  325. 'url' => null,
  326. 'options' => [],
  327. ],
  328. [
  329. 'title' => 'Some text',
  330. 'url' => [
  331. 'controller' => 'Some',
  332. 'action' => 'text',
  333. ],
  334. 'options' => [],
  335. ],
  336. [
  337. 'title' => 'Home',
  338. 'url' => '/',
  339. 'options' => [
  340. 'class' => 'first',
  341. ],
  342. ],
  343. ];
  344. $this->assertEquals($expected, $result);
  345. }
  346. /**
  347. * Tests the render method
  348. *
  349. * @return void
  350. */
  351. public function testRender()
  352. {
  353. $this->assertSame('', $this->breadcrumbs->render());
  354. $this->breadcrumbs
  355. ->add('Home', '/', ['class' => 'first', 'innerAttrs' => ['data-foo' => 'bar']])
  356. ->add('Some text', ['controller' => 'tests_apps', 'action' => 'some_method'])
  357. ->add('Final crumb', null, ['class' => 'final', 'innerAttrs' => ['class' => 'final-link']]);
  358. $result = $this->breadcrumbs->render(
  359. ['data-stuff' => 'foo and bar'],
  360. ['separator' => '<i class="fa fa-angle-right"></i>', 'class' => 'separator']
  361. );
  362. $expected = [
  363. ['ul' => ['data-stuff' => 'foo and bar']],
  364. ['li' => ['class' => 'first']],
  365. ['a' => ['href' => '/', 'data-foo' => 'bar']],
  366. 'Home',
  367. '/a',
  368. '/li',
  369. ['li' => ['class' => 'separator']],
  370. ['span' => []],
  371. ['i' => ['class' => 'fa fa-angle-right']],
  372. '/i',
  373. '/span',
  374. '/li',
  375. ['li' => []],
  376. ['a' => ['href' => '/some_alias']],
  377. 'Some text',
  378. '/a',
  379. '/li',
  380. ['li' => ['class' => 'separator']],
  381. ['span' => []],
  382. ['i' => ['class' => 'fa fa-angle-right']],
  383. '/i',
  384. '/span',
  385. '/li',
  386. ['li' => ['class' => 'final']],
  387. ['span' => ['class' => 'final-link']],
  388. 'Final crumb',
  389. '/span',
  390. '/li',
  391. '/ul',
  392. ];
  393. $this->assertHtml($expected, $result);
  394. }
  395. /**
  396. * Tests the render method with custom templates
  397. *
  398. * @return void
  399. */
  400. public function testRenderCustomTemplate()
  401. {
  402. $this->breadcrumbs = new BreadcrumbsHelper(new View(), [
  403. 'templates' => [
  404. 'wrapper' => '<ol itemtype="http://schema.org/BreadcrumbList"{{attrs}}>{{content}}</ol>',
  405. 'item' => '<li itemprop="itemListElement" itemtype="http://schema.org/ListItem"{{attrs}}><a itemtype="http://schema.org/Thing" itemprop="item" href="{{url}}"{{innerAttrs}}><span itemprop="name">{{title}}</span></a></li>',
  406. 'itemWithoutLink' => '<li itemprop="itemListElement" itemtype="http://schema.org/ListItem"{{attrs}}><span itemprop="name"{{innerAttrs}}>{{title}}</span></li>',
  407. ],
  408. ]);
  409. $this->breadcrumbs
  410. ->add('Home', '/', ['class' => 'first', 'innerAttrs' => ['data-foo' => 'bar']])
  411. ->add('Final crumb', null, ['class' => 'final', 'innerAttrs' => ['class' => 'final-link']]);
  412. $result = $this->breadcrumbs->render(
  413. ['data-stuff' => 'foo and bar'],
  414. ['separator' => ' > ', 'class' => 'separator']
  415. );
  416. $expected = [
  417. ['ol' => ['itemtype' => 'http://schema.org/BreadcrumbList', 'data-stuff' => 'foo and bar']],
  418. ['li' => ['itemprop' => 'itemListElement', 'itemtype' => 'http://schema.org/ListItem', 'class' => 'first']],
  419. ['a' => ['itemtype' => 'http://schema.org/Thing', 'itemprop' => 'item', 'href' => '/', 'data-foo' => 'bar']],
  420. ['span' => ['itemprop' => 'name']],
  421. 'Home',
  422. '/span',
  423. '/a',
  424. '/li',
  425. ['li' => ['itemprop' => 'itemListElement', 'itemtype' => 'http://schema.org/ListItem', 'class' => 'final']],
  426. ['span' => ['itemprop' => 'name', 'class' => 'final-link']],
  427. 'Final crumb',
  428. '/span',
  429. '/li',
  430. '/ol',
  431. ];
  432. $this->assertHtml($expected, $result, true);
  433. }
  434. /**
  435. * Tests the render method with template vars
  436. *
  437. * @return void
  438. */
  439. public function testRenderCustomTemplateTemplateVars()
  440. {
  441. $this->breadcrumbs = new BreadcrumbsHelper(new View(), [
  442. 'templates' => [
  443. 'wrapper' => '{{thing}}<ol itemtype="http://schema.org/BreadcrumbList"{{attrs}}>{{content}}</ol>',
  444. 'item' => '<li itemprop="itemListElement" itemtype="http://schema.org/ListItem"{{attrs}}><a itemtype="http://schema.org/Thing" itemprop="item" href="{{url}}"{{innerAttrs}}><span itemprop="name">{{title}}</span></a>{{foo}}</li>',
  445. 'itemWithoutLink' => '<li itemprop="itemListElement" itemtype="http://schema.org/ListItem"{{attrs}}><span itemprop="name"{{innerAttrs}}>{{title}}</span>{{barbaz}}</li>',
  446. ],
  447. ]);
  448. $this->breadcrumbs
  449. ->add('Home', '/', ['class' => 'first', 'innerAttrs' => ['data-foo' => 'bar'], 'templateVars' => ['foo' => 'barbaz']])
  450. ->add('Final crumb', null, ['class' => 'final', 'innerAttrs' => ['class' => 'final-link'], 'templateVars' => ['barbaz' => 'foo']]);
  451. $result = $this->breadcrumbs->render(
  452. ['data-stuff' => 'foo and bar', 'templateVars' => ['thing' => 'somestuff']],
  453. ['separator' => ' > ', 'class' => 'separator']
  454. );
  455. $expected = [
  456. 'somestuff',
  457. ['ol' => ['itemtype' => 'http://schema.org/BreadcrumbList', 'data-stuff' => 'foo and bar']],
  458. ['li' => ['itemprop' => 'itemListElement', 'itemtype' => 'http://schema.org/ListItem', 'class' => 'first']],
  459. ['a' => ['itemtype' => 'http://schema.org/Thing', 'itemprop' => 'item', 'href' => '/', 'data-foo' => 'bar']],
  460. ['span' => ['itemprop' => 'name']],
  461. 'Home',
  462. '/span',
  463. '/a',
  464. 'barbaz',
  465. '/li',
  466. ['li' => ['itemprop' => 'itemListElement', 'itemtype' => 'http://schema.org/ListItem', 'class' => 'final']],
  467. ['span' => ['itemprop' => 'name', 'class' => 'final-link']],
  468. 'Final crumb',
  469. '/span',
  470. 'foo',
  471. '/li',
  472. '/ol',
  473. ];
  474. $this->assertHtml($expected, $result, true);
  475. }
  476. }