DefenceTest   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 143
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 7
eloc 70
dl 0
loc 143
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A testEachFilterInTheFilterChainIsInvoked() 0 40 1
A createFilterMock() 0 5 1
A createEnvelope() 0 3 1
A testExecuteWillNotExecuteTheHandlerIfTheRequestIsNotSuspicious() 0 30 1
A createHandlerMock() 0 5 1
A testExecuteExecutesTheHandlerIfTheRequestIsSuspicious() 0 31 1
A testConstructor() 0 11 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DanBettles\Defence\Tests;
6
7
use DanBettles\Defence\Defence;
8
use DanBettles\Defence\Envelope;
9
use DanBettles\Defence\Filter\FilterInterface;
10
use DanBettles\Defence\Handler\HandlerInterface;
11
use DanBettles\Defence\Logger\NullLogger;
12
use DanBettles\Gestalt\SimpleFilterChain;
13
use PHPUnit\Framework\MockObject\MockObject;
14
use PHPUnit\Framework\TestCase;
15
use Symfony\Component\HttpFoundation\Request;
16
17
use const false;
18
use const true;
19
20
class DefenceTest extends TestCase
21
{
22
    //###> Factory Methods ###
23
    private function createEnvelope(): Envelope
24
    {
25
        return new Envelope(Request::createFromGlobals(), new NullLogger());
26
    }
27
28
    private function createHandlerMock(): MockObject
29
    {
30
        return $this
31
            ->getMockBuilder(HandlerInterface::class)
32
            ->getMock()
33
        ;
34
    }
35
36
    private function createFilterMock(): MockObject
37
    {
38
        return $this
39
            ->getMockBuilder(FilterInterface::class)
40
            ->getMock()
41
        ;
42
    }
43
    //###< Factory Methods ###
44
45
    public function testConstructor(): void
46
    {
47
        $filterChain = new SimpleFilterChain([]);
48
        $handlerMock = $this->createHandlerMock();
49
50
        /** @var HandlerInterface $handlerMock */
51
52
        $defence = new Defence($filterChain, $handlerMock);
53
54
        $this->assertSame($filterChain, $defence->getFilterChain());
55
        $this->assertSame($handlerMock, $defence->getHandler());
56
    }
57
58
    public function testExecuteExecutesTheHandlerIfTheRequestIsSuspicious(): void
59
    {
60
        $envelope = $this->createEnvelope();
61
62
        $filterChainMock = $this
63
            ->getMockBuilder(SimpleFilterChain::class)
64
            ->onlyMethods(['execute'])
65
            ->getMock()
66
        ;
67
68
        $filterChainMock
69
            ->expects($this->once())
70
            ->method('execute')
71
            ->with($envelope, true)  //Pass the envelope to each filter, break if a filter returns `true`.
72
            ->willReturn(true)  //Simulate request is suspicious.
73
        ;
74
75
        /** @var SimpleFilterChain $filterChainMock */
76
77
        $handlerMock = $this->createHandlerMock();
78
79
        $handlerMock
80
            ->expects($this->once())
81
            ->method('__invoke')
82
            ->with($envelope)
83
        ;
84
85
        /** @var HandlerInterface $handlerMock */
86
87
        $defence = new Defence($filterChainMock, $handlerMock);
88
        $defence->execute($envelope);
89
    }
90
91
    public function testExecuteWillNotExecuteTheHandlerIfTheRequestIsNotSuspicious(): void
92
    {
93
        $envelope = $this->createEnvelope();
94
95
        $filterChainMock = $this
96
            ->getMockBuilder(SimpleFilterChain::class)
97
            ->onlyMethods(['execute'])
98
            ->getMock()
99
        ;
100
101
        $filterChainMock
102
            ->expects($this->once())
103
            ->method('execute')
104
            ->with($envelope, true)  //Pass the envelope to each filter, break if a filter returns `true`.
105
            ->willReturn(false)  //Simulate request is _not_ suspicious.
106
        ;
107
108
        /** @var SimpleFilterChain $filterChainMock */
109
110
        $handlerMock = $this->createHandlerMock();
111
112
        $handlerMock
113
            ->expects($this->never())  //The handler must never be called if the request is not suspicious.
114
            ->method('__invoke')
115
        ;
116
117
        /** @var HandlerInterface $handlerMock */
118
119
        $defence = new Defence($filterChainMock, $handlerMock);
120
        $defence->execute($envelope);
121
    }
122
123
    public function testEachFilterInTheFilterChainIsInvoked(): void
124
    {
125
        $envelope = $this->createEnvelope();
126
127
        $falseFilterMock = $this->createFilterMock();
128
129
        $falseFilterMock
130
            ->expects($this->once())  //Yes, the filter will be called.
131
            ->method('__invoke')
132
            ->with($envelope)
133
            ->willReturn(false)  //No, the request looks okay.
134
        ;
135
136
        $trueFilterMock = $this->createFilterMock();
137
138
        $trueFilterMock
139
            ->expects($this->once())  //Yes, the filter will be called.
140
            ->method('__invoke')
141
            ->with($envelope)
142
            ->willReturn(true)  //Yes, the request looks suspicious.
143
        ;
144
145
        $neverFilterMock = $this->createFilterMock();
146
147
        $neverFilterMock
148
            ->expects($this->never())  //No, the filter won't be called -- it'll never be reached.
149
            ->method('__invoke')
150
        ;
151
152
        $filterChain = new SimpleFilterChain([
153
            $falseFilterMock,
154
            $trueFilterMock,
155
            $neverFilterMock,
156
        ]);
157
158
        $handlerMock = $this->createHandlerMock();
159
        /** @var HandlerInterface $handlerMock */
160
161
        $defence = new Defence($filterChain, $handlerMock);
162
        $defence->execute($envelope);
163
    }
164
}
165