Completed
Push — master ( 25a785...8d412e )
by Alejandro
27s queued 11s
created

optionsRequestParsesRouteMatchToDetermineAllowedMethods()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace ShlinkioTest\Shlink\Rest\Middleware;
5
6
use PHPUnit\Framework\TestCase;
7
use Prophecy\Argument;
8
use Prophecy\Prophecy\ObjectProphecy;
9
use Psr\Http\Server\RequestHandlerInterface;
10
use Shlinkio\Shlink\Rest\Middleware\CrossDomainMiddleware;
11
use Zend\Diactoros\Response;
12
use Zend\Diactoros\ServerRequest;
13
use Zend\Expressive\Router\Route;
14
use Zend\Expressive\Router\RouteResult;
15
16
use function Zend\Stratigility\middleware;
17
18
class CrossDomainMiddlewareTest extends TestCase
19
{
20
    /** @var CrossDomainMiddleware */
21
    private $middleware;
22
    /** @var ObjectProphecy */
23
    private $handler;
24
25
    public function setUp(): void
26
    {
27
        $this->middleware = new CrossDomainMiddleware();
28
        $this->handler = $this->prophesize(RequestHandlerInterface::class);
29
    }
30
31
    /** @test */
32
    public function nonCrossDomainRequestsAreNotAffected(): void
33
    {
34
        $originalResponse = new Response();
35
        $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce();
36
37
        $response = $this->middleware->process(new ServerRequest(), $this->handler->reveal());
38
        $this->assertSame($originalResponse, $response);
39
40
        $headers = $response->getHeaders();
41
        $this->assertArrayNotHasKey('Access-Control-Allow-Origin', $headers);
42
        $this->assertArrayNotHasKey('Access-Control-Expose-Headers', $headers);
43
        $this->assertArrayNotHasKey('Access-Control-Allow-Methods', $headers);
44
        $this->assertArrayNotHasKey('Access-Control-Max-Age', $headers);
45
        $this->assertArrayNotHasKey('Access-Control-Allow-Headers', $headers);
46
    }
47
48
    /** @test */
49
    public function anyRequestIncludesTheAllowAccessHeader(): void
50
    {
51
        $originalResponse = new Response();
52
        $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce();
53
54
        $response = $this->middleware->process(
55
            (new ServerRequest())->withHeader('Origin', 'local'),
56
            $this->handler->reveal()
57
        );
58
        $this->assertNotSame($originalResponse, $response);
59
60
        $headers = $response->getHeaders();
61
        $this->assertArrayHasKey('Access-Control-Allow-Origin', $headers);
62
        $this->assertArrayHasKey('Access-Control-Expose-Headers', $headers);
63
        $this->assertArrayNotHasKey('Access-Control-Allow-Methods', $headers);
64
        $this->assertArrayNotHasKey('Access-Control-Max-Age', $headers);
65
        $this->assertArrayNotHasKey('Access-Control-Allow-Headers', $headers);
66
    }
67
68
    /** @test */
69
    public function optionsRequestIncludesMoreHeaders(): void
70
    {
71
        $originalResponse = new Response();
72
        $request = (new ServerRequest())->withMethod('OPTIONS')->withHeader('Origin', 'local');
73
        $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce();
74
75
        $response = $this->middleware->process($request, $this->handler->reveal());
76
        $this->assertNotSame($originalResponse, $response);
77
78
        $headers = $response->getHeaders();
79
        $this->assertArrayHasKey('Access-Control-Allow-Origin', $headers);
80
        $this->assertArrayHasKey('Access-Control-Expose-Headers', $headers);
81
        $this->assertArrayHasKey('Access-Control-Allow-Methods', $headers);
82
        $this->assertArrayHasKey('Access-Control-Max-Age', $headers);
83
        $this->assertArrayHasKey('Access-Control-Allow-Headers', $headers);
84
    }
85
86
    /**
87
     * @test
88
     * @dataProvider provideRouteResults
89
     */
90
    public function optionsRequestParsesRouteMatchToDetermineAllowedMethods(
91
        ?RouteResult $result,
92
        string $expectedAllowedMethods
93
    ): void {
94
        $originalResponse = new Response();
95
        $request = (new ServerRequest())->withAttribute(RouteResult::class, $result)
96
                                        ->withMethod('OPTIONS')
97
                                        ->withHeader('Origin', 'local');
98
        $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce();
99
100
        $response = $this->middleware->process($request, $this->handler->reveal());
101
102
        $this->assertEquals($response->getHeaderLine('Access-Control-Allow-Methods'), $expectedAllowedMethods);
103
    }
104
105
    public function provideRouteResults(): iterable
106
    {
107
        yield 'with no route result' => [null, 'GET,POST,PUT,PATCH,DELETE,OPTIONS'];
108
        yield 'with failed route result' => [RouteResult::fromRouteFailure(['POST', 'GET']), 'POST,GET'];
109
        yield 'with success route result' => [
110
            RouteResult::fromRoute(
111
                new Route('/', middleware(function () {
112
                }), ['DELETE', 'PATCH', 'PUT'])
113
            ),
114
            'DELETE,PATCH,PUT',
115
        ];
116
    }
117
}
118