Passed
Push — master ( 7438ce...69adc8 )
by Guilherme
01:29 queued 11s
created

PhoneVerificationSubscriberTest::getPhoneVerificationSubscriber()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 32
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 5
eloc 16
nc 4
nop 4
dl 0
loc 32
ccs 0
cts 26
cp 0
crap 30
rs 8.439
c 1
b 1
f 0
1
<?php
2
/**
3
 * This file is part of the login-cidadao project or it's bundles.
4
 *
5
 * (c) Guilherme Donato <guilhermednt on github>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace PROCERGS\LoginCidadao\PhoneVerificationBundle\Tests\Event;
12
13
use Eljam\CircuitBreaker\Breaker;
14
use Eljam\CircuitBreaker\Exception\CircuitOpenException;
15
use libphonenumber\PhoneNumber;
16
use LoginCidadao\CoreBundle\Model\PersonInterface;
17
use LoginCidadao\PhoneVerificationBundle\Event\SendPhoneVerificationEvent;
18
use LoginCidadao\PhoneVerificationBundle\Model\PhoneVerificationInterface;
19
use LoginCidadao\PhoneVerificationBundle\PhoneVerificationEvents;
20
use PHPUnit\Framework\TestCase;
21
use PROCERGS\LoginCidadao\PhoneVerificationBundle\Event\PhoneVerificationSubscriber;
22
use PROCERGS\Sms\Exception\InvalidCountryException;
23
use PROCERGS\Sms\SmsService;
24
use Psr\Log\LogLevel;
25
26
class PhoneVerificationSubscriberTest extends TestCase
27
{
28
    public function testGetSubscribedEvents()
29
    {
30
        $this->assertArrayHasKey(
31
            PhoneVerificationEvents::PHONE_VERIFICATION_REQUESTED,
32
            PhoneVerificationSubscriber::getSubscribedEvents()
33
        );
34
    }
35
36
    public function testOnVerificationRequestClosedCircuitBreaker()
37
    {
38
        $phoneNumber = $this->createMock('libphonenumber\PhoneNumber');
39
        $person = $this->createMock('LoginCidadao\CoreBundle\Model\PersonInterface');
40
        $phoneVerification = $this->getPhoneVerification($person, $phoneNumber);
41
        $event = $this->getEvent($phoneVerification, true);
42
        $dispatcher = $this->getDispatcher($event);
43
44
        $subscriber = $this->getPhoneVerificationSubscriber();
45
        $subscriber->onVerificationRequest($event, PhoneVerificationEvents::PHONE_VERIFICATION_REQUESTED, $dispatcher);
46
    }
47
48
    public function testOnVerificationRequestOpenCircuitBreaker()
49
    {
50
        $phoneNumber = $this->createMock('libphonenumber\PhoneNumber');
51
        $person = $this->createMock('LoginCidadao\CoreBundle\Model\PersonInterface');
52
        $phoneVerification = $this->getPhoneVerification($person, $phoneNumber);
53
        $event = $this->getEvent($phoneVerification, false);
54
        $dispatcher = $this->getDispatcher();
55
        $breaker = $this->getBreaker(new CircuitOpenException());
56
57
        $subscriber = $this->getPhoneVerificationSubscriber($breaker, false);
58
        $subscriber->onVerificationRequest($event, PhoneVerificationEvents::PHONE_VERIFICATION_REQUESTED, $dispatcher);
59
    }
60
61
    public function testOnVerificationRequestCloseCircuitBreaker()
62
    {
63
        $phoneNumber = $this->createMock('libphonenumber\PhoneNumber');
64
        $person = $this->createMock('LoginCidadao\CoreBundle\Model\PersonInterface');
65
        $phoneVerification = $this->getPhoneVerification($person, $phoneNumber);
66
        $event = $this->getEvent($phoneVerification, false);
67
        $dispatcher = $this->getDispatcher();
68
        $breaker = $this->getBreaker(new \Exception("Generic error"));
69
70
        $subscriber = $this->getPhoneVerificationSubscriber($breaker, false);
71
        $subscriber->onVerificationRequest($event, PhoneVerificationEvents::PHONE_VERIFICATION_REQUESTED, $dispatcher);
72
    }
73
74
    public function testUnsupportedCountry()
75
    {
76
        $phoneNumber = new PhoneNumber();
77
        $phoneNumber->setCountryCode(1)
78
            ->setNationalNumber('123456');
79
        $person = $this->createMock('LoginCidadao\CoreBundle\Model\PersonInterface');
80
        $phoneVerification = $this->getPhoneVerification($person, $phoneNumber);
81
        $event = $this->getEvent($phoneVerification, false);
82
        $dispatcher = $this->getDispatcher();
83
        $breakerConfig = [
84
            'allowed_exceptions' => ['PROCERGS\Sms\Exception\InvalidCountryException'],
85
        ];
86
        $breaker = new Breaker('my_breaker', $breakerConfig);
87
88
        $logger = $this->createMock('Psr\Log\LoggerInterface');
89
        $logger->expects($this->once())->method('log')->with(LogLevel::ERROR);
90
91
        $smsService = $this->getSmsService();
92
        $smsService->expects($this->once())->method('easySend')
93
            ->willThrowException(new InvalidCountryException('Unsupported Country'));
94
95
        $subscriber = $this->getPhoneVerificationSubscriber($breaker, false, $smsService, $logger);
96
        $subscriber->setLogger($logger);
97
98
        $subscriber->onVerificationRequest($event, PhoneVerificationEvents::PHONE_VERIFICATION_REQUESTED, $dispatcher);
99
    }
100
101
    /**
102
     * @param Breaker|null $breaker
103
     * @param bool $expectEasySend
104
     * @return PhoneVerificationSubscriber
105
     */
