SelectBoxWidgetTest.php 27 KB

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