Test Failed
Pull Request — master (#34)
by Anatoly
02:07
created

RouterTest::testHandle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 21
nc 1
nop 0
dl 0
loc 30
rs 9.584
c 0
b 0
f 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\MethodNotAllowedException;
12
use Sunrise\Http\Router\Exception\MiddlewareAlreadyExistsException;
13
use Sunrise\Http\Router\Exception\RouteAlreadyExistsException;
14
use Sunrise\Http\Router\Exception\RouteNotFoundException;
15
use Sunrise\Http\Router\Loader\LoaderInterface;
16
use Sunrise\Http\Router\RouteCollection;
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(MiddlewareInterface::class, $router);
39
        $this->assertInstanceOf(RequestHandlerInterface::class, $router);
40
    }
41
42
    /**
43
     * @return void
44
     */
45
    public function testAddRoute() : void
46
    {
47
        $routes = [
48
            new Fixture\TestRoute(),
49
            new Fixture\TestRoute(),
50
            new Fixture\TestRoute(),
51
        ];
52
53
        $router = new Router();
54
        $router->addRoute(...$routes);
55
56
        $this->assertSame($routes, $router->getRoutes());
57
    }
58
59
    /**
60
     * @return void
61
     */
62
    public function testAddMiddleware() : void
63
    {
64
        $middlewares = [
65
            new Fixture\BlankMiddleware(),
66
            new Fixture\BlankMiddleware(),
67
            new Fixture\BlankMiddleware(),
68
        ];
69
70
        $router = new Router();
71
        $router->addMiddleware(...$middlewares);
72
73
        $this->assertSame($middlewares, $router->getMiddlewares());
74
    }
75
76
    /**
77
     * @return void
78
     */
79
    public function testAddExistingRoute() : void
80
    {
81
        $route = new Fixture\TestRoute();
82
83
        $router = new Router();
84
        $router->addRoute($route);
85
86
        // the given exception message should be tested through exceptions factory...
87
        $this->expectException(RouteAlreadyExistsException::class);
88
89
        try {
90
            $router->addRoute($route);
91
        } catch (RouteAlreadyExistsException $e) {
92
            // $this->assertSame($route, $e->fromContext('route'));
93
94
            throw $e;
95
        }
96
    }
97
98
    /**
99
     * @return void
100
     */
101
    public function testAddExistingMiddleware() : void
102
    {
103
        $middleware = new Fixture\BlankMiddleware();
104
105
        $router = new Router();
106
        $router->addMiddleware($middleware);
107
108
        // the given exception message should be tested through exceptions factory...
109
        $this->expectException(MiddlewareAlreadyExistsException::class);
110
111
        try {
112
            $router->addMiddleware($middleware);
113
        } catch (MiddlewareAlreadyExistsException $e) {
114
            // $this->assertSame($middleware, $e->fromContext('middleware'));
115
116
            throw $e;
117
        }
118
    }
119
120
    /**
121
     * @return void
122
     */
123
    public function testGetAllowedMethods() : void
124
    {
125
        $routes = [
126
            new Fixture\TestRoute(),
127
            new Fixture\TestRoute(),
128
            new Fixture\TestRoute(),
129
        ];
130
131
        $expectedMethods = array_merge(
132
            $routes[0]->getMethods(),
133
            $routes[1]->getMethods(),
134
            $routes[2]->getMethods()
135
        );
136
137
        $router = new Router();
138
139
        $this->assertSame([], $router->getAllowedMethods());
140
141
        $router->addRoute(...$routes);
142
143
        $this->assertSame($expectedMethods, $router->getAllowedMethods());
144
    }
145
146
    /**
147
     * @return void
148
     */
149
    public function testGetRoute() : void
150
    {
151
        $routes = [
152
            new Fixture\TestRoute(),
153
            new Fixture\TestRoute(),
154
            new Fixture\TestRoute(),
155
        ];
156
157
        $router = new Router();
158
        $router->addRoute(...$routes);
159
160
        $this->assertSame($routes[1], $router->getRoute($routes[1]->getName()));
161
    }
162
163
    /**
164
     * @return void
165
     */
166
    public function testGetUndefinedRoute() : void
