Completed
Push — master ( e6c9d7...cc6bd7 )
by Grégoire
12:23
created

FormMapperTest::testAddOptionRole()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.552
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\Form;
15
16
use PHPUnit\Framework\TestCase;
17
use Sonata\AdminBundle\Admin\AdminInterface;
18
use Sonata\AdminBundle\Admin\BaseFieldDescription;
19
use Sonata\AdminBundle\Builder\FormContractorInterface;
20
use Sonata\AdminBundle\Form\FormMapper;
21
use Sonata\AdminBundle\Model\ModelManagerInterface;
22
use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface;
23
use Sonata\AdminBundle\Tests\Fixtures\Admin\CleanAdmin;
24
use Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface;
25
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
26
use Symfony\Component\Form\Extension\Core\Type\FormType;
27
use Symfony\Component\Form\FormBuilder;
28
use Symfony\Component\Form\FormFactoryInterface;
29
use Symfony\Component\Form\ResolvedFormTypeInterface;
30
31
class FormMapperTest extends TestCase
32
{
33
    private const DEFAULT_GRANTED_ROLE = 'ROLE_ADMIN_BAZ';
34
35
    /**
36
     * @var FormContractorInterface
37
     */
38
    protected $contractor;
39
40
    /**
41
     * @var AdminInterface
42
     */
43
    protected $admin;
44
45
    /**
46
     * @var ModelManagerInterface
47
     */
48
    protected $modelManager;
49
50
    /**
51
     * @var FormMapper
52
     */
53
    protected $formMapper;
54
55
    protected function setUp(): void
56
    {
57
        $this->contractor = $this->createMock(FormContractorInterface::class);
58
59
        $formFactory = $this->createMock(FormFactoryInterface::class);
60
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
61
62
        $formBuilder = new FormBuilder('test', 'stdClass', $eventDispatcher, $formFactory);
63
64
        $this->admin = new CleanAdmin('code', 'class', 'controller');
65
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
66
        $securityHandler
67
            ->expects($this->any())
68
            ->method('isGranted')
69
            ->willReturnCallback(static function (AdminInterface $admin, $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...
70
                return self::DEFAULT_GRANTED_ROLE === $attributes;
71
            });
72
73
        $this->admin->setSecurityHandler($securityHandler);
74
75
        $this->modelManager = $this->getMockForAbstractClass(ModelManagerInterface::class);
76
77
        $this->modelManager->expects($this->any())
78
            ->method('getNewFieldDescriptionInstance')
79
            ->willReturnCallback(function ($class, $name, array $options = []) {
80
                $fieldDescription = $this->getFieldDescriptionMock();
81
                $fieldDescription->setName($name);
82
                $fieldDescription->setOptions($options);
83
84
                return $fieldDescription;
85
            });
86
87
        $this->admin->setModelManager($this->modelManager);
88
89
        $labelTranslatorStrategy = $this->getMockForAbstractClass(LabelTranslatorStrategyInterface::class);
90
        $this->admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
91
92
        $this->formMapper = new FormMapper(
93
            $this->contractor,
94
            $formBuilder,
95
            $this->admin
96
        );
97
    }
98
99
    public function testWithNoOptions(): void
100
    {
101
        $this->formMapper->with('foobar');
102
103
        $this->assertSame(['default' => [
104
            'collapsed' => false,
105
            'class' => false,
106
            'description' => false,
107
            'label' => 'default',
108
            'translation_domain' => null,
109
            'name' => 'default',
110
            'box_class' => 'box box-primary',
111
            'auto_created' => true,
112
            'groups' => ['foobar'],
113
            'tab' => true,
114
        ]], $this->admin->getFormTabs());
115
116
        $this->assertSame(['foobar' => [
117
            'collapsed' => false,
118
            'class' => false,
119
            'description' => false,
120
            'label' => 'foobar',
121
            'translation_domain' => null,
122
            'name' => 'foobar',
123
            'box_class' => 'box box-primary',
124
            'fields' => [],
125
        ]], $this->admin->getFormGroups());
126
    }
127
128
    public function testWithOptions(): void
129
    {
130
        $this->formMapper->with('foobar', [
131
            'translation_domain' => 'Foobar',
132
            'role' => self::DEFAULT_GRANTED_ROLE,
133
        ]);
134
135
        $this->assertSame(['foobar' => [
136
            'collapsed' => false,
137
            'class' => false,
138
            'description' => false,
139
            'label' => 'foobar',
140
            'translation_domain' => 'Foobar',
141
            'name' => 'foobar',
142
            'box_class' => 'box box-primary',
143
            'fields' => [],
144
            'role' => self::DEFAULT_GRANTED_ROLE,
145
        ]], $this->admin->getFormGroups());
146
147
        $this->assertSame(['default' => [
148
            'collapsed' => false,
149
            'class' => false,
150
            'description' => false,
151
            'label' => 'default',
152
            'translation_domain' => 'Foobar',
153
            'name' => 'default',
154
            'box_class' => 'box box-primary',
155
            'auto_created' => true,
156
            'groups' => ['foobar'],
157
            'tab' => true,
158
        ]], $this->admin->getFormTabs());
159
    }
160
161
    public function testWithFieldsCascadeTranslationDomain(): void
162
    {
163
        $this->contractor->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ormContractorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
164
            ->method('getDefaultOptions')
165
            ->willReturn([]);
166
167
        $this->formMapper->with('foobar', [
168
                'translation_domain' => 'Foobar',
169
            ])
170
            ->add('foo', 'bar')
171
        ->end();
172
173
        $fieldDescription = $this->admin->getFormFieldDescription('foo');
174
        $this->assertSame('foo', $fieldDescription->getName());
175
        $this->assertSame('bar', $fieldDescription->getType());
176
        $this->assertSame('Foobar', $fieldDescription->getTranslationDomain());
177
178
        $this->assertTrue($this->formMapper->has('foo'));
179
180
        $this->assertSame(['default' => [
181
            'collapsed' => false,
182
            'class' => false,
183
            'description' => false,
184
            'label' => 'default',
185
            'translation_domain' => 'Foobar',
186
            'name' => 'default',
187
            'box_class' => 'box box-primary',
188
            'auto_created' => true,
189
            'groups' => ['foobar'],
190
            'tab' => true,
191
        ]], $this->admin->getFormTabs());
192
193
        $this->assertSame(['foobar' => [
194
            'collapsed' => false,
195
            'class' => false,
196
            'description' => false,
197
            'label' => 'foobar',
198
            'translation_domain' => 'Foobar',
199
            'name' => 'foobar',
200
            'box_class' => 'box box-primary',
201
            'fields' => [
202
                'foo' => 'foo',
203
            ],
204
        ]], $this->admin->getFormGroups());
205
    }
206
207
    /**
208
     * @doesNotPerformAssertions
209
     */
210
    public function testRemoveCascadeRemoveFieldFromFormGroup(): void
211
    {
212
        $this->formMapper->with('foo');
213
        $this->formMapper->remove('foo');
214
    }
215
216
    public function testIfTrueApply(): void
217
    {
218
        $this->contractor->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ormContractorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
219
            ->method('getDefaultOptions')
220
            ->willReturn([]);
221
222
        $this->formMapper
223
            ->ifTrue(true)
224
            ->add('foo', 'bar')
225
            ->ifEnd()
226
        ;
227
228
        $this->assertTrue($this->formMapper->has('foo'));
229
    }
230
231
    public function testIfTrueNotApply(): void
232
    {
233
        $this->formMapper
234
            ->ifTrue(false)
235
            ->add('foo', 'bar')
236
            ->ifEnd()
237
        ;
238
239
        $this->assertFalse($this->formMapper->has('foo'));
240
    }
241
242
    public function testIfTrueCombination(): void
243
    {
244
        $this->contractor->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ormContractorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
245
            ->method('getDefaultOptions')
246
            ->willReturn([]);
247
248
        $this->formMapper
249
            ->ifTrue(false)
250
            ->add('foo', 'bar')
251
            ->ifEnd()
252
            ->add('baz', 'foobaz')
253
        ;
254
255
        $this->assertFalse($this->formMapper->has('foo'));
256
        $this->assertTrue($this->formMapper->has('baz'));
257
    }
258
259
    public function testIfFalseApply(): void
260
    {
261
        $this->contractor->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ormContractorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
262
            ->method('getDefaultOptions')
263
            ->willReturn([]);
264
265
        $this->formMapper
266
            ->ifFalse(false)
267
            ->add('foo', 'bar')
268
            ->ifEnd()
269
        ;
270
271
        $this->assertTrue($this->formMapper->has('foo'));
272
    }
273
274
    public function testIfFalseNotApply(): void
275
    {
276
        $this->formMapper
277
            ->ifFalse(true)
278
            ->add('foo', 'bar')
279
            ->ifEnd()
280
        ;
281
282
        $this->assertFalse($this->formMapper->has('foo'));
283
    }
284
285
    public function testIfFalseCombination(): void
286
    {
287
        $this->contractor->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ormContractorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
288
            ->method('getDefaultOptions')
289
            ->willReturn([]);
290
291
        $this->formMapper
292
            ->ifFalse(true)
293
            ->add('foo', 'bar')
294
            ->ifEnd()
295
            ->add('baz', 'foobaz')
296
        ;
297
298
        $this->assertFalse($this->formMapper->has('foo'));
299
        $this->assertTrue($this->formMapper->has('baz'));
300
    }
301
302
    public function testIfTrueNested(): void
303
    {
304
        $this->expectException(\RuntimeException::class);
305
        $this->expectExceptionMessage('Cannot nest ifTrue or ifFalse call');
306
307
        $this->formMapper->ifTrue(true);
308
        $this->formMapper->ifTrue(true);
309
    }
310
311
    public function testIfFalseNested(): void
312
    {
313
        $this->expectException(\RuntimeException::class);
314
        $this->expectExceptionMessage('Cannot nest ifTrue or ifFalse call');
315
316
        $this->formMapper->ifFalse(false);
317
        $this->formMapper->ifFalse(false);
318
    }
319
320
    public function testIfCombinationNested(): void
321
    {
322
        $this->expectException(\RuntimeException::class);
323
        $this->expectExceptionMessage('Cannot nest ifTrue or ifFalse call');
324
325
        $this->formMapper->ifTrue(true);
326
        $this->formMapper->ifFalse(false);
327
    }
328
329
    public function testIfFalseCombinationNested2(): void
330
    {
331
        $this->expectException(\RuntimeException::class);
332
        $this->expectExceptionMessage('Cannot nest ifTrue or ifFalse call');
333
334
        $this->formMapper->ifFalse(false);
335
        $this->formMapper->ifTrue(true);
336
    }
337
338
    public function testIfFalseCombinationNested3(): void
339
    {
340
        $this->expectException(\RuntimeException::class);
341
        $this->expectExceptionMessage('Cannot nest ifTrue or ifFalse call');
342
343
        $this->formMapper->ifFalse(true);
344
        $this->formMapper->ifTrue(false);
345
    }
346
347
    public function testIfFalseCombinationNested4(): void
348
    {
349
        $this->expectException(\RuntimeException::class);
350
        $this->expectExceptionMessage('Cannot nest ifTrue or ifFalse call');
351
352
        $this->formMapper->ifTrue(false);
353
        $this->formMapper->ifFalse(true);
354
    }
355
356
    public function testAddAcceptFormBuilder(): void
357
    {
358
        $formBuilder = $this
359
            ->getMockBuilder(FormBuilder::class)
360
            ->disableOriginalConstructor()
361
            ->getMock();
362
363
        $formBuilder->expects($this->any())
364
            ->method('getName')
365
            ->willReturn('foo');
366
367
        $formType = $this
368
            ->getMockBuilder(ResolvedFormTypeInterface::class)
369
            ->getMock();
370
371
        $innerType = $this
372
            ->getMockBuilder(FormType::class)
373
            ->getMock();
374
375
        $formType->expects($this->once())
376
            ->method('getInnerType')
377
            ->willReturn($innerType);
378
379
        $formBuilder->expects($this->once())
380
            ->method('getType')
381
            ->willReturn($formType);
382
383
        $this->formMapper->add($formBuilder);
384
        $this->assertSame($this->formMapper->get('foo'), $formBuilder);
385
    }
386
387
    public function testAddFormBuilderWithType(): void
388
    {
389
        $formBuilder = $this
390
            ->getMockBuilder(FormBuilder::class)
391
            ->disableOriginalConstructor()
392
            ->getMock();
393
394
        $formBuilder->expects($this->any())
395
            ->method('getName')
396
            ->willReturn('foo');
397
398
        $formBuilder->expects($this->never())
399
            ->method('getType');
400
401
        $this->formMapper->add($formBuilder, FormType::class);
402
        $this->assertSame($this->formMapper->get('foo'), $formBuilder);
403
    }
404
405
    public function testGroupRemovingWithoutTab(): void
406
    {
407
        $this->formMapper->with('foobar');
408
409
        $this->formMapper->removeGroup('foobar');
410
411
        $this->assertSame([], $this->admin->getFormGroups());
412
    }
413
414
    public function testGroupRemovingWithTab(): void
415
    {
416
        $this->formMapper->tab('mytab')->with('foobar');
417
418
        $this->formMapper->removeGroup('foobar', 'mytab');
419
420
        $this->assertSame([], $this->admin->getFormGroups());
421
    }
422
423
    public function testGroupRemovingWithoutTabAndWithTabRemoving(): void
424
    {
425
        $this->formMapper->with('foobar');
426
427
        $this->formMapper->removeGroup('foobar', 'default', true);
428
429
        $this->assertSame([], $this->admin->getFormGroups());
430
        $this->assertSame([], $this->admin->getFormTabs());
431
    }
432
433
    public function testGroupRemovingWithTabAndWithTabRemoving(): void
434
    {
435
        $this->formMapper->tab('mytab')->with('foobar');
436
437
        $this->formMapper->removeGroup('foobar', 'mytab', true);
438
439
        $this->assertSame([], $this->admin->getFormGroups());
440
        $this->assertSame([], $this->admin->getFormTabs());
441
    }
442
443
    public function testKeys(): void
444
    {
445
        $this->contractor->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ormContractorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
446
            ->method('getDefaultOptions')
447
            ->willReturn([]);
448
449
        $this->formMapper
450
            ->add('foo', 'bar')
451
            ->add('baz', 'foobaz')
452
        ;
453
454
        $this->assertSame(['foo', 'baz'], $this->formMapper->keys());
455
    }
456
457
    public function testFieldNameIsSanitized(): void
458
    {
459
        $this->contractor->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ormContractorInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
460
            ->method('getDefaultOptions')
461
            ->willReturn([]);
462
463
        $this->formMapper
464
            ->add('fo.o', 'bar')
465
            ->add('ba__z', 'foobaz')
466
        ;
467
468
        $this->assertSame(['fo__o', 'ba____z'], $this->formMapper->keys());
469
    }
470
471
    public function testAddOptionRole(): void
472
    {
473
        $this->formMapper->add('bar', 'bar');
474
475
        $this->assertTrue($this->formMapper->has('bar'));
476
477
        $this->formMapper->add('quux', 'bar', [], ['role' => 'ROLE_QUX']);
478
479
        $this->assertTrue($this->formMapper->has('bar'));
480
        $this->assertFalse($this->formMapper->has('quux'));
481
482
        $this->formMapper
483
            ->with('qux')
484
                ->add('foobar', 'bar', [], ['role' => self::DEFAULT_GRANTED_ROLE])
485
                ->add('foo', 'bar', [], ['role' => 'ROLE_QUX'])
486
                ->add('baz', 'bar')
487
            ->end();
488
489
        $this->assertArrayHasKey('qux', $this->admin->getFormGroups());
490
        $this->assertTrue($this->formMapper->has('foobar'));
491
        $this->assertFalse($this->formMapper->has('foo'));
492
        $this->assertTrue($this->formMapper->has('baz'));
493
    }
494
495
    private function getFieldDescriptionMock(
496
        ?string $name = null,
497
        ?string $label = null,
498
        ?string $translationDomain = null
499
    ): BaseFieldDescription {
500
        $fieldDescription = $this->getMockForAbstractClass(BaseFieldDescription::class);
501
502
        if (null !== $name) {
503
            $fieldDescription->setName($name);
504
        }
505
506
        if (null !== $label) {
507
            $fieldDescription->setOption('label', $label);
508
        }
509
510
        if (null !== $translationDomain) {
511
            $fieldDescription->setOption('translation_domain', $translationDomain);
512
        }
513
514
        return $fieldDescription;
515
    }
516
}
517