testFilterWillThrowInvalidArgumentExceptionIfTheRequiredFromCriteriaIsMissing()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 14
rs 10
cc 1
nc 1
nop 0
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\Exception\InvalidArgumentException;
10
use Arp\DoctrineQueryFilter\Filter\FilterInterface;
11
use Arp\DoctrineQueryFilter\Filter\IsBetween;
12
use Doctrine\ORM\Query\Expr;
13
use PHPUnit\Framework\MockObject\MockObject;
14
15
/**
16
 * @covers  \Arp\DoctrineQueryFilter\Filter\IsBetween
17
 * @covers  \Arp\DoctrineQueryFilter\Filter\AbstractFilter
18
 */
19
final class IsBetweenTest extends AbstractFilterTest
20
{
21
    /**
22
     * Assert that the class implements FilterInterface
23
     */
24
    public function testImplementsFilterInterface(): void
25
    {
26
        $filter = new IsBetween($this->queryFilterManager, $this->typecaster, $this->paramNameGenerator);
27
28
        $this->assertInstanceOf(FilterInterface::class, $filter);
29
    }
30
31
    /**
32
     * Assert that a InvalidArgumentException is thrown when attempting to call filter() without
33
     * the required 'from' key
34
     *
35
     * @throws FilterException
36
     * @throws InvalidArgumentException
37
     */
38
    public function testFilterWillThrowInvalidArgumentExceptionIfTheRequiredFromCriteriaIsMissing(): void
39
    {
40
        $filter = new IsBetween($this->queryFilterManager, $this->typecaster, $this->paramNameGenerator);
41
42
        $criteria = [
43
            // Missing 'from' key
44
        ];
45
46
        $this->expectException(InvalidArgumentException::class);
47
        $this->expectExceptionMessage(
48
            sprintf('The required \'from\' criteria option is missing for filter \'%s\'', IsBetween::class)
49
        );
50
51
        $filter->filter($this->queryBuilder, $this->metadata, $criteria);
52
    }
53
54
    /**
55
     * Assert that a InvalidArgumentException is thrown when attempting to call filter() without
56
     * the required 'to' key
57
     *
58
     * @throws FilterException
59
     * @throws InvalidArgumentException
60
     */
61
    public function testFilterWillThrowInvalidArgumentExceptionIfTheRequiredToCriteriaIsMissing(): void
62
    {
63
        $filter = new IsBetween($this->queryFilterManager, $this->typecaster, $this->paramNameGenerator);
64
65
        $criteria = [
66
            'from' => '2021-03-01 00:00:00',
67
            // Missing required 'to' key
68
        ];
69
70
        $this->expectException(InvalidArgumentException::class);
71
        $this->expectExceptionMessage(
72
            sprintf('The required \'to\' criteria option is missing for filter \'%s\'', IsBetween::class)
73
        );
74
75
        $filter->filter($this->queryBuilder, $this->metadata, $criteria);
76
    }
77
78
    /**
79
     * @param array<mixed> $criteria
80
     *
81
     * @throws FilterException
82
     * @throws InvalidArgumentException
83
     *
84
     * @dataProvider getFilterIsBetweenData
85
     */
86
    public function testFilterIsBetween(array $criteria): void
87
    {
88
        /** @var IsBetween&MockObject $filter */
89
        $filter = $this->getMockBuilder(IsBetween::class)
90
            ->setConstructorArgs([$this->queryFilterManager, $this->typecaster, $this->paramNameGenerator])
91
            ->onlyMethods(['createParamName'])
92
            ->getMock();
93
94
        $rootAlias = 'entity';
95
        $from = $criteria['from'] ?? '';
96
        $to = $criteria['to'] ?? '';
97
        $alias = $criteria['alias'] ?? 'entity';
98
        $fieldName = $criteria['field'] = $criteria['field'] ?? 'test';
99
        $formatType = $criteria['format'] ?? null;
100
101
        $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

101
        $this->metadata->/** @scrutinizer ignore-call */ 
102
                         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...
102
            ->method('hasField')
103
            ->with($fieldName)
104
            ->willReturn(true);
105
106
        if (empty($criteria['alias'])) {
107
            $alias = $rootAlias;
108
109
            $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

109
            $this->queryBuilder->/** @scrutinizer ignore-call */ 
110
                                 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...
110
                ->method('getRootAlias')
111
                ->willReturn($rootAlias);
112
        }
113
114
        /** @var Expr&MockObject $expr */
115
        $expr = $this->createMock(Expr::class);
116
117
        $this->queryBuilder->expects($this->once())
118
            ->method('expr')
119
            ->willReturn($expr);
120
121
        $fromParam = $alias . 'abc123';
122
        $toParam = $alias . 'zyx999';
123
124
        $filter->expects($this->exactly(2))
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\MockOb...cker::withConsecutive() has been deprecated. ( Ignorable by Annotation )

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

124
        /** @scrutinizer ignore-deprecated */ $filter->expects($this->exactly(2))
Loading history...
125
            ->method('createParamName')
126
            ->withConsecutive(
127
                ['from', $fieldName, $alias],
128
                ['to', $fieldName, $alias]
129
            )->willReturnOnConsecutiveCalls(
130
                $fromParam,
131
                $toParam
132
            );
133
134
        $isBetween = $alias . '.' . $fieldName . ' BETWEEN ' . $fromParam . ' AND ' . $toParam;
135
        $expr->expects($this->once())
136
            ->method('between')
137
            ->with(
138
                $alias . '.' . $fieldName,
139
                ':' . $fromParam,
140
                ':' . $toParam
141
            )->willReturn(
142
                $isBetween
143
            );
144
145
        if (empty($criteria['where']) || WhereType::AND === $criteria['where']) {
146
            $this->queryBuilder->expects($this->once())
147
                ->method('andWhere')
148
                ->with($isBetween);
149
        } else {
150
            $this->queryBuilder->expects($this->once())
151
                ->method('orWhere')
152
                ->with($isBetween);
153
        }
154
155
        $this->typecaster->expects($this->exactly(2))
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

155
        $this->typecaster->/** @scrutinizer ignore-call */ 
156
                           expects($this->exactly(2))

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...
156
            ->method('typecast')
157
            ->withConsecutive(
158
                [$this->metadata, $fieldName, $from, $formatType, []],
159
                [$this->metadata, $fieldName, $to, $formatType, []],
160
            )->willReturnOnConsecutiveCalls(
161
                $from,
162
                $to
163
            );
164
165
        $this->queryBuilder->expects($this->exactly(2))
166
            ->method('setParameter')
167
            ->withConsecutive(
168
                [$fromParam, $from],
169
                [$toParam, $to]
170
            );
171
172
        $filter->filter($this->queryBuilder, $this->metadata, $criteria);
173
    }
174
175
    /**
176
     * @return array<mixed><mixed>
177
     */
178
    public function getFilterIsBetweenData(): array
179
    {
180
        return [
181
            [
182
                [
183
                    'to'   => '2021-01-01 00:00:00',
184
                    'from' => '2021-02-01 00:00:00',
185
                ],
186
            ],
187
188
            [
189
                [
190
                    'to'    => '2021-01-01 00:00:00',
191
                    'from'  => '2021-02-01 00:00:00',
192
                    'where' => WhereType::AND,
193
                ],
194
            ],
195
196
            [
197
                [
198
                    'to'    => '2021-01-01 00:00:00',
199
                    'from'  => '2021-02-01 00:00:00',
200
                    'where' => WhereType::OR,
201
                ],
202
            ],
203
204
            [
205
                [
206
                    'to'    => '2000-01-01 11:12:45',
207
                    'from'  => '2021-01-01 07:35:17',
208
                    'alias' => 'test_alias_123',
209
                ],
210
            ],
211
        ];
212
    }
213
}
214