Passed
Pull Request — master (#4)
by Alex
03:07
created

testImplementsFilterInterface()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
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\Constant\WhereType;
8
use Arp\DoctrineQueryFilter\Filter\Exception\FilterException;
9
use Arp\DoctrineQueryFilter\Filter\FilterInterface;
10
use Doctrine\ORM\Query\Expr;
11
use PHPUnit\Framework\MockObject\MockObject;
12
13
/**
14
 * @author  Alex Patterson <[email protected]>
15
 * @package ArpTest\DoctrineQueryFilter\Filter
16
 */
17
abstract class AbstractComparisonTest extends AbstractFilterTest
18
{
19
    /**
20
     * @var FilterInterface
21
     */
22
    protected FilterInterface $filter;
23
24
    /**
25
     * @var string
26
     */
27
    protected string $filterClassName;
28
29
    /**
30
     * @var string
31
     */
32
    protected string $expressionMethodName;
33
34
    /**
35
     * @var string
36
     */
37
    protected string $expressionSymbol;
38
39
    /**
40
     * Prepare the test case dependencies
41
     */
42
    public function setUp(): void
43
    {
44
        parent::setUp();
45
46
        $this->filter = new $this->filterClassName($this->queryFilterManager, $this->typecaster);
47
    }
48
49
    /**
50
     * Assert that the filter implements FilterInterface
51
     */
52
    public function testImplementsFilterInterface(): void
53
    {
54
        $this->assertInstanceOf(FilterInterface::class, $this->filter);
55
    }
56
57
    /**
58
     * Assert that the query filter can be applied with the provided $criteria
59
     *
60
     * @param array<mixed> $criteria
61
     *
62
     * @dataProvider getFilterWillApplyFilteringData
63
     *
64
     * @throws FilterException
65
     */
66
    public function testFilterWillApplyFiltering(array $criteria): void
67
    {
68
        $fieldName = $criteria['field'] ?? 'testFieldName';
69
        $alias = $criteria['alias'] ?? null;
70
71
        $this->metadata->expects($this->once())
72
            ->method('hasField')
73
            ->with($fieldName)
74
            ->willReturn(true);
75
76
        /** @var Expr&MockObject $expr */
77
        $expr = $this->createMock(Expr::class);
78
79
        $this->queryBuilder->expects($this->once())
80
            ->method('expr')
81
            ->willReturn($expr);
82
83
        /** @var Expr\Comparison&MockObject $comparisonExpr */
84
        $comparisonExpr = $this->createMock(Expr\Comparison::class);
85
86
        if (null === $alias) {
87
            $alias = 'entity';
88
            $this->queryBuilder->expects($this->once())
89
                ->method('getRootAlias')
90
                ->willReturn($alias);
91
        }
92
93
        $expressionString = $this->getExpressionString($fieldName, $alias, $criteria);
94
95
        $expr->expects($this->once())
96
            ->method($this->expressionMethodName)
97
            ->willReturn($comparisonExpr);
98
99
        $comparisonExpr->expects($this->once())
100
            ->method('__toString')
101
            ->willReturn($expressionString);
102
103
        $methodName = (!isset($criteria['where']) || WhereType::AND === $criteria['where'])
104
            ? 'andWhere'
105
            : 'orWhere';
106
107
        $this->queryBuilder->expects($this->once())->method($methodName);
108
109
        if (array_key_exists('value', $criteria)) {
110
            $this->typecaster->expects($this->once())
111
                ->method('typecast')
112
                ->with($this->metadata, $fieldName, $criteria['value'])
113
                ->willReturn($criteria['value']);
114
115
            $this->queryBuilder->expects($this->once())
116
                ->method('setParameter')
117
                ->with($this->callback(static function ($argument) {
118
                    return is_string($argument);
119
                }), $criteria['value']);
120
        }
121
122
        $this->filter->filter($this->queryBuilder, $this->metadata, $criteria);
123
    }
124
125
    /**
126
     * @return array<mixed>
127
     */
128
    abstract public function getFilterWillApplyFilteringData(): array;
129
130
    /**
131
     * @param string      $fieldName
132
     * @param string|null $alias
133
     * @param array<mixed>      $criteria
134
     *
135
     * @return string
136
     */
137
    protected function getExpressionString(string $fieldName, ?string $alias, array $criteria): string
138
    {
139
        $expressionString = $alias . '.' . $fieldName . ' ' . $this->expressionSymbol;
140
        if (array_key_exists('value', $criteria)) {
141
            $expressionString .= ' :param_name';
142
        }
143
        return $expressionString;
144
    }
145
}
146