]> git.immae.eu Git - github/wallabag/wallabag.git/blob - vendor/symfony/form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php
twig implementation
[github/wallabag/wallabag.git] / vendor / symfony / form / Symfony / Component / Form / Tests / AbstractTableLayoutTest.php
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 }