RadioWidgetTest.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  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\Collection\Collection;
  17. use Cake\TestSuite\TestCase;
  18. use Cake\View\StringTemplate;
  19. use Cake\View\Widget\NestingLabelWidget;
  20. use Cake\View\Widget\RadioWidget;
  21. /**
  22. * Radio test case
  23. */
  24. class RadioWidgetTest extends TestCase
  25. {
  26. /**
  27. * setup method.
  28. *
  29. * @return void
  30. */
  31. public function setUp()
  32. {
  33. parent::setUp();
  34. $templates = [
  35. 'radio' => '<input type="radio" name="{{name}}" value="{{value}}"{{attrs}}>',
  36. 'nestingLabel' => '<label{{attrs}}>{{input}}{{text}}</label>',
  37. 'radioWrapper' => '{{label}}',
  38. 'selectedClass' => 'selected',
  39. ];
  40. $this->templates = new StringTemplate($templates);
  41. $this->context = $this->getMockBuilder('Cake\View\Form\ContextInterface')->getMock();
  42. }
  43. /**
  44. * Test rendering basic radio buttons without nested inputs
  45. *
  46. * @return void
  47. */
  48. public function testRenderSimpleNotNested()
  49. {
  50. $this->templates->add([
  51. 'nestingLabel' => '<label{{attrs}}>{{text}}</label>',
  52. 'radioWrapper' => '{{input}}{{label}}',
  53. ]);
  54. $label = new NestingLabelWidget($this->templates);
  55. $radio = new RadioWidget($this->templates, $label);
  56. $data = [
  57. 'name' => 'Crayons[color]',
  58. 'label' => null,
  59. 'options' => ['r' => 'Red', 'b' => 'Black'],
  60. ];
  61. $result = $radio->render($data, $this->context);
  62. $expected = [
  63. ['input' => [
  64. 'type' => 'radio',
  65. 'name' => 'Crayons[color]',
  66. 'value' => 'r',
  67. 'id' => 'crayons-color-r',
  68. ]],
  69. ['label' => ['for' => 'crayons-color-r']],
  70. 'Red',
  71. '/label',
  72. ['input' => [
  73. 'type' => 'radio',
  74. 'name' => 'Crayons[color]',
  75. 'value' => 'b',
  76. 'id' => 'crayons-color-b',
  77. ]],
  78. ['label' => ['for' => 'crayons-color-b']],
  79. 'Black',
  80. '/label',
  81. ];
  82. $this->assertHtml($expected, $result);
  83. $data = [
  84. 'name' => 'Crayons[color]',
  85. 'label' => false,
  86. 'options' => ['r' => 'Red', 'b' => 'Black'],
  87. ];
  88. $result = $radio->render($data, $this->context);
  89. $expected = [
  90. ['input' => [
  91. 'type' => 'radio',
  92. 'name' => 'Crayons[color]',
  93. 'value' => 'r',
  94. 'id' => 'crayons-color-r',
  95. ]],
  96. ['input' => [
  97. 'type' => 'radio',
  98. 'name' => 'Crayons[color]',
  99. 'value' => 'b',
  100. 'id' => 'crayons-color-b',
  101. ]],
  102. ];
  103. $this->assertHtml($expected, $result);
  104. }
  105. /**
  106. * Test rendering basic radio buttons.
  107. *
  108. * @return void
  109. */
  110. public function testRenderSimple()
  111. {
  112. $label = new NestingLabelWidget($this->templates);
  113. $radio = new RadioWidget($this->templates, $label);
  114. $data = [
  115. 'name' => 'Crayons[color]',
  116. 'label' => null,
  117. 'options' => ['r' => 'Red', 'b' => 'Black'],
  118. ];
  119. $result = $radio->render($data, $this->context);
  120. $expected = [
  121. ['label' => ['for' => 'crayons-color-r']],
  122. ['input' => [
  123. 'type' => 'radio',
  124. 'name' => 'Crayons[color]',
  125. 'value' => 'r',
  126. 'id' => 'crayons-color-r',
  127. ]],
  128. 'Red',
  129. '/label',
  130. ['label' => ['for' => 'crayons-color-b']],
  131. ['input' => [
  132. 'type' => 'radio',
  133. 'name' => 'Crayons[color]',
  134. 'value' => 'b',
  135. 'id' => 'crayons-color-b',
  136. ]],
  137. 'Black',
  138. '/label',
  139. ];
  140. $this->assertHtml($expected, $result);
  141. $data = [
  142. 'name' => 'Crayons[color]',
  143. 'options' => new Collection(['r' => 'Red', 'b' => 'Black']),
  144. ];
  145. $result = $radio->render($data, $this->context);
  146. $this->assertHtml($expected, $result);
  147. }
  148. /**
  149. * Test rendering the activeClass template var
  150. *
  151. * @return void
  152. */
  153. public function testRenderSimpleActiveTemplateVar()
  154. {
  155. $this->templates->add([
  156. 'nestingLabel' => '<label class="{{activeClass}}"{{attrs}}>{{text}}</label>',
  157. 'radioWrapper' => '{{input}}{{label}}',
  158. ]);
  159. $label = new NestingLabelWidget($this->templates);
  160. $radio = new RadioWidget($this->templates, $label);
  161. $data = [
  162. 'name' => 'Crayons[color]',
  163. 'val' => 'r',
  164. 'options' => ['r' => 'Red', 'b' => 'Black'],
  165. ];
  166. $result = $radio->render($data, $this->context);
  167. $expected = [
  168. ['input' => [
  169. 'type' => 'radio',
  170. 'name' => 'Crayons[color]',
  171. 'value' => 'r',
  172. 'id' => 'crayons-color-r',
  173. 'checked' => 'checked',
  174. ]],
  175. ['label' => ['class' => 'active', 'for' => 'crayons-color-r']],
  176. 'Red',
  177. '/label',
  178. ['input' => [
  179. 'type' => 'radio',
  180. 'name' => 'Crayons[color]',
  181. 'value' => 'b',
  182. 'id' => 'crayons-color-b',
  183. ]],
  184. ['label' => ['class' => '', 'for' => 'crayons-color-b']],
  185. 'Black',
  186. '/label',
  187. ];
  188. $this->assertHtml($expected, $result);
  189. }
  190. /**
  191. * Test rendering inputs with the complex option form.
  192. *
  193. * @return void
  194. */
  195. public function testRenderComplex()
  196. {
  197. $label = new NestingLabelWidget($this->templates);
  198. $radio = new RadioWidget($this->templates, $label);
  199. $data = [
  200. 'name' => 'Crayons[color]',
  201. 'options' => [
  202. ['value' => 'r', 'text' => 'Red', 'id' => 'my_id'],
  203. ['value' => 'b', 'text' => 'Black', 'id' => 'my_id_2', 'data-test' => 'test'],
  204. ],
  205. ];
  206. $result = $radio->render($data, $this->context);
  207. $expected = [
  208. ['label' => ['for' => 'my_id']],
  209. ['input' => [
  210. 'type' => 'radio',
  211. 'name' => 'Crayons[color]',
  212. 'value' => 'r',
  213. 'id' => 'my_id',
  214. ]],
  215. 'Red',
  216. '/label',
  217. ['label' => ['for' => 'my_id_2']],
  218. ['input' => [
  219. 'type' => 'radio',
  220. 'name' => 'Crayons[color]',
  221. 'value' => 'b',
  222. 'id' => 'my_id_2',
  223. 'data-test' => 'test',
  224. ]],
  225. 'Black',
  226. '/label',
  227. ];
  228. $this->assertHtml($expected, $result);
  229. }
  230. /**
  231. * Test rendering inputs with label options
  232. *
  233. * @return void
  234. */
  235. public function testRenderComplexLabelAttributes()
  236. {
  237. $label = new NestingLabelWidget($this->templates);
  238. $radio = new RadioWidget($this->templates, $label);
  239. $data = [
  240. 'name' => 'Crayons[color]',
  241. 'options' => [
  242. ['value' => 'r', 'text' => 'Red', 'label' => ['style' => 'color:red']],
  243. ['value' => 'b', 'text' => 'Black', 'label' => ['data-test' => 'yes']],
  244. ],
  245. ];
  246. $result = $radio->render($data, $this->context);
  247. $expected = [
  248. ['label' => ['for' => 'crayons-color-r', 'style' => 'color:red']],
  249. ['input' => [
  250. 'type' => 'radio',
  251. 'name' => 'Crayons[color]',
  252. 'value' => 'r',
  253. 'id' => 'crayons-color-r',
  254. ]],
  255. 'Red',
  256. '/label',
  257. ['label' => ['for' => 'crayons-color-b', 'data-test' => 'yes']],
  258. ['input' => [
  259. 'type' => 'radio',
  260. 'name' => 'Crayons[color]',
  261. 'value' => 'b',
  262. 'id' => 'crayons-color-b',
  263. ]],
  264. 'Black',
  265. '/label',
  266. ];
  267. $this->assertHtml($expected, $result);
  268. }
  269. /**
  270. * Test that id suffixes are generated to not collide
  271. *
  272. * @return void
  273. */
  274. public function testRenderIdSuffixGeneration()
  275. {
  276. $label = new NestingLabelWidget($this->templates);
  277. $radio = new RadioWidget($this->templates, $label);
  278. $data = [
  279. 'name' => 'Thing[value]',
  280. 'options' => ['a>b' => 'First', 'a<b' => 'Second'],
  281. ];
  282. $result = $radio->render($data, $this->context);
  283. $expected = [
  284. ['label' => ['for' => 'thing-value-a-b']],
  285. ['input' => [
  286. 'type' => 'radio',
  287. 'name' => 'Thing[value]',
  288. 'value' => 'a&gt;b',
  289. 'id' => 'thing-value-a-b',
  290. ]],
  291. 'First',
  292. '/label',
  293. ['label' => ['for' => 'thing-value-a-b1']],
  294. ['input' => [
  295. 'type' => 'radio',
  296. 'name' => 'Thing[value]',
  297. 'value' => 'a&lt;b',
  298. 'id' => 'thing-value-a-b1',
  299. ]],
  300. 'Second',
  301. '/label',
  302. ];
  303. $this->assertHtml($expected, $result);
  304. }
  305. /**
  306. * Test rendering checks the right option with booleanish values.
  307. *
  308. * @return void
  309. */
  310. public function testRenderBooleanishValues()
  311. {
  312. $label = new NestingLabelWidget($this->templates);
  313. $radio = new RadioWidget($this->templates, $label);
  314. $data = [
  315. 'name' => 'Model[field]',
  316. 'options' => ['1' => 'Yes', '0' => 'No'],
  317. 'val' => '0',
  318. ];
  319. $result = $radio->render($data, $this->context);
  320. $expected = [
  321. ['label' => ['for' => 'model-field-1']],
  322. ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1']],
  323. 'Yes',
  324. '/label',
  325. ['label' => ['for' => 'model-field-0']],
  326. ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0', 'checked' => 'checked']],
  327. 'No',
  328. '/label',
  329. ];
  330. $this->assertHtml($expected, $result);
  331. $data['val'] = 0;
  332. $result = $radio->render($data, $this->context);
  333. $this->assertHtml($expected, $result);
  334. $data['val'] = false;
  335. $result = $radio->render($data, $this->context);
  336. $this->assertHtml($expected, $result);
  337. $expected = [
  338. ['label' => ['for' => 'model-field-1']],
  339. ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1']],
  340. 'Yes',
  341. '/label',
  342. ['label' => ['for' => 'model-field-0']],
  343. ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0']],
  344. 'No',
  345. '/label',
  346. ];
  347. $data['val'] = null;
  348. $result = $radio->render($data, $this->context);
  349. $this->assertHtml($expected, $result);
  350. $data['val'] = '';
  351. $result = $radio->render($data, $this->context);
  352. $this->assertHtml($expected, $result);
  353. $expected = [
  354. ['label' => ['for' => 'model-field-1']],
  355. ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1', 'checked' => 'checked']],
  356. 'Yes',
  357. '/label',
  358. ['label' => ['for' => 'model-field-0']],
  359. ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0']],
  360. 'No',
  361. '/label',
  362. ];
  363. $data['val'] = '1';
  364. $result = $radio->render($data, $this->context);
  365. $this->assertHtml($expected, $result);
  366. $data['val'] = 1;
  367. $result = $radio->render($data, $this->context);
  368. $this->assertHtml($expected, $result);
  369. $data['val'] = true;
  370. $result = $radio->render($data, $this->context);
  371. $this->assertHtml($expected, $result);
  372. }
  373. /**
  374. * Test that render() works with the required attribute.
  375. *
  376. * @return void
  377. */
  378. public function testRenderRequiredAndFormAttribute()
  379. {
  380. $label = new NestingLabelWidget($this->templates);
  381. $radio = new RadioWidget($this->templates, $label);
  382. $data = [
  383. 'name' => 'published',
  384. 'options' => ['option A', 'option B'],
  385. 'required' => true,
  386. 'form' => 'my-form',
  387. ];
  388. $result = $radio->render($data, $this->context);
  389. $expected = [
  390. ['label' => ['for' => 'published-0']],
  391. ['input' => ['type' => 'radio', 'name' => 'published', 'value' => '0',
  392. 'id' => 'published-0', 'required' => 'required', 'form' => 'my-form']],
  393. 'option A',
  394. '/label',
  395. ['label' => ['for' => 'published-1']],
  396. ['input' => ['type' => 'radio', 'name' => 'published', 'value' => '1',
  397. 'id' => 'published-1', 'required' => 'required', 'form' => 'my-form']],
  398. 'option B',
  399. '/label',
  400. ];
  401. $this->assertHtml($expected, $result);
  402. }
  403. /**
  404. * Test rendering the empty option.
  405. *
  406. * @return void
  407. */
  408. public function testRenderEmptyOption()
  409. {
  410. $label = new NestingLabelWidget($this->templates);
  411. $radio = new RadioWidget($this->templates, $label);
  412. $data = [
  413. 'name' => 'Crayons[color]',
  414. 'options' => ['r' => 'Red'],
  415. 'empty' => true,
  416. ];
  417. $result = $radio->render($data, $this->context);
  418. $expected = [
  419. ['label' => ['for' => 'crayons-color']],
  420. ['input' => [
  421. 'type' => 'radio',
  422. 'name' => 'Crayons[color]',
  423. 'value' => '',
  424. 'id' => 'crayons-color',
  425. ]],
  426. 'empty',
  427. '/label',
  428. ['label' => ['for' => 'crayons-color-r']],
  429. ['input' => [
  430. 'type' => 'radio',
  431. 'name' => 'Crayons[color]',
  432. 'value' => 'r',
  433. 'id' => 'crayons-color-r',
  434. ]],
  435. 'Red',
  436. '/label',
  437. ];
  438. $this->assertHtml($expected, $result);
  439. $data['empty'] = 'Choose one';
  440. $result = $radio->render($data, $this->context);
  441. $expected = [
  442. ['label' => ['for' => 'crayons-color']],
  443. ['input' => [
  444. 'type' => 'radio',
  445. 'name' => 'Crayons[color]',
  446. 'value' => '',
  447. 'id' => 'crayons-color',
  448. ]],
  449. 'Choose one',
  450. '/label',
  451. ['label' => ['for' => 'crayons-color-r']],
  452. ['input' => [
  453. 'type' => 'radio',
  454. 'name' => 'Crayons[color]',
  455. 'value' => 'r',
  456. 'id' => 'crayons-color-r',
  457. ]],
  458. 'Red',
  459. '/label',
  460. ];
  461. $this->assertHtml($expected, $result);
  462. }
  463. /**
  464. * Test rendering the input inside the label.
  465. *
  466. * @return void
  467. */
  468. public function testRenderInputInsideLabel()
  469. {
  470. $this->templates->add([
  471. 'label' => '<label{{attrs}}>{{input}}{{text}}</label>',
  472. 'radioWrapper' => '{{label}}',
  473. ]);
  474. $label = new NestingLabelWidget($this->templates);
  475. $radio = new RadioWidget($this->templates, $label);
  476. $data = [
  477. 'name' => 'Crayons[color]',
  478. 'options' => ['r' => 'Red'],
  479. ];
  480. $result = $radio->render($data, $this->context);
  481. $expected = [
  482. ['label' => ['for' => 'crayons-color-r']],
  483. ['input' => [
  484. 'type' => 'radio',
  485. 'name' => 'Crayons[color]',
  486. 'value' => 'r',
  487. 'id' => 'crayons-color-r',
  488. ]],
  489. 'Red',
  490. '/label',
  491. ];
  492. $this->assertHtml($expected, $result);
  493. }
  494. /**
  495. * test render() and selected inputs.
  496. *
  497. * @return void
  498. */
  499. public function testRenderSelected()
  500. {
  501. $label = new NestingLabelWidget($this->templates);
  502. $radio = new RadioWidget($this->templates, $label);
  503. $data = [
  504. 'name' => 'Versions[ver]',
  505. 'val' => '1',
  506. 'options' => [
  507. 1 => 'one',
  508. '1x' => 'one x',
  509. '2' => 'two',
  510. ],
  511. ];
  512. $result = $radio->render($data, $this->context);
  513. $expected = [
  514. ['label' => ['for' => 'versions-ver-1']],
  515. ['input' => [
  516. 'id' => 'versions-ver-1',
  517. 'name' => 'Versions[ver]',
  518. 'type' => 'radio',
  519. 'value' => '1',
  520. 'checked' => 'checked',
  521. ]],
  522. 'one',
  523. '/label',
  524. ['label' => ['for' => 'versions-ver-1x']],
  525. ['input' => [
  526. 'id' => 'versions-ver-1x',
  527. 'name' => 'Versions[ver]',
  528. 'type' => 'radio',
  529. 'value' => '1x',
  530. ]],
  531. 'one x',
  532. '/label',
  533. ['label' => ['for' => 'versions-ver-2']],
  534. ['input' => [
  535. 'id' => 'versions-ver-2',
  536. 'name' => 'Versions[ver]',
  537. 'type' => 'radio',
  538. 'value' => '2',
  539. ]],
  540. 'two',
  541. '/label',
  542. ];
  543. $this->assertHtml($expected, $result);
  544. }
  545. /**
  546. * Test rendering with disable inputs
  547. *
  548. * @return void
  549. */
  550. public function testRenderDisabled()
  551. {
  552. $label = new NestingLabelWidget($this->templates);
  553. $radio = new RadioWidget($this->templates, $label);
  554. $data = [
  555. 'name' => 'Versions[ver]',
  556. 'options' => [
  557. 1 => 'one',
  558. '1x' => 'one x',
  559. '2' => 'two',
  560. ],
  561. 'disabled' => true,
  562. ];
  563. $result = $radio->render($data, $this->context);
  564. $expected = [
  565. ['label' => ['for' => 'versions-ver-1']],
  566. ['input' => [
  567. 'id' => 'versions-ver-1',
  568. 'name' => 'Versions[ver]',
  569. 'type' => 'radio',
  570. 'value' => '1',
  571. 'disabled' => 'disabled',
  572. ]],
  573. 'one',
  574. '/label',
  575. ['label' => ['for' => 'versions-ver-1x']],
  576. ['input' => [
  577. 'id' => 'versions-ver-1x',
  578. 'name' => 'Versions[ver]',
  579. 'type' => 'radio',
  580. 'value' => '1x',
  581. 'disabled' => 'disabled',
  582. ]],
  583. 'one x',
  584. '/label',
  585. ];
  586. $this->assertHtml($expected, $result);
  587. $data['disabled'] = 'a string';
  588. $result = $radio->render($data, $this->context);
  589. $this->assertHtml($expected, $result);
  590. $data['disabled'] = ['1'];
  591. $result = $radio->render($data, $this->context);
  592. $expected = [
  593. ['label' => ['for' => 'versions-ver-1']],
  594. ['input' => [
  595. 'id' => 'versions-ver-1',
  596. 'name' => 'Versions[ver]',
  597. 'type' => 'radio',
  598. 'value' => '1',
  599. 'disabled' => 'disabled',
  600. ]],
  601. 'one',
  602. '/label',
  603. ['label' => ['for' => 'versions-ver-1x']],
  604. ['input' => [
  605. 'id' => 'versions-ver-1x',
  606. 'name' => 'Versions[ver]',
  607. 'type' => 'radio',
  608. 'value' => '1x',
  609. ]],
  610. 'one x',
  611. '/label',
  612. ];
  613. $this->assertHtml($expected, $result);
  614. }
  615. /**
  616. * Test rendering with label options.
  617. *
  618. * @return void
  619. */
  620. public function testRenderLabelOptions()
  621. {
  622. $label = new NestingLabelWidget($this->templates);
  623. $radio = new RadioWidget($this->templates, $label);
  624. $data = [
  625. 'name' => 'Versions[ver]',
  626. 'options' => [
  627. 1 => 'one',
  628. '1x' => 'one x',
  629. '2' => 'two',
  630. ],
  631. 'label' => false,
  632. ];
  633. $result = $radio->render($data, $this->context);
  634. $expected = [
  635. ['input' => [
  636. 'id' => 'versions-ver-1',
  637. 'name' => 'Versions[ver]',
  638. 'type' => 'radio',
  639. 'value' => '1',
  640. ]],
  641. ['input' => [
  642. 'id' => 'versions-ver-1x',
  643. 'name' => 'Versions[ver]',
  644. 'type' => 'radio',
  645. 'value' => '1x',
  646. ]],
  647. ];
  648. $this->assertHtml($expected, $result);
  649. $data = [
  650. 'name' => 'Versions[ver]',
  651. 'options' => [
  652. 1 => 'one',
  653. '1x' => 'one x',
  654. '2' => 'two',
  655. ],
  656. 'label' => [
  657. 'class' => 'my-class',
  658. ],
  659. ];
  660. $result = $radio->render($data, $this->context);
  661. $expected = [
  662. ['label' => ['class' => 'my-class', 'for' => 'versions-ver-1']],
  663. ['input' => [
  664. 'id' => 'versions-ver-1',
  665. 'name' => 'Versions[ver]',
  666. 'type' => 'radio',
  667. 'value' => '1',
  668. ]],
  669. 'one',
  670. '/label',
  671. ['label' => ['class' => 'my-class', 'for' => 'versions-ver-1x']],
  672. ['input' => [
  673. 'id' => 'versions-ver-1x',
  674. 'name' => 'Versions[ver]',
  675. 'type' => 'radio',
  676. 'value' => '1x',
  677. ]],
  678. 'one x',
  679. '/label',
  680. ];
  681. $this->assertHtml($expected, $result);
  682. }
  683. /**
  684. * Ensure that the input + label are composed with
  685. * a template.
  686. *
  687. * @return void
  688. */
  689. public function testRenderContainerTemplate()
  690. {
  691. $this->templates->add([
  692. 'radioWrapper' => '<div class="radio">{{input}}{{label}}</div>',
  693. ]);
  694. $label = new NestingLabelWidget($this->templates);
  695. $radio = new RadioWidget($this->templates, $label);
  696. $data = [
  697. 'name' => 'Versions[ver]',
  698. 'options' => [
  699. 1 => 'one',
  700. '1x' => 'one x',
  701. '2' => 'two',
  702. ],
  703. ];
  704. $result = $radio->render($data, $this->context);
  705. $this->assertContains(
  706. '<div class="radio"><input type="radio"',
  707. $result
  708. );
  709. $this->assertContains(
  710. '</label></div>',
  711. $result
  712. );
  713. }
  714. /**
  715. * Ensure that template vars work.
  716. *
  717. * @return void
  718. */
  719. public function testRenderTemplateVars()
  720. {
  721. $this->templates->add([
  722. 'radioWrapper' => '<div class="radio" data-var="{{wrapperVar}}">{{label}}</div>',
  723. 'radio' => '<input type="radio" data-i="{{inputVar}}" name="{{name}}" value="{{value}}"{{attrs}}>',
  724. 'nestingLabel' => '<label{{attrs}}>{{input}}{{text}} {{labelVar}} {{wrapperVar}}</label>',
  725. ]);
  726. $label = new NestingLabelWidget($this->templates);
  727. $radio = new RadioWidget($this->templates, $label);
  728. $data = [
  729. 'name' => 'Versions[ver]',
  730. 'options' => [
  731. ['value' => '1x', 'text' => 'one x', 'templateVars' => ['labelVar' => 'l-var', 'inputVar' => 'i-var']],
  732. '2' => 'two',
  733. ],
  734. 'templateVars' => [
  735. 'wrapperVar' => 'wrap-var',
  736. ],
  737. ];
  738. $result = $radio->render($data, $this->context);
  739. $this->assertContains('data-var="wrap-var"><label', $result);
  740. $this->assertContains('type="radio" data-i="i-var"', $result);
  741. $this->assertContains('one x l-var wrap-var</label>', $result);
  742. $this->assertContains('two wrap-var</label>', $result);
  743. }
  744. /**
  745. * testRenderCustomAttributes method
  746. *
  747. * Test render with custom attributes.
  748. *
  749. * @return void
  750. */
  751. public function testRenderCustomAttributes()
  752. {
  753. $label = new NestingLabelWidget($this->templates);
  754. $radio = new RadioWidget($this->templates, $label);
  755. $result = $radio->render([
  756. 'name' => 'Model[field]',
  757. 'label' => null,
  758. 'options' => ['option A', 'option B'],
  759. 'class' => 'my-class',
  760. 'data-ref' => 'custom-attr',
  761. ], $this->context);
  762. $expected = [
  763. ['label' => ['for' => 'model-field-0']],
  764. [
  765. 'input' => [
  766. 'type' => 'radio',
  767. 'name' => 'Model[field]',
  768. 'value' => '0',
  769. 'id' => 'model-field-0',
  770. 'class' => 'my-class',
  771. 'data-ref' => 'custom-attr',
  772. ],
  773. ],
  774. 'option A',
  775. '/label',
  776. ['label' => ['for' => 'model-field-1']],
  777. [
  778. 'input' => [
  779. 'type' => 'radio',
  780. 'name' => 'Model[field]',
  781. 'value' => '1',
  782. 'id' => 'model-field-1',
  783. 'class' => 'my-class',
  784. 'data-ref' => 'custom-attr',
  785. ],
  786. ],
  787. 'option B',
  788. '/label',
  789. ];
  790. $this->assertHtml($expected, $result);
  791. }
  792. /**
  793. * testRenderExplicitId method
  794. *
  795. * Test that the id passed is actually used
  796. * Issue: https://github.com/cakephp/cakephp/issues/13342
  797. *
  798. * @return void
  799. */
  800. public function testRenderExplicitId()
  801. {
  802. $label = new NestingLabelWidget($this->templates);
  803. $input = new RadioWidget($this->templates, $label);
  804. $data = [
  805. 'name' => 'field',
  806. 'options' => ['value1', 'value2', -1 => 'negative'],
  807. 'id' => 'alternative-id',
  808. 'idPrefix' => 'willBeIgnored',
  809. ];
  810. $result = $input->render($data, $this->context);
  811. $expected = [
  812. [
  813. 'label' => ['for' => 'alternative-id-0'],
  814. 'input' => ['type' => 'radio', 'name' => 'field', 'value' => '0', 'id' => 'alternative-id-0'],
  815. ],
  816. 'value1',
  817. '/label',
  818. [
  819. 'label' => ['for' => 'alternative-id-1'],
  820. 'input' => ['type' => 'radio', 'name' => 'field', 'value' => '1', 'id' => 'alternative-id-1'],
  821. ],
  822. 'value2',
  823. '/label',
  824. [
  825. 'label' => ['for' => 'alternative-id--1'],
  826. 'input' => ['type' => 'radio', 'name' => 'field', 'value' => '-1', 'id' => 'alternative-id--1'],
  827. ],
  828. 'negative',
  829. '/label',
  830. ];
  831. $this->assertHtml($expected, $result);
  832. $data = [
  833. 'name' => 'field',
  834. 'options' => ['value1', 'value2'],
  835. 'idPrefix' => 'formprefix',
  836. ];
  837. $result = $input->render($data, $this->context);
  838. $expected = [
  839. [
  840. 'label' => ['for' => 'formprefix-field-0'],
  841. 'input' => ['type' => 'radio', 'name' => 'field', 'value' => '0', 'id' => 'formprefix-field-0'],
  842. ],
  843. 'value1',
  844. '/label',
  845. [
  846. 'label' => ['for' => 'formprefix-field-1'],
  847. 'input' => ['type' => 'radio', 'name' => 'field', 'value' => '1', 'id' => 'formprefix-field-1'],
  848. ],
  849. 'value2',
  850. '/label',
  851. ];
  852. $this->assertHtml($expected, $result);
  853. }
  854. /**
  855. * testRenderSelectedClass method
  856. *
  857. * Test that the custom selected class is passed to label
  858. * Issue: https://github.com/cakephp/cakephp/issues/11249
  859. *
  860. * @return void
  861. */
  862. public function testRenderSelectedClass()
  863. {
  864. $this->templates->add(['selectedClass' => 'active']);
  865. $label = new NestingLabelWidget($this->templates);
  866. $input = new RadioWidget($this->templates, $label);
  867. $data = [
  868. 'name' => 'field',
  869. 'options' => ['value1' => 'title1'],
  870. 'val' => 'value1',
  871. 'label' => ['title' => 'my label'],
  872. ];
  873. $result = $input->render($data, $this->context);
  874. $expected = [
  875. ['label' => [
  876. 'title' => 'my label',
  877. 'class' => 'active',
  878. 'for' => 'field-value1',
  879. ]],
  880. ];
  881. $this->assertHtml($expected, $result);
  882. }
  883. }