Passed
Pull Request — master (#548)
by Alejandro
06:02
created

UrlValidatorTest::provideAttemptThatThrows()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ShlinkioTest\Shlink\Core\Util;
6
7
use Fig\Http\Message\RequestMethodInterface;
8
use GuzzleHttp\ClientInterface;
9
use GuzzleHttp\Exception\ClientException;
10
use PHPUnit\Framework\TestCase;
11
use Prophecy\Argument;
12
use Prophecy\Prophecy\ObjectProphecy;
13
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
14
use Shlinkio\Shlink\Core\Util\UrlValidator;
15
use Zend\Diactoros\Request;
16
use Zend\Diactoros\Response;
17
18
use function Functional\map;
19
use function range;
20
21
class UrlValidatorTest extends TestCase
22
{
23
    /** @var UrlValidator */
24
    private $urlValidator;
25
    /** @var ObjectProphecy */
26
    private $httpClient;
27
28
    public function setUp(): void
29
    {
30
        $this->httpClient = $this->prophesize(ClientInterface::class);
31
        $this->urlValidator = new UrlValidator($this->httpClient->reveal());
32
    }
33
34
    /**
35
     * @test
36
     * @dataProvider provideAttemptThatThrows
37
     */
38
    public function exceptionIsThrownWhenUrlIsInvalid(int $attemptThatThrows): void
39
    {
40
        $callNum = 1;
41
        $e = new ClientException('', $this->prophesize(Request::class)->reveal());
42
43
        $request = $this->httpClient->request(Argument::cetera())->will(
44
            function () use ($e, $attemptThatThrows, &$callNum) {
45
                if ($callNum === $attemptThatThrows) {
46
                    throw $e;
47
                }
48
49
                $callNum++;
50
                return new Response('php://memory', 302, ['Location' => 'http://foo.com']);
51
            }
52
        );
53
54
        $request->shouldBeCalledTimes($attemptThatThrows);
55
        $this->expectException(InvalidUrlException::class);
56
57
        $this->urlValidator->validateUrl('http://foobar.com/12345/hello?foo=bar');
58
    }
59
60
    public function provideAttemptThatThrows(): iterable
61
    {
62
        return map(range(1, 15), function (int $attempt) {
63
            return [$attempt];
64
        });
65
    }
66
67
    /**
68
     * @test
69
     * @dataProvider provideUrls
70
     */
71
    public function expectedUrlIsCalledInOrderToVerifyProvidedUrl(string $providedUrl, string $expectedUrl): void
72
    {
73
        $request = $this->httpClient->request(
74
            RequestMethodInterface::METHOD_GET,
75
            $expectedUrl,
76
            Argument::cetera()
77
        )->willReturn(new Response());
78
79
        $this->urlValidator->validateUrl($providedUrl);
80
81
        $request->shouldHaveBeenCalledOnce();
82
    }
83
84
    public function provideUrls(): iterable
85
    {
86
        yield 'regular domain' => ['http://foobar.com', 'http://foobar.com'];
87
        yield 'IDN' => ['https://cédric.laubacher.io/', 'https://xn--cdric-bsa.laubacher.io/'];
88
    }
89
90
    /** @test */
91
    public function considersUrlValidWhenTooManyRedirectsAreReturned(): void
92
    {
93
        $request = $this->httpClient->request(Argument::cetera())->willReturn(
94
            new Response('php://memory', 302, ['Location' => 'http://foo.com'])
95
        );
96
97
        $this->urlValidator->validateUrl('http://foobar.com');
98
99
        $request->shouldHaveBeenCalledTimes(15);
100
    }
101
}
102