AbstractLayoutTest.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  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\Tests\Component\Form;
  11. use Symfony\Component\Form\FormError;
  12. use Symfony\Component\Form\FormView;
  13. use Symfony\Component\Form\FormFactory;
  14. use Symfony\Component\Form\CsrfProvider\DefaultCsrfProvider;
  15. use Symfony\Component\Form\Type\Loader\DefaultTypeLoader;
  16. use Symfony\Component\EventDispatcher\EventDispatcher;
  17. abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
  18. {
  19. protected $csrfProvider;
  20. protected $factory;
  21. protected function setUp()
  22. {
  23. \Locale::setDefault('en');
  24. $dispatcher = new EventDispatcher();
  25. $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
  26. $this->csrfProvider = $this->getMock('Symfony\Component\Form\CsrfProvider\CsrfProviderInterface');
  27. $storage = new \Symfony\Component\HttpFoundation\File\TemporaryStorage('foo', 1, \sys_get_temp_dir());
  28. $loader = new DefaultTypeLoader($validator, $this->csrfProvider , $storage);
  29. $this->factory = new FormFactory($loader);
  30. }
  31. protected function assertXpathNodeValue(\DomElement $element, $expression, $nodeValue)
  32. {
  33. $xpath = new \DOMXPath($element->ownerDocument);
  34. $nodeList = $xpath->evaluate($expression);
  35. $this->assertEquals(1, $nodeList->length);
  36. $this->assertEquals($nodeValue, $nodeList->item(0)->nodeValue);
  37. }
  38. protected function assertMatchesXpath($html, $expression, $count = 1)
  39. {
  40. $dom = new \DomDocument('UTF-8');
  41. try {
  42. // Wrap in <root> node so we can load HTML with multiple tags at
  43. // the top level
  44. $dom->loadXml('<root>'.$html.'</root>');
  45. } catch (\Exception $e) {
  46. return $this->fail(sprintf(
  47. "Failed loading HTML:\n\n%s\n\nError: %s",
  48. $html,
  49. $e->getMessage()
  50. ));
  51. }
  52. $xpath = new \DOMXPath($dom);
  53. $nodeList = $xpath->evaluate('/root'.$expression);
  54. if ($nodeList->length != $count) {
  55. $dom->formatOutput = true;
  56. $this->fail(sprintf(
  57. "Failed asserting that \n\n%s\n\nmatches exactly %s. Matches %s in \n\n%s",
  58. $expression,
  59. $count == 1 ? 'once' : $count . ' times',
  60. $nodeList->length == 1 ? 'once' : $nodeList->length . ' times',
  61. // strip away <root> and </root>
  62. substr($dom->saveHTML(), 6, -8)
  63. ));
  64. }
  65. }
  66. protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath)
  67. {
  68. // include ampersands everywhere to validate escaping
  69. $html = $this->renderWidget($view, array_merge(array(
  70. 'id' => 'my&id',
  71. 'attr' => array('class' => 'my&class'),
  72. ), $vars));
  73. $xpath = trim($xpath).'
  74. [@id="my&id"]
  75. [@class="my&class"]';
  76. $this->assertMatchesXpath($html, $xpath);
  77. }
  78. abstract protected function renderEnctype(FormView $view);
  79. abstract protected function renderLabel(FormView $view, $label = null);
  80. abstract protected function renderErrors(FormView $view);
  81. abstract protected function renderWidget(FormView $view, array $vars = array());
  82. abstract protected function renderRow(FormView $view, array $vars = array());
  83. abstract protected function renderRest(FormView $view, array $vars = array());
  84. public function testEnctype()
  85. {
  86. $form = $this->factory->createBuilder('form', 'na&me', array('property_path' => 'name'))
  87. ->add('file', 'file')
  88. ->getForm();
  89. $this->assertEquals('enctype="multipart/form-data"', $this->renderEnctype($form->createView()));
  90. }
  91. public function testNoEnctype()
  92. {
  93. $form = $this->factory->createBuilder('form', 'na&me', array('property_path' => 'name'))
  94. ->add('text', 'text')
  95. ->getForm();
  96. $this->assertEquals('', $this->renderEnctype($form->createView()));
  97. }
  98. public function testLabel()
  99. {
  100. $form = $this->factory->create('text', 'na&me', array('property_path' => 'name'));
  101. $html = $this->renderLabel($form->createView());
  102. $this->assertMatchesXpath($html,
  103. '/label
  104. [@for="na&me"]
  105. [.="[trans]Na&me[/trans]"]
  106. '
  107. );
  108. }
  109. public function testLabelWithCustomText()
  110. {
  111. $form = $this->factory->create('text', 'na&me', array('property_path' => 'name'));
  112. $html = $this->renderLabel($form->createView(), 'Custom label');
  113. $this->assertMatchesXpath($html,
  114. '/label
  115. [@for="na&me"]
  116. [.="[trans]Custom label[/trans]"]
  117. '
  118. );
  119. }
  120. public function testErrors()
  121. {
  122. $form = $this->factory->create('text', 'na&me', array('property_path' => 'name'));
  123. $form->addError(new FormError('Error 1'));
  124. $form->addError(new FormError('Error 2'));
  125. $view = $form->createView();
  126. $html = $this->renderErrors($view);
  127. $this->assertMatchesXpath($html,
  128. '/ul
  129. [
  130. ./li[.="[trans]Error 1[/trans]"]
  131. /following-sibling::li[.="[trans]Error 2[/trans]"]
  132. ]
  133. [count(./li)=2]
  134. '
  135. );
  136. }
  137. public function testCheckedCheckbox()
  138. {
  139. $form = $this->factory->create('checkbox', 'na&me', array(
  140. 'property_path' => 'name',
  141. 'data' => true,
  142. ));
  143. $this->assertWidgetMatchesXpath($form->createView(), array(),
  144. '/input
  145. [@type="checkbox"]
  146. [@name="na&me"]
  147. [@checked="checked"]
  148. [@value="1"]
  149. '
  150. );
  151. }
  152. public function testCheckedCheckboxWithValue()
  153. {
  154. $form = $this->factory->create('checkbox', 'na&me', array(
  155. 'property_path' => 'name',
  156. 'value' => 'foo&bar',
  157. 'data' => true,
  158. ));
  159. $this->assertWidgetMatchesXpath($form->createView(), array(),
  160. '/input
  161. [@type="checkbox"]
  162. [@name="na&me"]
  163. [@checked="checked"]
  164. [@value="foo&bar"]
  165. '
  166. );
  167. }
  168. public function testUncheckedCheckbox()
  169. {
  170. $form = $this->factory->create('checkbox', 'na&me', array(
  171. 'property_path' => 'name',
  172. 'data' => false,
  173. ));
  174. $this->assertWidgetMatchesXpath($form->createView(), array(),
  175. '/input
  176. [@type="checkbox"]
  177. [@name="na&me"]
  178. [not(@checked)]
  179. '
  180. );
  181. }
  182. public function testSingleChoice()
  183. {
  184. $form = $this->factory->create('choice', 'na&me', array(
  185. 'property_path' => 'name',
  186. 'choices' => array('a' => 'A', 'b' => 'B'),
  187. 'data' => 'a',
  188. 'multiple' => false,
  189. 'expanded' => false,
  190. ));
  191. $this->assertWidgetMatchesXpath($form->createView(), array(),
  192. '/select
  193. [@name="na&me"]
  194. [
  195. ./option[@value="a"][@selected="selected"][.="A"]
  196. /following-sibling::option[@value="b"][not(@selected)][.="B"]
  197. ]
  198. [count(./option)=2]
  199. '
  200. );
  201. }
  202. public function testSingleChoiceWithPreferred()
  203. {
  204. $form = $this->factory->create('choice', 'na&me', array(
  205. 'property_path' => 'name',
  206. 'choices' => array('a' => 'A', 'b' => 'B'),
  207. 'preferred_choices' => array('b'),
  208. 'data' => 'a',
  209. 'multiple' => false,
  210. 'expanded' => false,
  211. ));
  212. $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '-- sep --'),
  213. '/select
  214. [@name="na&me"]
  215. [
  216. ./option[@value="b"][not(@selected)][.="B"]
  217. /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"]
  218. /following-sibling::option[@value="a"][@selected="selected"][.="A"]
  219. ]
  220. [count(./option)=3]
  221. '
  222. );
  223. }
  224. public function testSingleChoiceNonRequired()
  225. {
  226. $form = $this->factory->create('choice', 'na&me', array(
  227. 'property_path' => 'name',
  228. 'choices' => array('a' => 'A', 'b' => 'B'),
  229. 'required' => false,
  230. 'data' => 'a',
  231. 'multiple' => false,
  232. 'expanded' => false,
  233. ));
  234. $this->assertWidgetMatchesXpath($form->createView(), array(),
  235. '/select
  236. [@name="na&me"]
  237. [
  238. ./option[@value=""][.=""]
  239. /following-sibling::option[@value="a"][@selected="selected"][.="A"]
  240. /following-sibling::option[@value="b"][not(@selected)][.="B"]
  241. ]
  242. [count(./option)=3]
  243. '
  244. );
  245. }
  246. public function testSingleChoiceGrouped()
  247. {
  248. $form = $this->factory->create('choice', 'na&me', array(
  249. 'property_path' => 'name',
  250. 'choices' => array(
  251. 'Group1' => array('a' => 'A', 'b' => 'B'),
  252. 'Group2' => array('c' => 'C'),
  253. ),
  254. 'data' => 'a',
  255. 'multiple' => false,
  256. 'expanded' => false,
  257. ));
  258. $this->assertWidgetMatchesXpath($form->createView(), array(),
  259. '/select
  260. [@name="na&me"]
  261. [./optgroup[@label="Group1"]
  262. [
  263. ./option[@value="a"][@selected="selected"][.="A"]
  264. /following-sibling::option[@value="b"][not(@selected)][.="B"]
  265. ]
  266. [count(./option)=2]
  267. ]
  268. [./optgroup[@label="Group2"]
  269. [./option[@value="c"][not(@selected)][.="C"]]
  270. [count(./option)=1]
  271. ]
  272. [count(./optgroup)=2]
  273. '
  274. );
  275. }
  276. public function testMultipleChoice()
  277. {
  278. $form = $this->factory->create('choice', 'na&me', array(
  279. 'property_path' => 'name',
  280. 'choices' => array('a' => 'A', 'b' => 'B'),
  281. 'data' => array('a'),
  282. 'multiple' => true,
  283. 'expanded' => false,
  284. ));
  285. $this->assertWidgetMatchesXpath($form->createView(), array(),
  286. '/select
  287. [@name="na&me[]"]
  288. [@multiple="multiple"]
  289. [
  290. ./option[@value="a"][@selected="selected"][.="A"]
  291. /following-sibling::option[@value="b"][not(@selected)][.="B"]
  292. ]
  293. [count(./option)=2]
  294. '
  295. );
  296. }
  297. public function testMultipleChoiceNonRequired()
  298. {
  299. $form = $this->factory->create('choice', 'na&me', array(
  300. 'property_path' => 'name',
  301. 'choices' => array('a' => 'A', 'b' => 'B'),
  302. 'data' => array('a'),
  303. 'required' => false,
  304. 'multiple' => true,
  305. 'expanded' => false,
  306. ));
  307. $this->assertWidgetMatchesXpath($form->createView(), array(),
  308. '/select
  309. [@name="na&me[]"]
  310. [@multiple="multiple"]
  311. [
  312. ./option[@value="a"][@selected="selected"][.="A"]
  313. /following-sibling::option[@value="b"][not(@selected)][.="B"]
  314. ]
  315. [count(./option)=2]
  316. '
  317. );
  318. }
  319. public function testSingleChoiceExpanded()
  320. {
  321. $form = $this->factory->create('choice', 'na&me', array(
  322. 'property_path' => 'name',
  323. 'choices' => array('a' => 'A', 'b' => 'B'),
  324. 'data' => 'a',
  325. 'multiple' => false,
  326. 'expanded' => true,
  327. ));
  328. $this->assertWidgetMatchesXpath($form->createView(), array(),
  329. '/div
  330. [
  331. ./input[@type="radio"][@name="na&me"][@id="na&me_a"][@checked]
  332. /following-sibling::label[@for="na&me_a"][.="[trans]A[/trans]"]
  333. /following-sibling::input[@type="radio"][@name="na&me"][@id="na&me_b"][not(@checked)]
  334. /following-sibling::label[@for="na&me_b"][.="[trans]B[/trans]"]
  335. ]
  336. [count(./input)=2]
  337. '
  338. );
  339. }
  340. public function testMultipleChoiceExpanded()
  341. {
  342. $form = $this->factory->create('choice', 'na&me', array(
  343. 'property_path' => 'name',
  344. 'choices' => array('a' => 'A', 'b' => 'B', 'c' => 'C'),
  345. 'data' => array('a', 'c'),
  346. 'multiple' => true,
  347. 'expanded' => true,
  348. ));
  349. $this->assertWidgetMatchesXpath($form->createView(), array(),
  350. '/div
  351. [
  352. ./input[@type="checkbox"][@name="na&me[a]"][@id="na&me_a"][@checked]
  353. /following-sibling::label[@for="na&me_a"][.="[trans]A[/trans]"]
  354. /following-sibling::input[@type="checkbox"][@name="na&me[b]"][@id="na&me_b"][not(@checked)]
  355. /following-sibling::label[@for="na&me_b"][.="[trans]B[/trans]"]
  356. /following-sibling::input[@type="checkbox"][@name="na&me[c]"][@id="na&me_c"][@checked]
  357. /following-sibling::label[@for="na&me_c"][.="[trans]C[/trans]"]
  358. ]
  359. [count(./input)=3]
  360. '
  361. );
  362. }
  363. public function testCountry()
  364. {
  365. $form = $this->factory->create('country', 'na&me', array(
  366. 'property_path' => 'name',
  367. 'data' => 'AT',
  368. ));
  369. $this->assertWidgetMatchesXpath($form->createView(), array(),
  370. '/select
  371. [@name="na&me"]
  372. [./option[@value="AT"][@selected="selected"][.="Austria"]]
  373. [count(./option)>200]
  374. '
  375. );
  376. }
  377. public function testCsrf()
  378. {
  379. $this->csrfProvider->expects($this->any())
  380. ->method('generateCsrfToken')
  381. ->will($this->returnValue('foo&bar'));
  382. $form = $this->factory->create('csrf', 'na&me', array('property_path' => 'name'));
  383. $this->assertWidgetMatchesXpath($form->createView(), array(),
  384. '/input
  385. [@type="hidden"]
  386. [@value="foo&bar"]
  387. '
  388. );
  389. }
  390. public function testCsrfWithNonRootParent()
  391. {
  392. $form = $this->factory->create('csrf', 'na&me', array('property_path' => 'name'));
  393. $form->setParent($this->factory->create('form'));
  394. $form->getParent()->setParent($this->factory->create('form'));
  395. $html = $this->renderWidget($form->createView());
  396. $this->assertEquals('', trim($html));
  397. }
  398. public function testDateTime()
  399. {
  400. $form = $this->factory->create('datetime', 'na&me', array(
  401. 'property_path' => 'name',
  402. 'data' => '2011-02-03 04:05:06',
  403. 'input' => 'string',
  404. 'with_seconds' => false,
  405. ));
  406. $this->assertWidgetMatchesXpath($form->createView(), array(),
  407. '/div
  408. [
  409. ./div
  410. [@id="na&me_date"]
  411. [
  412. ./select
  413. [@id="na&me_date_month"]
  414. [./option[@value="2"][@selected="selected"]]
  415. /following-sibling::select
  416. [@id="na&me_date_day"]
  417. [./option[@value="3"][@selected="selected"]]
  418. /following-sibling::select
  419. [@id="na&me_date_year"]
  420. [./option[@value="2011"][@selected="selected"]]
  421. ]
  422. /following-sibling::div
  423. [@id="na&me_time"]
  424. [
  425. ./select
  426. [@id="na&me_time_hour"]
  427. [./option[@value="4"][@selected="selected"]]
  428. /following-sibling::select
  429. [@id="na&me_time_minute"]
  430. [./option[@value="5"][@selected="selected"]]
  431. ]
  432. ]
  433. [count(.//select)=5]
  434. '
  435. );
  436. }
  437. public function testDateTimeWithSeconds()
  438. {
  439. $form = $this->factory->create('datetime', 'na&me', array(
  440. 'property_path' => 'name',
  441. 'data' => '2011-02-03 04:05:06',
  442. 'input' => 'string',
  443. 'with_seconds' => true,
  444. ));
  445. $this->assertWidgetMatchesXpath($form->createView(), array(),
  446. '/div
  447. [
  448. ./div
  449. [@id="na&me_date"]
  450. [
  451. ./select
  452. [@id="na&me_date_month"]
  453. [./option[@value="2"][@selected="selected"]]
  454. /following-sibling::select
  455. [@id="na&me_date_day"]
  456. [./option[@value="3"][@selected="selected"]]
  457. /following-sibling::select
  458. [@id="na&me_date_year"]
  459. [./option[@value="2011"][@selected="selected"]]
  460. ]
  461. /following-sibling::div
  462. [@id="na&me_time"]
  463. [
  464. ./select
  465. [@id="na&me_time_hour"]
  466. [./option[@value="4"][@selected="selected"]]
  467. /following-sibling::select
  468. [@id="na&me_time_minute"]
  469. [./option[@value="5"][@selected="selected"]]
  470. /following-sibling::select
  471. [@id="na&me_time_second"]
  472. [./option[@value="6"][@selected="selected"]]
  473. ]
  474. ]
  475. [count(.//select)=6]
  476. '
  477. );
  478. }
  479. public function testDateChoice()
  480. {
  481. $form = $this->factory->create('date', 'na&me', array(
  482. 'property_path' => 'name',
  483. 'data' => '2011-02-03',
  484. 'input' => 'string',
  485. 'widget' => 'choice',
  486. ));
  487. $this->assertWidgetMatchesXpath($form->createView(), array(),
  488. '/div
  489. [
  490. ./select
  491. [@id="na&me_month"]
  492. [./option[@value="2"][@selected="selected"]]
  493. /following-sibling::select
  494. [@id="na&me_day"]
  495. [./option[@value="3"][@selected="selected"]]
  496. /following-sibling::select
  497. [@id="na&me_year"]
  498. [./option[@value="2011"][@selected="selected"]]
  499. ]
  500. [count(./select)=3]
  501. '
  502. );
  503. }
  504. public function testDateText()
  505. {
  506. $form = $this->factory->create('date', 'na&me', array(
  507. 'property_path' => 'name',
  508. 'data' => '2011-02-03',
  509. 'input' => 'string',
  510. 'widget' => 'text',
  511. ));
  512. $this->assertWidgetMatchesXpath($form->createView(), array(),
  513. '/input
  514. [@type="text"]
  515. [@name="na&me"]
  516. [@value="Feb 3, 2011"]
  517. '
  518. );
  519. }
  520. public function testFile()
  521. {
  522. $form = $this->factory->create('file', 'na&me', array('property_path' => 'name'));
  523. $this->assertWidgetMatchesXpath($form->createView(), array(),
  524. '/div
  525. [
  526. ./input[@type="file"][@id="na&me_file"]
  527. /following-sibling::input[@type="hidden"][@id="na&me_token"]
  528. /following-sibling::input[@type="hidden"][@id="na&me_name"]
  529. ]
  530. [count(./input)=3]
  531. '
  532. );
  533. }
  534. public function testHidden()
  535. {
  536. $form = $this->factory->create('hidden', 'na&me', array(
  537. 'property_path' => 'name',
  538. 'data' => 'foo&bar',
  539. ));
  540. $this->assertWidgetMatchesXpath($form->createView(), array(),
  541. '/input
  542. [@type="hidden"]
  543. [@name="na&me"]
  544. [@value="foo&bar"]
  545. '
  546. );
  547. }
  548. public function testInteger()
  549. {
  550. $form = $this->factory->create('integer', 'na&me', array(
  551. 'property_path' => 'name',
  552. 'data' => '123',
  553. ));
  554. $this->assertWidgetMatchesXpath($form->createView(), array(),
  555. '/input
  556. [@type="number"]
  557. [@name="na&me"]
  558. [@value="123"]
  559. '
  560. );
  561. }
  562. public function testLanguage()
  563. {
  564. $form = $this->factory->create('language', 'na&me', array(
  565. 'property_path' => 'name',
  566. 'data' => 'de',
  567. ));
  568. $this->assertWidgetMatchesXpath($form->createView(), array(),
  569. '/select
  570. [@name="na&me"]
  571. [./option[@value="de"][@selected="selected"][.="German"]]
  572. [count(./option)>200]
  573. '
  574. );
  575. }
  576. public function testLocale()
  577. {
  578. $form = $this->factory->create('locale', 'na&me', array(
  579. 'property_path' => 'name',
  580. 'data' => 'de_AT',
  581. ));
  582. $this->assertWidgetMatchesXpath($form->createView(), array(),
  583. '/select
  584. [@name="na&me"]
  585. [./option[@value="de_AT"][@selected="selected"][.="German (Austria)"]]
  586. [count(./option)>200]
  587. '
  588. );
  589. }
  590. public function testMoney()
  591. {
  592. $form = $this->factory->create('money', 'na&me', array(
  593. 'property_path' => 'name',
  594. 'data' => 1234.56,
  595. 'currency' => 'EUR',
  596. ));
  597. $this->assertWidgetMatchesXpath($form->createView(), array(),
  598. '/input
  599. [@type="text"]
  600. [@name="na&me"]
  601. [@value="1234.56"]
  602. [contains(.., "€")]
  603. '
  604. );
  605. }
  606. public function testNumber()
  607. {
  608. $form = $this->factory->create('number', 'na&me', array(
  609. 'property_path' => 'name',
  610. 'data' => 1234.56,
  611. ));
  612. $this->assertWidgetMatchesXpath($form->createView(), array(),
  613. '/input
  614. [@type="text"]
  615. [@name="na&me"]
  616. [@value="1234.56"]
  617. '
  618. );
  619. }
  620. public function testPassword()
  621. {
  622. $form = $this->factory->create('password', 'na&me', array(
  623. 'property_path' => 'name',
  624. 'data' => 'foo&bar',
  625. ));
  626. $this->assertWidgetMatchesXpath($form->createView(), array(),
  627. '/input
  628. [@type="password"]
  629. [@name="na&me"]
  630. [@value=""]
  631. '
  632. );
  633. }
  634. public function testPasswordBoundNotAlwaysEmpty()
  635. {
  636. $form = $this->factory->create('password', 'na&me', array(
  637. 'property_path' => 'name',
  638. 'always_empty' => false,
  639. ));
  640. $form->bind('foo&bar');
  641. $this->assertWidgetMatchesXpath($form->createView(), array(),
  642. '/input
  643. [@type="password"]
  644. [@name="na&me"]
  645. [@value="foo&bar"]
  646. '
  647. );
  648. }
  649. public function testPasswordWithMaxLength()
  650. {
  651. $form = $this->factory->create('password', 'na&me', array(
  652. 'property_path' => 'name',
  653. 'data' => 'foo&bar',
  654. 'max_length' => 123,
  655. ));
  656. $this->assertWidgetMatchesXpath($form->createView(), array(),
  657. '/input
  658. [@type="password"]
  659. [@name="na&me"]
  660. [@value=""]
  661. [@maxlength="123"]
  662. '
  663. );
  664. }
  665. public function testPercent()
  666. {
  667. $form = $this->factory->create('percent', 'na&me', array(
  668. 'property_path' => 'name',
  669. 'data' => 0.1,
  670. ));
  671. $this->assertWidgetMatchesXpath($form->createView(), array(),
  672. '/input
  673. [@type="text"]
  674. [@name="na&me"]
  675. [@value="10"]
  676. [contains(.., "%")]
  677. '
  678. );
  679. }
  680. public function testCheckedRadio()
  681. {
  682. $form = $this->factory->create('radio', 'na&me', array(
  683. 'property_path' => 'name',
  684. 'data' => true,
  685. ));
  686. $this->assertWidgetMatchesXpath($form->createView(), array(),
  687. '/input
  688. [@type="radio"]
  689. [@name="na&me"]
  690. [@checked="checked"]
  691. [@value=""]
  692. '
  693. );
  694. }
  695. public function testCheckedRadioWithValue()
  696. {
  697. $form = $this->factory->create('radio', 'na&me', array(
  698. 'property_path' => 'name',
  699. 'data' => true,
  700. 'value' => 'foo&bar',
  701. ));
  702. $this->assertWidgetMatchesXpath($form->createView(), array(),
  703. '/input
  704. [@type="radio"]
  705. [@name="na&me"]
  706. [@checked="checked"]
  707. [@value="foo&bar"]
  708. '
  709. );
  710. }
  711. public function testUncheckedRadio()
  712. {
  713. $form = $this->factory->create('radio', 'na&me', array(
  714. 'property_path' => 'name',
  715. 'data' => false,
  716. ));
  717. $this->assertWidgetMatchesXpath($form->createView(), array(),
  718. '/input
  719. [@type="radio"]
  720. [@name="na&me"]
  721. [not(@checked)]
  722. '
  723. );
  724. }
  725. public function testTextarea()
  726. {
  727. $form = $this->factory->create('textarea', 'na&me', array(
  728. 'property_path' => 'name',
  729. 'data' => 'foo&bar',
  730. ));
  731. $this->assertWidgetMatchesXpath($form->createView(), array(),
  732. '/textarea
  733. [@name="na&me"]
  734. [.="foo&bar"]
  735. '
  736. );
  737. }
  738. public function testText()
  739. {
  740. $form = $this->factory->create('text', 'na&me', array(
  741. 'property_path' => 'name',
  742. 'data' => 'foo&bar',
  743. ));
  744. $this->assertWidgetMatchesXpath($form->createView(), array(),
  745. '/input
  746. [@type="text"]
  747. [@name="na&me"]
  748. [@value="foo&bar"]
  749. [not(@maxlength)]
  750. '
  751. );
  752. }
  753. public function testTextWithMaxLength()
  754. {
  755. $form = $this->factory->create('text', 'na&me', array(
  756. 'property_path' => 'name',
  757. 'data' => 'foo&bar',
  758. 'max_length' => 123,
  759. ));
  760. $this->assertWidgetMatchesXpath($form->createView(), array(),
  761. '/input
  762. [@type="text"]
  763. [@name="na&me"]
  764. [@value="foo&bar"]
  765. [@maxlength="123"]
  766. '
  767. );
  768. }
  769. public function testTime()
  770. {
  771. $form = $this->factory->create('time', 'na&me', array(
  772. 'property_path' => 'name',
  773. 'data' => '04:05:06',
  774. 'input' => 'string',
  775. 'with_seconds' => false,
  776. ));
  777. $this->assertWidgetMatchesXpath($form->createView(), array(),
  778. '/div
  779. [
  780. ./select
  781. [@id="na&me_hour"]
  782. [@size="1"]
  783. [./option[@value="4"][@selected="selected"]]
  784. /following-sibling::select
  785. [@id="na&me_minute"]
  786. [@size="1"]
  787. [./option[@value="5"][@selected="selected"]]
  788. ]
  789. [count(./select)=2]
  790. '
  791. );
  792. }
  793. public function testTimeWithSeconds()
  794. {
  795. $form = $this->factory->create('time', 'na&me', array(
  796. 'property_path' => 'name',
  797. 'data' => '04:05:06',
  798. 'input' => 'string',
  799. 'with_seconds' => true,
  800. ));
  801. $this->assertWidgetMatchesXpath($form->createView(), array(),
  802. '/div
  803. [
  804. ./select
  805. [@id="na&me_hour"]
  806. [@size="1"]
  807. [./option[@value="4"][@selected="selected"]]
  808. /following-sibling::select
  809. [@id="na&me_minute"]
  810. [@size="1"]
  811. [./option[@value="5"][@selected="selected"]]
  812. /following-sibling::select
  813. [@id="na&me_second"]
  814. [@size="1"]
  815. [./option[@value="6"][@selected="selected"]]
  816. ]
  817. [count(./select)=3]
  818. '
  819. );
  820. }
  821. public function testTimezone()
  822. {
  823. $form = $this->factory->create('timezone', 'na&me', array(
  824. 'property_path' => 'name',
  825. 'data' => 'Europe/Vienna',
  826. ));
  827. $this->assertWidgetMatchesXpath($form->createView(), array(),
  828. '/select
  829. [@name="na&me"]
  830. [./optgroup
  831. [@label="Europe"]
  832. [./option[@value="Europe/Vienna"][@selected="selected"][.="Vienna"]]
  833. ]
  834. [count(./optgroup)>10]
  835. [count(.//option)>200]
  836. '
  837. );
  838. }
  839. public function testUrl()
  840. {
  841. $form = $this->factory->create('url', 'na&me', array(
  842. 'property_path' => 'name',
  843. 'data' => 'http://www.google.com?foo1=bar1&foo2=bar2',
  844. ));
  845. $this->assertWidgetMatchesXpath($form->createView(), array(),
  846. '/input
  847. [@type="url"]
  848. [@name="na&me"]
  849. [@value="http://www.google.com?foo1=bar1&foo2=bar2"]
  850. '
  851. );
  852. }
  853. }