167
    {
168
        $routes = [
169
            new Fixture\TestRoute(),
170
            new Fixture\TestRoute(),
171
            new Fixture\TestRoute(),
172
        ];
173
174
        $router = new Router();
175
        $router->addRoute(...$routes);
176
177
        // the given exception message should be tested through exceptions factory...
178
        $this->expectException(RouteNotFoundException::class);
179
180
        try {
181
            $router->getRoute('foo');
182
        } catch (RouteNotFoundException $e) {
183
            // $this->assertSame('foo', $e->fromContext('name'));
184
185
            throw $e;
186
        }
187
    }
188
189
    /**
190
     * The test method only proxies the function `path_build`,
191
     * the function should be tested separately.
192
     *
193
     * @return void
194
     */
195
    public function testGenerateUri() : void
196
    {
197
        $route = new Fixture\TestRoute();
198
199
        $router = new Router();
200
        $router->addRoute($route);
201
202
        $this->assertSame($route->getPath(), $router->generateUri($route->getName()));
203
    }
204
205
    /**
206
     * @return void
207
     */
208
    public function testMatch() : void
209
    {
210
        $routes = [
211
            new Fixture\TestRoute(),
212
            new Fixture\TestRoute(),
213
            new Fixture\TestRoute(),
214
            new Fixture\TestRoute(),
215
            new Fixture\TestRoute(),
216
        ];
217
218
        $router = new Router();
219
        $router->addRoute(...$routes);
220
221
        $foundRoute = $router->match((new ServerRequestFactory)
222
            ->createServerRequest(
223
                $routes[2]->getMethods()[1],
224
                $routes[2]->getPath()
225
            ));
226
227
        $this->assertSame($routes[2]->getName(), $foundRoute->getName());
228
    }
229
230
    /**
231
     * @return void
232
     */
233
    public function testMatchForUnallowedMethod() : void
234
    {
235
        $routes = [
236
            new Fixture\TestRoute(),
237
            new Fixture\TestRoute(),
238
            new Fixture\TestRoute(),
239
        ];
240
241
        $router = new Router();
242
        $router->addRoute(...$routes);
243
244
        $request = (new ServerRequestFactory)
245
            ->createServerRequest('GET', $routes[0]->getPath());
246
247
        // the given exception message should be tested through exceptions factory...
248
        $this->expectException(MethodNotAllowedException::class);
249
250
        try {
251
            $router->match($request);
252
        } catch (MethodNotAllowedException $e) {
253
            $allowedMethods = array_merge(
254
                $routes[0]->getMethods(),
255
                $routes[1]->getMethods(),
256
                $routes[2]->getMethods()
257
            );
258
259
            // $this->assertSame('GET', $e->fromContext('method'));
260
            $this->assertSame($allowedMethods, $e->fromContext('allowed'));
261
            $this->assertSame($allowedMethods, $e->getAllowedMethods());
262
263
            throw $e;
264
        }
265
    }
266
267
    /**
268
     * @return void
269
     */
270
    public function testMatchForUndefinedRoute() : void
271
    {
272
        $routes = [
273
            new Fixture\TestRoute(),
274
            new Fixture\TestRoute(),
275
            new Fixture\TestRoute(),
276
        ];
277
278
        $router = new Router();
279
        $router->addRoute(...$routes);
280
281
        $request = (new ServerRequestFactory)
282
            ->createServerRequest($routes[0]->getMethods()[0], '/');
283
284
        // the given exception message should be tested through exceptions factory...
285
        $this->expectException(RouteNotFoundException::class);
286
287
        try {
288
            $router->match($request);
289
        } catch (RouteNotFoundException $e) {
290
            // $this->assertSame('/', $e->fromContext('uri'));
291
292
            throw $e;
293
        }
294
    }
295
296
    /**
297
     * @return void
298
     */
299
    public function testHandle() : void
300
    {
301
        $routes = [
302
            new Fixture\TestRoute(),
303
            new Fixture\TestRoute(),
304
            new Fixture\TestRoute(),
305
            new Fixture\TestRoute(),
306
            new Fixture\TestRoute(),
307
        ];
308
309
        $router = new Router();
310
        $router->addRoute(...$routes);
311
312
        $router->handle((new ServerRequestFactory)
313
            ->createServerRequest(
314
                $routes[2]->getMethods()[1],
315
                $routes[2]->getPath()
316
            ));
317
318
        $this->assertTrue($routes[2]->getRequestHandler()->isRunned());
319
    }
320
321
    /**
322
     * @return void
323
     */
324
    public function testHandleWithMiddlewares() : void
325
    {
326
        $route = new Fixture\TestRoute();
327
328
        $middlewares = [
329
            new Fixture\BlankMiddleware(),
330
            new Fixture\BlankMiddleware(),
331
            new Fixture\BlankMiddleware(),
332
        ];
333
334
        $router = new Router();
335
        $router->addRoute($route);
336
        $router->addMiddleware(...$middlewares);
337
        $router->handle((new ServerRequestFactory)
338
            ->createServerRequest(
339
                $route->getMethods()[0],
340
                $route->getPath()
341
            ));
342
343
        $this->assertTrue($middlewares[0]->isRunned());
344
        $this->assertTrue($middlewares[1]->isRunned());
345
        $this->assertTrue($middlewares[2]->isRunned());
346
        $this->assertTrue($route->getRequestHandler()->isRunned());
347
    }
348
349
    /**
350
     * @return void
351
     */
352
    public function testHandleWithBrokenMiddleware() : void
353
    {
354
        $route = new Fixture\TestRoute();
355
356
        $middlewares = [
357
            new Fixture\BlankMiddleware(),
358
            new Fixture\BlankMiddleware(true),
359
            new Fixture\BlankMiddleware(),
360
        ];
361
362
        $router = new Router();
363
        $router->addRoute($route);
364
        $router->addMiddleware(...$middlewares);
365
        $router->handle((new ServerRequestFactory)
366
            ->createServerRequest(
367
                $route->getMethods()[0],
368
                $route->getPath()
369
            ));
370
371
        $this->assertTrue($middlewares[0]->isRunned());
372
        $this->assertTrue($middlewares[1]->isRunned());
373
        $this->assertFalse($middlewares[2]->isRunned());
374
        $this->assertFalse($route->getRequestHandler()->isRunned());
375
    }
376
377
    /**
378
     * @return void
379
     */
380
    public function testHandleForUnallowedMethod() : void
381
    {
382
        $routes = [
383
            new Fixture\TestRoute(),
384
            new Fixture\TestRoute(),
385
            new Fixture\TestRoute(),
386
        ];
387
388
        $router = new Router();
389
        $router->addRoute(...$routes);
390
391
        $request = (new ServerRequestFactory)
392
            ->createServerRequest('GET', '/');
393
394
        // the given exception message should be tested through exceptions factory...
395
        $this->expectException(MethodNotAllowedException::class);
396
397
        try {
398
            $router->handle($request);
399
        } catch (MethodNotAllowedException $e) {
400
            $allowedMethods = array_merge(
401
                $routes[0]->getMethods(),
402
                $routes[1]->getMethods(),
403
                $routes[2]->getMethods()
404
            );
405
406
            // $this->assertSame('GET', $e->fromContext('method'));
407
            $this->assertSame($allowedMethods, $e->fromContext('allowed'));
408
            $this->assertSame($allowedMethods, $e->getAllowedMethods());
409
410
            throw $e;
411
        }
412
    }
413
414
    /**
415
     * @return void
416
     */
417
    public function testHandleForUndefinedRoute() : void
418
    {
419
        $routes = [
420
            new Fixture\TestRoute(),
421
            new Fixture\TestRoute(),
422
            new Fixture\TestRoute(),
423
        ];
424
425
        $router = new Router();
426
        $router->addRoute(...$routes);
427
428
        $request = (new ServerRequestFactory)
429
            ->createServerRequest($routes[0]->getMethods()[0], '/');
430
431
        // the given exception message should be tested through exceptions factory...
432
        $this->expectException(RouteNotFoundException::class);
433
434
        try {
435
            $router->handle($request);
436
        } catch (RouteNotFoundException $e) {
437
            // $this->assertSame('/', $e->fromContext('uri'));
438
439
            throw $e;
440
        }
441
    }
442
443
    /**
444
     * @return void
445
     */
446
    public function testProcess() : void
447
    {
448
        $routes = [
449
            new Fixture\TestRoute(),
450
            new Fixture\TestRoute(),
451
            new Fixture\TestRoute(),
452
            new Fixture\TestRoute(),
453
            new Fixture\TestRoute(),
454
        ];
455
456
        $router = new Router();
457
        $router->addRoute(...$routes);
458
459
        $fallback = new Fixture\BlankRequestHandler();
460
461
        $router->process((new ServerRequestFactory)
462
            ->createServerRequest(
463
                $routes[2]->getMethods()[1],
464
                $routes[2]->getPath()
465
            ), $fallback);
466
467
        $this->assertTrue($routes[2]->getRequestHandler()->isRunned());
468
        $this->assertFalse($fallback->isRunned());
469
    }
470
471
    /**
472
     * @return void
473
     */
474
    public function testProcessForUnallowedMethod() : void
475
    {
476
        $routes = [
477
            new Fixture\TestRoute(),
478
            new Fixture\TestRoute(),
479
            new Fixture\TestRoute(),
480
        ];
481
482
        $router = new Router();
483
        $router->addRoute(...$routes);
484
485
        $request = (new ServerRequestFactory)
486
            ->createServerRequest('GET', '/');
487
488
        $fallback = new Fixture\BlankRequestHandler();
489
490
        $router->process($request, $fallback);
491
492
        $this->assertInstanceOf(
493
            MethodNotAllowedException::class,
494
            $fallback->getAttribute(Router::ATTR_NAME_FOR_ROUTING_ERROR)
495
        );
496
497
        $this->assertTrue($fallback->isRunned());
498
    }
499
500
    /**
501
     * @return void
502
     */
503
    public function testProcessForUndefinedRoute() : void
504
    {
505
        $routes = [
506
            new Fixture\TestRoute(),
507
            new Fixture\TestRoute(),
508
            new Fixture\TestRoute(),
509
        ];
510
511
        $router = new Router();
512
        $router->addRoute(...$routes);
513
514
        $request = (new ServerRequestFactory)
515
            ->createServerRequest($routes[0]->getMethods()[0], '/');
516
517
        $fallback = new Fixture\BlankRequestHandler();
518
519
        $router->process($request, $fallback);
520
521
        $this->assertInstanceOf(
522
            RouteNotFoundException::class,
523
            $fallback->getAttribute(Router::ATTR_NAME_FOR_ROUTING_ERROR)
524
        );
525
526
        $this->assertTrue($fallback->isRunned());
527
    }
528
529
    /**
530
     * @return void
531
     */
532
    public function testLoad() : void
533
    {
534
        $router = new Router();
535
536
        $expectedRoutes = [
537
            new Fixture\TestRoute(),
538
            new Fixture\TestRoute(),
539
            new Fixture\TestRoute(),
540
        ];
541
542
        $loader = $this->createMock(LoaderInterface::class);
543
544
        $loader->method('load')->willReturn(
545
            new RouteCollection(...$expectedRoutes)
546
        );
547
548
        $router->load($loader);
549
550
        $this->assertSame($expectedRoutes, $router->getRoutes());
551
    }
552
553
    /**
554
     * @return void
555
     */
556
    public function testMultipleLoad() : void
557
    {
558
        $router = new Router();
559
560
        $expectedRoutes = [
561
            new Fixture\TestRoute(),
562
            new Fixture\TestRoute(),
563
            new Fixture\TestRoute(),
564
        ];
565
566
        $loaders = [
567
            $this->createMock(LoaderInterface::class),
568
            $this->createMock(LoaderInterface::class),
569
            $this->createMock(LoaderInterface::class),
570
        ];
571
572
        $loaders[0]->method('load')->willReturn(
573
            new RouteCollection($expectedRoutes[0])
574
        );
575
576
        $loaders[1]->method('load')->willReturn(
577
            new RouteCollection($expectedRoutes[1])
578
        );
579
580
        $loaders[2]->method('load')->willReturn(
581
            new RouteCollection($expectedRoutes[2])
582
        );
583
584
        $router->load(...$loaders);
585
586
        $this->assertSame($expectedRoutes, $router->getRoutes());
587
    }
588
}
589