IsMemberOfTest::testFilterWillApplyFiltering()   B
last analyzed

Complexity

Conditions 5
Paths 16

Size

Total Lines 71
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 48
c 2
b 0
f 0
nc 16
nop 1
dl 0
loc 71
rs 8.8234

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\DoctrineQueryFilter\Filter;
6
7
use Arp\DoctrineQueryFilter\Enum\WhereType;
8
use Arp\DoctrineQueryFilter\Filter\Exception\FilterException;
9
use Arp\DoctrineQueryFilter\Filter\IsMemberOf;
10
use Doctrine\ORM\Mapping\ClassMetadataInfo;
11
use Doctrine\ORM\Query\Expr;
12
use PHPUnit\Framework\MockObject\MockObject;
13
14
/**
15
 * @covers \Arp\DoctrineQueryFilter\Filter\IsMemberOf
16
 * @covers \Arp\DoctrineQueryFilter\Filter\AbstractExpression
17
 * @covers \Arp\DoctrineQueryFilter\Filter\AbstractFilter
18
 */
19
final class IsMemberOfTest extends AbstractComparisonTest
20
{
21
    protected string $filterClassName = IsMemberOf::class;
22
23
    protected string $expressionMethodName = 'isMemberOf';
24
25
    protected string $expressionSymbol = 'MEMBER OF';
26
27
    /**
28
     * @dataProvider getInvalidNonCollectionFieldWillThrowInvalidArgumentExceptionData
29
     */
30
    public function testInvalidNonCollectionFieldWillThrowInvalidArgumentException(
31
        string $fieldName,
32
        ?int $associationType
33
    ): void {
34
        $parts = explode('.', $fieldName);
35
        $fieldName = array_pop($parts);
36
37
        $this->metadata->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Arp\DoctrineQueryFilter\Metadata\MetadataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

37
        $this->metadata->/** @scrutinizer ignore-call */ 
38
                         expects($this->once())

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...
38
            ->method('hasField')
39
            ->with($fieldName)
40
            ->willReturn(true);
41
42
        $this->metadata->expects($this->once())
43
            ->method('hasAssociation')
44
            ->with($fieldName)
45
            ->willReturn(true);
46
47
        $associationMapping = [
48
            'type' => $associationType,
49
        ];
50
51
        $this->metadata->expects($this->once())
52
            ->method('getAssociationMapping')
53
            ->with($fieldName)
54
            ->willReturn($associationMapping);
55
56
57
        $this->expectException(FilterException::class);
58
        $this->expectExceptionMessage(
59
            sprintf(
60
                'Unable to apply query filter \'%s\': '
61
                . 'The field \'%s\' is not a valid collection valued association',
62
                IsMemberOf::class,
63
                $fieldName,
64
            ),
65
        );
66
67
        $this->filter->filter($this->queryBuilder, $this->metadata, ['field' => $fieldName]);
68
    }
69
70
    public static function getInvalidNonCollectionFieldWillThrowInvalidArgumentExceptionData(): array
71
    {
72
        return [
73
            [
74
                'testFieldName',
75
                ClassMetadataInfo::MANY_TO_ONE,
76
            ],
77
            [
78
                'x.testFieldName',
79
                ClassMetadataInfo::ONE_TO_ONE,
80
            ],
81
            [
82
                'x.fooFieldName',
83
                null,
84
            ],
85
        ];
86
    }
87
88
    /**
89
     * Assert that the IsMemberOf query filter can be applied with the provided $criteria
90
     *
91
     * @dataProvider getFilterWillApplyFilteringData
92
     * @throws FilterException
93
     */
94
    public function testFilterWillApplyFiltering(array $criteria): void
95
    {
96
        $fieldName = $criteria['field'] ?? 'testFieldName';
97
        $alias = $criteria['alias'] ?? null;
98
99
        $mapping = [
100
            'type' => 4
101
        ];
102
103
        $this->metadata->expects($this->once())
104
            ->method('hasField')
105
            ->with($fieldName)
106
            ->willReturn(true);
107
108
        $this->metadata->expects($this->once())
109
            ->method('hasAssociation')
110
            ->with($fieldName)
111
            ->willReturn(true);
112
113
        $this->metadata->expects($this->once())
114
            ->method('getAssociationMapping')
115
            ->with($fieldName)
116
            ->willReturn($mapping);
117
118
        /** @var Expr&MockObject $expr */
119
        $expr = $this->createMock(Expr::class);
120
121
        $this->queryBuilder->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Arp\DoctrineQueryFilter\QueryBuilderInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

121
        $this->queryBuilder->/** @scrutinizer ignore-call */ 
122
                             expects($this->once())

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...
122
            ->method('expr')
123
            ->willReturn($expr);
124
125
        /** @var Expr\Comparison&MockObject $comparisonExpr */
126
        $comparisonExpr = $this->createMock(Expr\Comparison::class);
127
128
        if (null === $alias) {
129
            $alias = 'entity';
130
            $this->queryBuilder->expects($this->once())
131
                ->method('getRootAlias')
132
                ->willReturn($alias);
133
        }
134
135
        $expressionString = $this->getExpressionString($fieldName, $alias, $criteria);
136
137
        $expr->expects($this->once())
138
            ->method($this->expressionMethodName)
139
            ->willReturn($comparisonExpr);
140
141
        $comparisonExpr->expects($this->once())
142
            ->method('__toString')
143
            ->willReturn($expressionString);
144
145
        $methodName = (!isset($criteria['where']) || WhereType::AND === $criteria['where'])
146
            ? 'andWhere'
147
            : 'orWhere';
148
149
        $this->queryBuilder->expects($this->once())->method($methodName);
150
151
        if (array_key_exists('value', $criteria)) {
152
            $this->typecaster->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Arp\DoctrineQueryFilter\...ata\TypecasterInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

152
            $this->typecaster->/** @scrutinizer ignore-call */ 
153
                               expects($this->once())

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...
153
                ->method('typecast')
154
                ->with($this->metadata, $fieldName, $criteria['value'])
155
                ->willReturn($criteria['value']);
156
157
            $this->queryBuilder->expects($this->once())
158
                ->method('setParameter')
159
                ->with($this->callback(static function ($argument) {
160
                    return is_string($argument);
161
                }), $criteria['value']);
162
        }
163
164
        $this->filter->filter($this->queryBuilder, $this->metadata, $criteria);
165
    }
166
167
    protected function getExpressionString(string $fieldName, ?string $alias, array $criteria): string
168
    {
169
        return ':param_name ' . $this->expressionSymbol . $alias . '.' . $fieldName;
170
    }
171
172
    public function getFilterWillApplyFilteringData(): array
173
    {
174
        return [
175
            [
176
                [
177
                    'name' => 'test',
178
                    'field' => 'hello',
179
                    'value' => 123,
180
                ],
181
            ],
182
        ];
183
    }
184
}
185