MultiCheckboxWidgetTest.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  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.0.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\View\Widget;
  16. use Cake\TestSuite\TestCase;
  17. use Cake\View\StringTemplate;
  18. use Cake\View\Widget\LabelWidget;
  19. use Cake\View\Widget\MultiCheckboxWidget;
  20. /**
  21. * MultiCheckbox test case.
  22. */
  23. class MultiCheckboxWidgetTest extends TestCase
  24. {
  25. /**
  26. * setup method.
  27. *
  28. * @return void
  29. */
  30. public function setUp()
  31. {
  32. parent::setUp();
  33. $templates = [
  34. 'checkbox' => '<input type="checkbox" name="{{name}}" value="{{value}}"{{attrs}}>',
  35. 'label' => '<label{{attrs}}>{{text}}</label>',
  36. 'checkboxWrapper' => '<div class="checkbox">{{input}}{{label}}</div>',
  37. 'multicheckboxWrapper' => '<fieldset{{attrs}}>{{content}}</fieldset>',
  38. 'multicheckboxTitle' => '<legend>{{text}}</legend>',
  39. ];
  40. $this->templates = new StringTemplate($templates);
  41. $this->context = $this->getMockBuilder('Cake\View\Form\ContextInterface')->getMock();
  42. }
  43. /**
  44. * Test render simple option sets.
  45. *
  46. * @return void
  47. */
  48. public function testRenderSimple()
  49. {
  50. $label = new LabelWidget($this->templates);
  51. $input = new MultiCheckboxWidget($this->templates, $label);
  52. $data = [
  53. 'name' => 'Tags[id]',
  54. 'options' => [
  55. 1 => 'CakePHP',
  56. 2 => 'Development',
  57. ]
  58. ];
  59. $result = $input->render($data, $this->context);
  60. $expected = [
  61. ['div' => ['class' => 'checkbox']],
  62. ['input' => [
  63. 'type' => 'checkbox',
  64. 'name' => 'Tags[id][]',
  65. 'value' => 1,
  66. 'id' => 'tags-id-1',
  67. ]],
  68. ['label' => ['for' => 'tags-id-1']],
  69. 'CakePHP',
  70. '/label',
  71. '/div',
  72. ['div' => ['class' => 'checkbox']],
  73. ['input' => [
  74. 'type' => 'checkbox',
  75. 'name' => 'Tags[id][]',
  76. 'value' => 2,
  77. 'id' => 'tags-id-2',
  78. ]],
  79. ['label' => ['for' => 'tags-id-2']],
  80. 'Development',
  81. '/label',
  82. '/div',
  83. ];
  84. $this->assertHtml($expected, $result);
  85. }
  86. /**
  87. * Test render complex and additional attributes.
  88. *
  89. * @return void
  90. */
  91. public function testRenderComplex()
  92. {
  93. $label = new LabelWidget($this->templates);
  94. $input = new MultiCheckboxWidget($this->templates, $label);
  95. $data = [
  96. 'name' => 'Tags[id]',
  97. 'val' => 2,
  98. 'disabled' => ['1'],
  99. 'options' => [
  100. ['value' => '1', 'text' => 'CakePHP', 'data-test' => 'val'],
  101. ['value' => '2', 'text' => 'Development', 'class' => 'custom'],
  102. ]
  103. ];
  104. $result = $input->render($data, $this->context);
  105. $expected = [
  106. ['div' => ['class' => 'checkbox']],
  107. ['input' => [
  108. 'disabled' => 'disabled',
  109. 'type' => 'checkbox',
  110. 'name' => 'Tags[id][]',
  111. 'value' => 1,
  112. 'id' => 'tags-id-1',
  113. 'data-test' => 'val',
  114. ]],
  115. ['label' => ['for' => 'tags-id-1']],
  116. 'CakePHP',
  117. '/label',
  118. '/div',
  119. ['div' => ['class' => 'checkbox']],
  120. ['input' => [
  121. 'type' => 'checkbox',
  122. 'checked' => 'checked',
  123. 'name' => 'Tags[id][]',
  124. 'value' => 2,
  125. 'id' => 'tags-id-2',
  126. 'class' => 'custom',
  127. ]],
  128. ['label' => ['class' => 'selected', 'for' => 'tags-id-2']],
  129. 'Development',
  130. '/label',
  131. '/div',
  132. ];
  133. $this->assertHtml($expected, $result);
  134. }
  135. /**
  136. * Test render escpaing options.
  137. *
  138. * @return void
  139. */
  140. public function testRenderEscaping()
  141. {
  142. $label = new LabelWidget($this->templates);
  143. $input = new MultiCheckboxWidget($this->templates, $label);
  144. $data = [
  145. 'name' => 'Tags[id]',
  146. 'options' => [
  147. '>' => '>>',
  148. ]
  149. ];
  150. $result = $input->render($data, $this->context);
  151. $expected = [
  152. ['div' => ['class' => 'checkbox']],
  153. ['input' => [
  154. 'type' => 'checkbox',
  155. 'name' => 'Tags[id][]',
  156. 'value' => '&gt;',
  157. 'id' => 'tags-id',
  158. ]],
  159. ['label' => ['for' => 'tags-id']],
  160. '&gt;&gt;',
  161. '/label',
  162. '/div',
  163. ];
  164. $this->assertHtml($expected, $result);
  165. }
  166. /**
  167. * Test render selected checkboxes.
  168. *
  169. * @return void
  170. */
  171. public function testRenderSelected()
  172. {
  173. $label = new LabelWidget($this->templates);
  174. $input = new MultiCheckboxWidget($this->templates, $label);
  175. $data = [
  176. 'name' => 'Tags[id]',
  177. 'options' => [
  178. 1 => 'CakePHP',
  179. '1x' => 'Development',
  180. ],
  181. 'val' => [1],
  182. 'disabled' => false
  183. ];
  184. $result = $input->render($data, $this->context);
  185. $expected = [
  186. ['div' => ['class' => 'checkbox']],
  187. ['input' => [
  188. 'type' => 'checkbox',
  189. 'name' => 'Tags[id][]',
  190. 'value' => 1,
  191. 'id' => 'tags-id-1',
  192. 'checked' => 'checked'
  193. ]],
  194. ['label' => ['class' => 'selected', 'for' => 'tags-id-1']],
  195. 'CakePHP',
  196. '/label',
  197. '/div',
  198. ['div' => ['class' => 'checkbox']],
  199. ['input' => [
  200. 'type' => 'checkbox',
  201. 'name' => 'Tags[id][]',
  202. 'value' => '1x',
  203. 'id' => 'tags-id-1x',
  204. ]],
  205. ['label' => ['for' => 'tags-id-1x']],
  206. 'Development',
  207. '/label',
  208. '/div',
  209. ];
  210. $this->assertHtml($expected, $result);
  211. $data['val'] = 1;
  212. $result = $input->render($data, $this->context);
  213. $this->assertHtml($expected, $result);
  214. $data['val'] = '1';
  215. $result = $input->render($data, $this->context);
  216. $this->assertHtml($expected, $result);
  217. }
  218. /**
  219. * Test render disabled checkboxes.
  220. *
  221. * @return void
  222. */
  223. public function testRenderDisabled()
  224. {
  225. $label = new LabelWidget($this->templates);
  226. $input = new MultiCheckboxWidget($this->templates, $label);
  227. $data = [
  228. 'name' => 'Tags[id]',
  229. 'options' => [
  230. 1 => 'CakePHP',
  231. '1x' => 'Development',
  232. ],
  233. 'disabled' => true,
  234. ];
  235. $result = $input->render($data, $this->context);
  236. $expected = [
  237. ['div' => ['class' => 'checkbox']],
  238. ['input' => [
  239. 'type' => 'checkbox',
  240. 'name' => 'Tags[id][]',
  241. 'value' => 1,
  242. 'id' => 'tags-id-1',
  243. 'disabled' => 'disabled'
  244. ]],
  245. ['label' => ['for' => 'tags-id-1']],
  246. 'CakePHP',
  247. '/label',
  248. '/div',
  249. ['div' => ['class' => 'checkbox']],
  250. ['input' => [
  251. 'type' => 'checkbox',
  252. 'name' => 'Tags[id][]',
  253. 'value' => '1x',
  254. 'id' => 'tags-id-1x',
  255. 'disabled' => 'disabled'
  256. ]],
  257. ['label' => ['for' => 'tags-id-1x']],
  258. 'Development',
  259. '/label',
  260. '/div',
  261. ];
  262. $this->assertHtml($expected, $result);
  263. $data['disabled'] = 'a string';
  264. $result = $input->render($data, $this->context);
  265. $this->assertHtml($expected, $result);
  266. $data['disabled'] = ['1', '1x'];
  267. $this->assertHtml($expected, $result);
  268. $data = [
  269. 'name' => 'Tags[id]',
  270. 'options' => [
  271. 1 => 'CakePHP',
  272. '1x' => 'Development',
  273. ],
  274. 'disabled' => [1]
  275. ];
  276. $result = $input->render($data, $this->context);
  277. $expected = [
  278. ['div' => ['class' => 'checkbox']],
  279. ['input' => [
  280. 'type' => 'checkbox',
  281. 'name' => 'Tags[id][]',
  282. 'value' => 1,
  283. 'id' => 'tags-id-1',
  284. 'disabled' => 'disabled'
  285. ]],
  286. ['label' => ['for' => 'tags-id-1']],
  287. 'CakePHP',
  288. '/label',
  289. '/div',
  290. ['div' => ['class' => 'checkbox']],
  291. ['input' => [
  292. 'type' => 'checkbox',
  293. 'name' => 'Tags[id][]',
  294. 'value' => '1x',
  295. 'id' => 'tags-id-1x',
  296. ]],
  297. ['label' => ['for' => 'tags-id-1x']],
  298. 'Development',
  299. '/label',
  300. '/div',
  301. ];
  302. $this->assertHtml($expected, $result);
  303. }
  304. /**
  305. * Test render templateVars
  306. *
  307. * @return void
  308. */
  309. public function testRenderTemplateVars()
  310. {
  311. $templates = [
  312. 'checkbox' => '<input type="checkbox" name="{{name}}" value="{{value}}" data-var="{{inputVar}}" {{attrs}}>',
  313. 'label' => '<label{{attrs}}>{{text}} {{inputVar}}</label>',
  314. 'checkboxWrapper' => '<div class="checkbox" data-wrap="{{wrapVar}}">{{input}}{{label}}</div>',
  315. ];
  316. $this->templates->add($templates);
  317. $label = new LabelWidget($this->templates);
  318. $input = new MultiCheckboxWidget($this->templates, $label);
  319. $data = [
  320. 'name' => 'Tags[id]',
  321. 'options' => [
  322. ['value' => '1', 'text' => 'CakePHP', 'templateVars' => ['inputVar' => 'i-var']],
  323. '1x' => 'Development',
  324. ],
  325. 'templateVars' => ['inputVar' => 'default', 'wrapVar' => 'val'],
  326. ];
  327. $result = $input->render($data, $this->context);
  328. $expected = [
  329. ['div' => ['class' => 'checkbox', 'data-wrap' => 'val']],
  330. ['input' => [
  331. 'type' => 'checkbox',
  332. 'name' => 'Tags[id][]',
  333. 'value' => 1,
  334. 'id' => 'tags-id-1',
  335. 'data-var' => 'i-var',
  336. ]],
  337. ['label' => ['for' => 'tags-id-1']],
  338. 'CakePHP i-var',
  339. '/label',
  340. '/div',
  341. ['div' => ['class' => 'checkbox', 'data-wrap' => 'val']],
  342. ['input' => [
  343. 'type' => 'checkbox',
  344. 'name' => 'Tags[id][]',
  345. 'value' => '1x',
  346. 'id' => 'tags-id-1x',
  347. 'data-var' => 'default'
  348. ]],
  349. ['label' => ['for' => 'tags-id-1x']],
  350. 'Development default',
  351. '/label',
  352. '/div',
  353. ];
  354. $this->assertHtml($expected, $result);
  355. }
  356. /**
  357. * Test label = false with checkboxWrapper option.
  358. *
  359. * @return void
  360. */
  361. public function testNoLabelWithCheckboxWrapperOption()
  362. {
  363. $data = [
  364. 'label' => false,
  365. 'name' => 'test',
  366. 'options' => [
  367. 1 => 'A',
  368. 2 => 'B',
  369. ],
  370. ];
  371. $label = new LabelWidget($this->templates);
  372. $input = new MultiCheckboxWidget($this->templates, $label);
  373. $result = $input->render($data, $this->context);
  374. $expected = [
  375. ['div' => ['class' => 'checkbox']],
  376. ['input' => [
  377. 'type' => 'checkbox',
  378. 'name' => 'test[]',
  379. 'value' => 1,
  380. 'id' => 'test-1',
  381. ]],
  382. ['label' => ['for' => 'test-1']],
  383. 'A',
  384. '/label',
  385. '/div',
  386. ['div' => ['class' => 'checkbox']],
  387. ['input' => [
  388. 'type' => 'checkbox',
  389. 'name' => 'test[]',
  390. 'value' => '2',
  391. 'id' => 'test-2',
  392. ]],
  393. ['label' => ['for' => 'test-2']],
  394. 'B',
  395. '/label',
  396. '/div',
  397. ];
  398. $this->assertHtml($expected, $result);
  399. $templates = [
  400. 'checkboxWrapper' => '<div class="checkbox">{{label}}</div>',
  401. ];
  402. $this->templates->add($templates);
  403. $result = $input->render($data, $this->context);
  404. $expected = [
  405. ['div' => ['class' => 'checkbox']],
  406. ['input' => [
  407. 'type' => 'checkbox',
  408. 'name' => 'test[]',
  409. 'value' => 1,
  410. 'id' => 'test-1',
  411. ]],
  412. '/div',
  413. ['div' => ['class' => 'checkbox']],
  414. ['input' => [
  415. 'type' => 'checkbox',
  416. 'name' => 'test[]',
  417. 'value' => '2',
  418. 'id' => 'test-2',
  419. ]],
  420. '/div',
  421. ];
  422. $this->assertHtml($expected, $result);
  423. }
  424. /**
  425. * Test render with groupings.
  426. *
  427. * @return void
  428. */
  429. public function testRenderGrouped()
  430. {
  431. $label = new LabelWidget($this->templates);
  432. $input = new MultiCheckboxWidget($this->templates, $label);
  433. $data = [
  434. 'name' => 'Tags[id]',
  435. 'options' => [
  436. 'Group 1' => [
  437. 1 => 'CakePHP',
  438. ],
  439. 'Group 2' => [
  440. 2 => 'Development',
  441. ]
  442. ]
  443. ];
  444. $result = $input->render($data, $this->context);
  445. $expected = [
  446. '<fieldset',
  447. '<legend', 'Group 1', '/legend',
  448. ['div' => ['class' => 'checkbox']],
  449. ['input' => [
  450. 'type' => 'checkbox',
  451. 'name' => 'Tags[id][]',
  452. 'value' => 1,
  453. 'id' => 'tags-id-1',
  454. ]],
  455. ['label' => ['for' => 'tags-id-1']],
  456. 'CakePHP',
  457. '/label',
  458. '/div',
  459. '/fieldset',
  460. '<fieldset',
  461. '<legend', 'Group 2', '/legend',
  462. ['div' => ['class' => 'checkbox']],
  463. ['input' => [
  464. 'type' => 'checkbox',
  465. 'name' => 'Tags[id][]',
  466. 'value' => 2,
  467. 'id' => 'tags-id-2',
  468. ]],
  469. ['label' => ['for' => 'tags-id-2']],
  470. 'Development',
  471. '/label',
  472. '/div',
  473. '/fieldset',
  474. ];
  475. $this->assertHtml($expected, $result);
  476. }
  477. /**
  478. * Test render with partial groupings.
  479. *
  480. * @return void
  481. */
  482. public function testRenderPartialGrouped()
  483. {
  484. $label = new LabelWidget($this->templates);
  485. $input = new MultiCheckboxWidget($this->templates, $label);
  486. $data = [
  487. 'name' => 'Tags[id]',
  488. 'options' => [
  489. 1 => 'PHP',
  490. 'Group 1' => [
  491. 2 => 'CakePHP',
  492. ],
  493. 3 => 'Development',
  494. ]
  495. ];
  496. $result = $input->render($data, $this->context);
  497. $expected = [
  498. ['div' => ['class' => 'checkbox']],
  499. ['input' => [
  500. 'type' => 'checkbox',
  501. 'name' => 'Tags[id][]',
  502. 'value' => 1,
  503. 'id' => 'tags-id-1',
  504. ]],
  505. ['label' => ['for' => 'tags-id-1']],
  506. 'PHP',
  507. '/label',
  508. '/div',
  509. '<fieldset',
  510. '<legend', 'Group 1', '/legend',
  511. ['div' => ['class' => 'checkbox']],
  512. ['input' => [
  513. 'type' => 'checkbox',
  514. 'name' => 'Tags[id][]',
  515. 'value' => 2,
  516. 'id' => 'tags-id-2',
  517. ]],
  518. ['label' => ['for' => 'tags-id-2']],
  519. 'CakePHP',
  520. '/label',
  521. '/div',
  522. '/fieldset',
  523. ['div' => ['class' => 'checkbox']],
  524. ['input' => [
  525. 'type' => 'checkbox',
  526. 'name' => 'Tags[id][]',
  527. 'value' => 3,
  528. 'id' => 'tags-id-3',
  529. ]],
  530. ['label' => ['for' => 'tags-id-3']],
  531. 'Development',
  532. '/label',
  533. '/div',
  534. ];
  535. $this->assertHtml($expected, $result);
  536. }
  537. /**
  538. * testRenderCustomAttributes method
  539. *
  540. * Test render with custom attributes
  541. *
  542. * @return void
  543. */
  544. public function testRenderCustomAttributes()
  545. {
  546. $label = new LabelWidget($this->templates);
  547. $input = new MultiCheckboxWidget($this->templates, $label);
  548. $result = $input->render([
  549. 'name' => 'category',
  550. 'options' => ['1', '2'],
  551. 'class' => 'my-class',
  552. 'data-ref' => 'custom-attr',
  553. ], $this->context);
  554. $expected = [
  555. ['div' => ['class' => 'checkbox']],
  556. [
  557. 'input' => [
  558. 'type' => 'checkbox',
  559. 'name' => 'category[]',
  560. 'value' => '0',
  561. 'id' => 'category-0',
  562. 'class' => 'my-class',
  563. 'data-ref' => 'custom-attr'
  564. ]
  565. ],
  566. ['label' => ['for' => 'category-0']],
  567. '1',
  568. '/label',
  569. '/div',
  570. ['div' => ['class' => 'checkbox']],
  571. [
  572. 'input' => [
  573. 'type' => 'checkbox',
  574. 'name' => 'category[]',
  575. 'value' => '1',
  576. 'id' => 'category-1',
  577. 'class' => 'my-class',
  578. 'data-ref' => 'custom-attr'
  579. ]
  580. ],
  581. ['label' => ['for' => 'category-1']],
  582. '2',
  583. '/label',
  584. '/div'
  585. ];
  586. $this->assertHtml($expected, $result);
  587. }
  588. }