AbstractBootstrap3LayoutTest.php 82 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Form\Tests;
  11. use Symfony\Component\Form\FormError;
  12. abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest
  13. {
  14. public function testLabelOnForm()
  15. {
  16. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType');
  17. $view = $form->createView();
  18. $this->renderWidget($view, array('label' => 'foo'));
  19. $html = $this->renderLabel($view);
  20. $this->assertMatchesXpath($html,
  21. '/label
  22. [@class="control-label required"]
  23. [.="[trans]Name[/trans]"]
  24. '
  25. );
  26. }
  27. public function testLabelDoesNotRenderFieldAttributes()
  28. {
  29. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
  30. $html = $this->renderLabel($form->createView(), null, array(
  31. 'attr' => array(
  32. 'class' => 'my&class',
  33. ),
  34. ));
  35. $this->assertMatchesXpath($html,
  36. '/label
  37. [@for="name"]
  38. [@class="control-label required"]
  39. '
  40. );
  41. }
  42. public function testLabelWithCustomAttributesPassedDirectly()
  43. {
  44. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
  45. $html = $this->renderLabel($form->createView(), null, array(
  46. 'label_attr' => array(
  47. 'class' => 'my&class',
  48. ),
  49. ));
  50. $this->assertMatchesXpath($html,
  51. '/label
  52. [@for="name"]
  53. [@class="my&class control-label required"]
  54. '
  55. );
  56. }
  57. public function testLabelWithCustomTextAndCustomAttributesPassedDirectly()
  58. {
  59. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
  60. $html = $this->renderLabel($form->createView(), 'Custom label', array(
  61. 'label_attr' => array(
  62. 'class' => 'my&class',
  63. ),
  64. ));
  65. $this->assertMatchesXpath($html,
  66. '/label
  67. [@for="name"]
  68. [@class="my&class control-label required"]
  69. [.="[trans]Custom label[/trans]"]
  70. '
  71. );
  72. }
  73. public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly()
  74. {
  75. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
  76. 'label' => 'Custom label',
  77. ));
  78. $html = $this->renderLabel($form->createView(), null, array(
  79. 'label_attr' => array(
  80. 'class' => 'my&class',
  81. ),
  82. ));
  83. $this->assertMatchesXpath($html,
  84. '/label
  85. [@for="name"]
  86. [@class="my&class control-label required"]
  87. [.="[trans]Custom label[/trans]"]
  88. '
  89. );
  90. }
  91. public function testErrors()
  92. {
  93. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
  94. $form->addError(new FormError('[trans]Error 1[/trans]'));
  95. $form->addError(new FormError('[trans]Error 2[/trans]'));
  96. $view = $form->createView();
  97. $html = $this->renderErrors($view);
  98. $this->assertMatchesXpath($html,
  99. '/div
  100. [@class="alert alert-danger"]
  101. [
  102. ./ul
  103. [@class="list-unstyled"]
  104. [
  105. ./li
  106. [.=" [trans]Error 1[/trans]"]
  107. [
  108. ./span[@class="glyphicon glyphicon-exclamation-sign"]
  109. ]
  110. /following-sibling::li
  111. [.=" [trans]Error 2[/trans]"]
  112. [
  113. ./span[@class="glyphicon glyphicon-exclamation-sign"]
  114. ]
  115. ]
  116. [count(./li)=2]
  117. ]
  118. '
  119. );
  120. }
  121. public function testOverrideWidgetBlock()
  122. {
  123. // see custom_widgets.html.twig
  124. $form = $this->factory->createNamed('text_id', 'Symfony\Component\Form\Extension\Core\Type\TextType');
  125. $html = $this->renderWidget($form->createView());
  126. $this->assertMatchesXpath($html,
  127. '/div
  128. [
  129. ./input
  130. [@type="text"]
  131. [@id="text_id"]
  132. [@class="form-control"]
  133. ]
  134. [@id="container"]
  135. '
  136. );
  137. }
  138. public function testCheckedCheckbox()
  139. {
  140. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', true);
  141. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  142. '/div
  143. [@class="checkbox"]
  144. [
  145. ./label
  146. [.=" [trans]Name[/trans]"]
  147. [
  148. ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][@checked="checked"][@value="1"]
  149. ]
  150. ]
  151. '
  152. );
  153. }
  154. public function testUncheckedCheckbox()
  155. {
  156. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false);
  157. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  158. '/div
  159. [@class="checkbox"]
  160. [
  161. ./label
  162. [.=" [trans]Name[/trans]"]
  163. [
  164. ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][not(@checked)]
  165. ]
  166. ]
  167. '
  168. );
  169. }
  170. public function testCheckboxWithValue()
  171. {
  172. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false, array(
  173. 'value' => 'foo&bar',
  174. ));
  175. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  176. '/div
  177. [@class="checkbox"]
  178. [
  179. ./label
  180. [.=" [trans]Name[/trans]"]
  181. [
  182. ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][@value="foo&bar"]
  183. ]
  184. ]
  185. '
  186. );
  187. }
  188. public function testSingleChoice()
  189. {
  190. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  191. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  192. 'choices_as_values' => true,
  193. 'multiple' => false,
  194. 'expanded' => false,
  195. ));
  196. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  197. '/select
  198. [@name="name"]
  199. [@class="my&class form-control"]
  200. [not(@required)]
  201. [
  202. ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  203. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  204. ]
  205. [count(./option)=2]
  206. '
  207. );
  208. }
  209. public function testSingleChoiceAttributesWithMainAttributes()
  210. {
  211. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  212. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  213. 'choices_as_values' => true,
  214. 'multiple' => false,
  215. 'expanded' => false,
  216. 'attr' => array('class' => 'bar&baz'),
  217. ));
  218. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')),
  219. '/select
  220. [@name="name"]
  221. [@class="bar&baz form-control"]
  222. [not(@required)]
  223. [
  224. ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  225. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  226. ]
  227. [count(./option)=2]
  228. '
  229. );
  230. }
  231. public function testSingleExpandedChoiceAttributesWithMainAttributes()
  232. {
  233. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  234. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  235. 'choices_as_values' => true,
  236. 'multiple' => false,
  237. 'expanded' => true,
  238. 'attr' => array('class' => 'bar&baz'),
  239. ));
  240. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')),
  241. '/div
  242. [@class="bar&baz"]
  243. [
  244. ./div
  245. [@class="radio"]
  246. [
  247. ./label
  248. [.=" [trans]Choice&A[/trans]"]
  249. [
  250. ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
  251. ]
  252. ]
  253. /following-sibling::div
  254. [@class="radio"]
  255. [
  256. ./label
  257. [.=" [trans]Choice&B[/trans]"]
  258. [
  259. ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
  260. ]
  261. ]
  262. /following-sibling::input[@type="hidden"][@id="name__token"]
  263. ]
  264. '
  265. );
  266. }
  267. public function testSelectWithSizeBiggerThanOneCanBeRequired()
  268. {
  269. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
  270. 'choices' => array('a', 'b'),
  271. 'choices_as_values' => true,
  272. 'multiple' => false,
  273. 'expanded' => false,
  274. 'attr' => array('size' => 2),
  275. ));
  276. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => '')),
  277. '/select
  278. [@name="name"]
  279. [@required="required"]
  280. [@size="2"]
  281. [count(./option)=2]
  282. '
  283. );
  284. }
  285. public function testSingleChoiceWithoutTranslation()
  286. {
  287. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  288. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  289. 'choices_as_values' => true,
  290. 'multiple' => false,
  291. 'expanded' => false,
  292. 'choice_translation_domain' => false,
  293. ));
  294. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  295. '/select
  296. [@name="name"]
  297. [@class="my&class form-control"]
  298. [not(@required)]
  299. [
  300. ./option[@value="&a"][@selected="selected"][.="Choice&A"]
  301. /following-sibling::option[@value="&b"][not(@selected)][.="Choice&B"]
  302. ]
  303. [count(./option)=2]
  304. '
  305. );
  306. }
  307. public function testSingleChoiceWithPlaceholderWithoutTranslation()
  308. {
  309. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  310. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  311. 'choices_as_values' => true,
  312. 'multiple' => false,
  313. 'expanded' => false,
  314. 'required' => false,
  315. 'translation_domain' => false,
  316. 'placeholder' => 'Placeholder&Not&Translated',
  317. ));
  318. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  319. '/select
  320. [@name="name"]
  321. [@class="my&class form-control"]
  322. [not(@required)]
  323. [
  324. ./option[@value=""][not(@selected)][not(@disabled)][.="Placeholder&Not&Translated"]
  325. /following-sibling::option[@value="&a"][@selected="selected"][.="Choice&A"]
  326. /following-sibling::option[@value="&b"][not(@selected)][.="Choice&B"]
  327. ]
  328. [count(./option)=3]
  329. '
  330. );
  331. }
  332. public function testSingleChoiceAttributes()
  333. {
  334. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  335. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  336. 'choices_as_values' => true,
  337. 'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')),
  338. 'multiple' => false,
  339. 'expanded' => false,
  340. ));
  341. $classPart = \in_array('choice_attr', $this->testableFeatures) ? '[@class="foo&bar"]' : '';
  342. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  343. '/select
  344. [@name="name"]
  345. [@class="my&class form-control"]
  346. [not(@required)]
  347. [
  348. ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  349. /following-sibling::option[@value="&b"]'.$classPart.'[not(@selected)][.="[trans]Choice&B[/trans]"]
  350. ]
  351. [count(./option)=2]
  352. '
  353. );
  354. }
  355. public function testSingleChoiceWithPreferred()
  356. {
  357. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  358. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  359. 'choices_as_values' => true,
  360. 'preferred_choices' => array('&b'),
  361. 'multiple' => false,
  362. 'expanded' => false,
  363. ));
  364. $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '-- sep --', 'attr' => array('class' => 'my&class')),
  365. '/select
  366. [@name="name"]
  367. [@class="my&class form-control"]
  368. [not(@required)]
  369. [
  370. ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  371. /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"]
  372. /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  373. ]
  374. [count(./option)=3]
  375. '
  376. );
  377. }
  378. public function testSingleChoiceWithPreferredAndNoSeparator()
  379. {
  380. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  381. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  382. 'choices_as_values' => true,
  383. 'preferred_choices' => array('&b'),
  384. 'multiple' => false,
  385. 'expanded' => false,
  386. ));
  387. $this->assertWidgetMatchesXpath($form->createView(), array('separator' => null, 'attr' => array('class' => 'my&class')),
  388. '/select
  389. [@name="name"]
  390. [@class="my&class form-control"]
  391. [not(@required)]
  392. [
  393. ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  394. /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  395. ]
  396. [count(./option)=2]
  397. '
  398. );
  399. }
  400. public function testSingleChoiceWithPreferredAndBlankSeparator()
  401. {
  402. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  403. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  404. 'choices_as_values' => true,
  405. 'preferred_choices' => array('&b'),
  406. 'multiple' => false,
  407. 'expanded' => false,
  408. ));
  409. $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '', 'attr' => array('class' => 'my&class')),
  410. '/select
  411. [@name="name"]
  412. [@class="my&class form-control"]
  413. [not(@required)]
  414. [
  415. ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  416. /following-sibling::option[@disabled="disabled"][not(@selected)][.=""]
  417. /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  418. ]
  419. [count(./option)=3]
  420. '
  421. );
  422. }
  423. public function testChoiceWithOnlyPreferred()
  424. {
  425. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  426. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  427. 'choices_as_values' => true,
  428. 'preferred_choices' => array('&a', '&b'),
  429. 'multiple' => false,
  430. 'expanded' => false,
  431. ));
  432. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  433. '/select
  434. [@class="my&class form-control"]
  435. [count(./option)=2]
  436. '
  437. );
  438. }
  439. public function testSingleChoiceNonRequired()
  440. {
  441. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  442. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  443. 'choices_as_values' => true,
  444. 'required' => false,
  445. 'multiple' => false,
  446. 'expanded' => false,
  447. ));
  448. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  449. '/select
  450. [@name="name"]
  451. [@class="my&class form-control"]
  452. [not(@required)]
  453. [
  454. ./option[@value=""][.=""]
  455. /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  456. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  457. ]
  458. [count(./option)=3]
  459. '
  460. );
  461. }
  462. public function testSingleChoiceNonRequiredNoneSelected()
  463. {
  464. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
  465. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  466. 'choices_as_values' => true,
  467. 'required' => false,
  468. 'multiple' => false,
  469. 'expanded' => false,
  470. ));
  471. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  472. '/select
  473. [@name="name"]
  474. [@class="my&class form-control"]
  475. [not(@required)]
  476. [
  477. ./option[@value=""][.=""]
  478. /following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"]
  479. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  480. ]
  481. [count(./option)=3]
  482. '
  483. );
  484. }
  485. public function testSingleChoiceNonRequiredWithPlaceholder()
  486. {
  487. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  488. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  489. 'choices_as_values' => true,
  490. 'multiple' => false,
  491. 'expanded' => false,
  492. 'required' => false,
  493. 'placeholder' => 'Select&Anything&Not&Me',
  494. ));
  495. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  496. '/select
  497. [@name="name"]
  498. [@class="my&class form-control"]
  499. [not(@required)]
  500. [
  501. ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Anything&Not&Me[/trans]"]
  502. /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  503. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  504. ]
  505. [count(./option)=3]
  506. '
  507. );
  508. }
  509. public function testSingleChoiceRequiredWithPlaceholder()
  510. {
  511. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  512. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  513. 'choices_as_values' => true,
  514. 'required' => true,
  515. 'multiple' => false,
  516. 'expanded' => false,
  517. 'placeholder' => 'Test&Me',
  518. ));
  519. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  520. '/select
  521. [@name="name"]
  522. [@class="my&class form-control"]
  523. [@required="required"]
  524. [
  525. ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Test&Me[/trans]"]
  526. /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  527. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  528. ]
  529. [count(./option)=3]
  530. '
  531. );
  532. }
  533. public function testSingleChoiceRequiredWithPlaceholderViaView()
  534. {
  535. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  536. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  537. 'choices_as_values' => true,
  538. 'required' => true,
  539. 'multiple' => false,
  540. 'expanded' => false,
  541. ));
  542. $this->assertWidgetMatchesXpath($form->createView(), array('placeholder' => '', 'attr' => array('class' => 'my&class')),
  543. '/select
  544. [@name="name"]
  545. [@class="my&class form-control"]
  546. [@required="required"]
  547. [
  548. ./option[@value=""][not(@selected)][not(@disabled)][.=""]
  549. /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  550. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  551. ]
  552. [count(./option)=3]
  553. '
  554. );
  555. }
  556. public function testSingleChoiceGrouped()
  557. {
  558. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  559. 'choices' => array(
  560. 'Group&1' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  561. 'Group&2' => array('Choice&C' => '&c'),
  562. ),
  563. 'choices_as_values' => true,
  564. 'multiple' => false,
  565. 'expanded' => false,
  566. ));
  567. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  568. '/select
  569. [@name="name"]
  570. [@class="my&class form-control"]
  571. [./optgroup[@label="[trans]Group&1[/trans]"]
  572. [
  573. ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  574. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  575. ]
  576. [count(./option)=2]
  577. ]
  578. [./optgroup[@label="[trans]Group&2[/trans]"]
  579. [./option[@value="&c"][not(@selected)][.="[trans]Choice&C[/trans]"]]
  580. [count(./option)=1]
  581. ]
  582. [count(./optgroup)=2]
  583. '
  584. );
  585. }
  586. public function testMultipleChoice()
  587. {
  588. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
  589. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  590. 'choices_as_values' => true,
  591. 'required' => true,
  592. 'multiple' => true,
  593. 'expanded' => false,
  594. ));
  595. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  596. '/select
  597. [@name="name[]"]
  598. [@class="my&class form-control"]
  599. [@required="required"]
  600. [@multiple="multiple"]
  601. [
  602. ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  603. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  604. ]
  605. [count(./option)=2]
  606. '
  607. );
  608. }
  609. public function testMultipleChoiceAttributes()
  610. {
  611. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
  612. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  613. 'choices_as_values' => true,
  614. 'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')),
  615. 'required' => true,
  616. 'multiple' => true,
  617. 'expanded' => false,
  618. ));
  619. $classPart = \in_array('choice_attr', $this->testableFeatures) ? '[@class="foo&bar"]' : '';
  620. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  621. '/select
  622. [@name="name[]"]
  623. [@class="my&class form-control"]
  624. [@required="required"]
  625. [@multiple="multiple"]
  626. [
  627. ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  628. /following-sibling::option[@value="&b"]'.$classPart.'[not(@selected)][.="[trans]Choice&B[/trans]"]
  629. ]
  630. [count(./option)=2]
  631. '
  632. );
  633. }
  634. public function testMultipleChoiceSkipsPlaceholder()
  635. {
  636. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
  637. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  638. 'choices_as_values' => true,
  639. 'multiple' => true,
  640. 'expanded' => false,
  641. 'placeholder' => 'Test&Me',
  642. ));
  643. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  644. '/select
  645. [@name="name[]"]
  646. [@class="my&class form-control"]
  647. [@multiple="multiple"]
  648. [
  649. ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  650. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  651. ]
  652. [count(./option)=2]
  653. '
  654. );
  655. }
  656. public function testMultipleChoiceNonRequired()
  657. {
  658. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
  659. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  660. 'choices_as_values' => true,
  661. 'required' => false,
  662. 'multiple' => true,
  663. 'expanded' => false,
  664. ));
  665. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  666. '/select
  667. [@name="name[]"]
  668. [@class="my&class form-control"]
  669. [@multiple="multiple"]
  670. [
  671. ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
  672. /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
  673. ]
  674. [count(./option)=2]
  675. '
  676. );
  677. }
  678. public function testSingleChoiceExpanded()
  679. {
  680. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  681. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  682. 'choices_as_values' => true,
  683. 'multiple' => false,
  684. 'expanded' => true,
  685. ));
  686. $this->assertWidgetMatchesXpath($form->createView(), array(),
  687. '/div
  688. [
  689. ./div
  690. [@class="radio"]
  691. [
  692. ./label
  693. [.=" [trans]Choice&A[/trans]"]
  694. [
  695. ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
  696. ]
  697. ]
  698. /following-sibling::div
  699. [@class="radio"]
  700. [
  701. ./label
  702. [.=" [trans]Choice&B[/trans]"]
  703. [
  704. ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
  705. ]
  706. ]
  707. /following-sibling::input[@type="hidden"][@id="name__token"]
  708. ]
  709. '
  710. );
  711. }
  712. public function testSingleChoiceExpandedWithLabelsAsFalse()
  713. {
  714. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  715. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  716. 'choices_as_values' => true,
  717. 'choice_label' => false,
  718. 'multiple' => false,
  719. 'expanded' => true,
  720. ));
  721. $this->assertWidgetMatchesXpath($form->createView(), array(),
  722. '/div
  723. [
  724. ./div
  725. [@class="radio"]
  726. [
  727. ./label
  728. [
  729. ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
  730. ]
  731. ]
  732. /following-sibling::div
  733. [@class="radio"]
  734. [
  735. ./label
  736. [
  737. ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
  738. ]
  739. ]
  740. /following-sibling::input[@type="hidden"][@id="name__token"]
  741. ]
  742. '
  743. );
  744. }
  745. public function testSingleChoiceExpandedWithLabelsSetByCallable()
  746. {
  747. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  748. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
  749. 'choices_as_values' => true,
  750. 'choice_label' => function ($choice, $label, $value) {
  751. if ('&b' === $choice) {
  752. return false;
  753. }
  754. return 'label.'.$value;
  755. },
  756. 'multiple' => false,
  757. 'expanded' => true,
  758. ));
  759. $this->assertWidgetMatchesXpath($form->createView(), array(),
  760. '/div
  761. [
  762. ./div
  763. [@class="radio"]
  764. [
  765. ./label
  766. [.=" [trans]label.&a[/trans]"]
  767. [
  768. ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
  769. ]
  770. ]
  771. /following-sibling::div
  772. [@class="radio"]
  773. [
  774. ./label
  775. [
  776. ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
  777. ]
  778. ]
  779. /following-sibling::div
  780. [@class="radio"]
  781. [
  782. ./label
  783. [.=" [trans]label.&c[/trans]"]
  784. [
  785. ./input[@type="radio"][@name="name"][@id="name_2"][@value="&c"][not(@checked)]
  786. ]
  787. ]
  788. /following-sibling::input[@type="hidden"][@id="name__token"]
  789. ]
  790. '
  791. );
  792. }
  793. public function testSingleChoiceExpandedWithLabelsSetFalseByCallable()
  794. {
  795. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  796. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  797. 'choices_as_values' => true,
  798. 'choice_label' => function () {
  799. return false;
  800. },
  801. 'multiple' => false,
  802. 'expanded' => true,
  803. ));
  804. $this->assertWidgetMatchesXpath($form->createView(), array(),
  805. '/div
  806. [
  807. ./div
  808. [@class="radio"]
  809. [
  810. ./label
  811. [
  812. ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
  813. ]
  814. ]
  815. /following-sibling::div
  816. [@class="radio"]
  817. [
  818. ./label
  819. [
  820. ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
  821. ]
  822. ]
  823. /following-sibling::input[@type="hidden"][@id="name__token"]
  824. ]
  825. '
  826. );
  827. }
  828. public function testSingleChoiceExpandedWithoutTranslation()
  829. {
  830. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  831. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  832. 'choices_as_values' => true,
  833. 'multiple' => false,
  834. 'expanded' => true,
  835. 'choice_translation_domain' => false,
  836. ));
  837. $this->assertWidgetMatchesXpath($form->createView(), array(),
  838. '/div
  839. [
  840. ./div
  841. [@class="radio"]
  842. [
  843. ./label
  844. [.=" Choice&A"]
  845. [
  846. ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
  847. ]
  848. ]
  849. /following-sibling::div
  850. [@class="radio"]
  851. [
  852. ./label
  853. [.=" Choice&B"]
  854. [
  855. ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
  856. ]
  857. ]
  858. /following-sibling::input[@type="hidden"][@id="name__token"]
  859. ]
  860. '
  861. );
  862. }
  863. public function testSingleChoiceExpandedAttributes()
  864. {
  865. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  866. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  867. 'choices_as_values' => true,
  868. 'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')),
  869. 'multiple' => false,
  870. 'expanded' => true,
  871. ));
  872. $classPart = \in_array('choice_attr', $this->testableFeatures) ? '[@class="foo&bar"]' : '';
  873. $this->assertWidgetMatchesXpath($form->createView(), array(),
  874. '/div
  875. [
  876. ./div
  877. [@class="radio"]
  878. [
  879. ./label
  880. [.=" [trans]Choice&A[/trans]"]
  881. [
  882. ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
  883. ]
  884. ]
  885. /following-sibling::div
  886. [@class="radio"]
  887. [
  888. ./label
  889. [.=" [trans]Choice&B[/trans]"]
  890. [
  891. ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]'.$classPart.'
  892. ]
  893. ]
  894. /following-sibling::input[@type="hidden"][@id="name__token"]
  895. ]
  896. '
  897. );
  898. }
  899. public function testSingleChoiceExpandedWithPlaceholder()
  900. {
  901. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  902. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  903. 'choices_as_values' => true,
  904. 'multiple' => false,
  905. 'expanded' => true,
  906. 'placeholder' => 'Test&Me',
  907. 'required' => false,
  908. ));
  909. $this->assertWidgetMatchesXpath($form->createView(), array(),
  910. '/div
  911. [
  912. ./div
  913. [@class="radio"]
  914. [
  915. ./label
  916. [.=" [trans]Test&Me[/trans]"]
  917. [
  918. ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)]
  919. ]
  920. ]
  921. /following-sibling::div
  922. [@class="radio"]
  923. [
  924. ./label
  925. [.=" [trans]Choice&A[/trans]"]
  926. [
  927. ./input[@type="radio"][@name="name"][@id="name_0"][@checked]
  928. ]
  929. ]
  930. /following-sibling::div
  931. [@class="radio"]
  932. [
  933. ./label
  934. [.=" [trans]Choice&B[/trans]"]
  935. [
  936. ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
  937. ]
  938. ]
  939. /following-sibling::input[@type="hidden"][@id="name__token"]
  940. ]
  941. '
  942. );
  943. }
  944. public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation()
  945. {
  946. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
  947. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  948. 'choices_as_values' => true,
  949. 'multiple' => false,
  950. 'expanded' => true,
  951. 'required' => false,
  952. 'choice_translation_domain' => false,
  953. 'placeholder' => 'Placeholder&Not&Translated',
  954. ));
  955. $this->assertWidgetMatchesXpath($form->createView(), array(),
  956. '/div
  957. [
  958. ./div
  959. [@class="radio"]
  960. [
  961. ./label
  962. [.=" Placeholder&Not&Translated"]
  963. [
  964. ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)]
  965. ]
  966. ]
  967. /following-sibling::div
  968. [@class="radio"]
  969. [
  970. ./label
  971. [.=" Choice&A"]
  972. [
  973. ./input[@type="radio"][@name="name"][@id="name_0"][@checked]
  974. ]
  975. ]
  976. /following-sibling::div
  977. [@class="radio"]
  978. [
  979. ./label
  980. [.=" Choice&B"]
  981. [
  982. ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
  983. ]
  984. ]
  985. /following-sibling::input[@type="hidden"][@id="name__token"]
  986. ]
  987. '
  988. );
  989. }
  990. public function testSingleChoiceExpandedWithBooleanValue()
  991. {
  992. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', true, array(
  993. 'choices' => array('Choice&A' => '1', 'Choice&B' => '0'),
  994. 'choices_as_values' => true,
  995. 'multiple' => false,
  996. 'expanded' => true,
  997. ));
  998. $this->assertWidgetMatchesXpath($form->createView(), array(),
  999. '/div
  1000. [
  1001. ./div
  1002. [@class="radio"]
  1003. [
  1004. ./label
  1005. [.=" [trans]Choice&A[/trans]"]
  1006. [
  1007. ./input[@type="radio"][@name="name"][@id="name_0"][@checked]
  1008. ]
  1009. ]
  1010. /following-sibling::div
  1011. [@class="radio"]
  1012. [
  1013. ./label
  1014. [.=" [trans]Choice&B[/trans]"]
  1015. [
  1016. ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
  1017. ]
  1018. ]
  1019. /following-sibling::input[@type="hidden"][@id="name__token"]
  1020. ]
  1021. '
  1022. );
  1023. }
  1024. public function testMultipleChoiceExpanded()
  1025. {
  1026. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array(
  1027. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
  1028. 'choices_as_values' => true,
  1029. 'multiple' => true,
  1030. 'expanded' => true,
  1031. 'required' => true,
  1032. ));
  1033. $this->assertWidgetMatchesXpath($form->createView(), array(),
  1034. '/div
  1035. [
  1036. ./div
  1037. [@class="checkbox"]
  1038. [
  1039. ./label
  1040. [.=" [trans]Choice&A[/trans]"]
  1041. [
  1042. ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)]
  1043. ]
  1044. ]
  1045. /following-sibling::div
  1046. [@class="checkbox"]
  1047. [
  1048. ./label
  1049. [.=" [trans]Choice&B[/trans]"]
  1050. [
  1051. ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)]
  1052. ]
  1053. ]
  1054. /following-sibling::div
  1055. [@class="checkbox"]
  1056. [
  1057. ./label
  1058. [.=" [trans]Choice&C[/trans]"]
  1059. [
  1060. ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)]
  1061. ]
  1062. ]
  1063. /following-sibling::input[@type="hidden"][@id="name__token"]
  1064. ]
  1065. '
  1066. );
  1067. }
  1068. public function testMultipleChoiceExpandedWithLabelsAsFalse()
  1069. {
  1070. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
  1071. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  1072. 'choices_as_values' => true,
  1073. 'choice_label' => false,
  1074. 'multiple' => true,
  1075. 'expanded' => true,
  1076. ));
  1077. $this->assertWidgetMatchesXpath($form->createView(), array(),
  1078. '/div
  1079. [
  1080. ./div
  1081. [@class="checkbox"]
  1082. [
  1083. ./label
  1084. [
  1085. ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
  1086. ]
  1087. ]
  1088. /following-sibling::div
  1089. [@class="checkbox"]
  1090. [
  1091. ./label
  1092. [
  1093. ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
  1094. ]
  1095. ]
  1096. /following-sibling::input[@type="hidden"][@id="name__token"]
  1097. ]
  1098. '
  1099. );
  1100. }
  1101. public function testMultipleChoiceExpandedWithLabelsSetByCallable()
  1102. {
  1103. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
  1104. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
  1105. 'choices_as_values' => true,
  1106. 'choice_label' => function ($choice, $label, $value) {
  1107. if ('&b' === $choice) {
  1108. return false;
  1109. }
  1110. return 'label.'.$value;
  1111. },
  1112. 'multiple' => true,
  1113. 'expanded' => true,
  1114. ));
  1115. $this->assertWidgetMatchesXpath($form->createView(), array(),
  1116. '/div
  1117. [
  1118. ./div
  1119. [@class="checkbox"]
  1120. [
  1121. ./label
  1122. [.=" [trans]label.&a[/trans]"]
  1123. [
  1124. ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
  1125. ]
  1126. ]
  1127. /following-sibling::div
  1128. [@class="checkbox"]
  1129. [
  1130. ./label
  1131. [
  1132. ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
  1133. ]
  1134. ]
  1135. /following-sibling::div
  1136. [@class="checkbox"]
  1137. [
  1138. ./label
  1139. [.=" [trans]label.&c[/trans]"]
  1140. [
  1141. ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@value="&c"][not(@checked)]
  1142. ]
  1143. ]
  1144. /following-sibling::input[@type="hidden"][@id="name__token"]
  1145. ]
  1146. '
  1147. );
  1148. }
  1149. public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable()
  1150. {
  1151. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
  1152. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
  1153. 'choices_as_values' => true,
  1154. 'choice_label' => function () {
  1155. return false;
  1156. },
  1157. 'multiple' => true,
  1158. 'expanded' => true,
  1159. ));
  1160. $this->assertWidgetMatchesXpath($form->createView(), array(),
  1161. '/div
  1162. [
  1163. ./div
  1164. [@class="checkbox"]
  1165. [
  1166. ./label
  1167. [
  1168. ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
  1169. ]
  1170. ]
  1171. /following-sibling::div
  1172. [@class="checkbox"]
  1173. [
  1174. ./label
  1175. [
  1176. ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
  1177. ]
  1178. ]
  1179. /following-sibling::input[@type="hidden"][@id="name__token"]
  1180. ]
  1181. '
  1182. );
  1183. }
  1184. public function testMultipleChoiceExpandedWithoutTranslation()
  1185. {
  1186. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array(
  1187. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
  1188. 'choices_as_values' => true,
  1189. 'multiple' => true,
  1190. 'expanded' => true,
  1191. 'required' => true,
  1192. 'choice_translation_domain' => false,
  1193. ));
  1194. $this->assertWidgetMatchesXpath($form->createView(), array(),
  1195. '/div
  1196. [
  1197. ./div
  1198. [@class="checkbox"]
  1199. [
  1200. ./label
  1201. [.=" Choice&A"]
  1202. [
  1203. ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)]
  1204. ]
  1205. ]
  1206. /following-sibling::div
  1207. [@class="checkbox"]
  1208. [
  1209. ./label
  1210. [.=" Choice&B"]
  1211. [
  1212. ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)]
  1213. ]
  1214. ]
  1215. /following-sibling::div
  1216. [@class="checkbox"]
  1217. [
  1218. ./label
  1219. [.=" Choice&C"]
  1220. [
  1221. ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)]
  1222. ]
  1223. ]
  1224. /following-sibling::input[@type="hidden"][@id="name__token"]
  1225. ]
  1226. '
  1227. );
  1228. }
  1229. public function testMultipleChoiceExpandedAttributes()
  1230. {
  1231. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array(
  1232. 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
  1233. 'choices_as_values' => true,
  1234. 'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')),
  1235. 'multiple' => true,
  1236. 'expanded' => true,
  1237. 'required' => true,
  1238. ));
  1239. $classPart = \in_array('choice_attr', $this->testableFeatures) ? '[@class="foo&bar"]' : '';
  1240. $this->assertWidgetMatchesXpath($form->createView(), array(),
  1241. '/div
  1242. [
  1243. ./div
  1244. [@class="checkbox"]
  1245. [
  1246. ./label
  1247. [.=" [trans]Choice&A[/trans]"]
  1248. [
  1249. ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)]
  1250. ]
  1251. ]
  1252. /following-sibling::div
  1253. [@class="checkbox"]
  1254. [
  1255. ./label
  1256. [.=" [trans]Choice&B[/trans]"]
  1257. [
  1258. ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)]'.$classPart.'
  1259. ]
  1260. ]
  1261. /following-sibling::div
  1262. [@class="checkbox"]
  1263. [
  1264. ./label
  1265. [.=" [trans]Choice&C[/trans]"]
  1266. [
  1267. ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)]
  1268. ]
  1269. ]
  1270. /following-sibling::input[@type="hidden"][@id="name__token"]
  1271. ]
  1272. '
  1273. );
  1274. }
  1275. public function testCountry()
  1276. {
  1277. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CountryType', 'AT');
  1278. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1279. '/select
  1280. [@name="name"]
  1281. [@class="my&class form-control"]
  1282. [./option[@value="AT"][@selected="selected"][.="Austria"]]
  1283. [count(./option)>200]
  1284. '
  1285. );
  1286. }
  1287. public function testCountryWithPlaceholder()
  1288. {
  1289. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CountryType', 'AT', array(
  1290. 'placeholder' => 'Select&Country',
  1291. 'required' => false,
  1292. ));
  1293. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1294. '/select
  1295. [@name="name"]
  1296. [@class="my&class form-control"]
  1297. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]]
  1298. [./option[@value="AT"][@selected="selected"][.="Austria"]]
  1299. [count(./option)>201]
  1300. '
  1301. );
  1302. }
  1303. public function testDateTime()
  1304. {
  1305. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', date('Y').'-02-03 04:05:06', array(
  1306. 'input' => 'string',
  1307. 'with_seconds' => false,
  1308. ));
  1309. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1310. '/div
  1311. [
  1312. ./select
  1313. [@id="name_date_month"]
  1314. [@class="form-control"]
  1315. [./option[@value="2"][@selected="selected"]]
  1316. /following-sibling::select
  1317. [@id="name_date_day"]
  1318. [@class="form-control"]
  1319. [./option[@value="3"][@selected="selected"]]
  1320. /following-sibling::select
  1321. [@id="name_date_year"]
  1322. [@class="form-control"]
  1323. [./option[@value="'.date('Y').'"][@selected="selected"]]
  1324. /following-sibling::select
  1325. [@id="name_time_hour"]
  1326. [@class="form-control"]
  1327. [./option[@value="4"][@selected="selected"]]
  1328. /following-sibling::select
  1329. [@id="name_time_minute"]
  1330. [@class="form-control"]
  1331. [./option[@value="5"][@selected="selected"]]
  1332. ]
  1333. [count(.//select)=5]
  1334. '
  1335. );
  1336. }
  1337. public function testDateTimeWithPlaceholderGlobal()
  1338. {
  1339. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', null, array(
  1340. 'input' => 'string',
  1341. 'placeholder' => 'Change&Me',
  1342. 'required' => false,
  1343. ));
  1344. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1345. '/div
  1346. [@class="my&class form-inline"]
  1347. [
  1348. ./select
  1349. [@id="name_date_month"]
  1350. [@class="form-control"]
  1351. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  1352. /following-sibling::select
  1353. [@id="name_date_day"]
  1354. [@class="form-control"]
  1355. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  1356. /following-sibling::select
  1357. [@id="name_date_year"]
  1358. [@class="form-control"]
  1359. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  1360. /following-sibling::select
  1361. [@id="name_time_hour"]
  1362. [@class="form-control"]
  1363. [./option[@value=""][.="[trans]Change&Me[/trans]"]]
  1364. /following-sibling::select
  1365. [@id="name_time_minute"]
  1366. [@class="form-control"]
  1367. [./option[@value=""][.="[trans]Change&Me[/trans]"]]
  1368. ]
  1369. [count(.//select)=5]
  1370. '
  1371. );
  1372. }
  1373. public function testDateTimeWithHourAndMinute()
  1374. {
  1375. $data = array('year' => date('Y'), 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5');
  1376. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', $data, array(
  1377. 'input' => 'array',
  1378. 'required' => false,
  1379. ));
  1380. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1381. '/div
  1382. [@class="my&class form-inline"]
  1383. [
  1384. ./select
  1385. [@id="name_date_month"]
  1386. [@class="form-control"]
  1387. [./option[@value="2"][@selected="selected"]]
  1388. /following-sibling::select
  1389. [@id="name_date_day"]
  1390. [@class="form-control"]
  1391. [./option[@value="3"][@selected="selected"]]
  1392. /following-sibling::select
  1393. [@id="name_date_year"]
  1394. [@class="form-control"]
  1395. [./option[@value="'.date('Y').'"][@selected="selected"]]
  1396. /following-sibling::select
  1397. [@id="name_time_hour"]
  1398. [@class="form-control"]
  1399. [./option[@value="4"][@selected="selected"]]
  1400. /following-sibling::select
  1401. [@id="name_time_minute"]
  1402. [@class="form-control"]
  1403. [./option[@value="5"][@selected="selected"]]
  1404. ]
  1405. [count(.//select)=5]
  1406. '
  1407. );
  1408. }
  1409. public function testDateTimeWithSeconds()
  1410. {
  1411. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', date('Y').'-02-03 04:05:06', array(
  1412. 'input' => 'string',
  1413. 'with_seconds' => true,
  1414. ));
  1415. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1416. '/div
  1417. [@class="my&class form-inline"]
  1418. [
  1419. ./select
  1420. [@id="name_date_month"]
  1421. [@class="form-control"]
  1422. [./option[@value="2"][@selected="selected"]]
  1423. /following-sibling::select
  1424. [@id="name_date_day"]
  1425. [@class="form-control"]
  1426. [./option[@value="3"][@selected="selected"]]
  1427. /following-sibling::select
  1428. [@id="name_date_year"]
  1429. [@class="form-control"]
  1430. [./option[@value="'.date('Y').'"][@selected="selected"]]
  1431. /following-sibling::select
  1432. [@id="name_time_hour"]
  1433. [@class="form-control"]
  1434. [./option[@value="4"][@selected="selected"]]
  1435. /following-sibling::select
  1436. [@id="name_time_minute"]
  1437. [@class="form-control"]
  1438. [./option[@value="5"][@selected="selected"]]
  1439. /following-sibling::select
  1440. [@id="name_time_second"]
  1441. [@class="form-control"]
  1442. [./option[@value="6"][@selected="selected"]]
  1443. ]
  1444. [count(.//select)=6]
  1445. '
  1446. );
  1447. }
  1448. public function testDateTimeSingleText()
  1449. {
  1450. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', '2011-02-03 04:05:06', array(
  1451. 'input' => 'string',
  1452. 'date_widget' => 'single_text',
  1453. 'time_widget' => 'single_text',
  1454. ));
  1455. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1456. '/div
  1457. [@class="my&class form-inline"]
  1458. [
  1459. ./input
  1460. [@type="date"]
  1461. [@id="name_date"]
  1462. [@name="name[date]"]
  1463. [@class="form-control"]
  1464. [@value="2011-02-03"]
  1465. /following-sibling::input
  1466. [@type="time"]
  1467. [@id="name_time"]
  1468. [@name="name[time]"]
  1469. [@class="form-control"]
  1470. [@value="04:05"]
  1471. ]
  1472. '
  1473. );
  1474. }
  1475. public function testDateTimeWithWidgetSingleText()
  1476. {
  1477. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', '2011-02-03 04:05:06', array(
  1478. 'input' => 'string',
  1479. 'widget' => 'single_text',
  1480. 'model_timezone' => 'UTC',
  1481. 'view_timezone' => 'UTC',
  1482. ));
  1483. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1484. '/input
  1485. [@type="datetime-local"]
  1486. [@name="name"]
  1487. [@class="my&class form-control"]
  1488. [@value="2011-02-03T04:05:06"]
  1489. '
  1490. );
  1491. }
  1492. public function testDateTimeWithWidgetSingleTextIgnoreDateAndTimeWidgets()
  1493. {
  1494. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', '2011-02-03 04:05:06', array(
  1495. 'input' => 'string',
  1496. 'date_widget' => 'choice',
  1497. 'time_widget' => 'choice',
  1498. 'widget' => 'single_text',
  1499. 'model_timezone' => 'UTC',
  1500. 'view_timezone' => 'UTC',
  1501. ));
  1502. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1503. '/input
  1504. [@type="datetime-local"]
  1505. [@name="name"]
  1506. [@class="my&class form-control"]
  1507. [@value="2011-02-03T04:05:06"]
  1508. '
  1509. );
  1510. }
  1511. public function testDateChoice()
  1512. {
  1513. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', date('Y').'-02-03', array(
  1514. 'input' => 'string',
  1515. 'widget' => 'choice',
  1516. ));
  1517. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1518. '/div
  1519. [@class="my&class form-inline"]
  1520. [
  1521. ./select
  1522. [@id="name_month"]
  1523. [@class="form-control"]
  1524. [./option[@value="2"][@selected="selected"]]
  1525. /following-sibling::select
  1526. [@id="name_day"]
  1527. [@class="form-control"]
  1528. [./option[@value="3"][@selected="selected"]]
  1529. /following-sibling::select
  1530. [@id="name_year"]
  1531. [@class="form-control"]
  1532. [./option[@value="'.date('Y').'"][@selected="selected"]]
  1533. ]
  1534. [count(./select)=3]
  1535. '
  1536. );
  1537. }
  1538. public function testDateChoiceWithPlaceholderGlobal()
  1539. {
  1540. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', null, array(
  1541. 'input' => 'string',
  1542. 'widget' => 'choice',
  1543. 'placeholder' => 'Change&Me',
  1544. 'required' => false,
  1545. ));
  1546. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1547. '/div
  1548. [@class="my&class form-inline"]
  1549. [
  1550. ./select
  1551. [@id="name_month"]
  1552. [@class="form-control"]
  1553. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  1554. /following-sibling::select
  1555. [@id="name_day"]
  1556. [@class="form-control"]
  1557. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  1558. /following-sibling::select
  1559. [@id="name_year"]
  1560. [@class="form-control"]
  1561. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  1562. ]
  1563. [count(./select)=3]
  1564. '
  1565. );
  1566. }
  1567. public function testDateChoiceWithPlaceholderOnYear()
  1568. {
  1569. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', null, array(
  1570. 'input' => 'string',
  1571. 'widget' => 'choice',
  1572. 'required' => false,
  1573. 'placeholder' => array('year' => 'Change&Me'),
  1574. ));
  1575. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1576. '/div
  1577. [@class="my&class form-inline"]
  1578. [
  1579. ./select
  1580. [@id="name_month"]
  1581. [@class="form-control"]
  1582. [./option[@value="1"]]
  1583. /following-sibling::select
  1584. [@id="name_day"]
  1585. [@class="form-control"]
  1586. [./option[@value="1"]]
  1587. /following-sibling::select
  1588. [@id="name_year"]
  1589. [@class="form-control"]
  1590. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  1591. ]
  1592. [count(./select)=3]
  1593. '
  1594. );
  1595. }
  1596. public function testDateText()
  1597. {
  1598. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', '2011-02-03', array(
  1599. 'input' => 'string',
  1600. 'widget' => 'text',
  1601. ));
  1602. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1603. '/div
  1604. [@class="my&class form-inline"]
  1605. [
  1606. ./input
  1607. [@id="name_month"]
  1608. [@type="text"]
  1609. [@class="form-control"]
  1610. [@value="2"]
  1611. /following-sibling::input
  1612. [@id="name_day"]
  1613. [@type="text"]
  1614. [@class="form-control"]
  1615. [@value="3"]
  1616. /following-sibling::input
  1617. [@id="name_year"]
  1618. [@type="text"]
  1619. [@class="form-control"]
  1620. [@value="2011"]
  1621. ]
  1622. [count(./input)=3]
  1623. '
  1624. );
  1625. }
  1626. public function testDateSingleText()
  1627. {
  1628. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', '2011-02-03', array(
  1629. 'input' => 'string',
  1630. 'widget' => 'single_text',
  1631. ));
  1632. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1633. '/input
  1634. [@type="date"]
  1635. [@name="name"]
  1636. [@class="my&class form-control"]
  1637. [@value="2011-02-03"]
  1638. '
  1639. );
  1640. }
  1641. public function testBirthDay()
  1642. {
  1643. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\BirthdayType', '2000-02-03', array(
  1644. 'input' => 'string',
  1645. ));
  1646. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1647. '/div
  1648. [@class="my&class form-inline"]
  1649. [
  1650. ./select
  1651. [@id="name_month"]
  1652. [@class="form-control"]
  1653. [./option[@value="2"][@selected="selected"]]
  1654. /following-sibling::select
  1655. [@id="name_day"]
  1656. [@class="form-control"]
  1657. [./option[@value="3"][@selected="selected"]]
  1658. /following-sibling::select
  1659. [@id="name_year"]
  1660. [@class="form-control"]
  1661. [./option[@value="2000"][@selected="selected"]]
  1662. ]
  1663. [count(./select)=3]
  1664. '
  1665. );
  1666. }
  1667. public function testBirthDayWithPlaceholder()
  1668. {
  1669. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\BirthdayType', '1950-01-01', array(
  1670. 'input' => 'string',
  1671. 'placeholder' => '',
  1672. 'required' => false,
  1673. ));
  1674. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1675. '/div
  1676. [@class="my&class form-inline"]
  1677. [
  1678. ./select
  1679. [@id="name_month"]
  1680. [@class="form-control"]
  1681. [./option[@value=""][not(@selected)][not(@disabled)][.=""]]
  1682. [./option[@value="1"][@selected="selected"]]
  1683. /following-sibling::select
  1684. [@id="name_day"]
  1685. [@class="form-control"]
  1686. [./option[@value=""][not(@selected)][not(@disabled)][.=""]]
  1687. [./option[@value="1"][@selected="selected"]]
  1688. /following-sibling::select
  1689. [@id="name_year"]
  1690. [@class="form-control"]
  1691. [./option[@value=""][not(@selected)][not(@disabled)][.=""]]
  1692. [./option[@value="1950"][@selected="selected"]]
  1693. ]
  1694. [count(./select)=3]
  1695. '
  1696. );
  1697. }
  1698. public function testEmail()
  1699. {
  1700. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\EmailType', 'foo&bar');
  1701. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1702. '/input
  1703. [@type="email"]
  1704. [@name="name"]
  1705. [@class="my&class form-control"]
  1706. [@value="foo&bar"]
  1707. [not(@maxlength)]
  1708. '
  1709. );
  1710. }
  1711. public function testEmailWithMaxLength()
  1712. {
  1713. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\EmailType', 'foo&bar', array(
  1714. 'attr' => array('maxlength' => 123),
  1715. ));
  1716. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1717. '/input
  1718. [@type="email"]
  1719. [@name="name"]
  1720. [@class="my&class form-control"]
  1721. [@value="foo&bar"]
  1722. [@maxlength="123"]
  1723. '
  1724. );
  1725. }
  1726. public function testHidden()
  1727. {
  1728. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\HiddenType', 'foo&bar');
  1729. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1730. '/input
  1731. [@type="hidden"]
  1732. [@name="name"]
  1733. [@class="my&class"]
  1734. [@value="foo&bar"]
  1735. '
  1736. );
  1737. }
  1738. /**
  1739. * @group legacy
  1740. */
  1741. public function testLegacyReadOnly()
  1742. {
  1743. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
  1744. 'read_only' => true,
  1745. ));
  1746. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1747. '/input
  1748. [@type="text"]
  1749. [@name="name"]
  1750. [@class="my&class form-control"]
  1751. [@readonly="readonly"]
  1752. '
  1753. );
  1754. }
  1755. public function testDisabled()
  1756. {
  1757. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
  1758. 'disabled' => true,
  1759. ));
  1760. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1761. '/input
  1762. [@type="text"]
  1763. [@name="name"]
  1764. [@class="my&class form-control"]
  1765. [@disabled="disabled"]
  1766. '
  1767. );
  1768. }
  1769. public function testInteger()
  1770. {
  1771. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\IntegerType', 123);
  1772. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1773. '/input
  1774. [@type="number"]
  1775. [@name="name"]
  1776. [@class="my&class form-control"]
  1777. [@value="123"]
  1778. '
  1779. );
  1780. }
  1781. public function testLanguage()
  1782. {
  1783. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\LanguageType', 'de');
  1784. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1785. '/select
  1786. [@name="name"]
  1787. [@class="my&class form-control"]
  1788. [./option[@value="de"][@selected="selected"][.="German"]]
  1789. [count(./option)>200]
  1790. '
  1791. );
  1792. }
  1793. public function testLocale()
  1794. {
  1795. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\LocaleType', 'de_AT');
  1796. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1797. '/select
  1798. [@name="name"]
  1799. [@class="my&class form-control"]
  1800. [./option[@value="de_AT"][@selected="selected"][.="German (Austria)"]]
  1801. [count(./option)>200]
  1802. '
  1803. );
  1804. }
  1805. public function testMoney()
  1806. {
  1807. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\MoneyType', 1234.56, array(
  1808. 'currency' => 'EUR',
  1809. ));
  1810. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  1811. '/div
  1812. [@class="input-group"]
  1813. [
  1814. ./span
  1815. [@class="input-group-addon"]
  1816. [contains(.., "€")]
  1817. /following-sibling::input
  1818. [@id="my&id"]
  1819. [@type="text"]
  1820. [@name="name"]
  1821. [@class="my&class form-control"]
  1822. [@value="1234.56"]
  1823. ]
  1824. '
  1825. );
  1826. }
  1827. public function testMoneyWithoutCurrency()
  1828. {
  1829. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\MoneyType', 1234.56, array(
  1830. 'currency' => false,
  1831. ));
  1832. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  1833. '/input
  1834. [@id="my&id"]
  1835. [@type="text"]
  1836. [@name="name"]
  1837. [@class="my&class form-control"]
  1838. [@value="1234.56"]
  1839. [not(preceding-sibling::*)]
  1840. [not(following-sibling::*)]
  1841. '
  1842. );
  1843. }
  1844. public function testNumber()
  1845. {
  1846. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\NumberType', 1234.56);
  1847. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1848. '/input
  1849. [@type="text"]
  1850. [@name="name"]
  1851. [@class="my&class form-control"]
  1852. [@value="1234.56"]
  1853. '
  1854. );
  1855. }
  1856. public function testPassword()
  1857. {
  1858. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PasswordType', 'foo&bar');
  1859. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1860. '/input
  1861. [@type="password"]
  1862. [@name="name"]
  1863. [@class="my&class form-control"]
  1864. '
  1865. );
  1866. }
  1867. public function testPasswordSubmittedWithNotAlwaysEmpty()
  1868. {
  1869. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PasswordType', null, array(
  1870. 'always_empty' => false,
  1871. ));
  1872. $form->submit('foo&bar');
  1873. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1874. '/input
  1875. [@type="password"]
  1876. [@name="name"]
  1877. [@class="my&class form-control"]
  1878. [@value="foo&bar"]
  1879. '
  1880. );
  1881. }
  1882. public function testPasswordWithMaxLength()
  1883. {
  1884. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PasswordType', 'foo&bar', array(
  1885. 'attr' => array('maxlength' => 123),
  1886. ));
  1887. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1888. '/input
  1889. [@type="password"]
  1890. [@name="name"]
  1891. [@class="my&class form-control"]
  1892. [@maxlength="123"]
  1893. '
  1894. );
  1895. }
  1896. public function testPercent()
  1897. {
  1898. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PercentType', 0.1);
  1899. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  1900. '/div
  1901. [@class="input-group"]
  1902. [
  1903. ./input
  1904. [@id="my&id"]
  1905. [@type="text"]
  1906. [@name="name"]
  1907. [@class="my&class form-control"]
  1908. [@value="10"]
  1909. /following-sibling::span
  1910. [@class="input-group-addon"]
  1911. [contains(.., "%")]
  1912. ]
  1913. '
  1914. );
  1915. }
  1916. public function testCheckedRadio()
  1917. {
  1918. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', true);
  1919. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  1920. '/div
  1921. [@class="radio"]
  1922. [
  1923. ./label
  1924. [@class="required"]
  1925. [
  1926. ./input
  1927. [@id="my&id"]
  1928. [@type="radio"]
  1929. [@name="name"]
  1930. [@class="my&class"]
  1931. [@checked="checked"]
  1932. [@value="1"]
  1933. ]
  1934. ]
  1935. '
  1936. );
  1937. }
  1938. public function testUncheckedRadio()
  1939. {
  1940. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false);
  1941. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  1942. '/div
  1943. [@class="radio"]
  1944. [
  1945. ./label
  1946. [@class="required"]
  1947. [
  1948. ./input
  1949. [@id="my&id"]
  1950. [@type="radio"]
  1951. [@name="name"]
  1952. [@class="my&class"]
  1953. [not(@checked)]
  1954. ]
  1955. ]
  1956. '
  1957. );
  1958. }
  1959. public function testRadioWithValue()
  1960. {
  1961. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false, array(
  1962. 'value' => 'foo&bar',
  1963. ));
  1964. $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
  1965. '/div
  1966. [@class="radio"]
  1967. [
  1968. ./label
  1969. [@class="required"]
  1970. [
  1971. ./input
  1972. [@id="my&id"]
  1973. [@type="radio"]
  1974. [@name="name"]
  1975. [@class="my&class"]
  1976. [@value="foo&bar"]
  1977. ]
  1978. ]
  1979. '
  1980. );
  1981. }
  1982. public function testRange()
  1983. {
  1984. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RangeType', 42, array('attr' => array('min' => 5)));
  1985. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1986. '/input
  1987. [@type="range"]
  1988. [@name="name"]
  1989. [@value="42"]
  1990. [@min="5"]
  1991. [@class="my&class form-control"]
  1992. '
  1993. );
  1994. }
  1995. public function testRangeWithMinMaxValues()
  1996. {
  1997. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RangeType', 42, array('attr' => array('min' => 5, 'max' => 57)));
  1998. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  1999. '/input
  2000. [@type="range"]
  2001. [@name="name"]
  2002. [@value="42"]
  2003. [@min="5"]
  2004. [@max="57"]
  2005. [@class="my&class form-control"]
  2006. '
  2007. );
  2008. }
  2009. public function testTextarea()
  2010. {
  2011. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextareaType', 'foo&bar', array(
  2012. 'attr' => array('pattern' => 'foo'),
  2013. ));
  2014. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2015. '/textarea
  2016. [@name="name"]
  2017. [@pattern="foo"]
  2018. [@class="my&class form-control"]
  2019. [.="foo&bar"]
  2020. '
  2021. );
  2022. }
  2023. public function testText()
  2024. {
  2025. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'foo&bar');
  2026. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2027. '/input
  2028. [@type="text"]
  2029. [@name="name"]
  2030. [@class="my&class form-control"]
  2031. [@value="foo&bar"]
  2032. [not(@maxlength)]
  2033. '
  2034. );
  2035. }
  2036. public function testTextWithMaxLength()
  2037. {
  2038. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'foo&bar', array(
  2039. 'attr' => array('maxlength' => 123),
  2040. ));
  2041. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2042. '/input
  2043. [@type="text"]
  2044. [@name="name"]
  2045. [@class="my&class form-control"]
  2046. [@value="foo&bar"]
  2047. [@maxlength="123"]
  2048. '
  2049. );
  2050. }
  2051. public function testSearch()
  2052. {
  2053. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\SearchType', 'foo&bar');
  2054. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2055. '/input
  2056. [@type="search"]
  2057. [@name="name"]
  2058. [@class="my&class form-control"]
  2059. [@value="foo&bar"]
  2060. [not(@maxlength)]
  2061. '
  2062. );
  2063. }
  2064. public function testTime()
  2065. {
  2066. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', '04:05:06', array(
  2067. 'input' => 'string',
  2068. 'with_seconds' => false,
  2069. ));
  2070. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2071. '/div
  2072. [@class="my&class form-inline"]
  2073. [
  2074. ./select
  2075. [@id="name_hour"]
  2076. [@class="form-control"]
  2077. [not(@size)]
  2078. [./option[@value="4"][@selected="selected"]]
  2079. /following-sibling::select
  2080. [@id="name_minute"]
  2081. [@class="form-control"]
  2082. [not(@size)]
  2083. [./option[@value="5"][@selected="selected"]]
  2084. ]
  2085. [count(./select)=2]
  2086. '
  2087. );
  2088. }
  2089. public function testTimeWithSeconds()
  2090. {
  2091. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', '04:05:06', array(
  2092. 'input' => 'string',
  2093. 'with_seconds' => true,
  2094. ));
  2095. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2096. '/div
  2097. [@class="my&class form-inline"]
  2098. [
  2099. ./select
  2100. [@id="name_hour"]
  2101. [@class="form-control"]
  2102. [not(@size)]
  2103. [./option[@value="4"][@selected="selected"]]
  2104. [count(./option)>23]
  2105. /following-sibling::select
  2106. [@id="name_minute"]
  2107. [@class="form-control"]
  2108. [not(@size)]
  2109. [./option[@value="5"][@selected="selected"]]
  2110. [count(./option)>59]
  2111. /following-sibling::select
  2112. [@id="name_second"]
  2113. [@class="form-control"]
  2114. [not(@size)]
  2115. [./option[@value="6"][@selected="selected"]]
  2116. [count(./option)>59]
  2117. ]
  2118. [count(./select)=3]
  2119. '
  2120. );
  2121. }
  2122. public function testTimeText()
  2123. {
  2124. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', '04:05:06', array(
  2125. 'input' => 'string',
  2126. 'widget' => 'text',
  2127. ));
  2128. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2129. '/div
  2130. [@class="my&class form-inline"]
  2131. [
  2132. ./input
  2133. [@type="text"]
  2134. [@id="name_hour"]
  2135. [@name="name[hour]"]
  2136. [@class="form-control"]
  2137. [@value="04"]
  2138. [@required="required"]
  2139. [not(@size)]
  2140. /following-sibling::input
  2141. [@type="text"]
  2142. [@id="name_minute"]
  2143. [@name="name[minute]"]
  2144. [@class="form-control"]
  2145. [@value="05"]
  2146. [@required="required"]
  2147. [not(@size)]
  2148. ]
  2149. [count(./input)=2]
  2150. '
  2151. );
  2152. }
  2153. public function testTimeSingleText()
  2154. {
  2155. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', '04:05:06', array(
  2156. 'input' => 'string',
  2157. 'widget' => 'single_text',
  2158. ));
  2159. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2160. '/input
  2161. [@type="time"]
  2162. [@name="name"]
  2163. [@class="my&class form-control"]
  2164. [@value="04:05"]
  2165. [not(@size)]
  2166. '
  2167. );
  2168. }
  2169. public function testTimeWithPlaceholderGlobal()
  2170. {
  2171. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', null, array(
  2172. 'input' => 'string',
  2173. 'placeholder' => 'Change&Me',
  2174. 'required' => false,
  2175. ));
  2176. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2177. '/div
  2178. [@class="my&class form-inline"]
  2179. [
  2180. ./select
  2181. [@id="name_hour"]
  2182. [@class="form-control"]
  2183. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  2184. [count(./option)>24]
  2185. /following-sibling::select
  2186. [@id="name_minute"]
  2187. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  2188. [count(./option)>60]
  2189. ]
  2190. [count(./select)=2]
  2191. '
  2192. );
  2193. }
  2194. public function testTimeWithPlaceholderOnYear()
  2195. {
  2196. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', null, array(
  2197. 'input' => 'string',
  2198. 'required' => false,
  2199. 'placeholder' => array('hour' => 'Change&Me'),
  2200. ));
  2201. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2202. '/div
  2203. [@class="my&class form-inline"]
  2204. [
  2205. ./select
  2206. [@id="name_hour"]
  2207. [@class="form-control"]
  2208. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]]
  2209. [count(./option)>24]
  2210. /following-sibling::select
  2211. [@id="name_minute"]
  2212. [./option[@value="1"]]
  2213. [count(./option)>59]
  2214. ]
  2215. [count(./select)=2]
  2216. '
  2217. );
  2218. }
  2219. public function testTimezone()
  2220. {
  2221. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimezoneType', 'Europe/Vienna');
  2222. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2223. '/select
  2224. [@name="name"]
  2225. [@class="my&class form-control"]
  2226. [not(@required)]
  2227. [./optgroup
  2228. [@label="Europe"]
  2229. [./option[@value="Europe/Vienna"][@selected="selected"][.="Vienna"]]
  2230. ]
  2231. [count(./optgroup)>10]
  2232. [count(.//option)>200]
  2233. '
  2234. );
  2235. }
  2236. public function testTimezoneWithPlaceholder()
  2237. {
  2238. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimezoneType', null, array(
  2239. 'placeholder' => 'Select&Timezone',
  2240. 'required' => false,
  2241. ));
  2242. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2243. '/select
  2244. [@class="my&class form-control"]
  2245. [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]]
  2246. [count(./optgroup)>10]
  2247. [count(.//option)>201]
  2248. '
  2249. );
  2250. }
  2251. public function testUrl()
  2252. {
  2253. $url = 'http://www.google.com?foo1=bar1&foo2=bar2';
  2254. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url);
  2255. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2256. '/input
  2257. [@type="url"]
  2258. [@name="name"]
  2259. [@class="my&class form-control"]
  2260. [@value="http://www.google.com?foo1=bar1&foo2=bar2"]
  2261. '
  2262. );
  2263. }
  2264. public function testButton()
  2265. {
  2266. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ButtonType');
  2267. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2268. '/button[@type="button"][@name="name"][.="[trans]Name[/trans]"][@class="my&class btn"]'
  2269. );
  2270. }
  2271. public function testButtonlabelWithoutTranslation()
  2272. {
  2273. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ButtonType', null, array(
  2274. 'translation_domain' => false,
  2275. ));
  2276. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2277. '/button[@type="button"][@name="name"][.="Name"][@class="my&class btn"]'
  2278. );
  2279. }
  2280. public function testSubmit()
  2281. {
  2282. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\SubmitType');
  2283. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2284. '/button[@type="submit"][@name="name"][@class="my&class btn"]'
  2285. );
  2286. }
  2287. public function testReset()
  2288. {
  2289. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ResetType');
  2290. $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')),
  2291. '/button[@type="reset"][@name="name"][@class="my&class btn"]'
  2292. );
  2293. }
  2294. public function testWidgetAttributes()
  2295. {
  2296. $form = $this->factory->createNamed('text', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'value', array(
  2297. 'required' => true,
  2298. 'disabled' => true,
  2299. 'attr' => array('readonly' => true, 'maxlength' => 10, 'pattern' => '\d+', 'class' => 'foobar', 'data-foo' => 'bar'),
  2300. ));
  2301. $html = $this->renderWidget($form->createView());
  2302. // compare plain HTML to check the whitespace
  2303. $this->assertSame('<input type="text" id="text" name="text" readonly="readonly" disabled="disabled" required="required" maxlength="10" pattern="\d+" class="foobar form-control" data-foo="bar" value="value" />', $html);
  2304. }
  2305. public function testWidgetAttributeNameRepeatedIfTrue()
  2306. {
  2307. $form = $this->factory->createNamed('text', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'value', array(
  2308. 'attr' => array('foo' => true),
  2309. ));
  2310. $html = $this->renderWidget($form->createView());
  2311. // foo="foo"
  2312. $this->assertSame('<input type="text" id="text" name="text" required="required" foo="foo" class="form-control" value="value" />', $html);
  2313. }
  2314. public function testButtonAttributes()
  2315. {
  2316. $form = $this->factory->createNamed('button', 'Symfony\Component\Form\Extension\Core\Type\ButtonType', null, array(
  2317. 'disabled' => true,
  2318. 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'),
  2319. ));
  2320. $html = $this->renderWidget($form->createView());
  2321. // compare plain HTML to check the whitespace
  2322. $this->assertSame('<button type="button" id="button" name="button" disabled="disabled" class="foobar btn" data-foo="bar">[trans]Button[/trans]</button>', $html);
  2323. }
  2324. public function testButtonAttributeNameRepeatedIfTrue()
  2325. {
  2326. $form = $this->factory->createNamed('button', 'Symfony\Component\Form\Extension\Core\Type\ButtonType', null, array(
  2327. 'attr' => array('foo' => true),
  2328. ));
  2329. $html = $this->renderWidget($form->createView());
  2330. // foo="foo"
  2331. $this->assertSame('<button type="button" id="button" name="button" foo="foo" class="btn-default btn">[trans]Button[/trans]</button>', $html);
  2332. }
  2333. }