Completed
Pull Request — master (#105)
by Mikołaj
03:28 queued 49s
created

UrlShortenerTest   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 153
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 2
Bugs 1 Features 0
Metric Value
dl 0
loc 153
rs 10
c 2
b 1
f 0
wmc 9
lcom 1
cbo 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
B setUp() 0 24 1
A setUrlShortener() 0 6 1
A urlIsProperlyShortened() 0 6 1
A exceptionIsThrownWhenOrmThrowsException() 0 11 1
A exceptionIsThrownWhenUrlDoesNotExist() 0 9 1
A whenShortUrlExistsItsShortcodeIsReturned() 0 11 1
A shortCodeIsProperlyParsed() 0 17 1
A invalidCharSetThrowsException() 0 4 1
A cachedShortCodeDoesNotHitDatabase() 0 10 1
1
<?php
2
namespace ShlinkioTest\Shlink\Core\Service;
3
4
use Doctrine\Common\Cache\ArrayCache;
5
use Doctrine\Common\Cache\Cache;
6
use Doctrine\Common\Persistence\ObjectRepository;
7
use Doctrine\DBAL\Connection;
8
use Doctrine\ORM\EntityManagerInterface;
9
use Doctrine\ORM\ORMException;
10
use GuzzleHttp\ClientInterface;
11
use GuzzleHttp\Exception\ClientException;
12
use GuzzleHttp\Psr7\Request;
13
use PHPUnit\Framework\TestCase;
14
use Prophecy\Argument;
15
use Prophecy\Prophecy\ObjectProphecy;
16
use Shlinkio\Shlink\Core\Entity\ShortUrl;
17
use Shlinkio\Shlink\Core\Service\UrlShortener;
18
use Zend\Diactoros\Uri;
19
20
class UrlShortenerTest extends TestCase
21
{
22
    /**
23
     * @var UrlShortener
24
     */
25
    protected $urlShortener;
26
    /**
27
     * @var ObjectProphecy
28
     */
29
    protected $em;
30
    /**
31
     * @var ObjectProphecy
32
     */
33
    protected $httpClient;
34
    /**
35
     * @var Cache
36
     */
37
    protected $cache;
38
39
    public function setUp()
40
    {
41
        $this->httpClient = $this->prophesize(ClientInterface::class);
42
43
        $this->em = $this->prophesize(EntityManagerInterface::class);
44
        $conn = $this->prophesize(Connection::class);
45
        $conn->isTransactionActive()->willReturn(false);
46
        $this->em->getConnection()->willReturn($conn->reveal());
47
        $this->em->flush()->willReturn(null);
48
        $this->em->commit()->willReturn(null);
49
        $this->em->beginTransaction()->willReturn(null);
50
        $this->em->persist(Argument::any())->will(function ($arguments) {
51
            /** @var ShortUrl $shortUrl */
52
            $shortUrl = $arguments[0];
53
            $shortUrl->setId(10);
54
        });
55
        $repo = $this->prophesize(ObjectRepository::class);
56
        $repo->findOneBy(Argument::any())->willReturn(null);
57
        $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
58
59
        $this->cache = new ArrayCache();
60
61
        $this->setUrlShortener(false);
62
    }
63
64
    /**
65
     * @param bool $isUrlValidationExists
66
     */
67
    public function setUrlShortener($isUrlValidationExists)
68
    {
69
        $this->urlShortener = new UrlShortener(
70
            $this->httpClient->reveal(), $this->em->reveal(), $this->cache, $isUrlValidationExists, UrlShortener::DEFAULT_CHARS
71
        );
72
    }
73
74
    /**
75
     * @test
76
     */
77
    public function urlIsProperlyShortened()
78
    {
79
        // 10 -> 12C1c
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
80
        $shortCode = $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar'));
81
        $this->assertEquals('12C1c', $shortCode);
82
    }
83
84
    /**
85
     * @test
86
     * @expectedException \Shlinkio\Shlink\Common\Exception\RuntimeException
87
     */
88
    public function exceptionIsThrownWhenOrmThrowsException()
89
    {
90
        $conn = $this->prophesize(Connection::class);
91
        $conn->isTransactionActive()->willReturn(true);
92
        $this->em->getConnection()->willReturn($conn->reveal());
93
        $this->em->rollback()->shouldBeCalledTimes(1);
94
        $this->em->close()->shouldBeCalledTimes(1);
95
96
        $this->em->flush()->willThrow(new ORMException());
97
        $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar'));
98
    }
99
100
    /**
101
     * @test
102
     * @expectedException \Shlinkio\Shlink\Core\Exception\InvalidUrlException
103
     */
104
    public function exceptionIsThrownWhenUrlDoesNotExist()
105
    {
106
        $this->setUrlShortener(true);
107
108
        $this->httpClient->request(Argument::cetera())->willThrow(
109
            new ClientException('', $this->prophesize(Request::class)->reveal())
110
        );
111
        $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar'));
112
    }
113
114
    /**
115
     * @test
116
     */
117
    public function whenShortUrlExistsItsShortcodeIsReturned()
118
    {
119
        $shortUrl = new ShortUrl();
120
        $shortUrl->setShortCode('expected_shortcode');
121
        $repo = $this->prophesize(ObjectRepository::class);
122
        $repo->findOneBy(Argument::any())->willReturn($shortUrl);
123
        $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
124
125
        $shortCode = $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar'));
126
        $this->assertEquals($shortUrl->getShortCode(), $shortCode);
127
    }
128
129
    /**
130
     * @test
131
     */
132
    public function shortCodeIsProperlyParsed()
133
    {
134
        // 12C1c -> 10
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
135
        $shortCode = '12C1c';
136
        $shortUrl = new ShortUrl();
137
        $shortUrl->setShortCode($shortCode)
138
                 ->setOriginalUrl('expected_url');
139
140
        $repo = $this->prophesize(ObjectRepository::class);
141
        $repo->findOneBy(['shortCode' => $shortCode])->willReturn($shortUrl);
142
        $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
143
144
        $this->assertFalse($this->cache->contains($shortCode . '_longUrl'));
145
        $url = $this->urlShortener->shortCodeToUrl($shortCode);
146
        $this->assertEquals($shortUrl->getOriginalUrl(), $url);
147
        $this->assertTrue($this->cache->contains($shortCode . '_longUrl'));
148
    }
149
150
    /**
151
     * @test
152
     * @expectedException \Shlinkio\Shlink\Core\Exception\InvalidShortCodeException
153
     */
154
    public function invalidCharSetThrowsException()
155
    {
156
        $this->urlShortener->shortCodeToUrl('&/(');
157
    }
158
159
    /**
160
     * @test
161
     */
162
    public function cachedShortCodeDoesNotHitDatabase()
163
    {
164
        $shortCode = '12C1c';
165
        $expectedUrl = 'expected_url';
166
        $this->cache->save($shortCode . '_longUrl', $expectedUrl);
167
        $this->em->getRepository(ShortUrl::class)->willReturn(null)->shouldBeCalledTimes(0);
168
169
        $url = $this->urlShortener->shortCodeToUrl($shortCode);
170
        $this->assertEquals($expectedUrl, $url);
171
    }
172
}
173