AbstractLayoutTest.php 23 KB

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