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