]>
Commit | Line | Data |
---|---|---|
4f5b44bd NL |
1 | <?php |
2 | ||
3 | /* | |
4 | * This file is part of the Symfony package. | |
5 | * | |
6 | * (c) Fabien Potencier <fabien@symfony.com> | |
7 | * | |
8 | * For the full copyright and license information, please view the LICENSE | |
9 | * file that was distributed with this source code. | |
10 | */ | |
11 | ||
12 | namespace Symfony\Component\Form\Tests; | |
13 | ||
14 | use Symfony\Component\Form\FormError; | |
15 | use Symfony\Component\Form\Tests\Fixtures\AlternatingRowType; | |
16 | ||
17 | abstract class AbstractDivLayoutTest extends AbstractLayoutTest | |
18 | { | |
19 | public function testRow() | |
20 | { | |
21 | $form = $this->factory->createNamed('name', 'text'); | |
22 | $form->addError(new FormError('[trans]Error![/trans]')); | |
23 | $view = $form->createView(); | |
24 | $html = $this->renderRow($view); | |
25 | ||
26 | $this->assertMatchesXpath($html, | |
27 | '/div | |
28 | [ | |
29 | ./label[@for="name"] | |
30 | /following-sibling::ul | |
31 | [./li[.="[trans]Error![/trans]"]] | |
32 | [count(./li)=1] | |
33 | /following-sibling::input[@id="name"] | |
34 | ] | |
35 | ' | |
36 | ); | |
37 | } | |
38 | ||
39 | public function testRowOverrideVariables() | |
40 | { | |
41 | $view = $this->factory->createNamed('name', 'text')->createView(); | |
42 | $html = $this->renderRow($view, array( | |
43 | 'attr' => array('class' => 'my&class'), | |
44 | 'label' => 'foo&bar', | |
45 | 'label_attr' => array('class' => 'my&label&class'), | |
46 | )); | |
47 | ||
48 | $this->assertMatchesXpath($html, | |
49 | '/div | |
50 | [ | |
51 | ./label[@for="name"][@class="my&label&class required"][.="[trans]foo&bar[/trans]"] | |
52 | /following-sibling::input[@id="name"][@class="my&class"] | |
53 | ] | |
54 | ' | |
55 | ); | |
56 | } | |
57 | ||
58 | public function testRepeatedRow() | |
59 | { | |
60 | $form = $this->factory->createNamed('name', 'repeated'); | |
61 | $form->addError(new FormError('[trans]Error![/trans]')); | |
62 | $view = $form->createView(); | |
63 | $html = $this->renderRow($view); | |
64 | ||
65 | // The errors of the form are not rendered by intention! | |
66 | // In practice, repeated fields cannot have errors as all errors | |
67 | // on them are mapped to the first child. | |
68 | // (see RepeatedTypeValidatorExtension) | |
69 | ||
70 | $this->assertMatchesXpath($html, | |
71 | '/div | |
72 | [ | |
73 | ./label[@for="name_first"] | |
74 | /following-sibling::input[@id="name_first"] | |
75 | ] | |
76 | /following-sibling::div | |
77 | [ | |
78 | ./label[@for="name_second"] | |
79 | /following-sibling::input[@id="name_second"] | |
80 | ] | |
81 | ' | |
82 | ); | |
83 | } | |
84 | ||
85 | public function testButtonRow() | |
86 | { | |
87 | $form = $this->factory->createNamed('name', 'button'); | |
88 | $view = $form->createView(); | |
89 | $html = $this->renderRow($view); | |
90 | ||
91 | $this->assertMatchesXpath($html, | |
92 | '/div | |
93 | [ | |
94 | ./button[@type="button"][@name="name"] | |
95 | ] | |
96 | [count(//label)=0] | |
97 | ' | |
98 | ); | |
99 | } | |
100 | ||
101 | public function testRest() | |
102 | { | |
103 | $view = $this->factory->createNamedBuilder('name', 'form') | |
104 | ->add('field1', 'text') | |
105 | ->add('field2', 'repeated') | |
106 | ->add('field3', 'text') | |
107 | ->add('field4', 'text') | |
108 | ->getForm() | |
109 | ->createView(); | |
110 | ||
111 | // Render field2 row -> does not implicitly call renderWidget because | |
112 | // it is a repeated field! | |
113 | $this->renderRow($view['field2']); | |
114 | ||
115 | // Render field3 widget | |
116 | $this->renderWidget($view['field3']); | |
117 | ||
118 | // Rest should only contain field1 and field4 | |
119 | $html = $this->renderRest($view); | |
120 | ||
121 | $this->assertMatchesXpath($html, | |
122 | '/div | |
123 | [ | |
124 | ./label[@for="name_field1"] | |
125 | /following-sibling::input[@type="text"][@id="name_field1"] | |
126 | ] | |
127 | /following-sibling::div | |
128 | [ | |
129 | ./label[@for="name_field4"] | |
130 | /following-sibling::input[@type="text"][@id="name_field4"] | |
131 | ] | |
132 | [count(../div)=2] | |
133 | [count(..//label)=2] | |
134 | [count(..//input)=3] | |
135 | /following-sibling::input | |
136 | [@type="hidden"] | |
137 | [@id="name__token"] | |
138 | ' | |
139 | ); | |
140 | } | |
141 | ||
142 | public function testRestWithChildrenForms() | |
143 | { | |
144 | $child1 = $this->factory->createNamedBuilder('child1', 'form') | |
145 | ->add('field1', 'text') | |
146 | ->add('field2', 'text'); | |
147 | ||
148 | $child2 = $this->factory->createNamedBuilder('child2', 'form') | |
149 | ->add('field1', 'text') | |
150 | ->add('field2', 'text'); | |
151 | ||
152 | $view = $this->factory->createNamedBuilder('parent', 'form') | |
153 | ->add($child1) | |
154 | ->add($child2) | |
155 | ->getForm() | |
156 | ->createView(); | |
157 | ||
158 | // Render child1.field1 row | |
159 | $this->renderRow($view['child1']['field1']); | |
160 | ||
161 | // Render child2.field2 widget (remember that widget don't render label) | |
162 | $this->renderWidget($view['child2']['field2']); | |
163 | ||
164 | // Rest should only contain child1.field2 and child2.field1 | |
165 | $html = $this->renderRest($view); | |
166 | ||
167 | $this->assertMatchesXpath($html, | |
168 | '/div | |
169 | [ | |
170 | ./label[not(@for)] | |
171 | /following-sibling::div[@id="parent_child1"] | |
172 | [ | |
173 | ./div | |
174 | [ | |
175 | ./label[@for="parent_child1_field2"] | |
176 | /following-sibling::input[@id="parent_child1_field2"] | |
177 | ] | |
178 | ] | |
179 | ] | |
180 | ||
181 | /following-sibling::div | |
182 | [ | |
183 | ./label[not(@for)] | |
184 | /following-sibling::div[@id="parent_child2"] | |
185 | [ | |
186 | ./div | |
187 | [ | |
188 | ./label[@for="parent_child2_field1"] | |
189 | /following-sibling::input[@id="parent_child2_field1"] | |
190 | ] | |
191 | ] | |
192 | ] | |
193 | [count(//label)=4] | |
194 | [count(//input[@type="text"])=2] | |
195 | /following-sibling::input[@type="hidden"][@id="parent__token"] | |
196 | ' | |
197 | ); | |
198 | } | |
199 | ||
200 | public function testRestAndRepeatedWithRow() | |
201 | { | |
202 | $view = $this->factory->createNamedBuilder('name', 'form') | |
203 | ->add('first', 'text') | |
204 | ->add('password', 'repeated') | |
205 | ->getForm() | |
206 | ->createView(); | |
207 | ||
208 | $this->renderRow($view['password']); | |
209 | ||
210 | $html = $this->renderRest($view); | |
211 | ||
212 | $this->assertMatchesXpath($html, | |
213 | '/div | |
214 | [ | |
215 | ./label[@for="name_first"] | |
216 | /following-sibling::input[@type="text"][@id="name_first"] | |
217 | ] | |
218 | [count(.//input)=1] | |
219 | /following-sibling::input | |
220 | [@type="hidden"] | |
221 | [@id="name__token"] | |
222 | ' | |
223 | ); | |
224 | } | |
225 | ||
226 | public function testRestAndRepeatedWithRowPerChild() | |
227 | { | |
228 | $view = $this->factory->createNamedBuilder('name', 'form') | |
229 | ->add('first', 'text') | |
230 | ->add('password', 'repeated') | |
231 | ->getForm() | |
232 | ->createView(); | |
233 | ||
234 | $this->renderRow($view['password']['first']); | |
235 | $this->renderRow($view['password']['second']); | |
236 | ||
237 | $html = $this->renderRest($view); | |
238 | ||
239 | $this->assertMatchesXpath($html, | |
240 | '/div | |
241 | [ | |
242 | ./label[@for="name_first"] | |
243 | /following-sibling::input[@type="text"][@id="name_first"] | |
244 | ] | |
245 | [count(.//input)=1] | |
246 | [count(.//label)=1] | |
247 | /following-sibling::input | |
248 | [@type="hidden"] | |
249 | [@id="name__token"] | |
250 | ' | |
251 | ); | |
252 | } | |
253 | ||
254 | public function testRestAndRepeatedWithWidgetPerChild() | |
255 | { | |
256 | $view = $this->factory->createNamedBuilder('name', 'form') | |
257 | ->add('first', 'text') | |
258 | ->add('password', 'repeated') | |
259 | ->getForm() | |
260 | ->createView(); | |
261 | ||
262 | // The password form is considered as rendered as all its children | |
263 | // are rendered | |
264 | $this->renderWidget($view['password']['first']); | |
265 | $this->renderWidget($view['password']['second']); | |
266 | ||
267 | $html = $this->renderRest($view); | |
268 | ||
269 | $this->assertMatchesXpath($html, | |
270 | '/div | |
271 | [ | |
272 | ./label[@for="name_first"] | |
273 | /following-sibling::input[@type="text"][@id="name_first"] | |
274 | ] | |
275 | [count(//input)=2] | |
276 | [count(//label)=1] | |
277 | /following-sibling::input | |
278 | [@type="hidden"] | |
279 | [@id="name__token"] | |
280 | ' | |
281 | ); | |
282 | } | |
283 | ||
284 | public function testCollection() | |
285 | { | |
286 | $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( | |
287 | 'type' => 'text', | |
288 | )); | |
289 | ||
290 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
291 | '/div | |
292 | [ | |
293 | ./div[./input[@type="text"][@value="a"]] | |
294 | /following-sibling::div[./input[@type="text"][@value="b"]] | |
295 | ] | |
296 | [count(./div[./input])=2] | |
297 | ' | |
298 | ); | |
299 | } | |
300 | ||
301 | // https://github.com/symfony/symfony/issues/5038 | |
302 | public function testCollectionWithAlternatingRowTypes() | |
303 | { | |
304 | $data = array( | |
305 | array('title' => 'a'), | |
306 | array('title' => 'b'), | |
307 | ); | |
308 | $form = $this->factory->createNamed('name', 'collection', $data, array( | |
309 | 'type' => new AlternatingRowType(), | |
310 | )); | |
311 | ||
312 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
313 | '/div | |
314 | [ | |
315 | ./div[./div/div/input[@type="text"][@value="a"]] | |
316 | /following-sibling::div[./div/div/textarea[.="b"]] | |
317 | ] | |
318 | [count(./div[./div/div/input])=1] | |
319 | [count(./div[./div/div/textarea])=1] | |
320 | ' | |
321 | ); | |
322 | } | |
323 | ||
324 | public function testEmptyCollection() | |
325 | { | |
326 | $form = $this->factory->createNamed('name', 'collection', array(), array( | |
327 | 'type' => 'text', | |
328 | )); | |
329 | ||
330 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
331 | '/div | |
332 | [./input[@type="hidden"][@id="name__token"]] | |
333 | [count(./div)=0] | |
334 | ' | |
335 | ); | |
336 | } | |
337 | ||
338 | public function testCollectionRow() | |
339 | { | |
340 | $collection = $this->factory->createNamedBuilder( | |
341 | 'collection', | |
342 | 'collection', | |
343 | array('a', 'b'), | |
344 | array('type' => 'text') | |
345 | ); | |
346 | ||
347 | $form = $this->factory->createNamedBuilder('form', 'form') | |
348 | ->add($collection) | |
349 | ->getForm(); | |
350 | ||
351 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
352 | '/div | |
353 | [ | |
354 | ./div | |
355 | [ | |
356 | ./label[not(@for)] | |
357 | /following-sibling::div | |
358 | [ | |
359 | ./div | |
360 | [ | |
361 | ./label[@for="form_collection_0"] | |
362 | /following-sibling::input[@type="text"][@value="a"] | |
363 | ] | |
364 | /following-sibling::div | |
365 | [ | |
366 | ./label[@for="form_collection_1"] | |
367 | /following-sibling::input[@type="text"][@value="b"] | |
368 | ] | |
369 | ] | |
370 | ] | |
371 | /following-sibling::input[@type="hidden"][@id="form__token"] | |
372 | ] | |
373 | [count(.//input)=3] | |
374 | ' | |
375 | ); | |
376 | } | |
377 | ||
378 | public function testForm() | |
379 | { | |
380 | $form = $this->factory->createNamedBuilder('name', 'form') | |
381 | ->setMethod('PUT') | |
382 | ->setAction('http://example.com') | |
383 | ->add('firstName', 'text') | |
384 | ->add('lastName', 'text') | |
385 | ->getForm(); | |
386 | ||
387 | // include ampersands everywhere to validate escaping | |
388 | $html = $this->renderForm($form->createView(), array( | |
389 | 'id' => 'my&id', | |
390 | 'attr' => array('class' => 'my&class'), | |
391 | )); | |
392 | ||
393 | $this->assertMatchesXpath($html, | |
394 | '/form | |
395 | [ | |
396 | ./input[@type="hidden"][@name="_method"][@value="PUT"] | |
397 | /following-sibling::div | |
398 | [ | |
399 | ./div | |
400 | [ | |
401 | ./label[@for="name_firstName"] | |
402 | /following-sibling::input[@type="text"][@id="name_firstName"] | |
403 | ] | |
404 | /following-sibling::div | |
405 | [ | |
406 | ./label[@for="name_lastName"] | |
407 | /following-sibling::input[@type="text"][@id="name_lastName"] | |
408 | ] | |
409 | /following-sibling::input[@type="hidden"][@id="name__token"] | |
410 | ] | |
411 | [count(.//input)=3] | |
412 | [@id="my&id"] | |
413 | [@class="my&class"] | |
414 | ] | |
415 | [@method="post"] | |
416 | [@action="http://example.com"] | |
417 | [@class="my&class"] | |
418 | ' | |
419 | ); | |
420 | } | |
421 | ||
422 | public function testFormWidget() | |
423 | { | |
424 | $form = $this->factory->createNamedBuilder('name', 'form') | |
425 | ->add('firstName', 'text') | |
426 | ->add('lastName', 'text') | |
427 | ->getForm(); | |
428 | ||
429 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
430 | '/div | |
431 | [ | |
432 | ./div | |
433 | [ | |
434 | ./label[@for="name_firstName"] | |
435 | /following-sibling::input[@type="text"][@id="name_firstName"] | |
436 | ] | |
437 | /following-sibling::div | |
438 | [ | |
439 | ./label[@for="name_lastName"] | |
440 | /following-sibling::input[@type="text"][@id="name_lastName"] | |
441 | ] | |
442 | /following-sibling::input[@type="hidden"][@id="name__token"] | |
443 | ] | |
444 | [count(.//input)=3] | |
445 | ' | |
446 | ); | |
447 | } | |
448 | ||
449 | // https://github.com/symfony/symfony/issues/2308 | |
450 | public function testNestedFormError() | |
451 | { | |
452 | $form = $this->factory->createNamedBuilder('name', 'form') | |
453 | ->add($this->factory | |
454 | ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false)) | |
455 | ->add('grandChild', 'form') | |
456 | ) | |
457 | ->getForm(); | |
458 | ||
459 | $form->get('child')->addError(new FormError('[trans]Error![/trans]')); | |
460 | ||
461 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
462 | '/div | |
463 | [ | |
464 | ./div/label | |
465 | /following-sibling::ul[./li[.="[trans]Error![/trans]"]] | |
466 | ] | |
467 | [count(.//li[.="[trans]Error![/trans]"])=1] | |
468 | ' | |
469 | ); | |
470 | } | |
471 | ||
472 | public function testCsrf() | |
473 | { | |
474 | $this->csrfProvider->expects($this->any()) | |
475 | ->method('generateCsrfToken') | |
476 | ->will($this->returnValue('foo&bar')); | |
477 | ||
478 | $form = $this->factory->createNamedBuilder('name', 'form') | |
479 | ->add($this->factory | |
480 | // No CSRF protection on nested forms | |
481 | ->createNamedBuilder('child', 'form') | |
482 | ->add($this->factory->createNamedBuilder('grandchild', 'text')) | |
483 | ) | |
484 | ->getForm(); | |
485 | ||
486 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
487 | '/div | |
488 | [ | |
489 | ./div | |
490 | /following-sibling::input[@type="hidden"][@id="name__token"][@value="foo&bar"] | |
491 | ] | |
492 | [count(.//input[@type="hidden"])=1] | |
493 | ' | |
494 | ); | |
495 | } | |
496 | ||
497 | public function testRepeated() | |
498 | { | |
499 | $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( | |
500 | 'type' => 'text', | |
501 | )); | |
502 | ||
503 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
504 | '/div | |
505 | [ | |
506 | ./div | |
507 | [ | |
508 | ./label[@for="name_first"] | |
509 | /following-sibling::input[@type="text"][@id="name_first"] | |
510 | ] | |
511 | /following-sibling::div | |
512 | [ | |
513 | ./label[@for="name_second"] | |
514 | /following-sibling::input[@type="text"][@id="name_second"] | |
515 | ] | |
516 | /following-sibling::input[@type="hidden"][@id="name__token"] | |
517 | ] | |
518 | [count(.//input)=3] | |
519 | ' | |
520 | ); | |
521 | } | |
522 | ||
523 | public function testRepeatedWithCustomOptions() | |
524 | { | |
525 | $form = $this->factory->createNamed('name', 'repeated', null, array( | |
526 | // the global required value cannot be overridden | |
527 | 'first_options' => array('label' => 'Test', 'required' => false), | |
528 | 'second_options' => array('label' => 'Test2') | |
529 | )); | |
530 | ||
531 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
532 | '/div | |
533 | [ | |
534 | ./div | |
535 | [ | |
536 | ./label[@for="name_first"][.="[trans]Test[/trans]"] | |
537 | /following-sibling::input[@type="text"][@id="name_first"][@required="required"] | |
538 | ] | |
539 | /following-sibling::div | |
540 | [ | |
541 | ./label[@for="name_second"][.="[trans]Test2[/trans]"] | |
542 | /following-sibling::input[@type="text"][@id="name_second"][@required="required"] | |
543 | ] | |
544 | /following-sibling::input[@type="hidden"][@id="name__token"] | |
545 | ] | |
546 | [count(.//input)=3] | |
547 | ' | |
548 | ); | |
549 | } | |
550 | ||
551 | public function testSearchInputName() | |
552 | { | |
553 | $form = $this->factory->createNamedBuilder('full', 'form') | |
554 | ->add('name', 'search') | |
555 | ->getForm(); | |
556 | ||
557 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
558 | '/div | |
559 | [ | |
560 | ./div | |
561 | [ | |
562 | ./label[@for="full_name"] | |
563 | /following-sibling::input[@type="search"][@id="full_name"][@name="full[name]"] | |
564 | ] | |
565 | /following-sibling::input[@type="hidden"][@id="full__token"] | |
566 | ] | |
567 | [count(//input)=2] | |
568 | ' | |
569 | ); | |
570 | } | |
571 | ||
572 | public function testLabelHasNoId() | |
573 | { | |
574 | $form = $this->factory->createNamed('name', 'text'); | |
575 | $html = $this->renderRow($form->createView()); | |
576 | ||
577 | $this->assertMatchesXpath($html, | |
578 | '/div | |
579 | [ | |
580 | ./label[@for="name"][not(@id)] | |
581 | /following-sibling::input[@id="name"] | |
582 | ] | |
583 | ' | |
584 | ); | |
585 | } | |
586 | ||
587 | public function testLabelIsNotRenderedWhenSetToFalse() | |
588 | { | |
589 | $form = $this->factory->createNamed('name', 'text', null, array( | |
590 | 'label' => false | |
591 | )); | |
592 | $html = $this->renderRow($form->createView()); | |
593 | ||
594 | $this->assertMatchesXpath($html, | |
595 | '/div | |
596 | [ | |
597 | ./input[@id="name"] | |
598 | ] | |
599 | [count(//label)=0] | |
600 | ' | |
601 | ); | |
602 | } | |
603 | ||
604 | /** | |
605 | * @dataProvider themeBlockInheritanceProvider | |
606 | */ | |
607 | public function testThemeBlockInheritance($theme) | |
608 | { | |
609 | $view = $this->factory | |
610 | ->createNamed('name', 'email') | |
611 | ->createView() | |
612 | ; | |
613 | ||
614 | $this->setTheme($view, $theme); | |
615 | ||
616 | $this->assertMatchesXpath( | |
617 | $this->renderWidget($view), | |
618 | '/input[@type="email"][@rel="theme"]' | |
619 | ); | |
620 | } | |
621 | ||
622 | /** | |
623 | * @dataProvider themeInheritanceProvider | |
624 | */ | |
625 | public function testThemeInheritance($parentTheme, $childTheme) | |
626 | { | |
627 | $child = $this->factory->createNamedBuilder('child', 'form') | |
628 | ->add('field', 'text'); | |
629 | ||
630 | $view = $this->factory->createNamedBuilder('parent', 'form') | |
631 | ->add('field', 'text') | |
632 | ->add($child) | |
633 | ->getForm() | |
634 | ->createView() | |
635 | ; | |
636 | ||
637 | $this->setTheme($view, $parentTheme); | |
638 | $this->setTheme($view['child'], $childTheme); | |
639 | ||
640 | $this->assertWidgetMatchesXpath($view, array(), | |
641 | '/div | |
642 | [ | |
643 | ./div | |
644 | [ | |
645 | ./label[.="parent"] | |
646 | /following-sibling::input[@type="text"] | |
647 | ] | |
648 | /following-sibling::div | |
649 | [ | |
650 | ./label[.="child"] | |
651 | /following-sibling::div | |
652 | [ | |
653 | ./div | |
654 | [ | |
655 | ./label[.="child"] | |
656 | /following-sibling::input[@type="text"] | |
657 | ] | |
658 | ] | |
659 | ] | |
660 | /following-sibling::input[@type="hidden"] | |
661 | ] | |
662 | ' | |
663 | ); | |
664 | } | |
665 | ||
666 | /** | |
667 | * The block "_name_child_label" should be overridden in the theme of the | |
668 | * implemented driver. | |
669 | */ | |
670 | public function testCollectionRowWithCustomBlock() | |
671 | { | |
672 | $collection = array('one', 'two', 'three'); | |
673 | $form = $this->factory->createNamedBuilder('name', 'collection', $collection) | |
674 | ->getForm(); | |
675 | ||
676 | $this->assertWidgetMatchesXpath($form->createView(), array(), | |
677 | '/div | |
678 | [ | |
679 | ./div[./label[.="Custom label: [trans]0[/trans]"]] | |
680 | /following-sibling::div[./label[.="Custom label: [trans]1[/trans]"]] | |
681 | /following-sibling::div[./label[.="Custom label: [trans]2[/trans]"]] | |
682 | ] | |
683 | ' | |
684 | ); | |
685 | } | |
686 | ||
687 | public function testFormEndWithRest() | |
688 | { | |
689 | $view = $this->factory->createNamedBuilder('name', 'form') | |
690 | ->add('field1', 'text') | |
691 | ->add('field2', 'text') | |
692 | ->getForm() | |
693 | ->createView(); | |
694 | ||
695 | $this->renderWidget($view['field1']); | |
696 | ||
697 | // Rest should only contain field2 | |
698 | $html = $this->renderEnd($view); | |
699 | ||
700 | // Insert the start tag, the end tag should be rendered by the helper | |
701 | $this->assertMatchesXpath('<form>' . $html, | |
702 | '/form | |
703 | [ | |
704 | ./div | |
705 | [ | |
706 | ./label[@for="name_field2"] | |
707 | /following-sibling::input[@type="text"][@id="name_field2"] | |
708 | ] | |
709 | /following-sibling::input | |
710 | [@type="hidden"] | |
711 | [@id="name__token"] | |
712 | ] | |
713 | ' | |
714 | ); | |
715 | } | |
716 | ||
717 | public function testFormEndWithoutRest() | |
718 | { | |
719 | $view = $this->factory->createNamedBuilder('name', 'form') | |
720 | ->add('field1', 'text') | |
721 | ->add('field2', 'text') | |
722 | ->getForm() | |
723 | ->createView(); | |
724 | ||
725 | $this->renderWidget($view['field1']); | |
726 | ||
727 | // Rest should only contain field2, but isn't rendered | |
728 | $html = $this->renderEnd($view, array('render_rest' => false)); | |
729 | ||
730 | $this->assertEquals('</form>', $html); | |
731 | } | |
732 | } |