Completed
Push — master ( 651a01...276b19 )
by Grégoire
03:01
created

testAppendFormFieldElementNested()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 61

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 61
rs 8.8509
c 0
b 0
f 0
cc 1
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Tests\Admin;
15
16
use PHPUnit\Framework\TestCase;
17
use Sonata\AdminBundle\Admin\AdminHelper;
18
use Sonata\AdminBundle\Admin\AdminInterface;
19
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
20
use Sonata\AdminBundle\Admin\Pool;
21
use Sonata\AdminBundle\Tests\Fixtures\Entity\Bar;
22
use Sonata\AdminBundle\Tests\Fixtures\Entity\Foo;
23
use Symfony\Component\DependencyInjection\Container;
24
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
25
use Symfony\Component\Form\DataMapperInterface;
26
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
27
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
28
use Symfony\Component\Form\FormBuilder;
29
use Symfony\Component\Form\FormFactoryInterface;
30
use Symfony\Component\Form\FormView;
31
use Symfony\Component\HttpFoundation\ParameterBag;
32
use Symfony\Component\HttpFoundation\Request;
33
use Symfony\Component\PropertyAccess\PropertyAccessorBuilder;
34
35
class AdminHelperTest extends TestCase
36
{
37
    /**
38
     * @var AdminHelper
39
     */
40
    protected $helper;
41
42
    protected function setUp(): void
43
    {
44
        $container = new Container();
45
46
        $pool = new Pool($container, 'title', 'logo.png');
47
        $this->helper = new AdminHelper($pool);
48
    }
49
50
    public function testGetChildFormBuilder(): void
51
    {
52
        $formFactory = $this->createMock(FormFactoryInterface::class);
53
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
54
55
        $formBuilder = new FormBuilder('test', \stdClass::class, $eventDispatcher, $formFactory);
56
57
        $childFormBuilder = new FormBuilder('elementId', \stdClass::class, $eventDispatcher, $formFactory);
58
        $formBuilder->add($childFormBuilder);
59
60
        $this->assertNull($this->helper->getChildFormBuilder($formBuilder, 'foo'));
61
        $this->assertInstanceOf(FormBuilder::class, $this->helper->getChildFormBuilder($formBuilder, 'test_elementId'));
62
    }
63
64
    public function testGetChildFormView(): void
65
    {
66
        $formView = new FormView();
67
        $formView->vars['id'] = 'test';
68
        $child = new FormView($formView);
0 ignored issues
show
Documentation introduced by
$formView is of type object<Symfony\Component\Form\FormView>, but the function expects a null|object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
69
        $formView->children[] = $child;
70
        $child->vars['id'] = 'test_elementId';
71
72
        $this->assertNull($this->helper->getChildFormView($formView, 'foo'));
73
        $this->assertInstanceOf(FormView::class, $this->helper->getChildFormView($formView, 'test_elementId'));
74
    }
75
76
    public function testAddNewInstance(): void
77
    {
78
        $admin = $this->createMock(AdminInterface::class);
79
        $admin->expects($this->once())->method('getNewInstance')->willReturn(new \stdClass());
80
81
        $fieldDescription = $this->createMock(FieldDescriptionInterface::class);
82
        $fieldDescription->expects($this->once())->method('getAssociationAdmin')->willReturn($admin);
83
        $fieldDescription->expects($this->once())->method('getAssociationMapping')->willReturn(['fieldName' => 'fooBar']);
84
        $fieldDescription->expects($this->once())->method('getParentAssociationMappings')->willReturn([]);
85
86
        $object = $this->getMockBuilder(\stdClass::class)
87
            ->setMethods(['addFooBar'])
88
            ->getMock();
89
        $object->expects($this->once())->method('addFooBar');
90
91
        $this->helper->addNewInstance($object, $fieldDescription);
92
    }
93
94
    public function testAddNewInstanceWithParentAssociation(): void
95
    {
96
        $admin = $this->createMock(AdminInterface::class);
97
        $admin->expects($this->once())->method('getNewInstance')->willReturn(new \stdClass());
98
99
        $fieldDescription = $this->createMock(FieldDescriptionInterface::class);
100
        $fieldDescription->expects($this->once())->method('getAssociationAdmin')->willReturn($admin);
101
        $fieldDescription->expects($this->once())->method('getAssociationMapping')->willReturn(['fieldName' => 'fooBar']);
102
        $fieldDescription->expects($this->once())->method('getParentAssociationMappings')->willReturn([['fieldName' => 'parent']]);
103
104
        $object2 = $this->getMockBuilder(\stdClass::class)
105
            ->setMethods(['addFooBar'])
106
            ->getMock();
107
        $object2->expects($this->once())->method('addFooBar');
108
109
        $object1 = $this->getMockBuilder(\stdClass::class)
110
            ->setMethods(['getParent'])
111
            ->getMock();
112
        $object1->expects($this->once())->method('getParent')->willReturn($object2);
113
114
        $this->helper->addNewInstance($object1, $fieldDescription);
115
    }
116
117
    public function testAddNewInstancePlural(): void
118
    {
119
        $admin = $this->createMock(AdminInterface::class);
120
        $admin->expects($this->once())->method('getNewInstance')->willReturn(new \stdClass());
121
122
        $fieldDescription = $this->createMock(FieldDescriptionInterface::class);
123
        $fieldDescription->expects($this->once())->method('getAssociationAdmin')->willReturn($admin);
124
        $fieldDescription->expects($this->once())->method('getAssociationMapping')->willReturn(['fieldName' => 'fooBars']);
125
        $fieldDescription->expects($this->once())->method('getParentAssociationMappings')->willReturn([]);
126
127
        $object = $this->getMockBuilder(\stdClass::class)
128
            ->setMethods(['addFooBar'])
129
            ->getMock();
130
        $object->expects($this->once())->method('addFooBar');
131
132
        $this->helper->addNewInstance($object, $fieldDescription);
133
    }
134
135
    public function testAddNewInstanceInflector(): void
136
    {
137
        $admin = $this->createMock(AdminInterface::class);
138
        $admin->expects($this->once())->method('getNewInstance')->willReturn(new \stdClass());
139
140
        $fieldDescription = $this->createMock(FieldDescriptionInterface::class);
141
        $fieldDescription->expects($this->once())->method('getAssociationAdmin')->willReturn($admin);
142
        $fieldDescription->expects($this->once())->method('getAssociationMapping')->willReturn(['fieldName' => 'entries']);
143
        $fieldDescription->expects($this->once())->method('getParentAssociationMappings')->willReturn([]);
144
145
        $object = $this->getMockBuilder(\stdClass::class)
146
            ->setMethods(['addEntry'])
147
            ->getMock();
148
        $object->expects($this->once())->method('addEntry');
149
150
        $this->helper->addNewInstance($object, $fieldDescription);
151
    }
152
153
    public function testGetElementAccessPath(): void
154
    {
155
        $object = $this->getMockBuilder(\stdClass::class)
156
            ->setMethods(['getPathToObject'])
157
            ->getMock();
158
        $subObject = $this->getMockBuilder(\stdClass::class)
159
            ->setMethods(['getAnother'])
160
            ->getMock();
161
        $sub2Object = $this->getMockBuilder(\stdClass::class)
162
            ->setMethods(['getMoreThings'])
163
            ->getMock();
164
165
        $object->expects($this->atLeastOnce())->method('getPathToObject')->willReturn([$subObject]);
166
        $subObject->expects($this->atLeastOnce())->method('getAnother')->willReturn($sub2Object);
167
        $sub2Object->expects($this->atLeastOnce())->method('getMoreThings')->willReturn('Value');
168
169
        $path = $this->helper->getElementAccessPath('uniquePartOfId_path_to_object_0_another_more_things', $object);
170
171
        $this->assertSame('path_to_object[0].another.more_things', $path);
172
    }
173
174
    public function testItThrowsExceptionWhenDoesNotFindTheFullPath(): void
175
    {
176
        $path = 'uniquePartOfId_path_to_object_0_more_calls';
177
        $object = $this->getMockBuilder(\stdClass::class)
178
            ->setMethods(['getPathToObject'])
179
            ->getMock();
180
        $subObject = $this->getMockBuilder(\stdClass::class)
181
            ->setMethods(['getMore'])
182
            ->getMock();
183
184
        $object->expects($this->atLeastOnce())->method('getPathToObject')->willReturn([$subObject]);
185
        $subObject->expects($this->atLeastOnce())->method('getMore')->willReturn('Value');
186
187
        $this->expectException(\Exception::class);
188
        $this->expectExceptionMessage('Could not get element id from '.$path.' Failing part: calls');
189
190
        $this->helper->getElementAccessPath($path, $object);
191
    }
192
193
    public function testAppendFormFieldElement(): void
194
    {
195
        $container = new Container();
196
197
        $propertyAccessorBuilder = new PropertyAccessorBuilder();
198
        $propertyAccessor = $propertyAccessorBuilder->getPropertyAccessor();
199
        $pool = new Pool($container, 'title', 'logo.png', [], $propertyAccessor);
200
        $helper = new AdminHelper($pool);
201
202
        $admin = $this->createMock(AdminInterface::class);
203
        $admin
204
            ->method('getClass')
205
            ->willReturn(Foo::class);
206
207
        $associationAdmin = $this->createMock(AdminInterface::class);
208
        $associationAdmin
209
            ->method('getClass')
210
            ->willReturn(Bar::class);
211
212
        $associationMapping = [
213
            'fieldName' => 'bar',
214
            'targetEntity' => Foo::class,
215
            'sourceEntity' => Foo::class,
216
            'isOwningSide' => false,
217
        ];
218
219
        $fieldDescription = $this->createMock(FieldDescriptionInterface::class);
220
        $fieldDescription->method('getAssociationAdmin')->willReturn($associationAdmin);
221
        $fieldDescription->method('getAssociationMapping')->willReturn($associationMapping);
222
        $fieldDescription->method('getParentAssociationMappings')->willReturn([]);
223
224
        $admin
225
            ->method('getFormFieldDescription')
226
            ->willReturn($fieldDescription);
227
228
        $associationAdmin
229
            ->method('getFormFieldDescriptions')
230
            ->willReturn([
231
                'bar' => $fieldDescription,
232
            ]);
233
234
        $request = $this->createMock(Request::class);
235
        $request
236
            ->method('get')
237
            ->willReturn([
238
                'bar' => [
239
                    [
240
                        'baz' => [
241
                            'baz' => true,
242
                        ],
243
                    ],
244
                    ['_delete' => true],
245
                ],
246
            ]);
247
248
        $request->request = new ParameterBag();
249
250
        $admin
251
            ->expects($this->atLeastOnce())
252
            ->method('getRequest')
253
            ->willReturn($request);
254
255
        $foo = $this->createMock(Foo::class);
256
        $admin
257
            ->method('hasSubject')
258
            ->willReturn(true);
259
        $admin
260
            ->method('getSubject')
261
            ->willReturn($foo);
262
263
        $bar = new \stdClass();
264
        $associationAdmin
265
            ->expects($this->atLeastOnce())
266
            ->method('getNewInstance')
267
            ->willReturn($bar);
268
269
        $foo->expects($this->atLeastOnce())->method('addBar')->with($bar);
270
271
        $dataMapper = $this->createMock(DataMapperInterface::class);
272
        $formFactory = $this->createMock(FormFactoryInterface::class);
273
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
274
        $formBuilder = new FormBuilder('test', \get_class($foo), $eventDispatcher, $formFactory);
275
        $childFormBuilder = new FormBuilder('bar', \stdClass::class, $eventDispatcher, $formFactory);
276
        $childFormBuilder->setCompound(true);
277
        $childFormBuilder->setDataMapper($dataMapper);
278
        $subChildFormBuilder = new FormBuilder('baz', \stdClass::class, $eventDispatcher, $formFactory);
279
        $subChildFormBuilder->setCompound(true);
280
        $subChildFormBuilder->setDataMapper($dataMapper);
281
        $childFormBuilder->add($subChildFormBuilder);
282
283
        $formBuilder->setRequestHandler(new HttpFoundationRequestHandler());
284
        $formBuilder->setCompound(true);
285
        $formBuilder->setDataMapper($dataMapper);
286
        $formBuilder->add($childFormBuilder);
287
288
        $associationAdmin->expects($this->atLeastOnce())->method('setSubject')->with($bar);
289
        $admin->method('getFormBuilder')->willReturn($formBuilder);
290
291
        $finalForm = $helper->appendFormFieldElement($admin, $foo, 'test_bar')[1];
292
293
        foreach ($finalForm->get($childFormBuilder->getName()) as $childField) {
294
            $this->assertFalse($childField->has('_delete'));
295
        }
296
297
        $deleteFormBuilder = new FormBuilder('_delete', null, $eventDispatcher, $formFactory);
298
        $subChildFormBuilder->add($deleteFormBuilder, CheckboxType::class, ['delete' => false]);
299
300
        $finalForm = $helper->appendFormFieldElement($admin, $foo, 'test_bar')[1];
301
302
        foreach ($finalForm->get($childFormBuilder->getName()) as $childField) {
303
            $this->assertTrue($childField->has('_delete'));
304
            $this->assertSame('', $childField->get('_delete')->getData());
305
        }
306
    }
307
308
    public function testAppendFormFieldElementNested(): void
309
    {
310
        $admin = $this->createMock(AdminInterface::class);
311
        $request = $this->createMock(Request::class);
312
        $request
313
            ->method('get')
314
            ->willReturn([
315
                'bar' => [
316
                    [
317
                        'baz' => [
318
                            'baz' => true,
319
                        ],
320
                    ],
321
                    ['_delete' => true],
322
                ],
323
            ]);
324
325
        $request->request = new ParameterBag();
326
327
        $admin
328
            ->expects($this->atLeastOnce())
329
            ->method('getRequest')
330
            ->willReturn($request);
331
        $object = $this->getMockBuilder(\stdClass::class)
332
            ->setMethods(['getSubObject'])
333
            ->getMock();
334
335
        $subObject = $this->getMockBuilder(\stdClass::class)
336
            ->setMethods(['getAnd'])
337
            ->getMock();
338
        $sub2Object = $this->getMockBuilder(\stdClass::class)
339
            ->setMethods(['getMore'])
340
            ->getMock();
341
        $sub3Object = $this->getMockBuilder(\stdClass::class)
342
            ->setMethods(['getFinalData'])
343
            ->getMock();
344
        $dataMapper = $this->createMock(DataMapperInterface::class);
345
        $formFactory = $this->createMock(FormFactoryInterface::class);
346
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
347
        $formBuilder = new FormBuilder('test', \get_class($object), $eventDispatcher, $formFactory);
348
        $childFormBuilder = new FormBuilder('subObject', \get_class($subObject), $eventDispatcher, $formFactory);
349
350
        $object->expects($this->atLeastOnce())->method('getSubObject')->willReturn([$subObject]);
351
        $subObject->expects($this->atLeastOnce())->method('getAnd')->willReturn($sub2Object);
352
        $sub2Object->expects($this->atLeastOnce())->method('getMore')->willReturn([$sub3Object]);
353
        $sub3Object->expects($this->atLeastOnce())->method('getFinalData')->willReturn('value');
354
355
        $formBuilder->setRequestHandler(new HttpFoundationRequestHandler());
356
        $formBuilder->setCompound(true);
357
        $formBuilder->setDataMapper($dataMapper);
358
        $formBuilder->add($childFormBuilder);
359
360
        $admin->method('hasSubject')->willReturn(true);
361
        $admin->method('getSubject')->willReturn($object);
362
        $admin->expects($this->once())->method('getFormBuilder')->willReturn($formBuilder);
363
364
        $this->expectException(\Exception::class);
365
        $this->expectExceptionMessage('unknown collection class');
366
367
        $this->helper->appendFormFieldElement($admin, $object, 'uniquePartOfId_sub_object_0_and_more_0_final_data');
368
    }
369
}
370