CreateShortUrlActionTest   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 7
eloc 49
dl 0
loc 97
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 4 1
A missingLongUrlParamReturnsError() 0 4 1
A properShortcodeConversionReturnsData() 0 19 2
A provideRequestBodies() 0 20 1
A provideInvalidDomains() 0 5 1
A anInvalidDomainReturnsError() 0 14 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl;
6
7
use Cake\Chronos\Chronos;
8
use Laminas\Diactoros\ServerRequest;
9
use Laminas\Diactoros\ServerRequestFactory;
10
use PHPUnit\Framework\TestCase;
11
use Prophecy\Argument;
12
use Prophecy\PhpUnit\ProphecyTrait;
13
use Prophecy\Prophecy\ObjectProphecy;
14
use Shlinkio\Shlink\Core\Entity\ShortUrl;
15
use Shlinkio\Shlink\Core\Exception\ValidationException;
16
use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
17
use Shlinkio\Shlink\Core\Service\UrlShortener;
18
use Shlinkio\Shlink\Rest\Action\ShortUrl\CreateShortUrlAction;
19
20
use function strpos;
21
22
class CreateShortUrlActionTest extends TestCase
23
{
24
    use ProphecyTrait;
25
26
    private const DOMAIN_CONFIG = [
27
        'schema' => 'http',
28
        'hostname' => 'foo.com',
29
    ];
30
31
    private CreateShortUrlAction $action;
32
    private ObjectProphecy $urlShortener;
33
34
    public function setUp(): void
35
    {
36
        $this->urlShortener = $this->prophesize(UrlShortener::class);
37
        $this->action = new CreateShortUrlAction($this->urlShortener->reveal(), self::DOMAIN_CONFIG);
38
    }
39
40
    /** @test */
41
    public function missingLongUrlParamReturnsError(): void
42
    {
43
        $this->expectException(ValidationException::class);
44
        $this->action->handle(new ServerRequest());
45
    }
46
47
    /**
48
     * @test
49
     * @dataProvider provideRequestBodies
50
     */
51
    public function properShortcodeConversionReturnsData(array $body, ShortUrlMeta $expectedMeta, ?string $apiKey): void
52
    {
53
        $shortUrl = new ShortUrl('');
54
        $shorten = $this->urlShortener->shorten(
55
            Argument::type('string'),
56
            Argument::type('array'),
57
            $expectedMeta,
58
        )->willReturn($shortUrl);
59
60
        $request = ServerRequestFactory::fromGlobals()->withParsedBody($body);
61
        if ($apiKey !== null) {
62
            $request = $request->withHeader('X-Api-Key', $apiKey);
63
        }
64
65
        $response = $this->action->handle($request);
66
67
        self::assertEquals(200, $response->getStatusCode());
68
        self::assertTrue(strpos($response->getBody()->getContents(), $shortUrl->toString(self::DOMAIN_CONFIG)) > 0);
69
        $shorten->shouldHaveBeenCalledOnce();
70
    }
71
72
    public function provideRequestBodies(): iterable
73
    {
74
        $fullMeta = [
75
            'longUrl' => 'http://www.domain.com/foo/bar',
76
            'validSince' => Chronos::now()->toAtomString(),
77
            'validUntil' => Chronos::now()->toAtomString(),
78
            'customSlug' => 'foo-bar-baz',
79
            'maxVisits' => 50,
80
            'findIfExists' => true,
81
            'domain' => 'my-domain.com',
82
        ];
83
84
        yield 'no data' => [['longUrl' => 'http://www.domain.com/foo/bar'], ShortUrlMeta::createEmpty(), null];
85
        yield 'all data' => [$fullMeta, ShortUrlMeta::fromRawData($fullMeta), null];
86
        yield 'all data and API key' => (static function (array $meta): array {
87
            $apiKey = 'abc123';
88
            $meta['apiKey'] = $apiKey;
89
90
            return [$meta, ShortUrlMeta::fromRawData($meta), $apiKey];
91
        })($fullMeta);
92
    }
93
94
    /**
95
     * @test
96
     * @dataProvider provideInvalidDomains
97
     */
98
    public function anInvalidDomainReturnsError(string $domain): void
99
    {
100
        $shortUrl = new ShortUrl('');
101
        $urlToShortCode = $this->urlShortener->shorten(Argument::cetera())->willReturn($shortUrl);
102
103
        $request = (new ServerRequest())->withParsedBody([
104
            'longUrl' => 'http://www.domain.com/foo/bar',
105
            'domain' => $domain,
106
        ]);
107
108
        $this->expectException(ValidationException::class);
109
        $urlToShortCode->shouldNotBeCalled();
110
111
        $this->action->handle($request);
112
    }
113
114
    public function provideInvalidDomains(): iterable
115
    {
116
        yield ['localhost:80000'];
117
        yield ['127.0.0.1'];
118
        yield ['???/&%$&'];
119
    }
120
}
121