106
    private function getPhoneVerificationSubscriber(
107
        Breaker $breaker = null,
108
        $expectEasySend = true,
109
        $smsService = null,
110
        $logger = null
111
    ) {
112
        $smsService = $smsService ?: $this->getSmsService();
113
        if ($expectEasySend) {
114
            $smsService->expects($this->once())->method('easySend')->willReturn('012345');
115
        }
116
117
        $translator = $this->createMock('Symfony\Component\Translation\TranslatorInterface');
118
        $translator->expects($this->once())->method('trans')->willReturn('message');
119
120
        $router = $this->createMock('Symfony\Component\Routing\RouterInterface');
121
        $router->expects($this->once())->method('generate')->willReturnCallback(
122
            function ($routeName) {
123
                return $routeName;
124
            }
125
        );
126
127
        $breaker = $breaker ?: new Breaker('breaker');
128
129
        if ($logger === null) {
130
            $logger = $this->createMock('Psr\Log\LoggerInterface');
131
            $logger->expects($this->once())->method('log');
132
        }
133
134
        $subscriber = new PhoneVerificationSubscriber($smsService, $translator, $router, $breaker);
135
        $subscriber->setLogger($logger);
136
137
        return $subscriber;
138
    }
139
140
    /**
141
     * @return \PHPUnit_Framework_MockObject_MockObject|SmsService
142
     */
143
    private function getSmsService()
144
    {
145
        $smsService = $this->getMockBuilder('PROCERGS\Sms\SmsService')
146
            ->disableOriginalConstructor()
147
            ->getMock();
148
149
        return $smsService;
150
    }
151
152
    private function getPhoneVerification(PersonInterface $person, PhoneNumber $phoneNumber)
153
    {
154
        $phoneVerificationClass = 'LoginCidadao\PhoneVerificationBundle\Model\PhoneVerificationInterface';
155
        $phoneVerification = $this->createMock($phoneVerificationClass);
156
        $phoneVerification->expects($this->any())->method('getPerson')->willReturn($person);
157
        $phoneVerification->expects($this->any())->method('getVerificationCode')->willReturn(123456);
158
        $phoneVerification->expects($this->any())->method('getPhone')->willReturn($phoneNumber);
159
160
        return $phoneVerification;
161
    }
162
163
    private function getEvent(PhoneVerificationInterface $phoneVerification = null, $sent = true)
164
    {
165
        $event = $this->getMockBuilder('LoginCidadao\PhoneVerificationBundle\Event\SendPhoneVerificationEvent')
166
            ->disableOriginalConstructor()
167
            ->getMock();
168
169
        $event->expects($this->atLeastOnce())->method('getPhoneVerification')->willReturn($phoneVerification);
170
171
        if ($sent) {
172
            $event->expects($this->once())->method('setSentVerification')->with(
173
                $this->isInstanceOf('LoginCidadao\PhoneVerificationBundle\Entity\SentVerification')
174
            );
175
        }
176
177
        return $event;
178
    }
179
180
    private function getDispatcher(SendPhoneVerificationEvent $event = null)
181
    {
182
        $dispatcher = $this->createMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
183
        if ($event) {
184
            $dispatcher->expects($this->once())->method('dispatch')->with(
185
                PhoneVerificationEvents::PHONE_VERIFICATION_CODE_SENT,
186
                $event
187
            );
188
        }
189
190
        return $dispatcher;
191
    }
192
193
    private function getBreaker($exception = null)
194
    {
195
        $breaker = null;
196
        if ($exception instanceof \Exception) {
197
            $breaker = $this->getMockBuilder('Eljam\CircuitBreaker\Breaker')
198
                ->disableOriginalConstructor()
199
                ->getMock();
200
            $breaker->expects($this->once())->method('protect')
201
                ->willThrowException($exception);
202
        }
203
204
        return $breaker ?: new Breaker('name');
205
    }
206
}
207