Completed
Push — 3.x ( a5a386...9dc6d5 )
by Christian
02:59
created

ShowMapperTest::testIfTrueApplyWithTab()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
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\Show;
15
16
use PHPUnit\Framework\TestCase;
17
use Sonata\AdminBundle\Admin\AdminInterface;
18
use Sonata\AdminBundle\Admin\BaseFieldDescription;
19
use Sonata\AdminBundle\Admin\FieldDescriptionCollection;
20
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
21
use Sonata\AdminBundle\Builder\ShowBuilderInterface;
22
use Sonata\AdminBundle\Model\ModelManagerInterface;
23
use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface;
24
use Sonata\AdminBundle\Show\ShowMapper;
25
use Sonata\AdminBundle\Tests\Fixtures\Admin\CleanAdmin;
26
use Sonata\AdminBundle\Translator\NoopLabelTranslatorStrategy;
27
28
/**
29
 * Test for ShowMapper.
30
 *
31
 * @author Andrej Hudec <[email protected]>
32
 */
33
class ShowMapperTest extends TestCase
34
{
35
    private const DEFAULT_GRANTED_ROLE = 'ROLE_ADMIN_BAZ';
36
37
    /**
38
     * @var ShowMapper
39
     */
40
    private $showMapper;
41
42
    /**
43
     * @var AdminInterface
44
     */
45
    private $admin;
46
47
    /**
48
     * @var ShowBuilderInterface
49
     */
50
    private $showBuilder;
51
52
    /**
53
     * @var FieldDescriptionCollection
54
     */
55
    private $fieldDescriptionCollection;
56
57
    /**
58
     * @var array
59
     */
60
    private $groups;
61
62
    /**
63
     * @var array
64
     */
65
    private $listShowFields;
66
67
    protected function setUp(): void
68
    {
69
        $this->showBuilder = $this->getMockForAbstractClass(ShowBuilderInterface::class);
70
        $this->fieldDescriptionCollection = new FieldDescriptionCollection();
71
        $this->admin = $this->getMockForAbstractClass(AdminInterface::class);
72
73
        $this->admin
74
            ->method('getLabel')
75
            ->willReturn('AdminLabel');
76
77
        $this->admin
78
            ->method('getShowTabs')
79
            ->willReturn([]);
80
81
        $this->groups = [];
82
        $this->listShowFields = [];
83
84
        $this->admin
85
            ->method('getShowGroups')
86
            ->willReturnCallback(function () {
87
                return $this->groups;
88
            });
89
90
        $this->admin
91
            ->method('setShowGroups')
92
            ->willReturnCallback(function (array $showGroups): void {
93
                $this->groups = $showGroups;
94
            });
95
96
        $this->admin
97
            ->method('reorderShowGroup')
98
            ->willReturnCallback(function (string $group, array $keys): void {
99
                $this->groups[$group]['fields'] = array_merge(array_flip($keys), $this->groups[$group]['fields']);
100
            });
101
102
        $modelManager = $this->getMockForAbstractClass(ModelManagerInterface::class);
103
104
        $modelManager
105
            ->method('getNewFieldDescriptionInstance')
106
            ->willReturnCallback(function (?string $class, string $name, array $options = []) {
107
                $fieldDescription = $this->getFieldDescriptionMock();
108
                $fieldDescription->setName($name);
109
                $fieldDescription->setOptions($options);
110
111
                return $fieldDescription;
112
            });
113
114
        $this->admin
115
            ->method('getModelManager')
116
            ->willReturn($modelManager);
117
118
        $labelTranslatorStrategy = new NoopLabelTranslatorStrategy();
119
120
        $this->admin
121
            ->method('getLabelTranslatorStrategy')
122
            ->willReturn($labelTranslatorStrategy);
123
124
        $this->admin
125
            ->method('hasShowFieldDescription')
126
            ->willReturnCallback(function (string $name): bool {
127
                if (isset($this->listShowFields[$name])) {
128
                    return true;
129
                }
130
                $this->listShowFields[$name] = true;
131
132
                return false;
133
            });
134
135
        $this->showBuilder
136
            ->method('addField')
137
            ->willReturnCallback(static function (
138
                FieldDescriptionCollection $list,
139
                ?string $type,
140
                FieldDescriptionInterface $fieldDescription,
141
                AdminInterface $admin
0 ignored issues
show
Unused Code introduced by
The parameter $admin is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
142
            ): void {
143
                $list->add($fieldDescription);
144
            });
145
146
        $this->showMapper = new ShowMapper($this->showBuilder, $this->fieldDescriptionCollection, $this->admin);
147
    }
148
149
    public function testFluidInterface(): void
150
    {
151
        $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel');
152
153
        $this->assertSame($this->showMapper, $this->showMapper->add($fieldDescription));
154
        $this->assertSame($this->showMapper, $this->showMapper->remove('fooName'));
155
        $this->assertSame($this->showMapper, $this->showMapper->reorder([]));
156
    }
157
158
    public function testGet(): void
159
    {
160
        $this->assertFalse($this->showMapper->has('fooName'));
161
162
        $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel');
163
164
        $this->showMapper->add($fieldDescription);
165
        $this->assertSame($fieldDescription, $this->showMapper->get('fooName'));
166
    }
167
168
    public function testAdd(): void
169
    {
170
        $this->showMapper->add('fooName');
171
172
        $this->assertTrue($this->showMapper->has('fooName'));
173
174
        $fieldDescription = $this->showMapper->get('fooName');
175
176
        $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription);
177
        $this->assertSame('fooName', $fieldDescription->getName());
178
        $this->assertSame('fooName', $fieldDescription->getOption('label'));
179
    }
