diff options
Diffstat (limited to 'vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php')
-rw-r--r-- | vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php new file mode 100644 index 00000000..5c911951 --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php | |||
@@ -0,0 +1,509 @@ | |||
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 | |||
16 | abstract class AbstractTableLayoutTest extends AbstractLayoutTest | ||
17 | { | ||
18 | public function testRow() | ||
19 | { | ||
20 | $form = $this->factory->createNamed('name', 'text'); | ||
21 | $form->addError(new FormError('[trans]Error![/trans]')); | ||
22 | $view = $form->createView(); | ||
23 | $html = $this->renderRow($view); | ||
24 | |||
25 | $this->assertMatchesXpath($html, | ||
26 | '/tr | ||
27 | [ | ||
28 | ./td | ||
29 | [./label[@for="name"]] | ||
30 | /following-sibling::td | ||
31 | [ | ||
32 | ./ul | ||
33 | [./li[.="[trans]Error![/trans]"]] | ||
34 | [count(./li)=1] | ||
35 | /following-sibling::input[@id="name"] | ||
36 | ] | ||
37 | ] | ||
38 | ' | ||
39 | ); | ||
40 | } | ||
41 | |||
42 | public function testLabelIsNotRenderedWhenSetToFalse() | ||
43 | { | ||
44 | $form = $this->factory->createNamed('name', 'text', null, array( | ||
45 | 'label' => false | ||
46 | )); | ||
47 | $html = $this->renderRow($form->createView()); | ||
48 | |||
49 | $this->assertMatchesXpath($html, | ||
50 | '/tr | ||
51 | [ | ||
52 | ./td | ||
53 | [count(//label)=0] | ||
54 | /following-sibling::td | ||
55 | [./input[@id="name"]] | ||
56 | ] | ||
57 | ' | ||
58 | ); | ||
59 | } | ||
60 | |||
61 | public function testRepeatedRow() | ||
62 | { | ||
63 | $form = $this->factory->createNamed('name', 'repeated'); | ||
64 | $html = $this->renderRow($form->createView()); | ||
65 | |||
66 | $this->assertMatchesXpath($html, | ||
67 | '/tr | ||
68 | [ | ||
69 | ./td | ||
70 | [./label[@for="name_first"]] | ||
71 | /following-sibling::td | ||
72 | [./input[@id="name_first"]] | ||
73 | ] | ||
74 | /following-sibling::tr | ||
75 | [ | ||
76 | ./td | ||
77 | [./label[@for="name_second"]] | ||
78 | /following-sibling::td | ||
79 | [./input[@id="name_second"]] | ||
80 | ] | ||
81 | /following-sibling::tr[@style="display: none"] | ||
82 | [./td[@colspan="2"]/input | ||
83 | [@type="hidden"] | ||
84 | [@id="name__token"] | ||
85 | ] | ||
86 | [count(../tr)=3] | ||
87 | ' | ||
88 | ); | ||
89 | } | ||
90 | |||
91 | public function testRepeatedRowWithErrors() | ||
92 | { | ||
93 | $form = $this->factory->createNamed('name', 'repeated'); | ||
94 | $form->addError(new FormError('[trans]Error![/trans]')); | ||
95 | $view = $form->createView(); | ||
96 | $html = $this->renderRow($view); | ||
97 | |||
98 | // The errors of the form are not rendered by intention! | ||
99 | // In practice, repeated fields cannot have errors as all errors | ||
100 | // on them are mapped to the first child. | ||
101 | // (see RepeatedTypeValidatorExtension) | ||
102 | |||
103 | $this->assertMatchesXpath($html, | ||
104 | '/tr | ||
105 | [ | ||
106 | ./td | ||
107 | [./label[@for="name_first"]] | ||
108 | /following-sibling::td | ||
109 | [./input[@id="name_first"]] | ||
110 | ] | ||
111 | /following-sibling::tr | ||
112 | [ | ||
113 | ./td | ||
114 | [./label[@for="name_second"]] | ||
115 | /following-sibling::td | ||
116 | [./input[@id="name_second"]] | ||
117 | ] | ||
118 | /following-sibling::tr[@style="display: none"] | ||
119 | [./td[@colspan="2"]/input | ||
120 | [@type="hidden"] | ||
121 | [@id="name__token"] | ||
122 | ] | ||
123 | [count(../tr)=3] | ||
124 | ' | ||
125 | ); | ||
126 | } | ||
127 | |||
128 | public function testButtonRow() | ||
129 | { | ||
130 | $form = $this->factory->createNamed('name', 'button'); | ||
131 | $view = $form->createView(); | ||
132 | $html = $this->renderRow($view); | ||
133 | |||
134 | $this->assertMatchesXpath($html, | ||
135 | '/tr | ||
136 | [ | ||
137 | ./td | ||
138 | [.=""] | ||
139 | /following-sibling::td | ||
140 | [./button[@type="button"][@name="name"]] | ||
141 | ] | ||
142 | [count(//label)=0] | ||
143 | ' | ||
144 | ); | ||
145 | } | ||
146 | |||
147 | public function testRest() | ||
148 | { | ||
149 | $view = $this->factory->createNamedBuilder('name', 'form') | ||
150 | ->add('field1', 'text') | ||
151 | ->add('field2', 'repeated') | ||
152 | ->add('field3', 'text') | ||
153 | ->add('field4', 'text') | ||
154 | ->getForm() | ||
155 | ->createView(); | ||
156 | |||
157 | // Render field2 row -> does not implicitly call renderWidget because | ||
158 | // it is a repeated field! | ||
159 | $this->renderRow($view['field2']); | ||
160 | |||
161 | // Render field3 widget | ||
162 | $this->renderWidget($view['field3']); | ||
163 | |||
164 | // Rest should only contain field1 and field4 | ||
165 | $html = $this->renderRest($view); | ||
166 | |||
167 | $this->assertMatchesXpath($html, | ||
168 | '/tr | ||
169 | [ | ||
170 | ./td | ||
171 | [./label[@for="name_field1"]] | ||
172 | /following-sibling::td | ||
173 | [./input[@id="name_field1"]] | ||
174 | ] | ||
175 | /following-sibling::tr | ||
176 | [ | ||
177 | ./td | ||
178 | [./label[@for="name_field4"]] | ||
179 | /following-sibling::td | ||
180 | [./input[@id="name_field4"]] | ||
181 | ] | ||
182 | [count(../tr)=3] | ||
183 | [count(..//label)=2] | ||
184 | [count(..//input)=3] | ||
185 | /following-sibling::tr[@style="display: none"] | ||
186 | [./td[@colspan="2"]/input | ||
187 | [@type="hidden"] | ||
188 | [@id="name__token"] | ||
189 | ] | ||
190 | ' | ||
191 | ); | ||
192 | } | ||
193 | |||
194 | public function testCollection() | ||
195 | { | ||
196 | $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( | ||
197 | 'type' => 'text', | ||
198 | )); | ||
199 | |||
200 | $this->assertWidgetMatchesXpath($form->createView(), array(), | ||
201 | '/table | ||
202 | [ | ||
203 | ./tr[./td/input[@type="text"][@value="a"]] | ||
204 | /following-sibling::tr[./td/input[@type="text"][@value="b"]] | ||
205 | /following-sibling::tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]] | ||
206 | ] | ||
207 | [count(./tr[./td/input])=3] | ||
208 | ' | ||
209 | ); | ||
210 | } | ||
211 | |||
212 | public function testEmptyCollection() | ||
213 | { | ||
214 | $form = $this->factory->createNamed('name', 'collection', array(), array( | ||
215 | 'type' => 'text', | ||
216 | )); | ||
217 | |||
218 | $this->assertWidgetMatchesXpath($form->createView(), array(), | ||
219 | '/table | ||
220 | [./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]]] | ||
221 | [count(./tr[./td/input])=1] | ||
222 | ' | ||
223 | ); | ||
224 | } | ||
225 | |||
226 | public function testForm() | ||
227 | { | ||
228 | $view = $this->factory->createNamedBuilder('name', 'form') | ||
229 | ->setMethod('PUT') | ||
230 | ->setAction('http://example.com') | ||
231 | ->add('firstName', 'text') | ||
232 | ->add('lastName', 'text') | ||
233 | ->getForm() | ||
234 | ->createView(); | ||
235 | |||
236 | $html = $this->renderForm($view, array( | ||
237 | 'id' => 'my&id', | ||
238 | 'attr' => array('class' => 'my&class'), | ||
239 | )); | ||
240 | |||
241 | $this->assertMatchesXpath($html, | ||
242 | '/form | ||
243 | [ | ||
244 | ./input[@type="hidden"][@name="_method"][@value="PUT"] | ||
245 | /following-sibling::table | ||
246 | [ | ||
247 | ./tr | ||
248 | [ | ||
249 | ./td | ||
250 | [./label[@for="name_firstName"]] | ||
251 | /following-sibling::td | ||
252 | [./input[@id="name_firstName"]] | ||
253 | ] | ||
254 | /following-sibling::tr | ||
255 | [ | ||
256 | ./td | ||
257 | [./label[@for="name_lastName"]] | ||
258 | /following-sibling::td | ||
259 | [./input[@id="name_lastName"]] | ||
260 | ] | ||
261 | /following-sibling::tr[@style="display: none"] | ||
262 | [./td[@colspan="2"]/input | ||
263 | [@type="hidden"] | ||
264 | [@id="name__token"] | ||
265 | ] | ||
266 | ] | ||
267 | [count(.//input)=3] | ||
268 | [@id="my&id"] | ||
269 | [@class="my&class"] | ||
270 | ] | ||
271 | [@method="post"] | ||
272 | [@action="http://example.com"] | ||
273 | [@class="my&class"] | ||
274 | ' | ||
275 | ); | ||
276 | } | ||
277 | |||
278 | public function testFormWidget() | ||
279 | { | ||
280 | $view = $this->factory->createNamedBuilder('name', 'form') | ||
281 | ->add('firstName', 'text') | ||
282 | ->add('lastName', 'text') | ||
283 | ->getForm() | ||
284 | ->createView(); | ||
285 | |||
286 | $this->assertWidgetMatchesXpath($view, array(), | ||
287 | '/table | ||
288 | [ | ||
289 | ./tr | ||
290 | [ | ||
291 | ./td | ||
292 | [./label[@for="name_firstName"]] | ||
293 | /following-sibling::td | ||
294 | [./input[@id="name_firstName"]] | ||
295 | ] | ||
296 | /following-sibling::tr | ||
297 | [ | ||
298 | ./td | ||
299 | [./label[@for="name_lastName"]] | ||
300 | /following-sibling::td | ||
301 | [./input[@id="name_lastName"]] | ||
302 | ] | ||
303 | /following-sibling::tr[@style="display: none"] | ||
304 | [./td[@colspan="2"]/input | ||
305 | [@type="hidden"] | ||
306 | [@id="name__token"] | ||
307 | ] | ||
308 | ] | ||
309 | [count(.//input)=3] | ||
310 | ' | ||
311 | ); | ||
312 | } | ||
313 | |||
314 | // https://github.com/symfony/symfony/issues/2308 | ||
315 | public function testNestedFormError() | ||
316 | { | ||
317 | $form = $this->factory->createNamedBuilder('name', 'form') | ||
318 | ->add($this->factory | ||
319 | ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false)) | ||
320 | ->add('grandChild', 'form') | ||
321 | ) | ||
322 | ->getForm(); | ||
323 | |||
324 | $form->get('child')->addError(new FormError('[trans]Error![/trans]')); | ||
325 | |||
326 | $this->assertWidgetMatchesXpath($form->createView(), array(), | ||
327 | '/table | ||
328 | [ | ||
329 | ./tr/td/ul[./li[.="[trans]Error![/trans]"]] | ||
330 | /following-sibling::table[@id="name_child"] | ||
331 | ] | ||
332 | [count(.//li[.="[trans]Error![/trans]"])=1] | ||
333 | ' | ||
334 | ); | ||
335 | } | ||
336 | |||
337 | public function testCsrf() | ||
338 | { | ||
339 | $this->csrfProvider->expects($this->any()) | ||
340 | ->method('generateCsrfToken') | ||
341 | ->will($this->returnValue('foo&bar')); | ||
342 | |||
343 | $form = $this->factory->createNamedBuilder('name', 'form') | ||
344 | ->add($this->factory | ||
345 | // No CSRF protection on nested forms | ||
346 | ->createNamedBuilder('child', 'form') | ||
347 | ->add($this->factory->createNamedBuilder('grandchild', 'text')) | ||
348 | ) | ||
349 | ->getForm(); | ||
350 | |||
351 | $this->assertWidgetMatchesXpath($form->createView(), array(), | ||
352 | '/table | ||
353 | [ | ||
354 | ./tr[@style="display: none"] | ||
355 | [./td[@colspan="2"]/input | ||
356 | [@type="hidden"] | ||
357 | [@id="name__token"] | ||
358 | ] | ||
359 | ] | ||
360 | [count(.//input[@type="hidden"])=1] | ||
361 | ' | ||
362 | ); | ||
363 | } | ||
364 | |||
365 | public function testRepeated() | ||
366 | { | ||
367 | $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( | ||
368 | 'type' => 'text', | ||
369 | )); | ||
370 | |||
371 | $this->assertWidgetMatchesXpath($form->createView(), array(), | ||
372 | '/table | ||
373 | [ | ||
374 | ./tr | ||
375 | [ | ||
376 | ./td | ||
377 | [./label[@for="name_first"]] | ||
378 | /following-sibling::td | ||
379 | [./input[@type="text"][@id="name_first"]] | ||
380 | ] | ||
381 | /following-sibling::tr | ||
382 | [ | ||
383 | ./td | ||
384 | [./label[@for="name_second"]] | ||
385 | /following-sibling::td | ||
386 | [./input[@type="text"][@id="name_second"]] | ||
387 | ] | ||
388 | /following-sibling::tr[@style="display: none"] | ||
389 | [./td[@colspan="2"]/input | ||
390 | [@type="hidden"] | ||
391 | [@id="name__token"] | ||
392 | ] | ||
393 | ] | ||
394 | [count(.//input)=3] | ||
395 | ' | ||
396 | ); | ||
397 | } | ||
398 | |||
399 | public function testRepeatedWithCustomOptions() | ||
400 | { | ||
401 | $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( | ||
402 | 'type' => 'password', | ||
403 | 'first_options' => array('label' => 'Test', 'required' => false), | ||
404 | 'second_options' => array('label' => 'Test2') | ||
405 | )); | ||
406 | |||
407 | $this->assertWidgetMatchesXpath($form->createView(), array(), | ||
408 | '/table | ||
409 | [ | ||
410 | ./tr | ||
411 | [ | ||
412 | ./td | ||
413 | [./label[@for="name_first"][.="[trans]Test[/trans]"]] | ||
414 | /following-sibling::td | ||
415 | [./input[@type="password"][@id="name_first"][@required="required"]] | ||
416 | ] | ||
417 | /following-sibling::tr | ||
418 | [ | ||
419 | ./td | ||
420 | [./label[@for="name_second"][.="[trans]Test2[/trans]"]] | ||
421 | /following-sibling::td | ||
422 | [./input[@type="password"][@id="name_second"][@required="required"]] | ||
423 | ] | ||
424 | /following-sibling::tr[@style="display: none"] | ||
425 | [./td[@colspan="2"]/input | ||
426 | [@type="hidden"] | ||
427 | [@id="name__token"] | ||
428 | ] | ||
429 | ] | ||
430 | [count(.//input)=3] | ||
431 | ' | ||
432 | ); | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * The block "_name_child_label" should be overridden in the theme of the | ||
437 | * implemented driver. | ||
438 | */ | ||
439 | public function testCollectionRowWithCustomBlock() | ||
440 | { | ||
441 | $collection = array('one', 'two', 'three'); | ||
442 | $form = $this->factory->createNamedBuilder('name', 'collection', $collection) | ||
443 | ->getForm(); | ||
444 | |||
445 | $this->assertWidgetMatchesXpath($form->createView(), array(), | ||
446 | '/table | ||
447 | [ | ||
448 | ./tr[./td/label[.="Custom label: [trans]0[/trans]"]] | ||
449 | /following-sibling::tr[./td/label[.="Custom label: [trans]1[/trans]"]] | ||
450 | /following-sibling::tr[./td/label[.="Custom label: [trans]2[/trans]"]] | ||
451 | ] | ||
452 | ' | ||
453 | ); | ||
454 | } | ||
455 | |||
456 | public function testFormEndWithRest() | ||
457 | { | ||
458 | $view = $this->factory->createNamedBuilder('name', 'form') | ||
459 | ->add('field1', 'text') | ||
460 | ->add('field2', 'text') | ||
461 | ->getForm() | ||
462 | ->createView(); | ||
463 | |||
464 | $this->renderWidget($view['field1']); | ||
465 | |||
466 | // Rest should only contain field2 | ||
467 | $html = $this->renderEnd($view); | ||
468 | |||
469 | // Insert the start tag, the end tag should be rendered by the helper | ||
470 | // Unfortunately this is not valid HTML, because the surrounding table | ||
471 | // tag is missing. If someone renders a form with table layout | ||
472 | // manually, she should call form_rest() explicitly within the <table> | ||
473 | // tag. | ||
474 | $this->assertMatchesXpath('<form>' . $html, | ||
475 | '/form | ||
476 | [ | ||
477 | ./tr | ||
478 | [ | ||
479 | ./td | ||
480 | [./label[@for="name_field2"]] | ||
481 | /following-sibling::td | ||
482 | [./input[@id="name_field2"]] | ||
483 | ] | ||
484 | /following-sibling::tr[@style="display: none"] | ||
485 | [./td[@colspan="2"]/input | ||
486 | [@type="hidden"] | ||
487 | [@id="name__token"] | ||
488 | ] | ||
489 | ] | ||
490 | ' | ||
491 | ); | ||
492 | } | ||
493 | |||
494 | public function testFormEndWithoutRest() | ||
495 | { | ||
496 | $view = $this->factory->createNamedBuilder('name', 'form') | ||
497 | ->add('field1', 'text') | ||
498 | ->add('field2', 'text') | ||
499 | ->getForm() | ||
500 | ->createView(); | ||
501 | |||
502 | $this->renderWidget($view['field1']); | ||
503 | |||
504 | // Rest should only contain field2, but isn't rendered | ||
505 | $html = $this->renderEnd($view, array('render_rest' => false)); | ||
506 | |||
507 | $this->assertEquals('</form>', $html); | ||
508 | } | ||
509 | } | ||