FilterTypeGuesserTest::testGuessTypeNoMetadata()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
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\DoctrineMongoDBAdminBundle\Tests\Guesser;
15
16
use Doctrine\Bundle\MongoDBBundle\Form\Type\DocumentType;
17
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
18
use Doctrine\ODM\MongoDB\Mapping\MappingException;
19
use Doctrine\ODM\MongoDB\Types\Type;
20
use PHPUnit\Framework\TestCase;
21
use Sonata\AdminBundle\Form\Type\Operator\EqualOperatorType;
22
use Sonata\DoctrineMongoDBAdminBundle\Filter\BooleanFilter;
23
use Sonata\DoctrineMongoDBAdminBundle\Filter\DateFilter;
24
use Sonata\DoctrineMongoDBAdminBundle\Filter\DateTimeFilter;
25
use Sonata\DoctrineMongoDBAdminBundle\Filter\ModelFilter;
26
use Sonata\DoctrineMongoDBAdminBundle\Filter\NumberFilter;
27
use Sonata\DoctrineMongoDBAdminBundle\Filter\StringFilter;
28
use Sonata\DoctrineMongoDBAdminBundle\Guesser\FilterTypeGuesser;
29
use Sonata\DoctrineMongoDBAdminBundle\Model\MissingPropertyMetadataException;
30
use Sonata\DoctrineMongoDBAdminBundle\Model\ModelManager;
31
use Sonata\Form\Type\BooleanType;
32
use Symfony\Component\Form\Extension\Core\Type\NumberType;
33
use Symfony\Component\Form\Extension\Core\Type\TextType;
34
use Symfony\Component\Form\Guess\Guess;
35
36
class FilterTypeGuesserTest extends TestCase
37
{
38
    private $guesser;
39
    private $modelManager;
40
41
    protected function setUp(): void
42
    {
43
        $this->guesser = new FilterTypeGuesser();
44
        $this->modelManager = $this->prophesize(ModelManager::class);
45
    }
46
47
    public function testThrowsOnMissingField(): void
48
    {
49
        $this->expectException(MissingPropertyMetadataException::class);
50
51
        $class = 'My\Model';
52
        $property = 'whatever';
53
54
        $metadata = $this->prophesize(ClassMetadata::class);
55
        $metadata->hasAssociation($property)->willReturn(false);
56
57
        $this->modelManager->getParentMetadataForProperty($class, $property)->willReturn([
58
            $metadata->reveal(),
59
            $property,
60
            'parent mappings, no idea what it looks like',
61
        ]);
62
        $this->guesser->guessType($class, $property, $this->modelManager->reveal());
63
    }
64
65
    public function testGuessTypeNoMetadata(): void
66
    {
67
        $this->modelManager->getParentMetadataForProperty(
68
            $class = 'FakeClass',
69
            $property = 'fakeProperty'
70
        )->willThrow(MappingException::class);
71
72
        $result = $this->guesser->guessType($class, $property, $this->modelManager->reveal());
73
74
        $this->assertFalse($result);
75
    }
76
77
    public function testGuessTypeWithAssociation(): void
78
    {
79
        $classMetadata = $this->prophesize(ClassMetadata::class);
80
81
        $classMetadata->hasAssociation($property = 'fakeProperty')->willReturn(true);
82
        $classMetadataObject = $classMetadata->reveal();
83
        $classMetadataObject->fieldMappings['fakeProperty'] = [
84
            'type' => ClassMetadata::ONE,
85
            'targetDocument' => $targetDocument = 'FakeEntity',
86
            'fieldName' => $fieldName = 'fakeName',
87
        ];
88
89
        $this->modelManager->getParentMetadataForProperty(
90
            $class = 'FakeClass',
91
            $property
92
        )->willReturn([$classMetadataObject, $property, $parentAssociation = 'parentAssociation']);
93
94
        $result = $this->guesser->guessType($class, $property, $this->modelManager->reveal());
95
96
        $options = $result->getOptions();
97
98
        $this->assertSame(ModelFilter::class, $result->getType());
99
        $this->assertSame(Guess::HIGH_CONFIDENCE, $result->getConfidence());
100
        $this->assertSame($parentAssociation, $options['parent_association_mappings']);
101
        $this->assertSame(ClassMetadata::ONE, $options['mapping_type']);
102
        $this->assertSame(EqualOperatorType::class, $options['operator_type']);
103
        $this->assertSame([], $options['operator_options']);
104
        $this->assertSame($fieldName, $options['field_name']);
105
        $this->assertSame(DocumentType::class, $options['field_type']);
106
        $this->assertSame($targetDocument, $options['field_options']['class']);
107
    }
108
109
    /**
110
     * @dataProvider noAssociationData
111
     */
112
    public function testGuessTypeNoAssociation(string $type, string $resultType, int $confidence, ?string $fieldType = null): void
113
    {
114
        $classMetadata = $this->prophesize(ClassMetadata::class);
115
116
        $classMetadata->hasAssociation($property = 'fakeProperty')->willReturn(false);
117
118
        $classMetadata->fieldMappings = [$property => ['fieldName' => $type]];
119
        $classMetadata->getTypeOfField($property)->willReturn($type);
120
121
        $this->modelManager->getParentMetadataForProperty(
122
            $class = 'FakeClass',
123
            $property
124
        )->willReturn([$classMetadata, $property, 'notUsed']);
125
126
        $result = $this->guesser->guessType($class, $property, $this->modelManager->reveal());
127
128
        $options = $result->getOptions();
129
130
        $this->assertSame($resultType, $result->getType());
131
        $this->assertSame($type, $options['field_name']);
132
        $this->assertSame($confidence, $result->getConfidence());
133
        $this->assertSame([], $options['options']);
134
        $this->assertSame([], $options['field_options']);
135
136
        if ($fieldType) {
137
            $this->assertSame($fieldType, $options['field_type']);
138
        }
139
    }
140
141
    public function noAssociationData(): array
142
    {
143
        return [
144
            Type::BOOLEAN => [
145
                'boolean',
146
                BooleanFilter::class,
147
                Guess::HIGH_CONFIDENCE,
148
                BooleanType::class,
149
            ],
150
            'datetime' => [
151
                'datetime',
152
                DateTimeFilter::class,
153
                Guess::HIGH_CONFIDENCE,
154
            ],
155
            Type::TIMESTAMP => [
156
                'datetime',
157
                DateTimeFilter::class,
158
                Guess::HIGH_CONFIDENCE,
159
            ],
160
            Type::DATE => [
161
                'date',
162
                DateFilter::class,
163
                Guess::HIGH_CONFIDENCE,
164
            ],
165
            'decimal' => [
166
                'decimal',
167
                NumberFilter::class,
168
                Guess::MEDIUM_CONFIDENCE,
169
                NumberType::class,
170
            ],
171
            Type::FLOAT => [
172
                'float',
173
                NumberFilter::class,
174
                Guess::MEDIUM_CONFIDENCE,
175
                NumberType::class,
176
            ],
177
            Type::INT => [
178
                'int',
179
                NumberFilter::class,
180
                Guess::MEDIUM_CONFIDENCE,
181
                NumberType::class,
182
            ],
183
            Type::STRING => [
184
                'string',
185
                StringFilter::class,
186
                Guess::MEDIUM_CONFIDENCE,
187
                TextType::class,
188
            ],
189
            'text' => [
190
                'text',
191
                StringFilter::class,
192
                Guess::MEDIUM_CONFIDENCE,
193
                TextType::class,
194
            ],
195
            'somefake' => [
196
                'somefake',
197
                StringFilter::class,
198
                Guess::LOW_CONFIDENCE,
199
            ],
200
        ];
201
    }
202
}
203