180
181
    public function testIfTrueApply(): void
182
    {
183
        $this->showMapper->ifTrue(true);
184
        $this->showMapper->add('fooName');
185
        $this->showMapper->ifEnd();
186
187
        $this->assertTrue($this->showMapper->has('fooName'));
188
        $fieldDescription = $this->showMapper->get('fooName');
189
190
        $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription);
191
        $this->assertSame('fooName', $fieldDescription->getName());
192
        $this->assertSame('fooName', $fieldDescription->getOption('label'));
193
    }
194
195
    public function testIfTrueApplyWithTab(): void
196
    {
197
        $this->showMapper->ifTrue(true);
198
        $this->showMapper->tab('fooTab')->add('fooName')->end();
199
        $this->showMapper->ifEnd();
200
201
        $this->assertTrue($this->showMapper->has('fooName'));
202
        $fieldDescription = $this->showMapper->get('fooName');
203
204
        $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription);
205
        $this->assertSame('fooName', $fieldDescription->getName());
206
        $this->assertSame('fooName', $fieldDescription->getOption('label'));
207
    }
208
209
    public function testIfTrueNotApply(): void
210
    {
211
        $this->showMapper->ifTrue(false);
212
        $this->showMapper->add('fooName');
213
        $this->showMapper->ifEnd();
214
215
        $this->assertFalse($this->showMapper->has('fooName'));
216
    }
217
218
    public function testIfTrueNotApplyWithTab(): void
219
    {
220
        $this->showMapper->ifTrue(false);
221
        $this->showMapper->tab('fooTab')->add('fooName')->end();
222
        $this->showMapper->ifEnd();
223
224
        $this->assertFalse($this->showMapper->has('fooName'));
225
    }
226
227
    public function testIfTrueCombination(): void
228
    {
229
        $this->showMapper->ifTrue(false);
230
        $this->showMapper->add('fooName');
231
        $this->showMapper->ifEnd();
232
        $this->showMapper->add('barName');
233
234
        $this->assertFalse($this->showMapper->has('fooName'));
235
        $this->assertTrue($this->showMapper->has('barName'));
236
        $fieldDescription = $this->showMapper->get('barName');
237
238
        $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription);
239
        $this->assertSame('barName', $fieldDescription->getName());
240
        $this->assertSame('barName', $fieldDescription->getOption('label'));
241
    }
242
243
    public function testIfFalseApply(): void
244
    {
245
        $this->showMapper->ifFalse(false);
246
        $this->showMapper->add('fooName');
247
        $this->showMapper->ifEnd();
248
249
        $this->assertTrue($this->showMapper->has('fooName'));
250
        $fieldDescription = $this->showMapper->get('fooName');
251
252
        $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription);
253
        $this->assertSame('fooName', $fieldDescription->getName());
254
        $this->assertSame('fooName', $fieldDescription->getOption('label'));
