SelectBoxWidgetTest.php 22 KB

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