OperatorsTest::testOperator()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
c 0
b 0
f 0
dl 0
loc 22
rs 9.8333
cc 3
nc 4
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQLTests\Doctrine\Definition\Operator;
6
7
use GraphQL\Doctrine\Definition\Operator\AbstractOperator;
8
use GraphQL\Doctrine\Definition\Operator\BetweenOperatorType;
9
use GraphQL\Doctrine\Definition\Operator\EmptyOperatorType;
10
use GraphQL\Doctrine\Definition\Operator\EqualOperatorType;
11
use GraphQL\Doctrine\Definition\Operator\GreaterOperatorType;
12
use GraphQL\Doctrine\Definition\Operator\GreaterOrEqualOperatorType;
13
use GraphQL\Doctrine\Definition\Operator\GroupOperatorType;
14
use GraphQL\Doctrine\Definition\Operator\HaveOperatorType;
15
use GraphQL\Doctrine\Definition\Operator\InOperatorType;
16
use GraphQL\Doctrine\Definition\Operator\LessOperatorType;
17
use GraphQL\Doctrine\Definition\Operator\LessOrEqualOperatorType;
18
use GraphQL\Doctrine\Definition\Operator\LikeOperatorType;
19
use GraphQL\Doctrine\Definition\Operator\NullOperatorType;
20
use GraphQL\Doctrine\Factory\UniqueNameFactory;
21
use GraphQL\Type\Definition\Type;
22
use GraphQLTests\Doctrine\Blog\Model\User;
23
use GraphQLTests\Doctrine\TypesTrait;
24
use PHPUnit\Framework\Attributes\DataProvider;
25
use PHPUnit\Framework\TestCase;
26
27
final class OperatorsTest extends TestCase
28
{
29
    use TypesTrait;
30
31
    /**
32
     * @param class-string<AbstractOperator> $className
33
     */
34
    #[DataProvider('providerOperator')]
35
    public function testOperator(string $expected, string $className, ?array $args, string $field = 'field'): void
36
    {
37
        $operator = new $className($this->types, Type::string());
38
        $uniqueNameFactory = new UniqueNameFactory();
39
        $metadata = $this->entityManager->getClassMetadata(User::class);
40
        $queryBuilder = $this->entityManager->createQueryBuilder();
41
        $alias = 'alias';
42
43
        $actual = $operator->getDqlCondition($uniqueNameFactory, $metadata, $queryBuilder, $alias, $field, $args);
44
45
        self::assertSame($expected, $actual, 'DQL condition should match');
46
47
        if (is_string($expected)) {
0 ignored issues
show
introduced by
The condition is_string($expected) is always true.
Loading history...
48
            self::assertSame(mb_substr_count($expected, ':'), $queryBuilder->getParameters()->count(), 'should declare the same number of parameters that are actually used');
49
        }
50
51
        if ($className === GroupOperatorType::class) {
52
            // @phpstan-ignore-next-line
53
            self::assertCount(1, $queryBuilder->getDQLPart('groupBy'));
54
            // @phpstan-ignore-next-line
55
            self::assertSame(['alias.field'], $queryBuilder->getDQLPart('groupBy')[0]->getParts());
56
        }
57
    }
58
59
    public static function providerOperator(): array
60
    {
61
        return [
62
            [
63
                '',
64
                BetweenOperatorType::class,
65
                null,
66
            ],
67
            ['alias.field BETWEEN :filter1 AND :filter2',
68
                BetweenOperatorType::class,
69
                [
70
                    'from' => 123,
71
                    'to' => 456,
72
                    'not' => false,
73
                ],
74
            ],
75
            [
76
                'alias.field NOT BETWEEN :filter1 AND :filter2',
77
                BetweenOperatorType::class,
78
                [
79
                    'from' => 123,
80
                    'to' => 456,
81
                    'not' => true,
82
                ],
83
            ],
84
            [
85
                '',
86
                HaveOperatorType::class,
87
                null,
88
                'posts',
89
            ],
90
            [
91
                'EXISTS (SELECT 1 FROM GraphQLTests\Doctrine\Blog\Model\Post post1 WHERE post1.user = alias.id AND post1.id IN (:filter1))',
92
                HaveOperatorType::class,
93
                [
94
                    'values' => [123, 456],
95
                    'not' => false,
96
                ],
97
                'posts',
98
            ],
99
            [
100
                'NOT EXISTS (SELECT 1 FROM GraphQLTests\Doctrine\Blog\Model\Post post1 WHERE post1.user = alias.id AND post1.id IN (:filter1))',
101
                HaveOperatorType::class,
102
                [
103
                    'values' => [123, 456],
104
                    'not' => true,
105
                ],
106
                'posts',
107
            ],
108
            [
109
                '',
110
                HaveOperatorType::class,
111
                null,
112
                'manager',
113
            ],
114
            [
115
                'alias.manager IN (:filter1)',
116
                HaveOperatorType::class,
117
                [
118
                    'values' => [123, 456],
119
                    'not' => false,
120
                ],
121
                'manager',
122
            ],
123
            [
124
                'alias.manager NOT IN (:filter1)',
125
                HaveOperatorType::class,
126
                [
127
                    'values' => [123, 456],
128
                    'not' => true,
129
                ],
130
                'manager',
131
            ],
132
            [
133
                ':filter1 MEMBER OF alias.favoritePosts',
134
                HaveOperatorType::class,
135
                [
136
                    'values' => [123, 456],
137
                    'not' => false,
138
                ],
139
                'favoritePosts',
140
            ],
141
            [
142
                ':filter1 NOT MEMBER OF alias.favoritePosts',
143
                HaveOperatorType::class,
144
                [
145
                    'values' => [123, 456],
146
                    'not' => true,
147
                ],
148
                'favoritePosts',
149
            ],
150
            [
151
                '',
152
                EmptyOperatorType::class,
153
                null,
154
                'posts',
155
            ],
156
            [
157
                'alias.posts IS EMPTY',
158
                EmptyOperatorType::class,
159
                [
160
                    'not' => false,
161
                ],
162
                'posts',
163
            ],
164
            [
165
                'alias.posts IS NOT EMPTY',
166
                EmptyOperatorType::class,
167
                [
168
                    'not' => true,
169
                ],
170
                'posts',
171
            ],
172
            [
173
                '',
174
                EmptyOperatorType::class,
175
                null,
176
                'manager',
177
            ],
178
            [
179
                'alias.manager IS NULL',
180
                EmptyOperatorType::class,
181
                [
182
                    'not' => false,
183
                ],
184
                'manager',
185
            ],
186
            [
187
                'alias.manager IS NOT NULL',
188
                EmptyOperatorType::class,
189
                [
190
                    'not' => true,
191
                ],
192
                'manager',
193
            ],
194
            [
195
                '',
196
                EqualOperatorType::class,
197
                null,
198
            ],
199
            [
200
                'alias.field = :filter1',
201
                EqualOperatorType::class,
202
                [
203
                    'value' => 123,
204
                    'not' => false,
205
                ],
206
            ],
207
            [
208
                'alias.field != :filter1',
209
                EqualOperatorType::class,
210
                [
211
                    'value' => 123,
212
                    'not' => true,
213
                ],
214
            ],
215
            [
216
                '',
217
                GreaterOperatorType::class,
218
                null,
219
            ],
220
            [
221
                'alias.field > :filter1',
222
                GreaterOperatorType::class,
223
                [
224
                    'value' => 123,
225
                    'not' => false,
226
                ],
227
            ],
228
            [
229
                'alias.field <= :filter1',
230
                GreaterOperatorType::class,
231
                [
232
                    'value' => 123,
233
                    'not' => true,
234
                ],
235
            ],
236
            [
237
                '',
238
                GreaterOrEqualOperatorType::class,
239
                null,
240
            ],
241
            [
242
                'alias.field >= :filter1',
243
                GreaterOrEqualOperatorType::class,
244
                [
245
                    'value' => 123,
246
                    'not' => false,
247
                ],
248
            ],
249
            [
250
                'alias.field < :filter1',
251
                GreaterOrEqualOperatorType::class,
252
                [
253
                    'value' => 123,
254
                    'not' => true,
255
                ],
256
            ],
257
            [
258
                '',
259
                InOperatorType::class,
260
                null,
261
            ],
262
            [
263
                'alias.field IN (:filter1)',
264
                InOperatorType::class,
265
                [
266
                    'values' => [123, 456],
267
                    'not' => false,
268
                ],
269
            ],
270
            [
271
                'alias.field NOT IN (:filter1)',
272
                InOperatorType::class,
273
                [
274
                    'values' => [123, 456],
275
                    'not' => true,
276
                ],
277
            ],
278
            [
279
                '',
280
                LessOperatorType::class,
281
                null,
282
            ],
283
            [
284
                'alias.field < :filter1',
285
                LessOperatorType::class,
286
                [
287
                    'value' => 123,
288
                    'not' => false,
289
                ],
290
            ],
291
            [
292
                'alias.field >= :filter1',
293
                LessOperatorType::class,
294
                [
295
                    'value' => 123,
296
                    'not' => true,
297
                ],
298
            ],
299
            [
300
                '',
301
                LessOrEqualOperatorType::class,
302
                null,
303
            ],
304
            [
305
                'alias.field <= :filter1',
306
                LessOrEqualOperatorType::class,
307
                [
308
                    'value' => 123,
309
                    'not' => false,
310
                ],
311
            ],
312
            [
313
                'alias.field > :filter1',
314
                LessOrEqualOperatorType::class,
315
                [
316
                    'value' => 123,
317
                    'not' => true,
318
                ],
319
            ],
320
            [
321
                '',
322
                LikeOperatorType::class,
323
                null,
324
            ],
325
            [
326
                'alias.field LIKE :filter1',
327
                LikeOperatorType::class,
328
                [
329
                    'value' => 123,
330
                    'not' => false,
331
                ],
332
            ],
333
            [
334
                'alias.field NOT LIKE :filter1',
335
                LikeOperatorType::class,
336
                [
337
                    'value' => 123,
338
                    'not' => true,
339
                ],
340
            ],
341
            [
342
                '',
343
                NullOperatorType::class,
344
                null,
345
            ],
346
            [
347
                'alias.field IS NULL',
348
                NullOperatorType::class,
349
                [
350
                    'value' => 123,
351
                    'not' => false,
352
                ],
353
            ],
354
            [
355
                'alias.field IS NOT NULL',
356
                NullOperatorType::class,
357
                [
358
                    'value' => 123,
359
                    'not' => true,
360
                ],
361
            ],
362
            [
363
                '',
364
                GroupOperatorType::class,
365
                null,
366
            ],
367
            [
368
                '',
369
                GroupOperatorType::class,
370
                [
371
                    'value' => null,
372
                ],
373
            ],
374
            [
375
                '',
376
                GroupOperatorType::class,
377
                [
378
                    'value' => true,
379
                ],
380
            ],
381
        ];
382
    }
383
}
384