255
    }
256
257
    public function testIfFalseApplyWithTab(): void
258
    {
259
        $this->showMapper->ifFalse(false);
260
        $this->showMapper->tab('fooTab')->add('fooName')->end();
261
        $this->showMapper->ifEnd();
262
263
        $this->assertTrue($this->showMapper->has('fooName'));
264
        $fieldDescription = $this->showMapper->get('fooName');
265
266
        $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription);
267
        $this->assertSame('fooName', $fieldDescription->getName());
268
        $this->assertSame('fooName', $fieldDescription->getOption('label'));
269
    }
270
271
    public function testIfFalseNotApply(): void
272
    {
273
        $this->showMapper->ifFalse(true);
274
        $this->showMapper->add('fooName');
275
        $this->showMapper->ifEnd();
276
277
        $this->assertFalse($this->showMapper->has('fooName'));
278
    }
279
280
    public function testIfFalseNotApplyWithTab(): void
281
    {
282
        $this->showMapper->ifFalse(true);
283
        $this->showMapper->tab('fooTab')->add('fooName')->end();
284
        $this->showMapper->ifEnd();
285
286
        $this->assertFalse($this->showMapper->has('fooName'));
287
    }
288
289
    public function testIfFalseCombination(): void
290
    {
291
        $this->showMapper->ifFalse(true);
292
        $this->showMapper->add('fooName');
293
        $this->showMapper->ifEnd();
294
        $this->showMapper->add('barName');
295
296
        $this->assertFalse($this->showMapper->has('fooName'));
297
        $this->assertTrue($this->showMapper->has('barName'));
298
        $fieldDescription = $this->showMapper->get('barName');
299
300
        $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription);
301
        $this->assertSame('barName', $fieldDescription->getName());
302
        $this->assertSame('barName', $fieldDescription->getOption('label'));
303
    }
304
305
    public function testIfTrueNested(): void
306
    {
307
        $this->showMapper
308
            ->ifTrue(true)
309
                ->ifTrue(true)
310
                    ->add('fooName')
311
                ->ifEnd()
312
            ->ifEnd()
313
        ;
314
315
        $this->assertTrue($this->showMapper->has('fooName'));
316
    }
317
318
    public function testIfFalseNested(): void
319
    {
320
        $this->showMapper
321
            ->ifFalse(false)
322
                ->ifFalse(false)
323
                    ->add('fooName')
324
                ->ifEnd()
325
            ->ifEnd()
326
        ;
327
328
        $this->assertTrue($this->showMapper->has('fooName'));
329
    }
330
331
    public function testIfCombinationNested(): void
332
    {
333
        $this->showMapper
334
            ->ifTrue(true)
335
                ->ifFalse(false)
336
                    ->add('fooName')
337
                ->ifEnd()
338
            ->ifEnd()
339
        ;
340
341
        $this->assertTrue($this->showMapper->has('fooName'));
342
    }
343
344
    public function testIfFalseCombinationNested2(): void
345
    {
346
        $this->showMapper
347
            ->ifFalse(false)
348
                ->ifTrue(true)
349
                    ->add('fooName')
350
                ->ifEnd()
351
            ->ifEnd()
352
        ;
353
354
        $this->assertTrue($this->showMapper->has('fooName'));
355
    }
356
357
    public function testIfFalseCombinationNested3(): void
358
    {
359
        $this->showMapper
360
            ->ifFalse(true)
361
                ->ifTrue(false)
362
                    ->add('fooName')
363
                ->ifEnd()
364
            ->ifEnd()
365
        ;
366
367
        $this->assertFalse($this->showMapper->has('fooName'));
368
    }
369
370
    public function testIfFalseCombinationNested4(): void
371
    {
372
        $this->showMapper
373
            ->ifTrue(false)
374
                ->ifFalse(true)
375
                    ->add('fooName')
376
                ->ifEnd()
377
            ->ifEnd()
378
        ;
379
380
        $this->assertFalse($this->showMapper->has('fooName'));
381
    }
382
383
    public function testAddRemove(): void
384
    {
385
        $this->assertFalse($this->showMapper->has('fooName'));
386
387
        $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel');
388
389
        $this->showMapper->add($fieldDescription);
390
        $this->assertTrue($this->showMapper->has('fooName'));
391
392
        $this->showMapper->remove('fooName');
393
        $this->assertFalse($this->showMapper->has('fooName'));
394
    }
