Test Setup Failed
Pull Request — master (#4)
by Alex
06:07
created

IsBetweenTest   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 190
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 8
eloc 92
c 2
b 0
f 0
dl 0
loc 190
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A testImplementsFilterInterface() 0 5 1
A testFilterWillThrowInvalidArgumentExceptionIfTheRequiredToCriteriaIsMissing() 0 15 1
A testFilterWillThrowInvalidArgumentExceptionIfTheRequiredFromCriteriaIsMissing() 0 14 1
B testFilterIsBetween() 0 87 4
A getFilterIsBetweenData() 0 31 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\DoctrineQueryFilter\Filter;
6
7
use Arp\DoctrineQueryFilter\Constant\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
 * @author  Alex Patterson <[email protected]>
20
 * @package ArpTest\DoctrineQueryFilter\Filter
21
 */
22
final class IsBetweenTest extends AbstractFilterTest
23
{
24
    /**
25
     * Assert that the class implements FilterInterface
26
     */
27
    public function testImplementsFilterInterface(): void
28
    {
29
        $filter = new IsBetween($this->queryFilterManager, $this->typecaster);
30
31
        $this->assertInstanceOf(FilterInterface::class, $filter);
32
    }
33
34
    /**
35
     * Assert that a InvalidArgumentException is thrown when attempting to call filter() without
36
     * the required 'from' key
37
     *
38
     * @throws FilterException
39
     * @throws InvalidArgumentException
40
     */
41
    public function testFilterWillThrowInvalidArgumentExceptionIfTheRequiredFromCriteriaIsMissing(): void
42
    {
43
        $filter = new IsBetween($this->queryFilterManager, $this->typecaster);
44
45
        $criteria = [
46
            // Missing 'from' key
47
        ];
48
49
        $this->expectException(InvalidArgumentException::class);
50
        $this->expectExceptionMessage(
51
            sprintf('The required \'from\' criteria option is missing for filter \'%s\'', IsBetween::class)
52
        );
53
54
        $filter->filter($this->queryBuilder, $this->metadata, $criteria);
55
    }
56
57
    /**
58
     * Assert that a InvalidArgumentException is thrown when attempting to call filter() without
59
     * the required 'to' key
60
     *
61
     * @throws FilterException
62
     * @throws InvalidArgumentException
63
     */
64
    public function testFilterWillThrowInvalidArgumentExceptionIfTheRequiredToCriteriaIsMissing(): void
65
    {
66
        $filter = new IsBetween($this->queryFilterManager, $this->typecaster);
67
68
        $criteria = [
69
            'from' => '2021-03-01 00:00:00',
70
            // Missing required 'to' key
71
        ];
72
73
        $this->expectException(InvalidArgumentException::class);
74
        $this->expectExceptionMessage(
75
            sprintf('The required \'to\' criteria option is missing for filter \'%s\'', IsBetween::class)
76
        );
77
78
        $filter->filter($this->queryBuilder, $this->metadata, $criteria);
79
    }
80
81
    /**
82
     * @param array $criteria
83
     *
84
     * @throws FilterException
85
     * @throws InvalidArgumentException
86
     *
87
     * @dataProvider getFilterIsBetweenData
88
     */
89
    public function testFilterIsBetween(array $criteria): void
90
    {
91
        /** @var IsBetween|MockObject $filter */
92
        $filter = $this->getMockBuilder(IsBetween::class)
93
            ->setConstructorArgs([$this->queryFilterManager, $this->typecaster])
94
            ->onlyMethods(['createParamName'])
95
            ->getMock();
96
97
        $rootAlias = 'entity';
98
        $from = $criteria['from'] ?? '';
99
        $to = $criteria['to'] ?? '';
100
        $alias = $criteria['alias'] ?? 'entity';
101
        $fieldName = $criteria['field'] = $criteria['field'] ?? 'test';
102
        $formatType = $criteria['format'] ?? null;
103
104
        $this->metadata->expects($this->once())
105
            ->method('hasField')
106
            ->with($fieldName)
107
            ->willReturn(true);
108
109
        if (empty($criteria['alias'])) {
110
            $alias = $rootAlias;
111
112
            $this->queryBuilder->expects($this->once())
113
                ->method('getRootAlias')
114
                ->willReturn($rootAlias);
115
        }
116
117
        /** @var Expr|MockObject $expr */
118
        $expr = $this->createMock(Expr::class);
119
120
        $this->queryBuilder->expects($this->once())
121
            ->method('expr')
122
            ->willReturn($expr);
123
124
        $fromParam = $alias . 'abc123';
125
        $toParam = $alias . 'zyx999';
126
127
        $filter->expects($this->exactly(2))
128
            ->method('createParamName')
129
            ->withConsecutive(
130
                [$alias],
131
                [$alias]
132
            )->willReturnOnConsecutiveCalls(
133
                $fromParam,
134
                $toParam
135
            );
136
137
        $isBetween = $alias . '.' . $fieldName . ' BETWEEN ' . $fromParam . ' AND ' . $toParam;
138
        $expr->expects($this->once())
139
            ->method('between')
140
            ->with(
141
                $alias . '.' . $fieldName,
142
                ':' . $fromParam,
143
                ':' . $toParam
144
            )->willReturn(
145
                $isBetween
146
            );
147
148
        if (empty($criteria['where']) || WhereType:: AND === $criteria['where']) {
149
            $this->queryBuilder->expects($this->once())
150
                ->method('andWhere')
151
                ->with($isBetween);
152
        } else {
153
            $this->queryBuilder->expects($this->once())
154
                ->method('orWhere')
155
                ->with($isBetween);
156
        }
157
158
        $this->typecaster->expects($this->exactly(2))
159
            ->method('typecast')
160
            ->withConsecutive(
161
                [$this->metadata, $fieldName, $from, $formatType, []],
162
                [$this->metadata, $fieldName, $to, $formatType, []],
163
            )->willReturnOnConsecutiveCalls(
164
                $from,
165
                $to
166
            );
167
168
        $this->queryBuilder->expects($this->exactly(2))
169
            ->method('setParameter')
170
            ->withConsecutive(
171
                [$fromParam, $from],
172
                [$toParam, $to]
173
            );
174
175
        $filter->filter($this->queryBuilder, $this->metadata, $criteria);
176
    }
177
178
    /**
179
     * @return array
180
     */
181
    public function getFilterIsBetweenData(): array
182
    {
183
        return [
184
            [
185
                [
186
                    'to'   => '2021-01-01 00:00:00',
187
                    'from' => '2021-02-01 00:00:00',
188
                ],
189
            ],
190
191
            [
192
                [
193
                    'to'    => '2021-01-01 00:00:00',
194
                    'from'  => '2021-02-01 00:00:00',
195
                    'where' => WhereType:: AND,
196
                ],
197
            ],
198
199
            [
200
                [
201
                    'to'    => '2021-01-01 00:00:00',
202
                    'from'  => '2021-02-01 00:00:00',
203
                    'where' => WhereType:: OR,
204
                ],
205
            ],
206
207
            [
208
                [
209
                    'to'    => '2000-01-01 11:12:45',
210
                    'from'  => '2021-01-01 07:35:17',
211
                    'alias' => 'test_alias_123',
212
                ],
213
            ],
214
        ];
215
    }
216
}
217