RadioWidgetTest.php 28 KB

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