Completed
Push — master ( 4a3e49...406f94 )
by Alejandro
16s queued 12s
created

noExceptionsAreThrownIfEverythingWorksFine()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
4
namespace ShlinkioTest\Shlink\IpGeolocation\GeoLite2;
5
6
use GuzzleHttp\ClientInterface;
7
use GuzzleHttp\Exception\ClientException;
8
use PHPUnit\Framework\TestCase;
9
use Prophecy\Argument;
10
use Prophecy\Prophecy\ObjectProphecy;
11
use Shlinkio\Shlink\Common\Exception\RuntimeException;
12
use Shlinkio\Shlink\IpGeolocation\GeoLite2\DbUpdater;
13
use Shlinkio\Shlink\IpGeolocation\GeoLite2\GeoLite2Options;
14
use Symfony\Component\Filesystem\Exception as FilesystemException;
15
use Symfony\Component\Filesystem\Filesystem;
16
use Zend\Diactoros\Response;
17
18
class DbUpdaterTest extends TestCase
19
{
20
    /** @var DbUpdater */
21
    private $dbUpdater;
22
    /** @var ObjectProphecy */
23
    private $httpClient;
24
    /** @var ObjectProphecy */
25
    private $filesystem;
26
    /** @var GeoLite2Options */
27
    private $options;
28
29
    public function setUp(): void
30
    {
31
        $this->httpClient = $this->prophesize(ClientInterface::class);
32
        $this->filesystem = $this->prophesize(Filesystem::class);
33
        $this->options = new GeoLite2Options([
34
            'temp_dir' => __DIR__ . '/../../test-resources',
35
            'db_location' => 'db_location',
36
            'download_from' => '',
37
        ]);
38
39
        $this->dbUpdater = new DbUpdater($this->httpClient->reveal(), $this->filesystem->reveal(), $this->options);
40
    }
41
42
    /** @test */
43
    public function anExceptionIsThrownIfFreshDbCannotBeDownloaded(): void
44
    {
45
        $request = $this->httpClient->request(Argument::cetera())->willThrow(ClientException::class);
46
47
        $this->expectException(RuntimeException::class);
48
        $this->expectExceptionCode(0);
49
        $this->expectExceptionMessage(
50
            'An error occurred while trying to download a fresh copy of the GeoLite2 database'
51
        );
52
        $request->shouldBeCalledOnce();
53
54
        $this->dbUpdater->downloadFreshCopy();
55
    }
56
57
    /** @test */
58
    public function anExceptionIsThrownIfFreshDbCannotBeExtracted(): void
59
    {
60
        $this->options->tempDir = '__invalid__';
0 ignored issues
show
Bug Best Practice introduced by
The property $tempDir is declared private in Shlinkio\Shlink\IpGeoloc...eoLite2\GeoLite2Options. Since you implement __set, consider adding a @property or @property-write.
Loading history...
61
62
        $request = $this->httpClient->request(Argument::cetera())->willReturn(new Response());
63
64
        $this->expectException(RuntimeException::class);
65
        $this->expectExceptionCode(0);
66
        $this->expectExceptionMessage(
67
            'An error occurred while trying to extract the GeoLite2 database from __invalid__/GeoLite2-City.tar.gz'
68
        );
69
        $request->shouldBeCalledOnce();
70
71
        $this->dbUpdater->downloadFreshCopy();
72
    }
73
74
    /**
75
     * @test
76
     * @dataProvider provideFilesystemExceptions
77
     */
78
    public function anExceptionIsThrownIfFreshDbCannotBeCopiedToDestination(string $e): void
79
    {
80
        $request = $this->httpClient->request(Argument::cetera())->willReturn(new Response());
81
        $copy = $this->filesystem->copy(Argument::cetera())->willThrow($e);
82
83
        $this->expectException(RuntimeException::class);
84
        $this->expectExceptionCode(0);
85
        $this->expectExceptionMessage('An error occurred while trying to copy GeoLite2 db file to destination');
86
        $request->shouldBeCalledOnce();
87
        $copy->shouldBeCalledOnce();
88
89
        $this->dbUpdater->downloadFreshCopy();
90
    }
91
92
    public function provideFilesystemExceptions(): iterable
93
    {
94
        yield 'file not found' => [FilesystemException\FileNotFoundException::class];
95
        yield 'IO error' => [FilesystemException\IOException::class];
96
    }
97
98
    /** @test */
99
    public function noExceptionsAreThrownIfEverythingWorksFine(): void
100
    {
101
        $request = $this->httpClient->request(Argument::cetera())->willReturn(new Response());
102
        $copy = $this->filesystem->copy(Argument::cetera())->will(function () {
103
        });
104
        $remove = $this->filesystem->remove(Argument::cetera())->will(function () {
105
        });
106
107
        $this->dbUpdater->downloadFreshCopy();
108
109
        $request->shouldHaveBeenCalledOnce();
110
        $copy->shouldHaveBeenCalledOnce();
111
        $remove->shouldHaveBeenCalledOnce();
112
    }
113
114
    /**
115
     * @test
116
     * @dataProvider provideExists
117
     */
118
    public function databaseFileExistsChecksIfTheFilesExistsInTheFilesystem(bool $expected): void
119
    {
120
        $exists = $this->filesystem->exists('db_location')->willReturn($expected);
121
122
        $result = $this->dbUpdater->databaseFileExists();
123
124
        $this->assertEquals($expected, $result);
125
        $exists->shouldHaveBeenCalledOnce();
126
    }
127
128
    public function provideExists(): iterable
129
    {
130
        return [[true], [false]];
131
    }
132
}
133