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\Datagrid; |
||
15 | |||
16 | use PHPUnit\Framework\TestCase; |
||
17 | use Sonata\AdminBundle\Admin\AbstractAdmin; |
||
18 | use Sonata\AdminBundle\Admin\AdminInterface; |
||
19 | use Sonata\AdminBundle\Admin\BaseFieldDescription; |
||
20 | use Sonata\AdminBundle\Admin\FieldDescriptionCollection; |
||
21 | use Sonata\AdminBundle\Admin\FieldDescriptionInterface; |
||
22 | use Sonata\AdminBundle\Builder\ListBuilderInterface; |
||
23 | use Sonata\AdminBundle\Datagrid\ListMapper; |
||
24 | use Sonata\AdminBundle\Model\ModelManagerInterface; |
||
25 | use Sonata\AdminBundle\Translator\NoopLabelTranslatorStrategy; |
||
26 | |||
27 | /** |
||
28 | * @author Andrej Hudec <[email protected]> |
||
29 | */ |
||
30 | class ListMapperTest extends TestCase |
||
31 | { |
||
32 | private const DEFAULT_GRANTED_ROLE = 'ROLE_ADMIN_BAZ'; |
||
33 | |||
34 | /** |
||
35 | * @var ListMapper |
||
36 | */ |
||
37 | private $listMapper; |
||
38 | |||
39 | /** |
||
40 | * @var FieldDescriptionCollection |
||
41 | */ |
||
42 | private $fieldDescriptionCollection; |
||
43 | |||
44 | /** |
||
45 | * @var AdminInterface |
||
46 | */ |
||
47 | private $admin; |
||
48 | |||
49 | protected function setUp(): void |
||
50 | { |
||
51 | $listBuilder = $this->createMock(ListBuilderInterface::class); |
||
52 | $this->fieldDescriptionCollection = new FieldDescriptionCollection(); |
||
53 | $this->admin = $this->createMock(AbstractAdmin::class); |
||
54 | |||
55 | $listBuilder->expects($this->any()) |
||
56 | ->method('addField') |
||
57 | ->willReturnCallback(static function ($list, $type, $fieldDescription, $admin): void { |
||
58 | $list->add($fieldDescription); |
||
59 | }); |
||
60 | |||
61 | $modelManager = $this->createMock(ModelManagerInterface::class); |
||
62 | |||
63 | $modelManager->expects($this->any()) |
||
64 | ->method('getNewFieldDescriptionInstance') |
||
65 | ->willReturnCallback(function ($class, $name, array $options = []) { |
||
66 | $fieldDescription = $this->getFieldDescriptionMock(); |
||
67 | $fieldDescription->setName($name); |
||
68 | $fieldDescription->setOptions($options); |
||
69 | |||
70 | return $fieldDescription; |
||
71 | }); |
||
72 | |||
73 | $this->admin->expects($this->any()) |
||
74 | ->method('getModelManager') |
||
75 | ->willReturn($modelManager); |
||
76 | |||
77 | $labelTranslatorStrategy = new NoopLabelTranslatorStrategy(); |
||
78 | |||
79 | $this->admin->expects($this->any()) |
||
80 | ->method('getLabelTranslatorStrategy') |
||
81 | ->willReturn($labelTranslatorStrategy); |
||
82 | |||
83 | $this->admin->expects($this->any()) |
||
84 | ->method('isGranted') |
||
85 | ->willReturnCallback(static function (string $name, object $object = null): bool { |
||
86 | return self::DEFAULT_GRANTED_ROLE === $name; |
||
87 | }); |
||
88 | |||
89 | $this->listMapper = new ListMapper($listBuilder, $this->fieldDescriptionCollection, $this->admin); |
||
90 | } |
||
91 | |||
92 | public function testFluidInterface(): void |
||
93 | { |
||
94 | $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel'); |
||
95 | |||
96 | $this->assertSame($this->listMapper, $this->listMapper->add($fieldDescription)); |
||
0 ignored issues
–
show
|
|||
97 | $this->assertSame($this->listMapper, $this->listMapper->remove('fooName')); |
||
98 | $this->assertSame($this->listMapper, $this->listMapper->reorder([])); |
||
99 | } |
||
100 | |||
101 | public function testGet(): void |
||
102 | { |
||
103 | $this->assertFalse($this->listMapper->has('fooName')); |
||
104 | |||
105 | $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel'); |
||
106 | |||
107 | $this->listMapper->add($fieldDescription); |
||
108 | $this->assertSame($fieldDescription, $this->listMapper->get('fooName')); |
||
109 | } |
||
110 | |||
111 | public function testAddIdentifier(): void |
||
112 | { |
||
113 | $this->assertFalse($this->listMapper->has('fooName')); |
||
114 | |||
115 | $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel'); |
||
116 | |||
117 | $this->listMapper->addIdentifier($fieldDescription); |
||
118 | $this->assertTrue($this->listMapper->has('fooName')); |
||
119 | |||
120 | $fieldDescription = $this->listMapper->get('fooName'); |
||
121 | $this->assertTrue($fieldDescription->getOption('identifier')); |
||
122 | } |
||
123 | |||
124 | public function testAddOptionIdentifier(): void |
||
125 | { |
||
126 | $this->assertFalse($this->listMapper->has('fooName')); |
||
127 | $this->assertFalse($this->listMapper->has('barName')); |
||
128 | $this->assertFalse($this->listMapper->has('bazName')); |
||
129 | |||
130 | $this->listMapper->add('barName'); |
||
131 | $this->assertNull($this->listMapper->get('barName')->getOption('identifier')); |
||
132 | $this->listMapper->add('fooName', null, ['identifier' => true]); |
||
133 | $this->assertTrue($this->listMapper->has('fooName')); |
||
134 | $this->assertTrue($this->listMapper->get('fooName')->getOption('identifier')); |
||
135 | $this->listMapper->add('bazName', null, ['identifier' => false]); |
||
136 | $this->assertTrue($this->listMapper->has('bazName')); |
||
137 | $this->assertFalse($this->listMapper->get('bazName')->getOption('identifier')); |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * @group legacy |
||
142 | * |
||
143 | * @expectedDeprecation Passing a non boolean value for the "identifier" option is deprecated since sonata-project/admin-bundle 3.x and will throw an exception in 4.0. |
||
144 | * |
||
145 | * @dataProvider getWrongIdentifierOptions |
||
146 | */ |
||
147 | public function testAddOptionIdentifierWithDeprecatedValue(bool $expected, $value): void |
||
148 | { |
||
149 | $this->assertFalse($this->listMapper->has('fooName')); |
||
150 | $this->listMapper->add('fooName', null, ['identifier' => $value]); |
||
151 | $this->assertTrue($this->listMapper->has('fooName')); |
||
152 | $this->assertSame($expected, $this->listMapper->get('fooName')->getOption('identifier')); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * @dataProvider getWrongIdentifierOptions |
||
157 | */ |
||
158 | public function testAddOptionIdentifierWithWrongValue(bool $expected, $value): void |
||
159 | { |
||
160 | // NEXT_MAJOR: Remove the following `markTestSkipped()` call and the `testAddOptionIdentifierWithDeprecatedValue()` test |
||
161 | $this->markTestSkipped('This test must be run in 4.0'); |
||
162 | |||
163 | $this->assertFalse($this->listMapper->has('fooName')); |
||
164 | |||
165 | $this->expectException(\InvalidArgumentException::class); |
||
166 | $this->expectExceptionMessageRegExp('{^Value for "identifier" option must be boolean, [^]+ given.$}'); |
||
167 | |||
168 | $this->listMapper->add('fooName', null, ['identifier' => $value]); |
||
169 | } |
||
170 | |||
171 | public function getWrongIdentifierOptions(): iterable |
||
172 | { |
||
173 | return [ |
||
174 | [true, 1], |
||
175 | [true, 'string'], |
||
176 | [true, new \stdClass()], |
||
177 | [true, [null]], |
||
178 | [false, 0], |
||
179 | [false, null], |
||
180 | [false, ''], |
||
181 | [false, '0'], |
||
182 | [false, []], |
||
183 | ]; |
||
184 | } |
||
185 | |||
186 | public function testAdd(): void |
||
187 | { |
||
188 | $this->listMapper->add('fooName'); |
||
189 | $this->listMapper->add('fooNameLabelBar', null, ['label' => 'Foo Bar']); |
||
190 | $this->listMapper->add('fooNameLabelFalse', null, ['label' => false]); |
||
191 | |||
192 | $this->assertTrue($this->listMapper->has('fooName')); |
||
193 | |||
194 | $fieldDescription = $this->listMapper->get('fooName'); |
||
195 | $fieldLabelBar = $this->listMapper->get('fooNameLabelBar'); |
||
196 | $fieldLabelFalse = $this->listMapper->get('fooNameLabelFalse'); |
||
197 | |||
198 | $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription); |
||
199 | $this->assertSame('fooName', $fieldDescription->getName()); |
||
200 | $this->assertSame('fooName', $fieldDescription->getOption('label')); |
||
201 | $this->assertSame('Foo Bar', $fieldLabelBar->getOption('label')); |
||
202 | $this->assertFalse($fieldLabelFalse->getOption('label')); |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * @group legacy |
||
207 | */ |
||
208 | public function testLegacyAddViewInlineAction(): void |
||
209 | { |
||
210 | $this->assertFalse($this->listMapper->has('_action')); |
||
211 | $this->listMapper->add('_action', 'actions', ['actions' => ['view' => []]]); |
||
212 | |||
213 | $this->assertTrue($this->listMapper->has('_action')); |
||
214 | |||
215 | $fieldDescription = $this->listMapper->get('_action'); |
||
216 | |||
217 | $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription); |
||
218 | $this->assertSame('_action', $fieldDescription->getName()); |
||
219 | $this->assertCount(1, $fieldDescription->getOption('actions')); |
||
220 | $this->assertSame(['show' => []], $fieldDescription->getOption('actions')); |
||
221 | } |
||
222 | |||
223 | public function testAddViewInlineAction(): void |
||
224 | { |
||
225 | $this->assertFalse($this->listMapper->has('_action')); |
||
226 | $this->listMapper->add('_action', 'actions', ['actions' => ['show' => []]]); |
||
227 | |||
228 | $this->assertTrue($this->listMapper->has('_action')); |
||
229 | |||
230 | $fieldDescription = $this->listMapper->get('_action'); |
||
231 | |||
232 | $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription); |
||
233 | $this->assertSame('_action', $fieldDescription->getName()); |
||
234 | $this->assertCount(1, $fieldDescription->getOption('actions')); |
||
235 | $this->assertSame(['show' => []], $fieldDescription->getOption('actions')); |
||
236 | } |
||
237 | |||
238 | public function testAddRemove(): void |
||
239 | { |
||
240 | $this->assertFalse($this->listMapper->has('fooName')); |
||
241 | |||
242 | $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel'); |
||
243 | |||
244 | $this->listMapper->add($fieldDescription); |
||
245 | $this->assertTrue($this->listMapper->has('fooName')); |
||
246 | |||
247 | $this->listMapper->remove('fooName'); |
||
248 | $this->assertFalse($this->listMapper->has('fooName')); |
||
249 | } |
||
250 | |||
251 | public function testAddDuplicateNameException(): void |
||
252 | { |
||
253 | $tmpNames = []; |
||
254 | $this->admin->expects($this->any()) |
||
255 | ->method('hasListFieldDescription') |
||
256 | ->willReturnCallback(static function ($name) use (&$tmpNames) { |
||
257 | if (isset($tmpNames[$name])) { |
||
258 | return true; |
||
259 | } |
||
260 | $tmpNames[$name] = $name; |
||
261 | |||
262 | return false; |
||
263 | }); |
||
264 | |||
265 | $this->expectException(\RuntimeException::class, 'Duplicate field name "fooName" in list mapper. Names should be unique.'); |
||
266 | |||
267 | $this->listMapper->add('fooName'); |
||
268 | $this->listMapper->add('fooName'); |
||
269 | } |
||
270 | |||
271 | public function testAddWrongTypeException(): void |
||
272 | { |
||
273 | $this->expectException(\RuntimeException::class, 'Unknown field name in list mapper. Field name should be either of FieldDescriptionInterface interface or string.'); |
||
274 | |||
275 | $this->listMapper->add(12345); |
||
276 | } |
||
277 | |||
278 | public function testAutoAddVirtualOption(): void |
||
279 | { |
||
280 | foreach (['actions', 'batch', 'select'] as $type) { |
||
281 | $this->listMapper->add('_'.$type, $type); |
||
282 | } |
||
283 | |||
284 | foreach ($this->fieldDescriptionCollection->getElements() as $field) { |
||
285 | $this->assertTrue( |
||
286 | $field->isVirtual(), |
||
287 | 'Failed asserting that FieldDescription with type "'.$field->getType().'" is tagged with virtual flag.' |
||
288 | ); |
||
289 | } |
||
290 | } |
||
291 | |||
292 | public function testKeys(): void |
||
293 | { |
||
294 | $fieldDescription1 = $this->getFieldDescriptionMock('fooName1', 'fooLabel1'); |
||
295 | $fieldDescription2 = $this->getFieldDescriptionMock('fooName2', 'fooLabel2'); |
||
296 | |||
297 | $this->listMapper->add($fieldDescription1); |
||
298 | $this->listMapper->add($fieldDescription2); |
||
299 | |||
300 | $this->assertSame(['fooName1', 'fooName2'], $this->listMapper->keys()); |
||
301 | } |
||
302 | |||
303 | public function testReorder(): void |
||
304 | { |
||
305 | $fieldDescription1 = $this->getFieldDescriptionMock('fooName1', 'fooLabel1'); |
||
306 | $fieldDescription2 = $this->getFieldDescriptionMock('fooName2', 'fooLabel2'); |
||
307 | $fieldDescription3 = $this->getFieldDescriptionMock('fooName3', 'fooLabel3'); |
||
308 | $fieldDescription4 = $this->getFieldDescriptionMock('fooName4', 'fooLabel4'); |
||
309 | |||
310 | $this->listMapper->add($fieldDescription1); |
||
311 | $this->listMapper->add($fieldDescription2); |
||
312 | $this->listMapper->add($fieldDescription3); |
||
313 | $this->listMapper->add($fieldDescription4); |
||
314 | |||
315 | $this->assertSame([ |
||
316 | 'fooName1' => $fieldDescription1, |
||
317 | 'fooName2' => $fieldDescription2, |
||
318 | 'fooName3' => $fieldDescription3, |
||
319 | 'fooName4' => $fieldDescription4, |
||
320 | ], $this->fieldDescriptionCollection->getElements()); |
||
321 | |||
322 | $this->listMapper->reorder(['fooName3', 'fooName2', 'fooName1', 'fooName4']); |
||
323 | |||
324 | // print_r is used to compare order of items in associative arrays |
||
325 | $this->assertSame(print_r([ |
||
326 | 'fooName3' => $fieldDescription3, |
||
327 | 'fooName2' => $fieldDescription2, |
||
328 | 'fooName1' => $fieldDescription1, |
||
329 | 'fooName4' => $fieldDescription4, |
||
330 | ], true), print_r($this->fieldDescriptionCollection->getElements(), true)); |
||
331 | } |
||
332 | |||
333 | public function testAddOptionRole(): void |
||
334 | { |
||
335 | $this->listMapper->add('bar', 'bar'); |
||
336 | |||
337 | $this->assertTrue($this->listMapper->has('bar')); |
||
338 | |||
339 | $this->listMapper->add('quux', 'bar', ['role' => 'ROLE_QUX']); |
||
340 | |||
341 | $this->assertTrue($this->listMapper->has('bar')); |
||
342 | $this->assertFalse($this->listMapper->has('quux')); |
||
343 | |||
344 | $this->listMapper |
||
345 | ->add('foobar', 'bar', ['role' => self::DEFAULT_GRANTED_ROLE]) |
||
346 | ->add('foo', 'bar', ['role' => 'ROLE_QUX']) |
||
347 | ->add('baz', 'bar'); |
||
348 | |||
349 | $this->assertTrue($this->listMapper->has('foobar')); |
||
350 | $this->assertFalse($this->listMapper->has('foo')); |
||
351 | $this->assertTrue($this->listMapper->has('baz')); |
||
352 | } |
||
353 | |||
354 | private function getFieldDescriptionMock(?string $name = null, ?string $label = null): BaseFieldDescription |
||
355 | { |
||
356 | $fieldDescription = $this->getMockForAbstractClass(BaseFieldDescription::class); |
||
357 | |||
358 | if (null !== $name) { |
||
359 | $fieldDescription->setName($name); |
||
360 | } |
||
361 | |||
362 | if (null !== $label) { |
||
363 | $fieldDescription->setOption('label', $label); |
||
364 | } |
||
365 | |||
366 | return $fieldDescription; |
||
367 | } |
||
368 | } |
||
369 |
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: