Passed
Branch release/v2.0.0 (caca50)
by Anatoly
02:10
created

RouterTest::testHandleForUnallowedMethod()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 18
c 1
b 0
f 0
dl 0
loc 28
rs 9.6666
cc 2
nc 2
nop 0
1
<?php declare(strict_types=1);
2
3
namespace Sunrise\Http\Router\Tests;
4
5
/**
6
 * Import classes
7
 */
8
use PHPUnit\Framework\TestCase;
9
use Psr\Http\Server\MiddlewareInterface;
10
use Psr\Http\Server\RequestHandlerInterface;
11
use Sunrise\Http\Router\Exception\ExceptionInterface;
12
use Sunrise\Http\Router\Exception\MethodNotAllowedException;
13
use Sunrise\Http\Router\Exception\RouteNotFoundException;
14
use Sunrise\Http\Router\RouteCollection;
15
use Sunrise\Http\Router\RouteCollectionInterface;
16
use Sunrise\Http\Router\RouteInterface;
17
use Sunrise\Http\Router\Router;
18
use Sunrise\Http\ServerRequest\ServerRequestFactory;
19
20
/**
21
 * Import functions
22
 */
23
use function array_merge;
24
25
/**
26
 * RouterTest
27
 */
28
class RouterTest extends TestCase
29
{
30
31
    /**
32
     * @return void
33
     */
34
    public function testConstructor() : void
35
    {
36
        $router = new Router();
37
38
        $this->assertInstanceOf(RouteCollection::class, $router);
39
        $this->assertInstanceOf(MiddlewareInterface::class, $router);
40
        $this->assertInstanceOf(RequestHandlerInterface::class, $router);
41
    }
42
43
    /**
44
     * @return void
45
     */
46
    public function testGetRoute() : void
47
    {
48
        $routes = [
49
            new Fixture\TestRoute(),
50
            new Fixture\TestRoute(),
51
            new Fixture\TestRoute(),
52
        ];
53
54
        $router = new Router();
55
        $router->addRoutes(...$routes);
56
57
        $this->assertSame($routes[0], $router->getRoute($routes[0]->getName()));
58
        $this->assertSame($routes[1], $router->getRoute($routes[1]->getName()));
59
        $this->assertSame($routes[2], $router->getRoute($routes[2]->getName()));
60
    }
61
62
    /**
63
     * @return void
64
     */
65
    public function testGetUndefinedRoute() : void
66
    {
67
        $router = new Router();
68
69
        $this->expectException(RouteNotFoundException::class);
70
        $router->getRoute('foo');
71
    }
72
73
    /**
74
     * @return void
75
     */
76
    public function testMatch() : void
77
    {
78
        $routes = [
79
            new Fixture\TestRoute(),
80
            new Fixture\TestRoute(),
81
            new Fixture\TestRoute(),
82
            new Fixture\TestRoute(),
83
            new Fixture\TestRoute(),
84
        ];
85
86
        $router = new Router();
87
        $router->addRoutes(...$routes);
88
89
        $request = (new ServerRequestFactory)
90
            ->createServerRequest(
91
                $routes[2]->getMethods()[1],
92
                $routes[2]->getPath()
93
            );
94
95
        $foundRoute = $router->match($request);
96
97
        $this->assertSame($routes[2]->getName(), $foundRoute->getName());
98
    }
99
100
    /**
101
     * @return void
102
     */
103
    public function testMatchForUnallowedMethod() : void
104
    {
105
        $routes = [
106
            new Fixture\TestRoute(),
107
            new Fixture\TestRoute(),
108
            new Fixture\TestRoute(),
109
        ];
110
111
        $router = new Router();
112
        $router->addRoutes(...$routes);
113
114
        $request = (new ServerRequestFactory)
115
            ->createServerRequest('GET', '/');
116
117
        $this->expectException(MethodNotAllowedException::class);
118
119
        try {
120
            $router->match($request);
121
        } catch (MethodNotAllowedException $e) {
122
            $allowedMethods = array_merge(
123
                $routes[0]->getMethods(),
124
                $routes[1]->getMethods(),
125
                $routes[2]->getMethods()
126
            );
127
128
            $this->assertSame($allowedMethods, $e->getAllowedMethods());
129
130
            throw $e;
131
        }
132
    }
133
134
    /**
135
     * @return void
136
     */
137
    public function testMatchForUndefinedRoute() : void
138
    {
139
        $routes = [
140
            new Fixture\TestRoute(),
141
            new Fixture\TestRoute(),
142
            new Fixture\TestRoute(),
143
        ];
144
145
        $router = new Router();
146
        $router->addRoutes(...$routes);
147
148
        $request = (new ServerRequestFactory)
149
            ->createServerRequest($routes[0]->getMethods()[0], '/');
150
151
        $this->expectException(RouteNotFoundException::class);
152
        $router->match($request);
153
    }
154
155
    /**
156
     * @return void
157
     */
158
    public function testHandle() : void
159
    {
160
        $routes = [
161
            new Fixture\TestRoute(),
162
            new Fixture\TestRoute(),
163
            new Fixture\TestRoute(),
164
            new Fixture\TestRoute(),
165
            new Fixture\TestRoute(),
166
        ];
167
168
        $router = new Router();
169
        $router->addRoutes(...$routes);
170
171
        $request = (new ServerRequestFactory)
172
            ->createServerRequest(
173
                $routes[2]->getMethods()[1],
174
                $routes[2]->getPath()
175
            );
176
177
        $router->handle($request);
178
179
        $this->assertTrue($routes[2]->getRequestHandler()->isRunned());
180
    }
181
182
    /**
183
     * @return void
184
     */
185
    public function testHandleForUnallowedMethod() : void
186
    {
187
        $routes = [
188
            new Fixture\TestRoute(),
189
            new Fixture\TestRoute(),
190
            new Fixture\TestRoute(),
191
        ];
192
193
        $router = new Router();
194
        $router->addRoutes(...$routes);
195
196
        $request = (new ServerRequestFactory)
197
            ->createServerRequest('GET', '/');
198
199
        $this->expectException(MethodNotAllowedException::class);
200
201
        try {
202
            $router->handle($request);
203
        } catch (MethodNotAllowedException $e) {
204
            $allowedMethods = array_merge(
205
                $routes[0]->getMethods(),
206
                $routes[1]->getMethods(),
207
                $routes[2]->getMethods()
208
            );
209
210
            $this->assertSame($allowedMethods, $e->getAllowedMethods());
211
212
            throw $e;
213
        }
214
    }
215
216
    /**
217
     * @return void
218
     */
219
    public function testHandleForUndefinedRoute() : void
220
    {
221
        $routes = [
222
            new Fixture\TestRoute(),
223
            new Fixture\TestRoute(),
224
            new Fixture\TestRoute(),
225
        ];
226
227
        $router = new Router();
228
        $router->addRoutes(...$routes);
229
230
        $request = (new ServerRequestFactory)
231
            ->createServerRequest($routes[0]->getMethods()[0], '/');
232
233
        $this->expectException(RouteNotFoundException::class);
234
        $router->handle($request);
235
    }
236
237
    /**
238
     * @return void
239
     */
240
    public function testProcess() : void
241
    {
242
        $routes = [
243
            new Fixture\TestRoute(),
244
            new Fixture\TestRoute(),
245
            new Fixture\TestRoute(),
246
            new Fixture\TestRoute(),
247
            new Fixture\TestRoute(),
248
        ];
249
250
        $router = new Router();
251
        $router->addRoutes(...$routes);
252
253
        $request = (new ServerRequestFactory)
254
            ->createServerRequest(
255
                $routes[2]->getMethods()[1],
256
                $routes[2]->getPath()
257
            );
258
259
        $fallback = new Fixture\BlankRequestHandler();
260
261
        $router->process($request, $fallback);
262
263
        $this->assertTrue($routes[2]->getRequestHandler()->isRunned());
264
        $this->assertFalse($fallback->isRunned());
265
    }
266
267
    /**
268
     * @return void
269
     */
270
    public function testProcessForUnallowedMethod() : void
271
    {
272
        $routes = [
273
            new Fixture\TestRoute(),
274
            new Fixture\TestRoute(),
275
            new Fixture\TestRoute(),
276
        ];
277
278
        $router = new Router();
279
        $router->addRoutes(...$routes);
280
281
        $request = (new ServerRequestFactory)
282
            ->createServerRequest('GET', '/');
283
284
        $fallback = new Fixture\BlankRequestHandler();
285
286
        $router->process($request, $fallback);
287
288
        $this->assertInstanceOf(
289
            MethodNotAllowedException::class,
290
            $fallback->getAttribute(Router::ATTR_NAME_FOR_ROUTING_ERROR)
291
        );
292
293
        $this->assertTrue($fallback->isRunned());
294
    }
295
296
    /**
297
     * @return void
298
     */
299
    public function testProcessForUndefinedRoute() : void
300
    {
301
        $routes = [
302
            new Fixture\TestRoute(),
303
            new Fixture\TestRoute(),
304
            new Fixture\TestRoute(),
305
        ];
306
307
        $router = new Router();
308
        $router->addRoutes(...$routes);
309
310
        $request = (new ServerRequestFactory)
311
            ->createServerRequest($routes[0]->getMethods()[0], '/');
312
313
        $fallback = new Fixture\BlankRequestHandler();
314
315
        $router->process($request, $fallback);
316
317
        $this->assertInstanceOf(
318
            RouteNotFoundException::class,
319
            $fallback->getAttribute(Router::ATTR_NAME_FOR_ROUTING_ERROR)
320
        );
321
322
        $this->assertTrue($fallback->isRunned());
323
    }
324
325
    /**
326
     * @return void
327
     */
328
    public function testMatchPatterns() : void
329
    {
330
        $router = new Router();
331
        $router->get('test', '/{foo<[0-9]+>}/{bar<[a-zA-Z]+>}(/{baz<.*?>})', new Fixture\BlankRequestHandler());
332
333
        $route = $this->discoverRoute($router, 'GET', '/1990/Surgut/Tyumen');
334
        $this->assertEquals($route->getAttributes(), [
335
            'foo' => '1990',
336
            'bar' => 'Surgut',
337
            'baz' => 'Tyumen',
338
        ]);
339
340
        $route = $this->discoverRoute($router, 'GET', '/1990/Surgut/Tyumen/Moscow');
341
        $this->assertEquals($route->getAttributes(), [
342
            'foo' => '1990',
343
            'bar' => 'Surgut',
344
            'baz' => 'Tyumen/Moscow',
345
        ]);
346
347
        $route = $this->discoverRoute($router, 'GET', '/Oops/Surgut/Tyumen/Moscow');
348
        $this->assertNull($route);
349
350
        $route = $this->discoverRoute($router, 'GET', '/1990/2018/Moscow');
351
        $this->assertNull($route);
352
    }
353
354
    /**
355
     * @param Router $router
356
     * @param string $method
357
     * @param string $uri
358
     *
359
     * @return null|RouteInterface
360
     */
361
    private function discoverRoute(Router $router, string $method, string $uri) : ?RouteInterface
362
    {
363
        $request = (new ServerRequestFactory)
364
        ->createServerRequest($method, $uri);
365
366
        try {
367
            return $router->match($request);
368
        } catch (ExceptionInterface $e) {
369
            return null;
370
        }
371
    }
372
}
373