Completed
Push — 3.x ( b75183...b1c847 )
by Oskar
04:45
created

Action/RetrieveAutocompleteItemsActionTest.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\Action;
15
16
use PHPUnit\Framework\TestCase;
17
use Prophecy\Argument;
18
use Prophecy\Prophecy\ObjectProphecy;
19
use Sonata\AdminBundle\Action\GetShortObjectDescriptionAction;
20
use Sonata\AdminBundle\Action\RetrieveAutocompleteItemsAction;
21
use Sonata\AdminBundle\Admin\AbstractAdmin;
22
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
23
use Sonata\AdminBundle\Admin\Pool;
24
use Sonata\AdminBundle\Datagrid\Pager;
25
use Sonata\AdminBundle\Object\MetadataInterface;
26
use Sonata\AdminBundle\Tests\Fixtures\Filter\FooFilter;
27
use Sonata\DatagridBundle\Datagrid\DatagridInterface;
28
use Symfony\Component\Form\Form;
29
use Symfony\Component\Form\FormConfigInterface;
30
use Symfony\Component\HttpFoundation\Request;
31
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
32
33
final class RetrieveAutocompleteItemsActionTest extends TestCase
34
{
35
    /**
36
     * @var Pool
37
     */
38
    private $pool;
39
40
    /**
41
     * @var GetShortObjectDescriptionAction
42
     */
43
    private $action;
44
45
    /**
46
     * @var AbstractAdmin
47
     */
48
    private $admin;
49
50
    protected function setUp(): void
51
    {
52
        $this->admin = $this->prophesize(AbstractAdmin::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->prophesize(\Sonat...n\AbstractAdmin::class) of type object<Prophecy\Prophecy\ObjectProphecy> is incompatible with the declared type object<Sonata\AdminBundle\Admin\AbstractAdmin> of property $admin.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
53
        $this->admin->setRequest(Argument::type(Request::class))->shouldBeCalled();
54
        $this->pool = $this->prophesize(Pool::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->prophesize(\Sonat...ndle\Admin\Pool::class) of type object<Prophecy\Prophecy\ObjectProphecy> is incompatible with the declared type object<Sonata\AdminBundle\Admin\Pool> of property $pool.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
55
        $this->pool->getInstance(Argument::any())->willReturn($this->admin->reveal());
56
        $this->action = new RetrieveAutocompleteItemsAction(
57
            $this->pool->reveal()
58
        );
59
    }
60
61
    public function testRetrieveAutocompleteItemsActionNotGranted(): void
62
    {
63
        $this->expectException(AccessDeniedException::class);
64
65
        $request = new Request([
66
            'admin_code' => 'foo.admin',
67
        ], [], [], [], [], ['REQUEST_METHOD' => 'GET', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
68
69
        $this->admin->hasAccess('create')->willReturn(false);
70
        $this->admin->hasAccess('edit')->willReturn(false);
71
72
        $action = $this->action;
73
        $action($request);
74
    }
75
76
    public function testRetrieveAutocompleteItemsActionDisabledFormelememt(): void
77
    {
78
        $this->expectException(AccessDeniedException::class);
79
        $this->expectExceptionMessage('Autocomplete list can`t be retrieved because the form element is disabled or read_only.');
80
81
        $object = new \stdClass();
82
        $request = new Request([
83
            'admin_code' => 'foo.admin',
84
            'field' => 'barField',
85
        ], [], [], [], [], ['REQUEST_METHOD' => 'GET', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
86
87
        $fieldDescription = $this->prophesize(FieldDescriptionInterface::class);
88
89
        $this->configureFormConfig('barField', true);
90
91
        $this->admin->getNewInstance()->willReturn($object);
92
        $this->admin->setSubject($object)->shouldBeCalled();
93
        $this->admin->hasAccess('create')->willReturn(true);
94
        $this->admin->getFormFieldDescriptions()->willReturn(null);
95
        $this->admin->getFormFieldDescription('barField')->willReturn($fieldDescription->reveal());
96
97
        $fieldDescription->getTargetEntity()->willReturn(Foo::class);
98
        $fieldDescription->getName()->willReturn('barField');
99
100
        $action = $this->action;
101
        $action($request);
102
    }
103
104
    public function testRetrieveAutocompleteItemsTooShortSearchString(): void
105
    {
106
        $object = new \stdClass();
107
        $request = new Request([
108
            'admin_code' => 'foo.admin',
109
            'field' => 'barField',
110
            'q' => 'so',
111
        ], [], [], [], [], ['REQUEST_METHOD' => 'GET', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
112
113
        $targetAdmin = $this->prophesize(AbstractAdmin::class);
114
        $fieldDescription = $this->prophesize(FieldDescriptionInterface::class);
115
116
        $this->configureFormConfig('barField');
117
118
        $this->admin->getNewInstance()->willReturn($object);
119
        $this->admin->setSubject($object)->shouldBeCalled();
120
        $this->admin->hasAccess('create')->willReturn(true);
121
        $this->admin->getFormFieldDescription('barField')->willReturn($fieldDescription->reveal());
122
        $this->admin->getFormFieldDescriptions()->willReturn(null);
123
        $targetAdmin->checkAccess('list')->willReturn(null);
124
        $fieldDescription->getTargetEntity()->willReturn(Foo::class);
125
        $fieldDescription->getName()->willReturn('barField');
126
        $fieldDescription->getAssociationAdmin()->willReturn($targetAdmin->reveal());
127
128
        $action = $this->action;
129
        $response = $action($request);
130
131
        $this->isInstanceOf(Response::class, $response);
0 ignored issues
show
The call to RetrieveAutocompleteItem...ionTest::isInstanceOf() has too many arguments starting with $response.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
132
        $this->assertSame('application/json', $response->headers->get('Content-Type'));
133
        $this->assertSame('{"status":"KO","message":"Too short search string."}', $response->getContent());
134
    }
135
136
    public function testRetrieveAutocompleteItems(): void
137
    {
138
        $entity = new \stdClass();
139
        $request = new Request([
140
            'admin_code' => 'foo.admin',
141
            'field' => 'barField',
142
            'q' => 'sonata',
143
        ], [], [], [], [], ['REQUEST_METHOD' => 'GET', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
144
145
        $targetAdmin = $this->prophesize(AbstractAdmin::class);
146
        $datagrid = $this->prophesize(DatagridInterface::class);
147
        $metadata = $this->prophesize(MetadataInterface::class);
148
        $pager = $this->prophesize(Pager::class);
149
        $fieldDescription = $this->prophesize(FieldDescriptionInterface::class);
150
151
        $this->configureFormConfig('barField');
152
153
        $datagrid = $this->configureAutocompleteItemsDatagrid();
154
        $filter = new FooFilter();
155
        $filter->initialize('foo');
156
157
        $datagrid->hasFilter('foo')->willReturn(true);
158
        $datagrid->getFilter('foo')->willReturn($filter);
159
        $datagrid->setValue('foo', null, 'sonata')->shouldBeCalled();
160
161
        $action = $this->action;
162
        $response = $action($request);
163
164
        $this->isInstanceOf(Response::class, $response);
0 ignored issues
show
The call to RetrieveAutocompleteItem...ionTest::isInstanceOf() has too many arguments starting with $response.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
165
        $this->assertSame('application/json', $response->headers->get('Content-Type'));
166
        $this->assertSame('{"status":"OK","more":false,"items":[{"id":123,"label":"FOO"}]}', $response->getContent());
167
    }
168
169
    public function testRetrieveAutocompleteItemsComplexPropertyArray(): void
170
    {
171
        $request = new Request([
172
            'admin_code' => 'foo.admin',
173
            'field' => 'barField',
174
            'q' => 'sonata',
175
        ], [], [], [], [], ['REQUEST_METHOD' => 'GET', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
176
177
        $this->configureFormConfigComplexPropertyArray('barField');
178
        $datagrid = $this->configureAutocompleteItemsDatagrid();
179
180
        $filter = new FooFilter();
181
        $filter->initialize('entity.property');
182
183
        $datagrid->hasFilter('entity.property')->willReturn(true);
184
        $datagrid->getFilter('entity.property')->willReturn($filter);
185
        $filter2 = new FooFilter();
186
        $filter2->initialize('entity2.property2');
187
188
        $datagrid->hasFilter('entity2.property2')->willReturn(true);
189
        $datagrid->getFilter('entity2.property2')->willReturn($filter2);
190
191
        $datagrid->setValue('entity__property', null, 'sonata')->shouldBeCalled();
192
        $datagrid->setValue('entity2__property2', null, 'sonata')->shouldBeCalled();
193
194
        $action = $this->action;
195
        $response = $action($request);
196
197
        $this->isInstanceOf(Response::class, $response);
0 ignored issues
show
The call to RetrieveAutocompleteItem...ionTest::isInstanceOf() has too many arguments starting with $response.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
198
        $this->assertSame('application/json', $response->headers->get('Content-Type'));
199
        $this->assertSame('{"status":"OK","more":false,"items":[{"id":123,"label":"FOO"}]}', $response->getContent());
200
    }
201
202
    public function testRetrieveAutocompleteItemsComplexProperty(): void
203
    {
204
        $request = new Request([
205
            'admin_code' => 'foo.admin',
206
            'field' => 'barField',
207
            'q' => 'sonata',
208
        ], [], [], [], [], ['REQUEST_METHOD' => 'GET', 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
209
210
        $this->configureFormConfigComplexProperty('barField');
211
        $datagrid = $this->configureAutocompleteItemsDatagrid();
212
213
        $filter = new FooFilter();
214
        $filter->initialize('entity.property');
215
216
        $datagrid->hasFilter('entity.property')->willReturn(true);
217
        $datagrid->getFilter('entity.property')->willReturn($filter);
218
        $datagrid->setValue('entity__property', null, 'sonata')->shouldBeCalled();
219
220
        $action = $this->action;
221
        $response = $action($request);
222
223
        $this->isInstanceOf(Response::class, $response);
0 ignored issues
show
The call to RetrieveAutocompleteItem...ionTest::isInstanceOf() has too many arguments starting with $response.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
224
        $this->assertSame('application/json', $response->headers->get('Content-Type'));
225
        $this->assertSame('{"status":"OK","more":false,"items":[{"id":123,"label":"FOO"}]}', $response->getContent());
226
    }
227
228
    private function configureAutocompleteItemsDatagrid(): ObjectProphecy
229
    {
230
        $entity = new \stdClass();
231
232
        $targetAdmin = $this->prophesize(AbstractAdmin::class);
233
        $datagrid = $this->prophesize(DatagridInterface::class);
234
        $metadata = $this->prophesize(MetadataInterface::class);
235
        $pager = $this->prophesize(Pager::class);
236
        $fieldDescription = $this->prophesize(FieldDescriptionInterface::class);
237
238
        $this->admin->getNewInstance()->willReturn($entity);
239
        $this->admin->setSubject($entity)->shouldBeCalled();
240
        $this->admin->hasAccess('create')->willReturn(true);
241
        $this->admin->getFormFieldDescription('barField')->willReturn($fieldDescription->reveal());
242
        $this->admin->getFormFieldDescriptions()->willReturn(null);
243
        $this->admin->id($entity)->willReturn(123);
244
        $targetAdmin->checkAccess('list')->shouldBeCalled();
245
        $targetAdmin->setFilterPersister(null)->shouldBeCalled();
246
        $targetAdmin->getDatagrid()->willReturn($datagrid->reveal());
247
        $targetAdmin->getObjectMetadata($entity)->willReturn($metadata->reveal());
248
        $metadata->getTitle()->willReturn('FOO');
249
250
        $datagrid->setValue('_per_page', null, 10)->shouldBeCalled();
251
        $datagrid->setValue('_page', null, 1)->shouldBeCalled();
252
        $datagrid->buildPager()->willReturn(null);
253
        $datagrid->getPager()->willReturn($pager->reveal());
254
        $pager->getResults()->willReturn([$entity]);
255
        $pager->isLastPage()->willReturn(true);
256
        $fieldDescription->getTargetEntity()->willReturn(Foo::class);
257
        $fieldDescription->getName()->willReturn('barField');
258
        $fieldDescription->getAssociationAdmin()->willReturn($targetAdmin->reveal());
259
260
        return $datagrid;
261
    }
262
263
    private function configureFormConfig(string $field, bool $disabled = false): void
264
    {
265
        $form = $this->prophesize(Form::class);
266
        $formType = $this->prophesize(Form::class);
267
        $formConfig = $this->prophesize(FormConfigInterface::class);
268
269
        $this->admin->getForm()->willReturn($form->reveal());
270
        $form->get($field)->willReturn($formType->reveal());
271
        $formType->getConfig()->willReturn($formConfig->reveal());
272
        $formConfig->getAttribute('disabled')->willReturn($disabled);
273
        $formConfig->getAttribute('property')->willReturn('foo');
274
        $formConfig->getAttribute('callback')->willReturn(null);
275
        $formConfig->getAttribute('minimum_input_length')->willReturn(3);
276
        $formConfig->getAttribute('items_per_page')->willReturn(10);
277
        $formConfig->getAttribute('req_param_name_page_number')->willReturn('_page');
278
        $formConfig->getAttribute('to_string_callback')->willReturn(null);
279
        $formConfig->getAttribute('target_admin_access_action')->willReturn('list');
280
    }
281
282
    private function configureFormConfigComplexProperty(string $field): void
283
    {
284
        $form = $this->prophesize(Form::class);
285
        $formType = $this->prophesize(Form::class);
286
        $formConfig = $this->prophesize(FormConfigInterface::class);
287
288
        $this->admin->getForm()->willReturn($form->reveal());
289
        $form->get($field)->willReturn($formType->reveal());
290
        $formType->getConfig()->willReturn($formConfig->reveal());
291
        $formConfig->getAttribute('disabled')->willReturn(false);
292
        $formConfig->getAttribute('property')->willReturn('entity.property');
293
        $formConfig->getAttribute('callback')->willReturn(null);
294
        $formConfig->getAttribute('minimum_input_length')->willReturn(3);
295
        $formConfig->getAttribute('items_per_page')->willReturn(10);
296
        $formConfig->getAttribute('req_param_name_page_number')->willReturn('_page');
297
        $formConfig->getAttribute('to_string_callback')->willReturn(null);
298
        $formConfig->getAttribute('target_admin_access_action')->willReturn('list');
299
    }
300
301
    private function configureFormConfigComplexPropertyArray($field): void
302
    {
303
        $form = $this->prophesize(Form::class);
304
        $formType = $this->prophesize(Form::class);
305
        $formConfig = $this->prophesize(FormConfigInterface::class);
306
307
        $this->admin->getForm()->willReturn($form->reveal());
308
        $form->get($field)->willReturn($formType->reveal());
309
        $formType->getConfig()->willReturn($formConfig->reveal());
310
        $formConfig->getAttribute('disabled')->willReturn(false);
311
        $formConfig->getAttribute('property')->willReturn(['entity.property', 'entity2.property2']);
312
        $formConfig->getAttribute('callback')->willReturn(null);
313
        $formConfig->getAttribute('minimum_input_length')->willReturn(3);
314
        $formConfig->getAttribute('items_per_page')->willReturn(10);
315
        $formConfig->getAttribute('req_param_name_page_number')->willReturn('_page');
316
        $formConfig->getAttribute('to_string_callback')->willReturn(null);
317
        $formConfig->getAttribute('target_admin_access_action')->willReturn('list');
318
    }
319
}
320