Completed
Pull Request — master (#105)
by Mikołaj
10:14
created

UrlShortenerTest   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

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

9 Methods

Rating   Name   Duplication   Size   Complexity  
B setUp() 0 24 1
A setUrlShortener() 0 10 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(),
71
            $this->em->reveal(),
72
            $this->cache,
73
            UrlShortener::DEFAULT_CHARS,
74
            $isUrlValidationExists
75
        );
76
    }
77
78
    /**
79
     * @test
80
     */
81
    public function urlIsProperlyShortened()
82
    {
83
        // 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...
84
        $shortCode = $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar'));
85
        $this->assertEquals('12C1c', $shortCode);
86
    }
87
88
    /**
89
     * @test
90
     * @expectedException \Shlinkio\Shlink\Common\Exception\RuntimeException
91
     */
92
    public function exceptionIsThrownWhenOrmThrowsException()
93
    {
94
        $conn = $this->prophesize(Connection::class);
95
        $conn->isTransactionActive()->willReturn(true);
96
        $this->em->getConnection()->willReturn($conn->reveal());
97
        $this->em->rollback()->shouldBeCalledTimes(1);
98
        $this->em->close()->shouldBeCalledTimes(1);
99
100
        $this->em->flush()->willThrow(new ORMException());
101
        $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar'));
102
    }
103
104
    /**
105
     * @test
106
     * @expectedException \Shlinkio\Shlink\Core\Exception\InvalidUrlException
107
     */
108
    public function exceptionIsThrownWhenUrlDoesNotExist()
109
    {
110
        $this->setUrlShortener(true);
111
112
        $this->httpClient->request(Argument::cetera())->willThrow(
113
            new ClientException('', $this->prophesize(Request::class)->reveal())
114
        );
115
        $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar'));
116
    }
117
118
    /**
119
     * @test
120
     */
121
    public function whenShortUrlExistsItsShortcodeIsReturned()
122
    {
123
        $shortUrl = new ShortUrl();
124
        $shortUrl->setShortCode('expected_shortcode');
125
        $repo = $this->prophesize(ObjectRepository::class);
126
        $repo->findOneBy(Argument::any())->willReturn($shortUrl);
127
        $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
128
129
        $shortCode = $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar'));
130
        $this->assertEquals($shortUrl->getShortCode(), $shortCode);
131
    }
132
133
    /**
134
     * @test
135
     */
136
    public function shortCodeIsProperlyParsed()
137
    {
138
        // 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...
139
        $shortCode = '12C1c';
140
        $shortUrl = new ShortUrl();
141
        $shortUrl->setShortCode($shortCode)
142
                 ->setOriginalUrl('expected_url');
143
144
        $repo = $this->prophesize(ObjectRepository::class);
145
        $repo->findOneBy(['shortCode' => $shortCode])->willReturn($shortUrl);
146
        $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
147
148
        $this->assertFalse($this->cache->contains($shortCode . '_longUrl'));
149
        $url = $this->urlShortener->shortCodeToUrl($shortCode);
150
        $this->assertEquals($shortUrl->getOriginalUrl(), $url);
151
        $this->assertTrue($this->cache->contains($shortCode . '_longUrl'));
152
    }
153
154
    /**
155
     * @test
156
     * @expectedException \Shlinkio\Shlink\Core\Exception\InvalidShortCodeException
157
     */
158
    public function invalidCharSetThrowsException()
159
    {
160
        $this->urlShortener->shortCodeToUrl('&/(');
161
    }
162
163
    /**
164
     * @test
165
     */
166
    public function cachedShortCodeDoesNotHitDatabase()
167
    {
168
        $shortCode = '12C1c';
169
        $expectedUrl = 'expected_url';
170
        $this->cache->save($shortCode . '_longUrl', $expectedUrl);
171
        $this->em->getRepository(ShortUrl::class)->willReturn(null)->shouldBeCalledTimes(0);
172
173
        $url = $this->urlShortener->shortCodeToUrl($shortCode);
174
        $this->assertEquals($expectedUrl, $url);
175
    }
176
}
177