395
396
    public function testAddException(): void
397
    {
398
        $this->expectException(\TypeError::class);
399
        $this->expectExceptionMessage('Unknown field name in show mapper. Field name should be either of FieldDescriptionInterface interface or string.');
400
401
        $this->showMapper->add(12345);
402
    }
403
404
    public function testAddDuplicateFieldNameException(): void
405
    {
406
        $name = 'name';
407
        $this->expectException(\LogicException::class);
408
        $this->expectExceptionMessage(
409
            sprintf('Duplicate field %s "name" in show mapper. Names should be unique.', $name)
410
        );
411
412
        $this->showMapper->add($name);
413
        $this->showMapper->add($name);
414
    }
415
416
    public function testKeys(): void
417
    {
418
        $fieldDescription1 = $this->getFieldDescriptionMock('fooName1', 'fooLabel1');
419
        $fieldDescription2 = $this->getFieldDescriptionMock('fooName2', 'fooLabel2');
420
421
        $this->showMapper->add($fieldDescription1);
422
        $this->showMapper->add($fieldDescription2);
423
424
        $this->assertSame(['fooName1', 'fooName2'], $this->showMapper->keys());
425
    }
426
427
    public function testReorder(): void
428
    {
429
        $this->assertSame([], $this->admin->getShowGroups());
430
431
        $fieldDescription1 = $this->getFieldDescriptionMock('fooName1', 'fooLabel1');
432
        $fieldDescription2 = $this->getFieldDescriptionMock('fooName2', 'fooLabel2');
433
        $fieldDescription3 = $this->getFieldDescriptionMock('fooName3', 'fooLabel3');
434
        $fieldDescription4 = $this->getFieldDescriptionMock('fooName4', 'fooLabel4');
435
436
        $this->showMapper->with('Group1');
437
        $this->showMapper->add($fieldDescription1);
438
        $this->showMapper->add($fieldDescription2);
439
        $this->showMapper->add($fieldDescription3);
440
        $this->showMapper->add($fieldDescription4);
441
442
        $this->assertSame([
443
            'Group1' => [
444
                'collapsed' => false,
445
                'class' => false,
446
                'description' => false,
447
                'label' => 'Group1',
448
                'translation_domain' => null,
449
                'name' => 'Group1',
450
                'box_class' => 'box box-primary',
451
                'fields' => ['fooName1' => 'fooName1', 'fooName2' => 'fooName2', 'fooName3' => 'fooName3', 'fooName4' => 'fooName4'],
452
            ], ], $this->admin->getShowGroups());
453
454
        $this->showMapper->reorder(['fooName3', 'fooName2', 'fooName1', 'fooName4']);
455
456
        // print_r is used to compare order of items in associative arrays
457
        $this->assertSame(print_r([
458
            'Group1' => [
459
                'collapsed' => false,
460
                'class' => false,
461
                'description' => false,
462
                'label' => 'Group1',
463
                'translation_domain' => null,
464
                'name' => 'Group1',
465
                'box_class' => 'box box-primary',
466
                'fields' => ['fooName3' => 'fooName3', 'fooName2' => 'fooName2', 'fooName1' => 'fooName1', 'fooName4' => 'fooName4'],
467
            ], ], true), print_r($this->admin->getShowGroups(), true));
468
    }
469
470
    public function testGroupRemovingWithoutTab(): void
471
    {
472
        $this->cleanShowMapper();
473
474
        $this->showMapper->with('groupfoo1');
475
        $this->showMapper->removeGroup('groupfoo1');
476
477
        $this->assertSame([], $this->admin->getShowGroups());
478
    }
479
480
    public function testGroupRemovingWithTab(): void
481
    {
482
        $this->cleanShowMapper();
483
484
        $this->showMapper->tab('mytab')->with('groupfoo2');
485
        $this->showMapper->removeGroup('groupfoo2', 'mytab');
486
487
        $this->assertSame([], $this->admin->getShowGroups());
488
    }
489
490
    public function testGroupRemovingWithoutTabAndWithTabRemoving(): void
