Completed
Pull Request — master (#790)
by Guilherme
08:21 queued 04:10
created

SystemsRegistryServiceTest   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 283
Duplicated Lines 0 %

Importance

Changes 4
Bugs 2 Features 0
Metric Value
dl 0
loc 283
rs 10
c 4
b 2
f 0
wmc 18
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\AccountingBundle\Tests\Service;
12
13
use GuzzleHttp\ClientInterface;
14
use GuzzleHttp\Exception\ClientException;
15
use function GuzzleHttp\Psr7\stream_for;
16
use LoginCidadao\OAuthBundle\Entity\Client;
17
use PHPUnit\Framework\MockObject\MockObject;
18
use PHPUnit\Framework\TestCase;
19
use PROCERGS\LoginCidadao\AccountingBundle\Entity\ProcergsLink;
20
use PROCERGS\LoginCidadao\AccountingBundle\Entity\ProcergsLinkRepository;
21
use PROCERGS\LoginCidadao\AccountingBundle\Service\SystemsRegistryService;
22
use Psr\Http\Message\ResponseInterface;
23
use Psr\Log\LoggerInterface;
24
25
/**
26
 * @codeCoverageIgnore
27
 */
28
class SystemsRegistryServiceTest extends TestCase
29
{
30
    private $config = [
31
        'apiUri' => 'https://api.uri/{host}',
32
        'organization' => 'MyOrganization',
33
        'registration_number' => 1234,
34
        'password' => 'ultra_top_secret_password',
35
    ];
36
37
    public function testGetSystemInitials()
38
    {
39
        $client = new Client();
40
        $client->setSiteUrl('http://host1/path');
41
        $client->setRedirectUris([
42
            'http://host1/path',
43
            'http://host2/path',
44
            'http://host2/path2',
45
        ]);
46
47
        $queries = [];
48
        $httpClient = $this->getHttpClient();
49
        $this->httpClientExpectGet($httpClient, $queries, 3);
50
51
        $registry = $this->getRegistry($httpClient);
52
53
        $initials = $registry->getSystemInitials($client);
54
55
        $this->assertContains('http://host1/path', $queries);
56
        $this->assertContains('http://host2/path', $queries);
57
        $this->assertContains('http://host2/path2', $queries);
58
        $this->assertCount(3, $queries);
59
        $this->assertContains('XPTO', $initials);
60
    }
61
62
    public function testGetSystemInitialsFromCache()
63
    {
64
        $client = new Client();
65
        $client->setSiteUrl('http://host1/path');
66
        $client->setRedirectUris([
67
            'http://host1/path',
68
            'http://host2/path',
69
            'http://host2/path2',
70
        ]);
71
72
        $queries = [];
73
        $httpClient = $this->getHttpClient();
74
        $this->httpClientExpectGet($httpClient, $queries, 3);
75
76
        /** @var LoggerInterface|MockObject $logger */
77
        $logger = $this->createMock('Psr\Log\LoggerInterface');
78
        // Logger should be called 11 times:
79
        //      2 for 'Fetching PROCERGS's system initials for client_id'
80
        //      6 for 'Searching for ...'
81
        //      3 for 'Returning cached result for ...'
82
        $logger->expects($this->exactly(11))->method('log')->with('info');
83
84
        $registry = $this->getRegistry($httpClient);
85
        $registry->setLogger($logger);
86
87
        $initials = $registry->getSystemInitials($client);
88
        $registry->getSystemInitials($client);
89
90
        $this->assertContains('http://host1/path', $queries);
91
        $this->assertContains('http://host2/path', $queries);
92
        $this->assertContains('http://host2/path2', $queries);
93
        $this->assertCount(3, $queries);
94
        $this->assertContains('XPTO', $initials);
95
    }
96
97
    public function testGetSystemInitialsNotFound()
98
    {
99
        $client = new Client();
100
        $client->setSiteUrl('http://host1/path');
101
102
        $queries = [];
103
        $httpClient = $this->getHttpClient();
104
        $httpClient->expects($this->once())->method('request')->with('get')
105
            ->willReturnCallback(function ($method, $url) use (&$queries) {
106
                $this->assertSame('get', $method);
107
                $queries[] = str_replace('https://api.uri/', '', $url);
108
109
                $e = $this->getMockBuilder('GuzzleHttp\Exception\ClientException')
110
                    ->disableOriginalConstructor()->getMock();
111
                $e->expects($this->exactly(2))->method('getResponse')
112
                    ->willReturn($this->getResponse(['error' => 'Not found!'], 404));
113
114
                throw $e;
115
            });
116
117
        $registry = $this->getRegistry($httpClient);
118
        $registry->getSystemInitials($client);
119
120
        $this->assertContains('http://host1/path', $queries);
121
        $this->assertCount(1, $queries);
122
    }
123
124
    public function testGetSystemInitialsServerError()
125
    {
126
        // Since this is a batch job, we do not handle errors so that the job can fail and alert us.
127
        $this->expectException(ClientException::class);
128
129
        $client = new Client();
130
        $client->setRedirectUris(['http://host1/path']);
131
132
        $queries = [];
133
        $httpClient = $this->getHttpClient();
134
        $httpClient->expects($this->once())->method('request')->with('get')
135
            ->willReturnCallback(function ($url) use (&$queries) {
136
                $queries[] = str_replace('https://api.uri/', '', $url);
137
138
                $e = $this->getMockBuilder(ClientException::class)
139
                    ->disableOriginalConstructor()->getMock();
140
                $e->expects($this->once())->method('getResponse')
141
                    ->willReturn($this->getResponse(null, 500));
142
143
                throw $e;
144
            });
145
146
        $registry = $this->getRegistry($httpClient);
147
        $registry->getSystemInitials($client);
148
    }
149
150
    public function testGetSystemInitialsIgnoreInactiveSystemsWithoutDecommissionDate()
151
    {
152
        $queries = [];
153
        $httpClient = $this->getHttpClient();
154
        $this->httpClientExpectGet($httpClient, $queries, 1, [
155
            ['sistema' => 'XPTO1', 'situacao' => 'Implantado'],
156
            ['sistema' => 'XPTO2', 'situacao' => 'Not Implantado'],
157
        ]);
158
159
        $client = new Client();
160
        $client->setSiteUrl('http://host1/path');
161
162
        $registry = $this->getRegistry($httpClient);
163
        $initials = $registry->getSystemInitials($client, new \DateTime());
164
165
        $this->assertNotEmpty($initials);
166
        $this->assertContains('XPTO1', $initials);
167
        $this->assertNotContains('XPTO2', $initials);
168
    }
169
170
    public function testGetSystemInitialsIgnoreInactiveSystemsWithDecommissionDate()
171
    {
172
        $queries = [];
173
        $httpClient = $this->getHttpClient();
174
        $this->httpClientExpectGet($httpClient, $queries, 1, [
175
            ['sistema' => 'XPTO1', 'decommissionedOn' => '2018-02-03'],
176
            ['sistema' => 'XPTO2', 'decommissionedOn' => '2018-01-31'],
177
        ]);
178
179
        $client = new Client();
180
        $client->setSiteUrl('http://host1/path');
181
182
        $registry = $this->getRegistry($httpClient);
183
        $initials = $registry->getSystemInitials($client, \DateTime::createFromFormat('Y-m-d', '2018-02-01'));
184
185
        $this->assertNotEmpty($initials);
186
        $this->assertContains('XPTO1', $initials);
187
        $this->assertNotContains('XPTO2', $initials);
188
    }
189
190
    public function testGetSystemOwners()
191
    {
192
        $client = new Client();
193
        $client->setRedirectUris(['https://host1/path', 'https://host2/path']);
194
195
        $registry = $this->getRegistry();
196
        $owners = $registry->getSystemOwners($client);
197
198
        $this->assertNotEmpty($owners);
199
    }
200
201
    public function testGetSystemOwnersNotFound()
202
    {
203
        $client = new Client();
204
        $client->setRedirectUris(['https://host1/path', 'https://host2/path']);
205
206
        $httpClient = $this->getHttpClient();
207
        $httpClient->expects($this->atLeastOnce())->method('request')->with('get')
208
            ->willReturnCallback(function () {
209
                $e = $this->getMockBuilder('GuzzleHttp\Exception\ClientException')
210
                    ->disableOriginalConstructor()->getMock();
211
                $e->expects($this->exactly(2))->method('getResponse')
212
                    ->willReturn($this->getResponse(['error' => 'Not found!'], 404));
213
214
                throw $e;
215
            });
216
217
        $registry = $this->getRegistry($httpClient);
218
        $owners = $registry->getSystemOwners($client);
219
220
        $this->assertEmpty($owners);
221
    }
222
223
    public function testFetchLinked()
224
    {
225
        $client = new Client();
226
        $client->setId(123);
227
228
        $link = new ProcergsLink();
229
        $link->setClient($client)
230
            ->setSystemType(ProcergsLink::TYPE_INTERNAL);
231
232
        /** @var ProcergsLinkRepository|MockObject $repo */
233
        $repo = $this->getMockBuilder(ProcergsLinkRepository::class)->disableOriginalConstructor()->getMock();
234
        $repo->expects($this->once())->method('findBy')->willReturn([$link]);
235
236
        /** @var ProcergsLinkRepository|MockObject $emptyRepo */
237
        $emptyRepo = $this->getMockBuilder(ProcergsLinkRepository::class)->disableOriginalConstructor()->getMock();
238
        $emptyRepo->expects($this->once())->method('findBy')->willReturn([]);
239
240
        $registry = $this->getRegistry($this->getHttpClient());
241
        $empty = $registry->fetchLinked([$client], $emptyRepo);
242
        $this->assertEmpty($empty);
243
244
        $links = $registry->fetchLinked([$client], $repo);
245
        $this->assertNotEmpty($links);
246
    }
247
248
    /**
249
     * @return MockObject|ClientInterface
250
     */
251
    private function getHttpClient()
252
    {
253
        return $this->createMock(ClientInterface::class);
254
    }
255
256
    private function getRegistry($client = null, $options = null)
257
    {
258
        if (!$client) {
259
            $client = $this->getHttpClient();
260
            $client->expects($this->any())
261
                ->method('request')->with('get')
262
                ->willReturn($this->getResponse([
263
                    [
264
                        'sistema' => 'XPTO',
265
                        'clienteDono' => 'CLIENT',
266
                        'urls' => [
267
                            'url' => 'https://url.tld/',
268
                            'ambiente' => 'Produção',
269
                        ],
270
                    ],
271
                ]));
272
        }
273
274
        if (!$options) {
275
            $options = $this->config;
276
        }
277
278
        return new SystemsRegistryService($client, $options);
279
    }
280
281
    /**
282
     * @param $json
283
     * @param null $statusCode
284
     * @return ResponseInterface|MockObject
285
     */
286
    private function getResponse($json = null, $statusCode = null)
287
    {
288
        $response = $this->createMock(ResponseInterface::class);
289
        if ($json) {
290
            $response->expects($this->atLeastOnce())->method('getBody')->willReturn(stream_for(json_encode($json)));
291
        }
292
293
        if ($statusCode) {
294
            $response->expects($this->once())->method('getStatusCode')
295
                ->willReturn($statusCode);
296
        }
297
298
        return $response;
299
    }
300
301
    /**
302
     * @param ClientInterface|MockObject $httpClient
303
     * @param $queries
304
     * @param $count
305
     * @param array|null $payload
306
     */
307
    private function httpClientExpectGet(&$httpClient, &$queries, $count, $payload = null)
308
    {
309
        $httpClient->expects($this->exactly($count))->method('request')->with('get')
310
            ->willReturnCallback(function ($method, $url, $options) use (&$queries, $payload) {
311
                $this->assertSame('get', $method);
312
                $queries[] = str_replace('https://api.uri/', '', $url);
313
314
                $headers = $options['headers'];
315
                $this->assertEquals($this->config['organization'], $headers['organizacao']);
316
317
                $response = $this->getResponse($payload ?: [['sistema' => 'XPTO']]);
318
319
                return $response;
320
            });
321
    }
322
}
323