Completed
Push — master ( 232bf5...c4ca59 )
by Alejandro
14s queued 11s
created

CreateShortUrlActionTest::provideInvalidDomains()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 5
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl;
6
7
use Exception;
8
use PHPUnit\Framework\TestCase;
9
use Prophecy\Argument;
10
use Prophecy\Prophecy\ObjectProphecy;
11
use Shlinkio\Shlink\Core\Entity\ShortUrl;
12
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
13
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
14
use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
15
use Shlinkio\Shlink\Core\Service\UrlShortener;
16
use Shlinkio\Shlink\Rest\Action\ShortUrl\CreateShortUrlAction;
17
use Shlinkio\Shlink\Rest\Util\RestUtils;
18
use Zend\Diactoros\Response\JsonResponse;
19
use Zend\Diactoros\ServerRequest;
20
use Zend\Diactoros\Uri;
21
22
use function strpos;
23
24
class CreateShortUrlActionTest extends TestCase
25
{
26
    private const DOMAIN_CONFIG = [
27
        'schema' => 'http',
28
        'hostname' => 'foo.com',
29
    ];
30
31
    /** @var CreateShortUrlAction */
32
    private $action;
33
    /** @var ObjectProphecy */
34
    private $urlShortener;
35
36
    public function setUp(): void
37
    {
38
        $this->urlShortener = $this->prophesize(UrlShortener::class);
39
        $this->action = new CreateShortUrlAction($this->urlShortener->reveal(), self::DOMAIN_CONFIG);
40
    }
41
42
    /** @test */
43
    public function missingLongUrlParamReturnsError(): void
44
    {
45
        $response = $this->action->handle(new ServerRequest());
46
        $this->assertEquals(400, $response->getStatusCode());
47
    }
48
49
    /** @test */
50
    public function properShortcodeConversionReturnsData(): void
51
    {
52
        $shortUrl = new ShortUrl('');
53
        $this->urlShortener->urlToShortCode(Argument::type(Uri::class), Argument::type('array'), Argument::cetera())
54
             ->willReturn($shortUrl)
55
             ->shouldBeCalledOnce();
56
57
        $request = (new ServerRequest())->withParsedBody([
58
            'longUrl' => 'http://www.domain.com/foo/bar',
59
        ]);
60
        $response = $this->action->handle($request);
61
        $this->assertEquals(200, $response->getStatusCode());
62
        $this->assertTrue(strpos($response->getBody()->getContents(), $shortUrl->toString(self::DOMAIN_CONFIG)) > 0);
63
    }
64
65
    /** @test */
66
    public function anInvalidUrlReturnsError(): void
67
    {
68
        $this->urlShortener->urlToShortCode(Argument::type(Uri::class), Argument::type('array'), Argument::cetera())
69
             ->willThrow(InvalidUrlException::class)
70
             ->shouldBeCalledOnce();
71
72
        $request = (new ServerRequest())->withParsedBody([
73
            'longUrl' => 'http://www.domain.com/foo/bar',
74
        ]);
75
        $response = $this->action->handle($request);
76
        $this->assertEquals(400, $response->getStatusCode());
77
        $this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::INVALID_URL_ERROR) > 0);
78
    }
79
80
    /**
81
     * @test
82
     * @dataProvider provideInvalidDomains
83
     */
84
    public function anInvalidDomainReturnsError(string $domain): void
85
    {
86
        $shortUrl = new ShortUrl('');
87
        $urlToShortCode = $this->urlShortener->urlToShortCode(Argument::cetera())->willReturn($shortUrl);
88
89
        $request = (new ServerRequest())->withParsedBody([
90
            'longUrl' => 'http://www.domain.com/foo/bar',
91
            'domain' => $domain,
92
        ]);
93
        /** @var JsonResponse $response */
94
        $response = $this->action->handle($request);
95
        $payload = $response->getPayload();
96
97
        $this->assertEquals(400, $response->getStatusCode());
98
        $this->assertEquals(RestUtils::INVALID_ARGUMENT_ERROR, $payload['error']);
99
        $urlToShortCode->shouldNotHaveBeenCalled();
100
    }
101
102
    public function provideInvalidDomains(): iterable
103
    {
104
        yield ['localhost:80000'];
105
        yield ['127.0.0.1'];
106
        yield ['???/&%$&'];
107
    }
108
109
    /** @test */
110
    public function nonUniqueSlugReturnsError(): void
111
    {
112
        $this->urlShortener->urlToShortCode(
113
            Argument::type(Uri::class),
114
            Argument::type('array'),
115
            ShortUrlMeta::createFromRawData(['customSlug' => 'foo']),
116
            Argument::cetera()
117
        )->willThrow(NonUniqueSlugException::class)->shouldBeCalledOnce();
118
119
        $request = (new ServerRequest())->withParsedBody([
120
            'longUrl' => 'http://www.domain.com/foo/bar',
121
            'customSlug' => 'foo',
122
        ]);
123
        $response = $this->action->handle($request);
124
        $this->assertEquals(400, $response->getStatusCode());
125
        $this->assertStringContainsString(RestUtils::INVALID_SLUG_ERROR, (string) $response->getBody());
126
    }
127
128
    /** @test */
129
    public function aGenericExceptionWillReturnError(): void
130
    {
131
        $this->urlShortener->urlToShortCode(Argument::type(Uri::class), Argument::type('array'), Argument::cetera())
132
            ->willThrow(Exception::class)
133
            ->shouldBeCalledOnce();
134
135
        $request = (new ServerRequest())->withParsedBody([
136
            'longUrl' => 'http://www.domain.com/foo/bar',
137
        ]);
138
        $response = $this->action->handle($request);
139
        $this->assertEquals(500, $response->getStatusCode());
140
        $this->assertTrue(strpos($response->getBody()->getContents(), RestUtils::UNKNOWN_ERROR) > 0);
141
    }
142
}
143