testItThrowsExceptionWhenDoesNotFindTheFullPath()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
cc 1
nc 1
nop 0
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\Tests\Fixtures\Entity\Bar;
21
use Sonata\AdminBundle\Tests\Fixtures\Entity\Foo;
22
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
23
use Symfony\Component\Form\DataMapperInterface;
24
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
25
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
26
use Symfony\Component\Form\FormBuilder;
27
use Symfony\Component\Form\FormFactoryInterface;
28
use Symfony\Component\Form\FormView;
29
use Symfony\Component\HttpFoundation\ParameterBag;
30
use Symfony\Component\HttpFoundation\Request;
31
use Symfony\Component\PropertyAccess\PropertyAccess;
32
33
class AdminHelperTest extends TestCase
34
{
35
    /**
36
     * @var AdminHelper
37
     */
38
    protected $helper;
39
40
    protected function setUp(): void
41
    {
42
        $this->helper = new AdminHelper(PropertyAccess::createPropertyAccessor());
43
    }
44
45
    public function testGetChildFormBuilder(): void
46
    {
47
        $formFactory = $this->createMock(FormFactoryInterface::class);
48
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
49
50
        $formBuilder = new FormBuilder('test', \stdClass::class, $eventDispatcher, $formFactory);
51
52
        $childFormBuilder = new FormBuilder('elementId', \stdClass::class, $eventDispatcher, $formFactory);
53
        $formBuilder->add($childFormBuilder);
54
55
        $this->assertNull($this->helper->getChildFormBuilder($formBuilder, 'foo'));
56
        $this->assertInstanceOf(FormBuilder::class, $this->helper->getChildFormBuilder($formBuilder, 'test_elementId'));
57
    }
58
59
    public function testGetChildFormView(): void
60
    {
61
        $formView = new FormView();
62
        $formView->vars['id'] = 'test';
63
        $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...
64
        $formView->children[] = $child;
65
        $child->vars['id'] = 'test_elementId';
66
67
        $this->assertNull($this->helper->getChildFormView($formView, 'foo'));
68
        $this->assertInstanceOf(FormView::class, $this->helper->getChildFormView($formView, 'test_elementId'));
69
    }
70
71
    public function testGetElementAccessPath(): void
72
    {
73
        $object = $this->getMockBuilder(\stdClass::class)
74
            ->setMethods(['getPathToObject'])
75
            ->getMock();
76
        $subObject = $this->getMockBuilder(\stdClass::class)
77
            ->setMethods(['getAnother'])
78
            ->getMock();
79
        $sub2Object = $this->getMockBuilder(\stdClass::class)
80
            ->setMethods(['getMoreThings'])
81
            ->getMock();
82
83
        $object->expects($this->atLeastOnce())->method('getPathToObject')->willReturn([$subObject]);
84
        $subObject->expects($this->atLeastOnce())->method('getAnother')->willReturn($sub2Object);
85
        $sub2Object->expects($this->atLeastOnce())->method('getMoreThings')->willReturn('Value');
86
87
        $path = $this->helper->getElementAccessPath('uniquePartOfId_path_to_object_0_another_more_things', $object);
88
89
        $this->assertSame('path_to_object[0].another.more_things', $path);
90
    }
91
92
    public function testItThrowsExceptionWhenDoesNotFindTheFullPath(): void
93
    {
94
        $path = 'uniquePartOfId_path_to_object_0_more_calls';
95
        $object = $this->getMockBuilder(\stdClass::class)
96
            ->setMethods(['getPathToObject'])
97
            ->getMock();
98
        $subObject = $this->getMockBuilder(\stdClass::class)
99
            ->setMethods(['getMore'])
100
            ->getMock();
101
102
        $object->expects($this->atLeastOnce())->method('getPathToObject')->willReturn([$subObject]);
103
        $subObject->expects($this->atLeastOnce())->method('getMore')->willReturn('Value');
104
105
        $this->expectException(\Exception::class);
106
        $this->expectExceptionMessage(sprintf('Could not get element id from %s Failing part: calls', $path));
107
108
        $this->helper->getElementAccessPath($path, $object);
109
    }
110
111
    public function testAppendFormFieldElement(): void
112
    {
113
        $admin = $this->createMock(AdminInterface::class);
114
        $admin
115
            ->method('getClass')
116
            ->willReturn(Foo::class);
117
118
        $associationAdmin = $this->createMock(AdminInterface::class);
119
        $associationAdmin
120
            ->method('getClass')
121
            ->willReturn(Bar::class);
122
123
        $associationMapping = [
124
            'fieldName' => 'bar',
125
            'targetEntity' => Foo::class,
126
            'sourceEntity' => Foo::class,
127
            'isOwningSide' => false,
128
        ];
129
130
        $fieldDescription = $this->createMock(FieldDescriptionInterface::class);
131
        $fieldDescription->method('getAssociationAdmin')->willReturn($associationAdmin);
132
        $fieldDescription->method('getAssociationMapping')->willReturn($associationMapping);
133
        $fieldDescription->method('getParentAssociationMappings')->willReturn([]);
134
135
        $admin
136
            ->method('getFormFieldDescription')
137
            ->willReturn($fieldDescription);
138
139
        $associationAdmin
140
            ->method('getFormFieldDescriptions')
141
            ->willReturn([
142
                'bar' => $fieldDescription,
143
            ]);
144
145
        $request = $this->createMock(Request::class);
146
        $request
147
            ->method('get')
148
            ->willReturn([
149
                'bar' => [
150
                    [
151
                        'baz' => [
152
                            'baz' => true,
153
                        ],
154
                    ],
155
                    ['_delete' => true],
156
                ],
157
            ]);
158
159
        $request->request = new ParameterBag();
160
161
        $admin
162
            ->expects($this->atLeastOnce())
163
            ->method('getRequest')
164
            ->willReturn($request);
165
166
        $foo = $this->createMock(Foo::class);
167
        $admin
168
            ->method('hasSubject')
169
            ->willReturn(true);
170
        $admin
171
            ->method('getSubject')
172
            ->willReturn($foo);
173
174
        $bar = new \stdClass();
175
        $associationAdmin
176
            ->expects($this->atLeastOnce())
177
            ->method('getNewInstance')
178
            ->willReturn($bar);
179
180
        $foo->expects($this->atLeastOnce())->method('addBar')->with($bar);
181
182
        $dataMapper = $this->createMock(DataMapperInterface::class);
183
        $formFactory = $this->createMock(FormFactoryInterface::class);
184
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
185
        $formBuilder = new FormBuilder('test', \get_class($foo), $eventDispatcher, $formFactory);
186
        $childFormBuilder = new FormBuilder('bar', \stdClass::class, $eventDispatcher, $formFactory);
187
        $childFormBuilder->setCompound(true);
188
        $childFormBuilder->setDataMapper($dataMapper);
189
        $subChildFormBuilder = new FormBuilder('baz', \stdClass::class, $eventDispatcher, $formFactory);
190
        $subChildFormBuilder->setCompound(true);
191
        $subChildFormBuilder->setDataMapper($dataMapper);
192
        $childFormBuilder->add($subChildFormBuilder);
193
194
        $formBuilder->setRequestHandler(new HttpFoundationRequestHandler());
195
        $formBuilder->setCompound(true);
196
        $formBuilder->setDataMapper($dataMapper);
197
        $formBuilder->add($childFormBuilder);
198
199
        $associationAdmin->expects($this->atLeastOnce())->method('setSubject')->with($bar);
200
        $admin->method('getFormBuilder')->willReturn($formBuilder);
201
202
        $finalForm = $this->helper->appendFormFieldElement($admin, $foo, 'test_bar')[1];
203
204
        foreach ($finalForm->get($childFormBuilder->getName()) as $childField) {
205
            $this->assertFalse($childField->has('_delete'));
206
        }
207
208
        $deleteFormBuilder = new FormBuilder('_delete', null, $eventDispatcher, $formFactory);
209
        $subChildFormBuilder->add($deleteFormBuilder, CheckboxType::class, ['delete' => false]);
210
211
        $finalForm = $this->helper->appendFormFieldElement($admin, $foo, 'test_bar')[1];
212
213
        foreach ($finalForm->get($childFormBuilder->getName()) as $childField) {
214
            $this->assertTrue($childField->has('_delete'));
215
            $this->assertSame('', $childField->get('_delete')->getData());
216
        }
217
    }
218
219
    public function testAppendFormFieldElementNested(): void
220
    {
221
        $admin = $this->createMock(AdminInterface::class);
222
        $request = $this->createMock(Request::class);
223
        $request
224
            ->method('get')
225
            ->willReturn([
226
                'bar' => [
227
                    [
228
                        'baz' => [
229
                            'baz' => true,
230
                        ],
231
                    ],
232
                    ['_delete' => true],
233
                ],
234
            ]);
235
236
        $request->request = new ParameterBag();
237
238
        $admin
239
            ->expects($this->atLeastOnce())
240
            ->method('getRequest')
241
            ->willReturn($request);
242
        $object = $this->getMockBuilder(\stdClass::class)
243
            ->setMethods(['getSubObject'])
244
            ->getMock();
245
246
        $subObject = $this->getMockBuilder(\stdClass::class)
247
            ->setMethods(['getAnd'])
248
            ->getMock();
249
        $sub2Object = $this->getMockBuilder(\stdClass::class)
250
            ->setMethods(['getMore'])
251
            ->getMock();
252
        $sub3Object = $this->getMockBuilder(\stdClass::class)
253
            ->setMethods(['getFinalData'])
254
            ->getMock();
255
        $dataMapper = $this->createMock(DataMapperInterface::class);
256
        $formFactory = $this->createMock(FormFactoryInterface::class);
257
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
258
        $formBuilder = new FormBuilder('test', \get_class($object), $eventDispatcher, $formFactory);
259
        $childFormBuilder = new FormBuilder('subObject', \get_class($subObject), $eventDispatcher, $formFactory);
260
261
        $object->expects($this->atLeastOnce())->method('getSubObject')->willReturn([$subObject]);
262
        $subObject->expects($this->atLeastOnce())->method('getAnd')->willReturn($sub2Object);
263
        $sub2Object->expects($this->atLeastOnce())->method('getMore')->willReturn([$sub3Object]);
264
        $sub3Object->expects($this->atLeastOnce())->method('getFinalData')->willReturn('value');
265
266
        $formBuilder->setRequestHandler(new HttpFoundationRequestHandler());
267
        $formBuilder->setCompound(true);
268
        $formBuilder->setDataMapper($dataMapper);
269
        $formBuilder->add($childFormBuilder);
270
271
        $admin->method('hasSubject')->willReturn(true);
272
        $admin->method('getSubject')->willReturn($object);
273
        $admin->expects($this->once())->method('getFormBuilder')->willReturn($formBuilder);
274
275
        $this->expectException(\Exception::class);
276
        $this->expectExceptionMessage('unknown collection class');
277
278
        $this->helper->appendFormFieldElement($admin, $object, 'uniquePartOfId_sub_object_0_and_more_0_final_data');
279
    }
280
}
281