SelectBoxWidgetTest.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice.
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 3.0.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\View\Widget;
  17. use ArrayObject;
  18. use Cake\Collection\Collection;
  19. use Cake\TestSuite\TestCase;
  20. use Cake\View\Form\NullContext;
  21. use Cake\View\StringTemplate;
  22. use Cake\View\Widget\SelectBoxWidget;
  23. /**
  24. * SelectBox test case
  25. */
  26. class SelectBoxWidgetTest extends TestCase
  27. {
  28. /**
  29. * @var \Cake\View\Form\NullContext
  30. */
  31. protected $context;
  32. /**
  33. * @var \Cake\View\StringTemplate
  34. */
  35. protected $templates;
  36. /**
  37. * setup method.
  38. */
  39. public function setUp(): void
  40. {
  41. parent::setUp();
  42. $templates = [
  43. 'select' => '<select name="{{name}}"{{attrs}}>{{content}}</select>',
  44. 'selectMultiple' => '<select name="{{name}}[]" multiple="multiple"{{attrs}}>{{content}}</select>',
  45. 'option' => '<option value="{{value}}"{{attrs}}>{{text}}</option>',
  46. 'optgroup' => '<optgroup label="{{label}}"{{attrs}}>{{content}}</optgroup>',
  47. ];
  48. $this->context = new NullContext([]);
  49. $this->templates = new StringTemplate($templates);
  50. }
  51. /**
  52. * test render no options
  53. */
  54. public function testRenderNoOptions(): void
  55. {
  56. $select = new SelectBoxWidget($this->templates);
  57. $data = [
  58. 'id' => 'BirdName',
  59. 'name' => 'Birds[name]',
  60. 'options' => [],
  61. ];
  62. $result = $select->render($data, $this->context);
  63. $expected = [
  64. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  65. '/select',
  66. ];
  67. $this->assertHtml($expected, $result);
  68. }
  69. /**
  70. * test simple rendering
  71. */
  72. public function testRenderSimple(): void
  73. {
  74. $select = new SelectBoxWidget($this->templates);
  75. $data = [
  76. 'id' => 'BirdName',
  77. 'name' => 'Birds[name]',
  78. 'options' => ['a' => 'Albatross', 'b' => 'Budgie'],
  79. ];
  80. $result = $select->render($data, $this->context);
  81. $expected = [
  82. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  83. ['option' => ['value' => 'a']], 'Albatross', '/option',
  84. ['option' => ['value' => 'b']], 'Budgie', '/option',
  85. '/select',
  86. ];
  87. $this->assertHtml($expected, $result);
  88. }
  89. /**
  90. * Test render boolean options
  91. */
  92. public function testRenderBoolean(): void
  93. {
  94. $select = new SelectBoxWidget($this->templates);
  95. $data = [
  96. 'id' => 'enabled',
  97. 'name' => 'enabled',
  98. 'options' => [0 => 'No', 1 => 'Yes'],
  99. 'val' => false,
  100. ];
  101. $result = $select->render($data, $this->context);
  102. $this->assertStringContainsString('<option value="0" selected="selected">No</option>', $result);
  103. $data['value'] = [false, 2];
  104. $result = $select->render($data, $this->context);
  105. $this->assertStringContainsString('<option value="0" selected="selected">No</option>', $result);
  106. }
  107. /**
  108. * Test render float options
  109. */
  110. public function testRenderFloat(): void
  111. {
  112. $select = new SelectBoxWidget($this->templates);
  113. $data = [
  114. 'id' => 'enabled',
  115. 'name' => 'enabled',
  116. 'options' => [0.5, 1.5],
  117. 'val' => 0.5,
  118. ];
  119. $result = $select->render($data, $this->context);
  120. $this->assertStringContainsString('<option value="0">0.5</option>', $result);
  121. $this->assertStringContainsString('<option value="1">1.5</option>', $result);
  122. }
  123. /**
  124. * test simple iterator rendering
  125. */
  126. public function testRenderSimpleIterator(): void
  127. {
  128. $select = new SelectBoxWidget($this->templates);
  129. $options = new ArrayObject(['a' => 'Albatross', 'b' => 'Budgie']);
  130. $data = [
  131. 'name' => 'Birds[name]',
  132. 'options' => $options,
  133. 'empty' => true,
  134. ];
  135. $result = $select->render($data, $this->context);
  136. $expected = [
  137. 'select' => ['name' => 'Birds[name]'],
  138. ['option' => ['value' => '']], '/option',
  139. ['option' => ['value' => 'a']], 'Albatross', '/option',
  140. ['option' => ['value' => 'b']], 'Budgie', '/option',
  141. '/select',
  142. ];
  143. $this->assertHtml($expected, $result);
  144. }
  145. /**
  146. * test simple iterator rendering with empty option
  147. */
  148. public function testRenderSimpleIteratorWithEmpty(): void
  149. {
  150. $select = new SelectBoxWidget($this->templates);
  151. $options = new Collection(['a' => 'Albatross', 'b' => 'Budgie']);
  152. $data = [
  153. 'name' => 'Birds[name]',
  154. 'options' => $options,
  155. 'empty' => 'Pick one',
  156. ];
  157. $result = $select->render($data, $this->context);
  158. $expected = [
  159. 'select' => ['name' => 'Birds[name]'],
  160. ['option' => ['value' => '']], 'Pick one', '/option',
  161. ['option' => ['value' => 'a']], 'Albatross', '/option',
  162. ['option' => ['value' => 'b']], 'Budgie', '/option',
  163. '/select',
  164. ];
  165. $this->assertHtml($expected, $result);
  166. }
  167. /**
  168. * test complex option rendering
  169. */
  170. public function testRenderComplex(): void
  171. {
  172. $select = new SelectBoxWidget($this->templates);
  173. $data = [
  174. 'id' => 'BirdName',
  175. 'name' => 'Birds[name]',
  176. 'options' => [
  177. ['value' => 'a', 'text' => 'Albatross'],
  178. ['value' => 'b', 'text' => 'Budgie', 'data-foo' => 'bar'],
  179. ],
  180. ];
  181. $result = $select->render($data, $this->context);
  182. $expected = [
  183. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  184. ['option' => ['value' => 'a']],
  185. 'Albatross',
  186. '/option',
  187. ['option' => ['value' => 'b', 'data-foo' => 'bar']],
  188. 'Budgie',
  189. '/option',
  190. '/select',
  191. ];
  192. $this->assertHtml($expected, $result);
  193. }
  194. /**
  195. * test rendering with a selected value
  196. */
  197. public function testRenderSelected(): void
  198. {
  199. $select = new SelectBoxWidget($this->templates);
  200. $data = [
  201. 'id' => 'BirdName',
  202. 'name' => 'Birds[name]',
  203. 'val' => '1',
  204. 'options' => [
  205. 1 => 'one',
  206. '1x' => 'one x',
  207. '2' => 'two',
  208. '2x' => 'two x',
  209. ],
  210. ];
  211. $result = $select->render($data, $this->context);
  212. $expected = [
  213. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  214. ['option' => ['value' => '1', 'selected' => 'selected']], 'one', '/option',
  215. ['option' => ['value' => '1x']], 'one x', '/option',
  216. ['option' => ['value' => '2']], 'two', '/option',
  217. ['option' => ['value' => '2x']], 'two x', '/option',
  218. '/select',
  219. ];
  220. $this->assertHtml($expected, $result);
  221. $data['val'] = 2;
  222. $result = $select->render($data, $this->context);
  223. $expected = [
  224. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  225. ['option' => ['value' => '1']], 'one', '/option',
  226. ['option' => ['value' => '1x']], 'one x', '/option',
  227. ['option' => ['value' => '2', 'selected' => 'selected']], 'two', '/option',
  228. ['option' => ['value' => '2x']], 'two x', '/option',
  229. '/select',
  230. ];
  231. $this->assertHtml($expected, $result);
  232. }
  233. /**
  234. * test complex option rendering with a selected value
  235. */
  236. public function testRenderComplexSelected(): void
  237. {
  238. $select = new SelectBoxWidget($this->templates);
  239. $data = [
  240. 'id' => 'BirdName',
  241. 'name' => 'Birds[name]',
  242. 'val' => 'a',
  243. 'options' => [
  244. ['value' => 'a', 'text' => 'Albatross'],
  245. ['value' => 'b', 'text' => 'Budgie', 'data-foo' => 'bar'],
  246. ],
  247. ];
  248. $result = $select->render($data, $this->context);
  249. $expected = [
  250. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  251. ['option' => ['value' => 'a', 'selected' => 'selected']],
  252. 'Albatross',
  253. '/option',
  254. ['option' => ['value' => 'b', 'data-foo' => 'bar']],
  255. 'Budgie',
  256. '/option',
  257. '/select',
  258. ];
  259. $this->assertHtml($expected, $result);
  260. }
  261. /**
  262. * test rendering a multi select
  263. */
  264. public function testRenderMultipleSelect(): void
  265. {
  266. $select = new SelectBoxWidget($this->templates);
  267. $data = [
  268. 'id' => 'BirdName',
  269. 'name' => 'Birds[name]',
  270. 'multiple' => true,
  271. 'options' => ['a' => 'Albatross', 'b' => 'Budgie'],
  272. ];
  273. $result = $select->render($data, $this->context);
  274. $expected = [
  275. 'select' => [
  276. 'name' => 'Birds[name][]',
  277. 'id' => 'BirdName',
  278. 'multiple' => 'multiple',
  279. ],
  280. ['option' => ['value' => 'a']], 'Albatross', '/option',
  281. ['option' => ['value' => 'b']], 'Budgie', '/option',
  282. '/select',
  283. ];
  284. $this->assertHtml($expected, $result);
  285. }
  286. /**
  287. * test rendering multi select & selected values
  288. */
  289. public function testRenderMultipleSelected(): void
  290. {
  291. $select = new SelectBoxWidget($this->templates);
  292. $data = [
  293. 'multiple' => true,
  294. 'id' => 'BirdName',
  295. 'name' => 'Birds[name]',
  296. 'val' => ['1', '2', 'burp'],
  297. 'options' => [
  298. 1 => 'one',
  299. '1x' => 'one x',
  300. '2' => 'two',
  301. '2x' => 'two x',
  302. ],
  303. ];
  304. $result = $select->render($data, $this->context);
  305. $expected = [
  306. 'select' => [
  307. 'name' => 'Birds[name][]',
  308. 'multiple' => 'multiple',
  309. 'id' => 'BirdName',
  310. ],
  311. ['option' => ['value' => '1', 'selected' => 'selected']], 'one', '/option',
  312. ['option' => ['value' => '1x']], 'one x', '/option',
  313. ['option' => ['value' => '2', 'selected' => 'selected']], 'two', '/option',
  314. ['option' => ['value' => '2x']], 'two x', '/option',
  315. '/select',
  316. ];
  317. $this->assertHtml($expected, $result);
  318. }
  319. /**
  320. * test rendering with option groups
  321. */
  322. public function testRenderOptionGroups(): void
  323. {
  324. $select = new SelectBoxWidget($this->templates);
  325. $data = [
  326. 'name' => 'Birds[name]',
  327. 'options' => [
  328. 'Mammal' => [
  329. 'beaver' => 'Beaver',
  330. 'elk' => 'Elk',
  331. ],
  332. 'Bird' => [
  333. 'budgie' => 'Budgie',
  334. 'eagle' => 'Eagle',
  335. ],
  336. ],
  337. ];
  338. $result = $select->render($data, $this->context);
  339. $expected = [
  340. 'select' => [
  341. 'name' => 'Birds[name]',
  342. ],
  343. ['optgroup' => ['label' => 'Mammal']],
  344. ['option' => ['value' => 'beaver']],
  345. 'Beaver',
  346. '/option',
  347. ['option' => ['value' => 'elk']],
  348. 'Elk',
  349. '/option',
  350. '/optgroup',
  351. ['optgroup' => ['label' => 'Bird']],
  352. ['option' => ['value' => 'budgie']],
  353. 'Budgie',
  354. '/option',
  355. ['option' => ['value' => 'eagle']],
  356. 'Eagle',
  357. '/option',
  358. '/optgroup',
  359. '/select',
  360. ];
  361. $this->assertHtml($expected, $result);
  362. }
  363. /**
  364. * test rendering with numeric option group keys
  365. */
  366. public function testRenderOptionGroupsIntegerKeys(): void
  367. {
  368. $select = new SelectBoxWidget($this->templates);
  369. $data = [
  370. 'name' => 'Year[key]',
  371. 'options' => [
  372. 2014 => [
  373. 'key' => 'value',
  374. ],
  375. 2013 => [
  376. 'text' => '2013-text',
  377. 'options' => [
  378. 'key2' => 'value2',
  379. ],
  380. ],
  381. ],
  382. ];
  383. $result = $select->render($data, $this->context);
  384. $expected = [
  385. 'select' => [
  386. 'name' => 'Year[key]',
  387. ],
  388. ['optgroup' => ['label' => '2014']],
  389. ['option' => ['value' => 'key']],
  390. 'value',
  391. '/option',
  392. '/optgroup',
  393. ['optgroup' => ['label' => '2013-text']],
  394. ['option' => ['value' => 'key2']],
  395. 'value2',
  396. '/option',
  397. '/optgroup',
  398. '/select',
  399. ];
  400. $this->assertHtml($expected, $result);
  401. }
  402. /**
  403. * test rendering with option groups and escaping
  404. */
  405. public function testRenderOptionGroupsEscape(): void
  406. {
  407. $select = new SelectBoxWidget($this->templates);
  408. $data = [
  409. 'name' => 'Birds[name]',
  410. 'options' => [
  411. '>XSS<' => [
  412. '1' => 'One>',
  413. ],
  414. ],
  415. ];
  416. $result = $select->render($data, $this->context);
  417. $expected = [
  418. 'select' => [
  419. 'name' => 'Birds[name]',
  420. ],
  421. ['optgroup' => ['label' => '&gt;XSS&lt;']],
  422. ['option' => ['value' => '1']],
  423. 'One&gt;',
  424. '/option',
  425. '/optgroup',
  426. '/select',
  427. ];
  428. $this->assertHtml($expected, $result);
  429. $data['escape'] = false;
  430. $result = $select->render($data, $this->context);
  431. $expected = [
  432. 'select' => [
  433. 'name' => 'Birds[name]',
  434. ],
  435. ['optgroup' => ['label' => '>XSS<']],
  436. ['option' => ['value' => '1']],
  437. 'One>',
  438. '/option',
  439. '/optgroup',
  440. '/select',
  441. ];
  442. $this->assertHtml($expected, $result);
  443. }
  444. /**
  445. * test rendering with option groups
  446. */
  447. public function testRenderOptionGroupsWithAttributes(): void
  448. {
  449. $select = new SelectBoxWidget($this->templates);
  450. $data = [
  451. 'name' => 'Birds[name]',
  452. 'options' => [
  453. [
  454. 'text' => 'Mammal',
  455. 'data-foo' => 'bar',
  456. 'options' => [
  457. 'beaver' => 'Beaver',
  458. 'elk' => 'Elk',
  459. ],
  460. ],
  461. ],
  462. ];
  463. $result = $select->render($data, $this->context);
  464. $expected = [
  465. 'select' => [
  466. 'name' => 'Birds[name]',
  467. ],
  468. ['optgroup' => ['data-foo' => 'bar', 'label' => 'Mammal']],
  469. ['option' => ['value' => 'beaver']],
  470. 'Beaver',
  471. '/option',
  472. ['option' => ['value' => 'elk']],
  473. 'Elk',
  474. '/option',
  475. '/optgroup',
  476. '/select',
  477. ];
  478. $this->assertHtml($expected, $result);
  479. }
  480. /**
  481. * test rendering with option groups with traversable nodes
  482. */
  483. public function testRenderOptionGroupsTraversable(): void
  484. {
  485. $select = new SelectBoxWidget($this->templates);
  486. $mammals = new ArrayObject(['beaver' => 'Beaver', 'elk' => 'Elk']);
  487. $data = [
  488. 'name' => 'Birds[name]',
  489. 'options' => [
  490. 'Mammal' => $mammals,
  491. 'Bird' => [
  492. 'budgie' => 'Budgie',
  493. 'eagle' => 'Eagle',
  494. ],
  495. ],
  496. ];
  497. $result = $select->render($data, $this->context);
  498. $expected = [
  499. 'select' => [
  500. 'name' => 'Birds[name]',
  501. ],
  502. ['optgroup' => ['label' => 'Mammal']],
  503. ['option' => ['value' => 'beaver']],
  504. 'Beaver',
  505. '/option',
  506. ['option' => ['value' => 'elk']],
  507. 'Elk',
  508. '/option',
  509. '/optgroup',
  510. ['optgroup' => ['label' => 'Bird']],
  511. ['option' => ['value' => 'budgie']],
  512. 'Budgie',
  513. '/option',
  514. ['option' => ['value' => 'eagle']],
  515. 'Eagle',
  516. '/option',
  517. '/optgroup',
  518. '/select',
  519. ];
  520. $this->assertHtml($expected, $result);
  521. }
  522. /**
  523. * test rendering option groups and selected values
  524. */
  525. public function testRenderOptionGroupsSelectedAndDisabled(): void
  526. {
  527. $select = new SelectBoxWidget($this->templates);
  528. $data = [
  529. 'name' => 'Birds[name]',
  530. 'val' => ['1', '2', 'burp'],
  531. 'disabled' => ['1x', '2x', 'nope'],
  532. 'options' => [
  533. 'ones' => [
  534. 1 => 'one',
  535. '1x' => 'one x',
  536. ],
  537. 'twos' => [
  538. '2' => 'two',
  539. '2x' => 'two x',
  540. ],
  541. ],
  542. ];
  543. $result = $select->render($data, $this->context);
  544. $expected = [
  545. 'select' => [
  546. 'name' => 'Birds[name]',
  547. ],
  548. ['optgroup' => ['label' => 'ones']],
  549. ['option' => ['value' => '1', 'selected' => 'selected']], 'one', '/option',
  550. ['option' => ['value' => '1x', 'disabled' => 'disabled']], 'one x', '/option',
  551. '/optgroup',
  552. ['optgroup' => ['label' => 'twos']],
  553. ['option' => ['value' => '2', 'selected' => 'selected']], 'two', '/option',
  554. ['option' => ['value' => '2x', 'disabled' => 'disabled']], 'two x', '/option',
  555. '/optgroup',
  556. '/select',
  557. ];
  558. $this->assertHtml($expected, $result);
  559. }
  560. /**
  561. * test rendering a totally disabled element
  562. */
  563. public function testRenderDisabled(): void
  564. {
  565. $select = new SelectBoxWidget($this->templates);
  566. $data = [
  567. 'disabled' => true,
  568. 'name' => 'Birds[name]',
  569. 'options' => ['a' => 'Albatross', 'b' => 'Budgie'],
  570. 'val' => 'a',
  571. ];
  572. $result = $select->render($data, $this->context);
  573. $expected = [
  574. 'select' => [
  575. 'name' => 'Birds[name]',
  576. 'disabled' => 'disabled',
  577. ],
  578. ['option' => ['value' => 'a', 'selected' => 'selected']], 'Albatross', '/option',
  579. ['option' => ['value' => 'b']], 'Budgie', '/option',
  580. '/select',
  581. ];
  582. $this->assertHtml($expected, $result);
  583. $select = new SelectBoxWidget($this->templates);
  584. $data = [
  585. 'disabled' => [1],
  586. 'name' => 'numbers',
  587. 'options' => ['1' => 'One', '2' => 'Two'],
  588. ];
  589. $result = $select->render($data, $this->context);
  590. $expected = [
  591. 'select' => [
  592. 'name' => 'numbers',
  593. ],
  594. ['option' => ['value' => '1', 'disabled' => 'disabled']], 'One', '/option',
  595. ['option' => ['value' => '2']], 'Two', '/option',
  596. '/select',
  597. ];
  598. $this->assertHtml($expected, $result);
  599. }
  600. /**
  601. * test rendering a disabled element
  602. */
  603. public function testRenderDisabledMultiple(): void
  604. {
  605. $select = new SelectBoxWidget($this->templates);
  606. $data = [
  607. 'disabled' => ['a', 'c'],
  608. 'val' => 'a',
  609. 'name' => 'Birds[name]',
  610. 'options' => [
  611. 'a' => 'Albatross',
  612. 'b' => 'Budgie',
  613. 'c' => 'Canary',
  614. ],
  615. ];
  616. $result = $select->render($data, $this->context);
  617. $expected = [
  618. 'select' => [
  619. 'name' => 'Birds[name]',
  620. ],
  621. ['option' => ['value' => 'a', 'selected' => 'selected', 'disabled' => 'disabled']],
  622. 'Albatross',
  623. '/option',
  624. ['option' => ['value' => 'b']],
  625. 'Budgie',
  626. '/option',
  627. ['option' => ['value' => 'c', 'disabled' => 'disabled']],
  628. 'Canary',
  629. '/option',
  630. '/select',
  631. ];
  632. $this->assertHtml($expected, $result);
  633. }
  634. /**
  635. * test complex option rendering with a disabled element
  636. */
  637. public function testRenderComplexDisabled(): void
  638. {
  639. $select = new SelectBoxWidget($this->templates);
  640. $data = [
  641. 'disabled' => ['b'],
  642. 'id' => 'BirdName',
  643. 'name' => 'Birds[name]',
  644. 'options' => [
  645. ['value' => 'a', 'text' => 'Albatross'],
  646. ['value' => 'b', 'text' => 'Budgie', 'data-foo' => 'bar'],
  647. ],
  648. ];
  649. $result = $select->render($data, $this->context);
  650. $expected = [
  651. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  652. ['option' => ['value' => 'a']],
  653. 'Albatross',
  654. '/option',
  655. ['option' => ['value' => 'b', 'data-foo' => 'bar', 'disabled' => 'disabled']],
  656. 'Budgie',
  657. '/option',
  658. '/select',
  659. ];
  660. $this->assertHtml($expected, $result);
  661. }
  662. /**
  663. * test rendering with an empty value
  664. */
  665. public function testRenderEmptyOption(): void
  666. {
  667. $select = new SelectBoxWidget($this->templates);
  668. $data = [
  669. 'id' => 'BirdName',
  670. 'name' => 'Birds[name]',
  671. 'empty' => true,
  672. 'options' => ['a' => 'Albatross', 'b' => 'Budgie'],
  673. ];
  674. $result = $select->render($data, $this->context);
  675. $expected = [
  676. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  677. ['option' => ['value' => '']], '/option',
  678. ['option' => ['value' => 'a']], 'Albatross', '/option',
  679. ['option' => ['value' => 'b']], 'Budgie', '/option',
  680. '/select',
  681. ];
  682. $this->assertHtml($expected, $result);
  683. $data['empty'] = 'empty';
  684. $result = $select->render($data, $this->context);
  685. $expected = [
  686. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  687. ['option' => ['value' => '']], 'empty', '/option',
  688. ['option' => ['value' => 'a']], 'Albatross', '/option',
  689. ['option' => ['value' => 'b']], 'Budgie', '/option',
  690. '/select',
  691. ];
  692. $this->assertHtml($expected, $result);
  693. $data['empty'] = ['99' => '(choose one)'];
  694. $result = $select->render($data, $this->context);
  695. $expected = [
  696. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  697. ['option' => ['value' => '99']], '(choose one)', '/option',
  698. ['option' => ['value' => 'a']], 'Albatross', '/option',
  699. ['option' => ['value' => 'b']], 'Budgie', '/option',
  700. '/select',
  701. ];
  702. $this->assertHtml($expected, $result);
  703. $data['empty'] = 'empty';
  704. $data['val'] = '';
  705. $result = $select->render($data, $this->context);
  706. $expected = [
  707. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  708. ['option' => ['value' => '', 'selected' => 'selected']], 'empty', '/option',
  709. ['option' => ['value' => 'a']], 'Albatross', '/option',
  710. ['option' => ['value' => 'b']], 'Budgie', '/option',
  711. '/select',
  712. ];
  713. $this->assertHtml($expected, $result);
  714. }
  715. /**
  716. * Test rendering with disabling escaping.
  717. */
  718. public function testRenderEscapingOption(): void
  719. {
  720. $select = new SelectBoxWidget($this->templates);
  721. $data = [
  722. 'name' => 'Birds[name]',
  723. 'options' => [
  724. 'a' => '>Albatross',
  725. 'b' => '>Budgie',
  726. 'c' => '>Canary',
  727. ],
  728. ];
  729. $result = $select->render($data, $this->context);
  730. $expected = [
  731. 'select' => [
  732. 'name' => 'Birds[name]',
  733. ],
  734. ['option' => ['value' => 'a']],
  735. '&gt;Albatross',
  736. '/option',
  737. ['option' => ['value' => 'b']],
  738. '&gt;Budgie',
  739. '/option',
  740. ['option' => ['value' => 'c']],
  741. '&gt;Canary',
  742. '/option',
  743. '/select',
  744. ];
  745. $this->assertHtml($expected, $result);
  746. $data = [
  747. 'escape' => false,
  748. 'name' => 'Birds[name]',
  749. 'options' => [
  750. '>a' => '>Albatross',
  751. ],
  752. ];
  753. $result = $select->render($data, $this->context);
  754. $expected = [
  755. 'select' => [
  756. 'name' => 'Birds[name]',
  757. ],
  758. ['option' => ['value' => '>a']],
  759. '>Albatross',
  760. '/option',
  761. '/select',
  762. ];
  763. $this->assertHtml($expected, $result);
  764. }
  765. /**
  766. * test render with null options
  767. */
  768. public function testRenderNullOptions(): void
  769. {
  770. $select = new SelectBoxWidget($this->templates);
  771. $data = [
  772. 'id' => 'BirdName',
  773. 'name' => 'Birds[name]',
  774. 'options' => null,
  775. ];
  776. $result = $select->render($data, $this->context);
  777. $expected = [
  778. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  779. '/select',
  780. ];
  781. $this->assertHtml($expected, $result);
  782. $data['empty'] = true;
  783. $result = $select->render($data, $this->context);
  784. $expected = [
  785. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  786. ['option' => ['value' => '']], '/option',
  787. '/select',
  788. ];
  789. $this->assertHtml($expected, $result);
  790. $data['empty'] = 'empty';
  791. $result = $select->render($data, $this->context);
  792. $expected = [
  793. 'select' => ['name' => 'Birds[name]', 'id' => 'BirdName'],
  794. ['option' => ['value' => '']], 'empty', '/option',
  795. '/select',
  796. ];
  797. $this->assertHtml($expected, $result);
  798. }
  799. /**
  800. * Ensure templateVars option is hooked up.
  801. */
  802. public function testRenderTemplateVars(): void
  803. {
  804. $this->templates->add([
  805. 'select' => '<select custom="{{custom}}" name="{{name}}"{{attrs}}>{{content}}</select>',
  806. 'option' => '<option opt="{{opt}}" value="{{value}}"{{attrs}}>{{text}}</option>',
  807. ]);
  808. $input = new SelectBoxWidget($this->templates);
  809. $data = [
  810. 'templateVars' => ['custom' => 'value', 'opt' => 'option'],
  811. 'name' => 'birds',
  812. 'options' => [
  813. ['value' => 'a', 'text' => 'Albatross', 'templateVars' => ['opt' => 'opt-1']],
  814. 'b' => 'Budgie',
  815. 'c' => 'Canary',
  816. ],
  817. ];
  818. $result = $input->render($data, $this->context);
  819. $expected = [
  820. 'select' => [
  821. 'name' => 'birds',
  822. 'custom' => 'value',
  823. ],
  824. ['option' => ['value' => 'a', 'opt' => 'opt-1']],
  825. 'Albatross',
  826. '/option',
  827. ['option' => ['value' => 'b', 'opt' => 'option']],
  828. 'Budgie',
  829. '/option',
  830. ['option' => ['value' => 'c', 'opt' => 'option']],
  831. 'Canary',
  832. '/option',
  833. '/select',
  834. ];
  835. $this->assertHtml($expected, $result);
  836. }
  837. }