10000 [Form] Improved test coverage of ResizeFormListener. Fixed https://gi… · symfony/symfony@77bea81 · GitHub
[go: up one dir, main page]

Skip to content

Commit 77bea81

Browse files
committed
[Form] Improved test coverage of ResizeFormListener. Fixed #493
1 parent fa457b1 commit 77bea81

File tree

3 files changed

+211
-41
lines changed

3 files changed

+211
-41
lines changed

src/Symfony/Component/Form/EventListener/ResizeFormListener.php

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,25 @@ public static function getSubscribedEvents()
6060
public function preSetData(DataEvent $event)
6161
{
6262
$form = $event->getForm();
63-
$collection = $event->getData();
63+
$data = $event->getData();
6464

65-
if (null === $collection) {
66-
$collection = array();
65+
if (null === $data) {
66+
$data = array();
6767
}
6868

69-
if (!is_array($collection) && !$collection instanceof \Traversable) {
70-
throw new UnexpectedTypeException($collection, 'array or \Traversable');
69+
if (!is_array($data) && !$data instanceof \Traversable) {
70+
throw new UnexpectedTypeException($data, 'array or \Traversable');
7171
}
7272

73+
// First remove all rows except for the prototype row
7374
foreach ($form as $name => $child) {
74-
if (!$this->resizeOnBind || '$$name$$' != $name) {
75+
if (!($this->resizeOnBind && '$$name$$' === $name)) {
7576
$form->remove($name);
7677
}
7778
}
7879

79-
foreach ($collection as $name => $value) {
80+
// Then add all rows again in the correct order
81+
foreach ($data as $name => $value) {
8082
$form->add($this->factory->create($this->type, $name, array(
8183
'property_path' => '['.$name.']',
8284
)));
@@ -96,12 +98,18 @@ public function preBind(DataEvent $event)
9698
$data = array();
9799
}
98100

101+
if (!is_array($data) && !$data instanceof \Traversable) {
102+
throw new UnexpectedTypeException($data, 'array or \Traversable');
103+
}
104+
105+
// Remove all empty rows except for the prototype row
99106
foreach ($form as $name => $child) {
100-
if (!isset($data[$name]) && '$$name$$' != $name) {
107+
if (!isset($data[$name]) && '$$name$$' !== $name) {
101108
$form->remove($name);
102109
}
103110
}
104111

112+
// Add all additional rows
105113
foreach ($data as $name => $value) {
106114
if (!$form->has($name)) {
107115
$form->add($this->factory->create($this->type, $name, array(
@@ -118,14 +126,22 @@ public function onBindNormData(FilterDataEvent $event)
118126
}
119127

120128
$form = $event->getForm();
121-
$collection = $event->getData();
129+
$data = $event->getData();
130+
131+
if (null === $data) {
132+
$data = array();
133+
}
134+
135+
if (!is_array($data) && !$data instanceof \Traversable) {
136+
throw new UnexpectedTypeException($data, 'array or \Traversable');
137+
}
122138

123-
foreach ($collection as $name => $child) {
139+
foreach ($data as $name => $child) {
124140
if (!$form->has($name)) {
125-
unset($collection[$name]);
141+
unset($data[$name]);
126142
}
127143
}
128144

129-
$event->setData($collection);
145+
$event->setData($data);
130146
}
131147
}

src/Symfony/Component/Form/FormInterface.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ function setParent(FormInterface $parent = null);
3232
*/
3333
function getParent();
3434

35+
function add(FormInterface $child);
36+
37+
function has($name);
38+
39+
function remove($name);
40+
3541
function getChildren();
3642

3743
function hasChildren();

tests/Symfony/Tests/Component/Form/EventListener/ResizeFormListenerTest.php

Lines changed: 177 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111

1212
namespace Symfony\Tests\Component\Form\EventListener;
1313

14+
use Symfony\Component\Form\Event\DataEvent;
1415
use Symfony\Component\Form\Event\FilterDataEvent;
1516
use Symfony\Component\Form\EventListener\ResizeFormListener;
16-
use Symfony\Component\Form\Event\DataEvent;
17+
use Symfony\Component\Form\FormBuilder;
1718

1819
class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
1920
{
@@ -22,63 +23,210 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
2223

2324
public function setUp()
2425
{
26+
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
2527
$this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
26-
$this->form = $this->getMock('Symfony\Component\Form\Form', array('add', 'has'), array(), '', false);
28+
$this->form = $this->getForm();
29+
}
30+
31+
protected function getBuilder($name = 'name')
32+
{
33+
return new FormBuilder($name, $this->factory, $this->dispatcher);
2734
}
2835

29-
public function testResizePreSetData()
36+
protected function getForm($name = 'name')
3037
{
31-
$expectedType = "text";
38+
return $this->getBuilder($name)->getForm();
39+
}
40+
41+
protected function getMockForm()
42+
{
43+
return $this->getMock('Symfony\Tests\Component\Form\FormInterface');
44+
}
45+
46+
public function testPreSetDataResizesForm()
47+
{
48+
$this->form->add($this->getForm('0'));
49+
$this->form->add($this->getForm('1'));
3250

3351
$this->factory->expects($this->at(0))
34-
->method('create')
35-
->with($this->equalTo($expectedType), $this->equalTo( 0 ), array('property_path' => '[0]'))
36-
->will($this->returnValue($this->getMock('Symfony\Tests\Component\Form\FormInterface')));
52+
->method('create')
53+
->with('text', 1, array('property_path' => '[1]'))
54+
->will($this->returnValue($this->getForm('1')));
3755
$this->factory->expects($this->at(1))
38-
->method('create')
39-
->with($this->equalTo($expectedType), $this->equalTo( 1 ), array('property_path' => '[1]'))
40-
->will($this->returnValue($this->getMock('Symfony\Tests\Component\Form\FormInterface')));
56+
->method('create')
57+
->with('text', 2, array('property_path' => '[2]'))
58+
->will($this->returnValue($this->getForm('2')));
4159

42-
$data = array("string", "string");
60+
$data = array(1 => 'string', 2 => 'string');
4361
$event = new DataEvent($this->form, $data);
44-
$listener = new ResizeFormListener($this->factory, $expectedType, false);
62+
$listener = new ResizeFormListener($this->factory, 'text', false);
4563
$listener->preSetData($event);
64+
65+
$this->assertFalse($this->form->has('0'));
66+
$this->assertTrue($this->form->has('1'));
67+
$this->assertTrue($this->form->has('2'));
4668
}
4769

48-
public function testResizePreSetDataNoArrayThrowsException()
70+
public function testPreSetDataRemovesPrototypeRowIfNotResizeOnBind()
4971
{
50-
$this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException');
51-
52-
$data = "no array or traversable";
72+
$this->form->add($this->getForm('$$name$$'));
73+
74+
$data = array();
5375
$event = new DataEvent($this->form, $data);
54-
$listener = new ResizeFormListener($this->factory, "text", false);
76+
$listener = new ResizeFormListener($this->factory, 'text', false);
5577
$listener->preSetData($event);
78+
79+
$this->assertFalse($this->form->has('$$name$$'));
5680
}
5781

58-
public function testResizePreSetDataNull()
82+
public function testPreSetDataDoesNotRemovePrototypeRowIfResizeOnBind()
83+
{
84+
$this->form->add($this->getForm('$$name$$'));
85+
86+
$data = array();
87+
$event = new DataEvent($this->form, $data);
88+
$listener = new ResizeFormListener($this->factory, 'text', true);
89+
$listener->preSetData($event);
90+
91+
$this->assertTrue($this->form->has('$$name$$'));
92+
}
93+
94+
/**
95+
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
96+
*/
97+
public function testPreSetDataRequiresArrayOrTraversable()
98+
{
99+
$data = 'no array or traversable';
100+
$event = new DataEvent($this->form, $data);
101+
$listener = new ResizeFormListener($this->factory, 'text', false);
102+
$listener->preSetData($event);
103+
}
104+
105+
public function testPreSetDataDealsWithNullData()
59106
{
60107
$this->factory->expects($this->never())->method('create');
61108

62109
$data = null;
63110
$event = new DataEvent($this->form, $data);
64-
$listener = new ResizeFormListener($this->factory, "text", false);
111+
$listener = new ResizeFormListener($this->factory, 'text', false);
65112
$listener->preSetData($event);
66113
}
67114

68-
public function testPreBind()
115+
public function testPreBindResizesFormIfResizable()
69116
{
70-
$expectedType = "text";
117+
$this->form->add($this->getForm('0'));
118+
$this->form->add($this->getForm('1'));
71119

72-
$this->form->expects($this->once())->method('has')->with($this->equalTo('foo'))->will($this->returnValue( false ));
73-
$this->form->expects($this->once())->method('add')->with($this->isInstanceOf('Symfony\Tests\Component\Form\FormInterface'));
74-
$this->factory->expects($this->at(0))
75-
->method('create')
76-
->with($this->equalTo($expectedType), $this->equalTo('foo'), $this->equalTo(array('property_path' => '[foo]')))
77-
->will($this->returnValue( $this->getMock('Symfony\Tests\Component\Form\FormInterface') ));
120+
$this->factory->expects($this->once())
121+
->method('create')
122+
->with('text', 2, array('property_path' => '[2]'))
123+
->will($this->returnValue($this->getForm('2')));
124+
125+
$data = array(0 => 'string', 2 => 'string');
126+
$event = new DataEvent($this->form, $data);
127+
$listener = new ResizeFormListener($this->factory, 'text', true);
128+
$listener->preBind($event);
129+
130+
$this->assertTrue($this->form->has('0'));
131+
$this->assertFalse($this->form->has('1'));
132+
$this->assertTrue($this->form->has('2'));
133+
}
134+
135+
// fix for https://github.com/symfony/symfony/pull/493
136+
public function testPreBindRemovesZeroKeys()
137+
{
138+
$this->form->add($this->getForm('0'));
139+
140+
$data = array();
141+
$event = new DataEvent($this->form, $data);
142+
$listener = new ResizeFormListener($this->factory, 'text', true);
143+
$listener->preBind($event);
78144

79-
$data = array("foo" => "bar");
145+
$this->assertFalse($this->form->has('0'));
146+
}
147+
148+
public function testPreBindDoesNothingIfNotResizable()
149+
{
150+
$this->form->add($this->getForm('0'));
151+
$this->form->add($this->getForm('1'));
152+
153+
$data = array(0 => 'string', 2 => 'string');
154+
$event = new DataEvent($this->form, $data);
155+
$listener = new ResizeFormListener($this->factory, 'text', false);
156+
$listener->preBind($event);
157+
158+
$this->assertTrue($this->form->has('0'));
159+
$this->assertTrue($this->form->has('1'));
160+
$this->assertFalse($this->form->has('2'));
161+
}
162+
163+
/**
164+
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
165+
*/
166+
public function testPreBindRequiresArrayOrTraversable()
167+
{
168+
$data = 'no array or traversable';
80169
$event = new DataEvent($this->form, $data);
81-
$listener = new ResizeFormListener($this->factory, "text", true);
170+
$listener = new ResizeFormListener($this->factory, 'text', true);
82171
$listener->preBind($event);
83172
}
173+
174+
public function testPreBindDealsWithNullData()
175+
{
176+
$this->form->add($this->getForm('1'));
177+
178+
$data = null;
179+
$event = new DataEvent($this->form, $data);
180+
$listener = new ResizeFormListener($this->factory, 'text', true);
181+
$listener->preBind($event);
182+
183+
$this->assertFalse($this->form->has('1'));
184+
}
185+
186+
public function testOnBindNormDataRemovesEntriesMissingInTheFormIfResizable()
187+
{
188+
$this->form->add($this->getForm('1'));
189+
190+
$data = array(0 => 'first', 1 => 'second', 2 => 'third');
191+
$event = new FilterDataEvent($this->form, $data);
192+
$listener = new ResizeFormListener($this->factory, 'text', true);
193+
$listener->onBindNormData($event);
194+
195+
$this->assertEquals(array(1 => 'second'), $event->getData());
196+
}
197+
198+
public function testOnBindNormDataDoesNothingIfNotResizable()
199+
{
200+
$this->form->add($this->getForm('1'));
201+
202+
$data = array(0 => 'first', 1 => 'second', 2 => 'third');
203+
$event = new FilterDataEvent($this->form, $data);
204+
$listener = new ResizeFormListener($this->factory, 'text', false);
205+
$listener->onBindNormData($event);
206+
207+
$this->assertEquals($data, $event->getData());
208+
}
209+
210+
/**
211+
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
212+
*/
213+
public function testOnBindNormDataRequiresArrayOrTraversable()
214+
{
215+
$data = 'no array or traversable';
216+
$event = new FilterDataEvent($this->form, $data);
217+
$listener = new ResizeFormListener($this->factory, 'text', true);
218+
$listener->onBindNormData($event);
219+
}
220+
221+
public function testOnBindNormDataDealsWithNullData()
222+
{
223+
$this->form->add($this->getForm('1'));
224+
225+
$data = null;
226+
$event = new FilterDataEvent($this->form, $data);
227+
$listener = new ResizeFormListener($this->factory, 'text', true);
228+
$listener->onBindNormData($event);
229+
230+
$this->assertEquals(array(), $event->getData());
231+
}
84232
}

0 commit comments

Comments
 (0)
0