WhereFilterTest::testFilter()   B
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 28
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 1
Metric Value
dl 0
loc 28
rs 8.8571
c 5
b 1
f 1
cc 3
eloc 21
nc 4
nop 4
1
<?php
2
3
/*
4
 * This file is part of the LoopBackApiBundle package.
5
 *
6
 * (c) Théo FIDRY <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Fidry\LoopBackApiBundle\Tests\Filter;
13
14
use Doctrine\Common\Persistence\ManagerRegistry;
15
use Doctrine\ORM\EntityRepository;
16
use Dunglas\ApiBundle\Api\IriConverter;
17
use Dunglas\ApiBundle\Api\Resource;
18
use Fidry\LoopBackApiBundle\Filter\WhereFilter;
19
use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
20
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpFoundation\RequestStack;
23
use Symfony\Component\PropertyAccess\PropertyAccessor;
24
25
/**
26
 * Class WhereFilter.
27
 *
28
 * @coversDefaultClass Fidry\LoopBackApiBundle\Filter\WhereFilter
29
 *
30
 * @author             Théo FIDRY <[email protected]>
31
 */
32
class WhereFilterTest extends KernelTestCase
33
{
34
    /**
35
     * @var string
36
     */
37
    private $entityClass;
38
39
    /**
40
     * @var IriConverter
41
     */
42
    private $iriConverter;
43
44
    /**
45
     * @var ManagerRegistry
46
     */
47
    private $managerRegistry;
48
49
    /**
50
     * @var PropertyAccessor
51
     */
52
    private $propertyAccessor;
53
54
    /**
55
     * @var EntityRepository
56
     */
57
    private $repository;
58
59
    /**
60
     * @var Resource
61
     */
62
    private $resource;
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    protected function setUp()
68
    {
69
        self::bootKernel();
70
        $this->entityClass = 'Fidry\LoopBackApiBundle\Tests\Functional\Bundle\TestBundle\Entity\Dummy';
71
        $this->managerRegistry = self::$kernel->getContainer()->get('doctrine');
72
        $this->iriConverter = self::$kernel->getContainer()->get('api.iri_converter');
73
        $this->propertyAccessor = self::$kernel->getContainer()->get('property_accessor');
74
        $this->repository = DoctrineTestHelper::createTestEntityManager()->getRepository($this->entityClass);
75
        $this->resource = new Resource($this->entityClass);
76
    }
77
78
    /**
79
     * @dataProvider filterProvider
80
     * @covers       ::apply
81
     *
82
     * @param array|null $properties Properties on which the filter may be enabled.
83
     * @param string     $url        URL.
84
     * @param string     $expected   Expected DQL query.
85
     * @param array      $parameters Expected parameters of the DQL query.
86
     */
87
    public function testFilter($properties, $url, $expected, $parameters = [])
88
    {
89
        $this->markTestSkipped('tempo');
90
        $request = Request::create($url, 'GET');
91
        $requestStack = $this->prophesize(RequestStack::class);
92
        $requestStack->getCurrentRequest()->willReturn($request);
93
94
        $filter = new WhereFilter(
95
            $this->managerRegistry,
96
            $requestStack->reveal(),
97
            $this->iriConverter,
98
            $this->propertyAccessor,
99
            $properties
0 ignored issues
show
Documentation introduced by
$properties is of type array|null, but the function expects a object<Fidry\LoopBackApi...ueryExtractorInterface>.

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:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
100
        );
101
        $filter->initParameter('where');
0 ignored issues
show
Bug introduced by
The method initParameter() does not seem to exist on object<Fidry\LoopBackApi...dle\Filter\WhereFilter>.

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...
102
        $queryBuilder = $this->getQueryBuilder();
103
104
        $filter->apply($this->resource, $queryBuilder);
105
        $actual = strtolower($queryBuilder->getQuery()->getDQL());
106
        $expected = ('' === $expected)
107
            ? strtolower(sprintf('SELECT o FROM %s o', $this->entityClass))
108
            : strtolower(sprintf('SELECT o FROM %s o WHERE %s', $this->entityClass, $expected));
109
110
        $this->assertEquals($expected, $actual);
111
        foreach ($parameters as $parameter => $value) {
112
            $this->assertEquals($value, $queryBuilder->getParameter($parameter)->getValue());
113
        }
114
    }
115
116
    /**
117
     * @return \Doctrine\ORM\QueryBuilder QueryBuilder for filters.
118
     */
119
    public function getQueryBuilder()
120
    {
121
        return $this->repository->createQueryBuilder('o');
122
    }
123
124
    /**
125
     * @return array
126
     */
127
    public function filterProvider()
128
    {
129
        $return = [];
130
131
        // Classical where
132
        $return[] = [
133
            null,
134
            '/api/dummies?filter[where][name]=test',
135
            'o.name = :name',
136
            [
137
                'name' => 'test',
138
            ],
139
        ];
140
        $return[] = [
141
            null,
142
            '/api/dummies?filter[where][unknown]=test',
143
            '',
144
            [],
145
        ];
146
        $return[] = [
147
            null,
148
            '/api/dummies?filter[yolo][name]=test',
149
            '',
150
            [],
151
        ];
152
153
        // Classical where on boolean
154
        $return[] = [
155
            null,
156
            '/api/dummies?filter[where][isEnabled]=0',
157
            'o.isEnabled = :isEnabled',
158
            [
159
                'isEnabled' => 0,
160
            ],
161
        ];
162
        $return[] = [
163
            null,
164
            '/api/dummies?filter[where][isEnabled]=1',
165
            'o.isEnabled = :isEnabled',
166
            [
167
                'isEnabled' => 1,
168
            ],
169
        ];
170
171
        // Classical where on DateTime
172
        //TODO: enable this test
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
173
//        $return[] = [
174
//            null,
175
//            '/api/dummies?filter[where][isEnabled]=0',
176
//            'o.name = test'
177
//        ];
178
//        $return[] = [
179
//            null,
180
//            '/api/dummies?filter[where][isEnabled]=1',
181
//            'o.name = test'
182
//        ];
183
184
        // Null value / Not null
185
        $return[] = [
186
            null,
187
            '/api/dummies?filter[where][name]=null',
188
            'o.name IS NULL',
189
        ];
190
        $return[] = [
191
            null,
192
            '/api/dummies?filter[where][name][neq]=null',
193
            'o.name IS NOT NULL',
194
        ];
195
196
        // Empty string value
197
        $return[] = [
198
            null,
199
            '/api/dummies?filter[where][name]=',
200
            'o.name = :name',
201
            [
202
                'name' => '',
203
            ],
204
        ];
205
        $return[] = [
206
            null,
207
            '/api/dummies?filter[where][name][neq]=',
208
            'o.name <> :name',
209
            [
210
                'name' => '',
211
            ],
212
        ];
213
214
        // Empty integer value
215
        $return[] = [
216
            null,
217
            '/api/dummies?filter[where][price]=',
218
            'o.price = :price',
219
            [
220
                'price' => '',
221
            ],
222
        ];
223
        $return[] = [
224
            null,
225
            '/api/dummies?filter[where][price][neq]=',
226
            'o.price <> :price',
227
            [
228
                'price' => '',
229
            ],
230
        ];
231
232
        // Empty boolean value
233
        $return[] = [
234
            null,
235
            '/api/dummies?filter[where][isEnabled]=',
236
            'o.isEnabled = :isEnabled',
237
            [
238
                'isEnabled' => '',
239
            ],
240
        ];
241
        $return[] = [
242
            null,
243
            '/api/dummies?filter[where][isEnabled][neq]=',
244
            'o.isEnabled <> :isEnabled',
245
            [
246
                'isEnabled' => '',
247
            ],
248
        ];
249
250
        // gt(e)/lt(e) operator
251
        $return[] = [
252
            null,
253
            '/api/dummies?filter[where][price][gt]=40',
254
            'o.price > :price',
255
            [
256
                'price' => 40,
257
            ],
258
        ];
259
        $return[] = [
260
            null,
261
            '/api/dummies?filter[where][price][gte]=40',
262
            'o.price >= :price',
263
            [
264
                'price' => 40,
265
            ],
266
        ];
267
        $return[] = [
268
            null,
269
            '/api/dummies?filter[where][price][lt]=40',
270
            'o.price < :price',
271
            [
272
                'price' => 40,
273
            ],
274
        ];
275
        $return[] = [
276
            null,
277
            '/api/dummies?filter[where][price][lte]=40',
278
            'o.price <= :price',
279
            [
280
                'price' => 40,
281
            ],
282
        ];
283
284
        // Between operator
285
        $return[] = [
286
            null,
287
            '/api/dummies?filter[where][price][between][0]=0&filter[where][price][between][1]=7',
288
            'o.price BETWEEN :between_before_price AND :between_after_price',
289
            [
290
                'between_before_price' => 0,
291
                'between_after_price'  => 7,
292
            ],
293
        ];
294
295
        // (n)like operator
296
        $return[] = [
297
            null,
298
            '/api/dummies?filter[where][name][like]=test',
299
            'o.name LIKE :name',
300
            [
301
                'name' => '%test%',
302
            ],
303
        ];
304
        $return[] = [
305
            null,
306
            '/api/dummies?filter[where][name][nlike]=test',
307
            'o.name NOT LIKE :name',
308
            [
309
                'name' => '%test%',
310
            ],
311
        ];
312
313
//
314
        // Or operator
315
        $return[] = [
316
            null,
317
            '/api/dummies?filter[where][or][0][][name]=test&filter[where][or][0][][price]=20',
318
            'o.name = :or_name00 OR o.price = :or_price01',
319
            [
320
                'or_name00'  => 'test',
321
                'or_price01' => 20,
322
            ],
323
        ];
324
        $return[] = [
325
            null,
326
            '/api/dummies?filter[where][or][0][][name][neq]=null&filter[where][or][0][][price]=20',
327
            'o.name IS NOT NULL OR o.price = :or_price01',
328
            [
329
                'or_price01' => 20,
330
            ],
331
        ];
332
        $return[] = [
333
            null,
334
            '/api/dummies?filter[where][or][0][][name]=test&filter[where][or][0][][name]=pol&filter[where][or][1][][price]=20&filter[where][or][1][][name]=toto',
335
            '(o.name = :or_name00 OR o.name = :or_name01) AND (o.price = :or_price10 OR o.name = :or_name11)',
336
            [
337
                'or_name00'  => 'test',
338
                'or_name01'  => 'pol',
339
                'or_price10' => 20,
340
                'or_name11'  => 'toto',
341
            ],
342
        ];
343
        $return[] = [
344
            null,
345
            '/api/dummies?filter[where][or][0][name]=test&filter[where][or][0][][price]=20',
346
            '',
347
            [],
348
        ];
349
350
        //TODO: test the config
351
352
        return $return;
353
    }
354
}
355