491
    {
492
        $this->cleanShowMapper();
493
494
        $this->showMapper->with('groupfoo3');
495
        $this->showMapper->removeGroup('groupfoo3', 'default', true);
496
497
        $this->assertSame([], $this->admin->getShowGroups());
498
        $this->assertSame([], $this->admin->getShowTabs());
499
    }
500
501
    public function testGroupRemovingWithTabAndWithTabRemoving(): void
502
    {
503
        $this->cleanShowMapper();
504
505
        $this->showMapper->tab('mytab2')->with('groupfoo4');
506
        $this->showMapper->removeGroup('groupfoo4', 'mytab2', true);
507
508
        $this->assertSame([], $this->admin->getShowGroups());
509
        $this->assertSame([], $this->admin->getShowTabs());
510
    }
511
512
    public function testEmptyFieldLabel(): void
513
    {
514
        $this->showMapper->add('foo', null, ['label' => false]);
515
516
        $this->assertFalse($this->showMapper->get('foo')->getOption('label'));
517
    }
518
519
    public function testAddOptionRole(): void
520
    {
521
        $this->cleanShowMapper();
522
523
        $this->showMapper->add('bar', 'bar');
524
525
        $this->assertTrue($this->showMapper->has('bar'));
526
527
        $this->showMapper->add('quux', 'bar', ['role' => 'ROLE_QUX']);
528
529
        $this->assertTrue($this->showMapper->has('bar'));
530
        $this->assertFalse($this->showMapper->has('quux'));
531
532
        $this->showMapper
533
            ->with('qux')
534
                ->add('foobar', 'bar', ['role' => self::DEFAULT_GRANTED_ROLE])
535
                ->add('foo', 'bar', ['role' => 'ROLE_QUX'])
536
                ->add('baz', 'bar')
537
            ->end();
538
539
        $this->assertArrayHasKey('qux', $this->admin->getShowGroups());
540
        $this->assertTrue($this->showMapper->has('foobar'));
541
        $this->assertFalse($this->showMapper->has('foo'));
542
        $this->assertTrue($this->showMapper->has('baz'));
543
    }
544
545
    private function cleanShowMapper(): void
546
    {
547
        $this->showBuilder = $this->getMockForAbstractClass(ShowBuilderInterface::class);
548
        $this->showBuilder
549
            ->method('addField')
550
            ->willReturnCallback(static function (FieldDescriptionCollection $list, ?string $type, FieldDescriptionInterface $fieldDescription, AdminInterface $admin): void {
0 ignored issues
show
Unused Code introduced by
The parameter $admin is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
551
                $list->add($fieldDescription);
552
            });
553
        $this->fieldDescriptionCollection = new FieldDescriptionCollection();
554
        $this->admin = new CleanAdmin('code', 'class', 'controller');
555
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
556
        $securityHandler
557
            ->method('isGranted')
558
            ->willReturnCallback(static function (AdminInterface $admin, string $attributes, $object = null): bool {
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
559
                return self::DEFAULT_GRANTED_ROLE === $attributes;
560
            });
561
562
        $this->admin->setSecurityHandler($securityHandler);
563
564
        $this->showMapper = new ShowMapper($this->showBuilder, $this->fieldDescriptionCollection, $this->admin);
565
566
        $modelManager = $this->getMockForAbstractClass(ModelManagerInterface::class);
567
568
        $modelManager
569
            ->method('getNewFieldDescriptionInstance')
570
            ->willReturnCallback(function (string $class, string $name, array $options = []): FieldDescriptionInterface {
571
                $fieldDescription = $this->getFieldDescriptionMock();
572
                $fieldDescription->setName($name);
573
                $fieldDescription->setOptions($options);
574
575
                return $fieldDescription;
576
            });
577
578
        $this->admin->setModelManager($modelManager);
579
        $this->admin->setLabelTranslatorStrategy(new NoopLabelTranslatorStrategy());
580
    }
581
582
    private function getFieldDescriptionMock(?string $name = null, ?string $label = null): BaseFieldDescription
583
    {
584
        $fieldDescription = $this->getMockForAbstractClass(BaseFieldDescription::class);
585
586
        if (null !== $name) {
587
            $fieldDescription->setName($name);
588
        }
589
590
        if (null !== $label) {
591
            $fieldDescription->setOption('label', $label);
592
        }
593
594
        return $fieldDescription;
595
    }
596
}
597