Completed
Push — master ( 6293d5...bf2466 )
by Alejandro
21s queued 10s
created

properErrorTemplateIsRendered()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
nc 1
nop 2
dl 0
loc 9
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ShlinkioTest\Shlink\Core\Response;
6
7
use PHPUnit\Framework\TestCase;
8
use Prophecy\Argument;
9
use Prophecy\Prophecy\ObjectProphecy;
10
use Psr\Http\Message\ServerRequestInterface;
11
use Psr\Http\Server\MiddlewareInterface;
12
use Shlinkio\Shlink\Core\Action\RedirectAction;
13
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
14
use Shlinkio\Shlink\Core\Response\NotFoundHandler;
15
use Zend\Diactoros\Response;
16
use Zend\Diactoros\ServerRequest;
17
use Zend\Diactoros\ServerRequestFactory;
18
use Zend\Diactoros\Uri;
19
use Zend\Expressive\Router\Route;
20
use Zend\Expressive\Router\RouteResult;
21
use Zend\Expressive\Template\TemplateRendererInterface;
22
23
class NotFoundHandlerTest extends TestCase
24
{
25
    /** @var NotFoundHandler */
26
    private $delegate;
27
    /** @var ObjectProphecy */
28
    private $renderer;
29
    /** @var NotFoundRedirectOptions */
30
    private $redirectOptions;
31
32
    public function setUp(): void
33
    {
34
        $this->renderer = $this->prophesize(TemplateRendererInterface::class);
35
        $this->redirectOptions = new NotFoundRedirectOptions();
36
37
        $this->delegate = new NotFoundHandler($this->renderer->reveal(), $this->redirectOptions, '');
38
    }
39
40
    /**
41
     * @test
42
     * @dataProvider provideResponses
43
     */
44
    public function properResponseTypeIsReturned(string $expectedResponse, string $accept, int $renderCalls): void
45
    {
46
        $request = (new ServerRequest())->withHeader('Accept', $accept);
47
        $render = $this->renderer->render(Argument::cetera())->willReturn('');
48
49
        $resp = $this->delegate->handle($request);
50
51
        $this->assertInstanceOf($expectedResponse, $resp);
52
        $render->shouldHaveBeenCalledTimes($renderCalls);
53
    }
54
55
    public function provideResponses(): iterable
56
    {
57
        yield 'application/json' => [Response\JsonResponse::class, 'application/json', 0];
58
        yield 'text/json' => [Response\JsonResponse::class, 'text/json', 0];
59
        yield 'application/x-json' => [Response\JsonResponse::class, 'application/x-json', 0];
60
        yield 'text/html' => [Response\HtmlResponse::class, 'text/html', 1];
61
    }
62
63
    /**
64
     * @test
65
     * @dataProvider provideRedirects
66
     */
67
    public function expectedRedirectionIsReturnedDependingOnTheCase(
68
        ServerRequestInterface $request,
69
        string $expectedRedirectTo
70
    ): void {
71
        $this->redirectOptions->invalidShortUrl = 'invalidShortUrl';
0 ignored issues
show
Bug Best Practice introduced by
The property $invalidShortUrl is declared private in Shlinkio\Shlink\Core\Opt...NotFoundRedirectOptions. Since you implement __set, consider adding a @property or @property-write.
Loading history...
72
        $this->redirectOptions->regular404 = 'regular404';
0 ignored issues
show
Bug Best Practice introduced by
The property $regular404 is declared private in Shlinkio\Shlink\Core\Opt...NotFoundRedirectOptions. Since you implement __set, consider adding a @property or @property-write.
Loading history...
73
        $this->redirectOptions->baseUrl = 'baseUrl';
0 ignored issues
show
Bug Best Practice introduced by
The property $baseUrl is declared private in Shlinkio\Shlink\Core\Opt...NotFoundRedirectOptions. Since you implement __set, consider adding a @property or @property-write.
Loading history...
74
75
        $resp = $this->delegate->handle($request);
76
77
        $this->assertInstanceOf(Response\RedirectResponse::class, $resp);
78
        $this->assertEquals($expectedRedirectTo, $resp->getHeaderLine('Location'));
79
        $this->renderer->render(Argument::cetera())->shouldNotHaveBeenCalled();
80
    }
81
82
    public function provideRedirects(): iterable
83
    {
84
        yield 'base URL with trailing slash' => [
85
            ServerRequestFactory::fromGlobals()->withUri(new Uri('/')),
86
            'baseUrl',
87
        ];
88
        yield 'base URL without trailing slash' => [
89
            ServerRequestFactory::fromGlobals()->withUri(new Uri('')),
90
            'baseUrl',
91
        ];
92
        yield 'regular 404' => [
93
            ServerRequestFactory::fromGlobals()->withUri(new Uri('/foo/bar')),
94
            'regular404',
95
        ];
96
        yield 'invalid short URL' => [
97
            ServerRequestFactory::fromGlobals()
98
                ->withAttribute(
99
                    RouteResult::class,
100
                    RouteResult::fromRoute(
101
                        new Route(
102
                            '',
103
                            $this->prophesize(MiddlewareInterface::class)->reveal(),
104
                            ['GET'],
105
                            RedirectAction::class
106
                        )
107
                    )
108
                )
109
                ->withUri(new Uri('/abc123')),
110
            'invalidShortUrl',
111
        ];
112
    }
113
114
    /**
115
     * @test
116
     * @dataProvider provideTemplates
117
     */
118
    public function properErrorTemplateIsRendered(ServerRequestInterface $request, string $expectedTemplate): void
119
    {
120
        $request = $request->withHeader('Accept', 'text/html');
121
        $render = $this->renderer->render($expectedTemplate)->willReturn('');
122
123
        $resp = $this->delegate->handle($request);
124
125
        $this->assertInstanceOf(Response\HtmlResponse::class, $resp);
126
        $render->shouldHaveBeenCalledOnce();
127
    }
128
129
    public function provideTemplates(): iterable
130
    {
131
        $request = ServerRequestFactory::fromGlobals();
132
133
        yield [$request, NotFoundHandler::NOT_FOUND_TEMPLATE];
134
        yield [
135
            $request->withAttribute(
136
                RouteResult::class,
137
                RouteResult::fromRoute(new Route('', $this->prophesize(MiddlewareInterface::class)->reveal()))
138
            ),
139
            NotFoundHandler::INVALID_SHORT_CODE_TEMPLATE,
140
        ];
141
    }
142
}
143