RadioTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since CakePHP(tm) v3.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\View\Widget;
  16. use Cake\Collection\Collection;
  17. use Cake\TestSuite\TestCase;
  18. use Cake\View\StringTemplate;
  19. use Cake\View\Widget\Label;
  20. use Cake\View\Widget\Radio;
  21. /**
  22. * Radio test case
  23. */
  24. class RadioTest extends TestCase {
  25. /**
  26. * setup method.
  27. *
  28. * @return void
  29. */
  30. public function setUp() {
  31. parent::setUp();
  32. $templates = [
  33. 'radio' => '<input type="radio" name="{{name}}" value="{{value}}"{{attrs}}>',
  34. 'label' => '<label{{attrs}}>{{text}}</label>',
  35. 'radioContainer' => '{{input}}{{label}}',
  36. ];
  37. $this->templates = new StringTemplate($templates);
  38. }
  39. /**
  40. * Test rendering basic radio buttons.
  41. *
  42. * @return void
  43. */
  44. public function testRenderSimple() {
  45. $label = new Label($this->templates);
  46. $radio = new Radio($this->templates, $label);
  47. $data = [
  48. 'name' => 'Crayons[color]',
  49. 'options' => ['r' => 'Red', 'b' => 'Black']
  50. ];
  51. $result = $radio->render($data);
  52. $expected = [
  53. ['input' => [
  54. 'type' => 'radio',
  55. 'name' => 'Crayons[color]',
  56. 'value' => 'r',
  57. 'id' => 'crayons-color-r'
  58. ]],
  59. ['label' => ['for' => 'crayons-color-r']],
  60. 'Red',
  61. '/label',
  62. ['input' => [
  63. 'type' => 'radio',
  64. 'name' => 'Crayons[color]',
  65. 'value' => 'b',
  66. 'id' => 'crayons-color-b'
  67. ]],
  68. ['label' => ['for' => 'crayons-color-b']],
  69. 'Black',
  70. '/label',
  71. ];
  72. $this->assertTags($result, $expected);
  73. $data = [
  74. 'name' => 'Crayons[color]',
  75. 'options' => new Collection(['r' => 'Red', 'b' => 'Black'])
  76. ];
  77. $result = $radio->render($data);
  78. $this->assertTags($result, $expected);
  79. }
  80. /**
  81. * Test rendering inputs with the complex option form.
  82. *
  83. * @return void
  84. */
  85. public function testRenderComplex() {
  86. $label = new Label($this->templates);
  87. $radio = new Radio($this->templates, $label);
  88. $data = [
  89. 'name' => 'Crayons[color]',
  90. 'options' => [
  91. ['value' => 'r', 'text' => 'Red', 'id' => 'my_id'],
  92. ['value' => 'b', 'text' => 'Black', 'id' => 'my_id_2', 'data-test' => 'test'],
  93. ]
  94. ];
  95. $result = $radio->render($data);
  96. $expected = [
  97. ['input' => [
  98. 'type' => 'radio',
  99. 'name' => 'Crayons[color]',
  100. 'value' => 'r',
  101. 'id' => 'my_id'
  102. ]],
  103. ['label' => ['for' => 'my_id']],
  104. 'Red',
  105. '/label',
  106. ['input' => [
  107. 'type' => 'radio',
  108. 'name' => 'Crayons[color]',
  109. 'value' => 'b',
  110. 'id' => 'my_id_2',
  111. 'data-test' => 'test'
  112. ]],
  113. ['label' => ['for' => 'my_id_2']],
  114. 'Black',
  115. '/label',
  116. ];
  117. $this->assertTags($result, $expected);
  118. }
  119. /**
  120. * Test that id suffixes are generated to not collide
  121. *
  122. * @return void
  123. */
  124. public function testRenderIdSuffixGeneration() {
  125. $label = new Label($this->templates);
  126. $radio = new Radio($this->templates, $label);
  127. $data = [
  128. 'name' => 'Thing[value]',
  129. 'options' => ['a>b' => 'First', 'a<b' => 'Second']
  130. ];
  131. $result = $radio->render($data);
  132. $expected = [
  133. ['input' => [
  134. 'type' => 'radio',
  135. 'name' => 'Thing[value]',
  136. 'value' => 'a&gt;b',
  137. 'id' => 'thing-value-a-b'
  138. ]],
  139. ['label' => ['for' => 'thing-value-a-b']],
  140. 'First',
  141. '/label',
  142. ['input' => [
  143. 'type' => 'radio',
  144. 'name' => 'Thing[value]',
  145. 'value' => 'a&lt;b',
  146. 'id' => 'thing-value-a-b1',
  147. ]],
  148. ['label' => ['for' => 'thing-value-a-b1']],
  149. 'Second',
  150. '/label',
  151. ];
  152. $this->assertTags($result, $expected);
  153. }
  154. /**
  155. * Test rendering checks the right option with booleanish values.
  156. *
  157. * @return void
  158. */
  159. public function testRenderBooleanishValues() {
  160. $label = new Label($this->templates);
  161. $radio = new Radio($this->templates, $label);
  162. $data = [
  163. 'name' => 'Model[field]',
  164. 'options' => ['1' => 'Yes', '0' => 'No'],
  165. 'val' => '0'
  166. ];
  167. $result = $radio->render($data);
  168. $expected = array(
  169. array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1')),
  170. array('label' => array('for' => 'model-field-1')),
  171. 'Yes',
  172. '/label',
  173. array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0', 'checked' => 'checked')),
  174. array('label' => array('for' => 'model-field-0')),
  175. 'No',
  176. '/label',
  177. );
  178. $this->assertTags($result, $expected);
  179. $data['val'] = 0;
  180. $result = $radio->render($data);
  181. $this->assertTags($result, $expected);
  182. $data['val'] = false;
  183. $result = $radio->render($data);
  184. $this->assertTags($result, $expected);
  185. $expected = array(
  186. array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1')),
  187. array('label' => array('for' => 'model-field-1')),
  188. 'Yes',
  189. '/label',
  190. array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0')),
  191. array('label' => array('for' => 'model-field-0')),
  192. 'No',
  193. '/label',
  194. );
  195. $data['val'] = null;
  196. $result = $radio->render($data);
  197. $this->assertTags($result, $expected);
  198. $data['val'] = '';
  199. $result = $radio->render($data);
  200. $this->assertTags($result, $expected);
  201. $expected = array(
  202. array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1', 'checked' => 'checked')),
  203. array('label' => array('for' => 'model-field-1')),
  204. 'Yes',
  205. '/label',
  206. array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0')),
  207. array('label' => array('for' => 'model-field-0')),
  208. 'No',
  209. '/label',
  210. );
  211. $data['val'] = '1';
  212. $result = $radio->render($data);
  213. $this->assertTags($result, $expected);
  214. $data['val'] = 1;
  215. $result = $radio->render($data);
  216. $this->assertTags($result, $expected);
  217. $data['val'] = true;
  218. $result = $radio->render($data);
  219. $this->assertTags($result, $expected);
  220. }
  221. /**
  222. * Test that render() works with the required attribute.
  223. *
  224. * @return void
  225. */
  226. public function testRenderRequired() {
  227. $label = new Label($this->templates);
  228. $radio = new Radio($this->templates, $label);
  229. $data = [
  230. 'name' => 'published',
  231. 'options' => ['option A', 'option B'],
  232. 'required' => true
  233. ];
  234. $result = $radio->render($data);
  235. $expected = [
  236. ['input' => ['type' => 'radio', 'name' => 'published', 'value' => '0', 'id' => 'published-0', 'required' => 'required']],
  237. ['label' => ['for' => 'published-0']],
  238. 'option A',
  239. '/label',
  240. ['input' => ['type' => 'radio', 'name' => 'published', 'value' => '1', 'id' => 'published-1', 'required' => 'required']],
  241. ['label' => ['for' => 'published-1']],
  242. 'option B',
  243. '/label',
  244. ];
  245. $this->assertTags($result, $expected);
  246. }
  247. /**
  248. * Test rendering the empty option.
  249. *
  250. * @return void
  251. */
  252. public function testRenderEmptyOption() {
  253. $label = new Label($this->templates);
  254. $radio = new Radio($this->templates, $label);
  255. $data = [
  256. 'name' => 'Crayons[color]',
  257. 'options' => ['r' => 'Red'],
  258. 'empty' => true,
  259. ];
  260. $result = $radio->render($data);
  261. $expected = [
  262. ['input' => [
  263. 'type' => 'radio',
  264. 'name' => 'Crayons[color]',
  265. 'value' => '',
  266. 'id' => 'crayons-color'
  267. ]],
  268. ['label' => ['for' => 'crayons-color']],
  269. 'empty',
  270. '/label',
  271. ['input' => [
  272. 'type' => 'radio',
  273. 'name' => 'Crayons[color]',
  274. 'value' => 'r',
  275. 'id' => 'crayons-color-r'
  276. ]],
  277. ['label' => ['for' => 'crayons-color-r']],
  278. 'Red',
  279. '/label',
  280. ];
  281. $this->assertTags($result, $expected);
  282. $data['empty'] = 'Choose one';
  283. $result = $radio->render($data);
  284. $expected = [
  285. ['input' => [
  286. 'type' => 'radio',
  287. 'name' => 'Crayons[color]',
  288. 'value' => '',
  289. 'id' => 'crayons-color'
  290. ]],
  291. ['label' => ['for' => 'crayons-color']],
  292. 'Choose one',
  293. '/label',
  294. ['input' => [
  295. 'type' => 'radio',
  296. 'name' => 'Crayons[color]',
  297. 'value' => 'r',
  298. 'id' => 'crayons-color-r'
  299. ]],
  300. ['label' => ['for' => 'crayons-color-r']],
  301. 'Red',
  302. '/label',
  303. ];
  304. $this->assertTags($result, $expected);
  305. }
  306. /**
  307. * Test rendering the input inside the label.
  308. *
  309. * @return void
  310. */
  311. public function testRenderInputInsideLabel() {
  312. $this->templates->add([
  313. 'label' => '<label{{attrs}}>{{input}}{{text}}</label>',
  314. 'radioContainer' => '{{label}}',
  315. ]);
  316. $label = new Label($this->templates);
  317. $radio = new Radio($this->templates, $label);
  318. $data = [
  319. 'name' => 'Crayons[color]',
  320. 'options' => ['r' => 'Red'],
  321. ];
  322. $result = $radio->render($data);
  323. $expected = [
  324. ['label' => ['for' => 'crayons-color-r']],
  325. ['input' => [
  326. 'type' => 'radio',
  327. 'name' => 'Crayons[color]',
  328. 'value' => 'r',
  329. 'id' => 'crayons-color-r'
  330. ]],
  331. 'Red',
  332. '/label',
  333. ];
  334. $this->assertTags($result, $expected);
  335. }
  336. /**
  337. * test render() and selected inputs.
  338. *
  339. * @return void
  340. */
  341. public function testRenderSelected() {
  342. $label = new Label($this->templates);
  343. $radio = new Radio($this->templates, $label);
  344. $data = [
  345. 'name' => 'Versions[ver]',
  346. 'val' => '1',
  347. 'options' => [
  348. 1 => 'one',
  349. '1x' => 'one x',
  350. '2' => 'two',
  351. ]
  352. ];
  353. $result = $radio->render($data);
  354. $expected = [
  355. ['input' => [
  356. 'id' => 'versions-ver-1',
  357. 'name' => 'Versions[ver]',
  358. 'type' => 'radio',
  359. 'value' => '1',
  360. 'checked' => 'checked'
  361. ]],
  362. ['label' => ['for' => 'versions-ver-1']],
  363. 'one',
  364. '/label',
  365. ['input' => [
  366. 'id' => 'versions-ver-1x',
  367. 'name' => 'Versions[ver]',
  368. 'type' => 'radio',
  369. 'value' => '1x'
  370. ]],
  371. ['label' => ['for' => 'versions-ver-1x']],
  372. 'one x',
  373. '/label',
  374. ['input' => [
  375. 'id' => 'versions-ver-2',
  376. 'name' => 'Versions[ver]',
  377. 'type' => 'radio',
  378. 'value' => '2'
  379. ]],
  380. ['label' => ['for' => 'versions-ver-2']],
  381. 'two',
  382. '/label',
  383. ];
  384. $this->assertTags($result, $expected);
  385. }
  386. /**
  387. * Test rendering with disable inputs
  388. *
  389. * @return void
  390. */
  391. public function testRenderDisabled() {
  392. $label = new Label($this->templates);
  393. $radio = new Radio($this->templates, $label);
  394. $data = [
  395. 'name' => 'Versions[ver]',
  396. 'options' => [
  397. 1 => 'one',
  398. '1x' => 'one x',
  399. '2' => 'two',
  400. ],
  401. 'disabled' => true,
  402. ];
  403. $result = $radio->render($data);
  404. $expected = [
  405. ['input' => [
  406. 'id' => 'versions-ver-1',
  407. 'name' => 'Versions[ver]',
  408. 'type' => 'radio',
  409. 'value' => '1',
  410. 'disabled' => 'disabled'
  411. ]],
  412. ['label' => ['for' => 'versions-ver-1']],
  413. 'one',
  414. '/label',
  415. ['input' => [
  416. 'id' => 'versions-ver-1x',
  417. 'name' => 'Versions[ver]',
  418. 'type' => 'radio',
  419. 'value' => '1x',
  420. 'disabled' => 'disabled'
  421. ]],
  422. ['label' => ['for' => 'versions-ver-1x']],
  423. 'one x',
  424. '/label',
  425. ];
  426. $this->assertTags($result, $expected);
  427. $data['disabled'] = 'a string';
  428. $result = $radio->render($data);
  429. $this->assertTags($result, $expected);
  430. $data['disabled'] = ['1'];
  431. $result = $radio->render($data);
  432. $expected = [
  433. ['input' => [
  434. 'id' => 'versions-ver-1',
  435. 'name' => 'Versions[ver]',
  436. 'type' => 'radio',
  437. 'value' => '1',
  438. 'disabled' => 'disabled'
  439. ]],
  440. ['label' => ['for' => 'versions-ver-1']],
  441. 'one',
  442. '/label',
  443. ['input' => [
  444. 'id' => 'versions-ver-1x',
  445. 'name' => 'Versions[ver]',
  446. 'type' => 'radio',
  447. 'value' => '1x',
  448. ]],
  449. ['label' => ['for' => 'versions-ver-1x']],
  450. 'one x',
  451. '/label',
  452. ];
  453. $this->assertTags($result, $expected);
  454. }
  455. /**
  456. * Test rendering with label options.
  457. *
  458. * @return void
  459. */
  460. public function testRenderLabelOptions() {
  461. $label = new Label($this->templates);
  462. $radio = new Radio($this->templates, $label);
  463. $data = [
  464. 'name' => 'Versions[ver]',
  465. 'options' => [
  466. 1 => 'one',
  467. '1x' => 'one x',
  468. '2' => 'two',
  469. ],
  470. 'label' => false,
  471. ];
  472. $result = $radio->render($data);
  473. $expected = [
  474. ['input' => [
  475. 'id' => 'versions-ver-1',
  476. 'name' => 'Versions[ver]',
  477. 'type' => 'radio',
  478. 'value' => '1',
  479. ]],
  480. ['input' => [
  481. 'id' => 'versions-ver-1x',
  482. 'name' => 'Versions[ver]',
  483. 'type' => 'radio',
  484. 'value' => '1x',
  485. ]],
  486. ];
  487. $this->assertTags($result, $expected);
  488. $data = [
  489. 'name' => 'Versions[ver]',
  490. 'options' => [
  491. 1 => 'one',
  492. '1x' => 'one x',
  493. '2' => 'two',
  494. ],
  495. 'label' => [
  496. 'class' => 'my-class',
  497. ]
  498. ];
  499. $result = $radio->render($data);
  500. $expected = [
  501. ['input' => [
  502. 'id' => 'versions-ver-1',
  503. 'name' => 'Versions[ver]',
  504. 'type' => 'radio',
  505. 'value' => '1',
  506. ]],
  507. ['label' => ['class' => 'my-class', 'for' => 'versions-ver-1']],
  508. 'one',
  509. '/label',
  510. ['input' => [
  511. 'id' => 'versions-ver-1x',
  512. 'name' => 'Versions[ver]',
  513. 'type' => 'radio',
  514. 'value' => '1x',
  515. ]],
  516. ['label' => ['class' => 'my-class', 'for' => 'versions-ver-1x']],
  517. 'one x',
  518. '/label',
  519. ];
  520. $this->assertTags($result, $expected);
  521. }
  522. /**
  523. * Ensure that the input + label are composed with
  524. * a template.
  525. *
  526. * @return void
  527. */
  528. public function testRenderContainerTemplate() {
  529. $this->templates->add([
  530. 'radioContainer' => '<div class="radio">{{input}}{{label}}</div>'
  531. ]);
  532. $label = new Label($this->templates);
  533. $radio = new Radio($this->templates, $label);
  534. $data = [
  535. 'name' => 'Versions[ver]',
  536. 'options' => [
  537. 1 => 'one',
  538. '1x' => 'one x',
  539. '2' => 'two',
  540. ],
  541. ];
  542. $result = $radio->render($data);
  543. $this->assertContains(
  544. '<div class="radio"><input type="radio"',
  545. $result
  546. );
  547. $this->assertContains(
  548. '</label></div>',
  549. $result
  550. );
  551. }
  552. }