Test Failed
Pull Request — master (#32)
by Anatoly
04:53
created

RouterTest::testMatchWithSeveralHttpMethods()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 22
nc 1
nop 0
dl 0
loc 34
rs 9.568
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\Router;
16
use Sunrise\Http\ServerRequest\ServerRequestFactory;
17
18
/**
19
 * Import functions
20
 */
21
use function array_merge;
22
23
/**
24
 * RouterTest
25
 */
26
class RouterTest extends TestCase
27
{
28
29
    /**
30
     * @return void
31
     */
32
    public function testConstructor() : void
33
    {
34
        $router = new Router();
35
36
        $this->assertInstanceOf(MiddlewareInterface::class, $router);
37
        $this->assertInstanceOf(RequestHandlerInterface::class, $router);
38
    }
39
40
    /**
41
     * @return void
42
     */
43
    public function testAddRoute() : void
44
    {
45
        $routes = [
46
            new Fixture\TestRoute(),
47
            new Fixture\TestRoute(),
48
            new Fixture\TestRoute(),
49
        ];
50
51
        $router = new Router();
52
        $router->addRoute(...$routes);
53
54
        $this->assertSame($routes, $router->getRoutes());
55
    }
56
57
    /**
58
     * @return void
59
     */
60
    public function testAddMiddleware() : void
61
    {
62
        $middlewares = [
63
            new Fixture\BlankMiddleware(),
64
            new Fixture\BlankMiddleware(),
65
            new Fixture\BlankMiddleware(),
66
        ];
67
68
        $router = new Router();
69
        $router->addMiddleware(...$middlewares);
70
71
        $this->assertSame($middlewares, $router->getMiddlewares());
72
    }
73
74
    /**
75
     * @return void
76
     */
77
    public function testAddExistingRoute() : void
78
    {
79
        $route = new Fixture\TestRoute();
80
81
        $router = new Router();
82
        $router->addRoute($route);
83
84
        $this->expectException(RouteAlreadyExistsException::class);
85
        $this->expectExceptionMessage('A route with the name "' . $route->getName() . '" already exists.');
86
87
        $router->addRoute($route);
88
    }
89
90
    /**
91
     * @return void
92
     */
93
    public function testAddExistingMiddleware() : void
94
    {
95
        $middleware = new Fixture\BlankMiddleware();
96
97
        $router = new Router();
98
        $router->addMiddleware($middleware);
99
100
        $this->expectException(MiddlewareAlreadyExistsException::class);
101
        $this->expectExceptionMessage('A middleware with the hash "' . $middleware->getHash() . '" already exists.');
102
103
        $router->addMiddleware($middleware);
104
    }
105
106
    /**
107
     * @return void
108
     */
109
    public function testGetAllowedMethods() : void
110
    {
111
        $routes = [
112
            new Fixture\TestRoute(),
113
            new Fixture\TestRoute(),
114
            new Fixture\TestRoute(),
115
        ];
116
117
        $expectedMethods = array_merge(
118
            $routes[0]->getMethods(),
119
            $routes[1]->getMethods(),
120
            $routes[2]->getMethods(),
121
        );
122
123
        $router = new Router();
124
125
        $this->assertSame([], $router->getAllowedMethods());
126
127
        $router->addRoute(...$routes);
128
129
        $this->assertSame($expectedMethods, $router->getAllowedMethods());
130
    }
131
132
    /**
133
     * @return void
134
     */
135
    public function testGetRoute() : void
136
    {
137
        $routes = [
138
            new Fixture\TestRoute(),
139
            new Fixture\TestRoute(),
140
            new Fixture\TestRoute(),
141
        ];
142
143
        $router = new Router();
144
        $router->addRoute(...$routes);
145
146
        $this->assertSame($routes[1], $router->getRoute($routes[1]->getName()));
147
    }
148
149
    /**
150
     * @return void
151
     */
152
    public function testGetUndefinedRoute() : void
153
    {
154
        $routes = [
155
            new Fixture\TestRoute(),
156
            new Fixture\TestRoute(),
157
            new Fixture\TestRoute(),
158
        ];
159
160
        $router = new Router();
161
        $router->addRoute(...$routes);
162
163
        $this->expectException(RouteNotFoundException::class);
164
        $this->expectExceptionMessage('No route found with the name "foo".');
165
166
        $router->getRoute('foo');
167
    }
168
169
    /**
170
     * The test method only proxies the function `path_build`,
171
     * the function should be tested separately.
172
     *
173
     * @return void
174
     */
175
    public function testGenerateUri() : void
176
    {
177
        $route = new Fixture\TestRoute();
178
179
        $router = new Router();
180
        $router->addRoute($route);
181
182
        $this->assertSame($route->getPath(), $router->generateUri($route->getName()));
183
    }
184
185
    /**
186
     * @return void
187
     */
188
    public function testMatch() : void
189
    {
190
        $routes = [
191
            new Fixture\TestRoute(),
192
            new Fixture\TestRoute(),
193
            new Fixture\TestRoute(),
194
            new Fixture\TestRoute(),
195
            new Fixture\TestRoute(),
196
        ];
197
198
        $router = new Router();
199
        $router->addRoute(...$routes);
200
201
        $foundRoute = $router->match((new ServerRequestFactory)
202
            ->createServerRequest(
203
                $routes[2]->getMethods()[1],
204
                $routes[2]->getPath()
205
            ));
206
207
        $this->assertSame($routes[2]->getName(), $foundRoute->getName());
208
    }
209
210
    /**
211
     * @return void
212
     */
213
    public function testMatchForUnallowedMethod() : void
214
    {
215
        $routes = [
216
            new Fixture\TestRoute(),
217
            new Fixture\TestRoute(),
218
            new Fixture\TestRoute(),
219
        ];
220
221
        $router = new Router();
222
        $router->addRoute(...$routes);
223
224
        $request = (new ServerRequestFactory)
225
            ->createServerRequest('GET', $routes[0]->getPath());
226
227
        $this->expectException(MethodNotAllowedException::class);
228
        $this->expectExceptionMessage('No route found for the method "GET".');
229
230
        try {
231
            $router->match($request);
232
        } catch (MethodNotAllowedException $e) {
233
            $allowedMethods = array_merge(
234
                $routes[0]->getMethods(),
235
                $routes[1]->getMethods(),
236
                $routes[2]->getMethods()
237
            );
238
239
            $this->assertSame($allowedMethods, $e->getAllowedMethods());
240
241
            throw $e;
242
        }
243
    }
244
245
    /**
246
     * @return void
247
     */
248
    public function testMatchForUndefinedRoute() : void
249
    {
250
        $routes = [
251
            new Fixture\TestRoute(),
252
            new Fixture\TestRoute(),
253
            new Fixture\TestRoute(),
254
        ];
255
256
        $router = new Router();
257
        $router->addRoute(...$routes);
258
259
        $request = (new ServerRequestFactory)
260
            ->createServerRequest($routes[0]->getMethods()[0], '/');
261
262
        $this->expectException(RouteNotFoundException::class);
263
        $this->expectExceptionMessage('No route found for the URI "/".');
264
265
        $router->match($request);
266
    }
267
268
    /**
269
     * @return void
270
     */
271
    public function testHandle() : void
272
    {
273
        $routes = [
274
            new Fixture\TestRoute(),
275
            new Fixture\TestRoute(),
276
            new Fixture\TestRoute(),
277
            new Fixture\TestRoute(),
278
            new Fixture\TestRoute(),
279
        ];
280
281
        $router = new Router();
282
        $router->addRoute(...$routes);
283
284
        $router->handle((new ServerRequestFactory)
285
            ->createServerRequest(
286
                $routes[2]->getMethods()[1],
287
                $routes[2]->getPath()
288
            ));
289
290
        $this->assertTrue($routes[2]->getRequestHandler()->isRunned());
291
    }
292
293
    /**
294
     * @return void
295
     */
296
    public function testHandleWithMiddlewares() : void
297
    {
298
        $route = new Fixture\TestRoute();
299
300
        $middlewares = [
301
            new Fixture\BlankMiddleware(),
302
            new Fixture\BlankMiddleware(),
303
            new Fixture\BlankMiddleware(),
304
        ];
305
306
        $router = new Router();
307
        $router->addRoute($route);
308
        $router->addMiddleware(...$middlewares);
309
        $router->handle((new ServerRequestFactory)
310
            ->createServerRequest(
311
                $route->getMethods()[0],
312
                $route->getPath()
313
            ));
314
315
        $this->assertTrue($middlewares[0]->isRunned());
316
        $this->assertTrue($middlewares[1]->isRunned());
317
        $this->assertTrue($middlewares[2]->isRunned());
318
        $this->assertTrue($route->getRequestHandler()->isRunned());
319
    }
320
321
    /**
322
     * @return void
323
     */
324
    public function testHandleWithBrokenMiddleware() : void
325
    {
326
        $route = new Fixture\TestRoute();
327
328
        $middlewares = [
329
            new Fixture\BlankMiddleware(),
330
            new Fixture\BlankMiddleware(true),
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->assertFalse($middlewares[2]->isRunned());
346
        $this->assertFalse($route->getRequestHandler()->isRunned());
347
    }
348
349
    /**
350
     * @return void
351
     */
352
    public function testHandleForUnallowedMethod() : void
353
    {
354
        $routes = [
355
            new Fixture\TestRoute(),
356
            new Fixture\TestRoute(),
357
            new Fixture\TestRoute(),
358
        ];
359
360
        $router = new Router();
361
        $router->addRoute(...$routes);
362
363
        $request = (new ServerRequestFactory)
364
            ->createServerRequest('GET', '/');
365
366
        $this->expectException(MethodNotAllowedException::class);
367
        $this->expectExceptionMessage('No route found for the method "GET".');
368
369
        try {
370
            $router->handle($request);
371
        } catch (MethodNotAllowedException $e) {
372
            $allowedMethods = array_merge(
373
                $routes[0]->getMethods(),
374
                $routes[1]->getMethods(),
375
                $routes[2]->getMethods()
376
            );
377
378
            $this->assertSame($allowedMethods, $e->getAllowedMethods());
379
380
            throw $e;
381
        }
382
    }
383
384
    /**
385
     * @return void
386
     */
387
    public function testHandleForUndefinedRoute() : void
388
    {
389
        $routes = [
390
            new Fixture\TestRoute(),
391
            new Fixture\TestRoute(),
392
            new Fixture\TestRoute(),
393
        ];
394
395
        $router = new Router();
396
        $router->addRoute(...$routes);
397
398
        $request = (new ServerRequestFactory)
399
            ->createServerRequest($routes[0]->getMethods()[0], '/');
400
401
        $this->expectException(RouteNotFoundException::class);
402
        $this->expectExceptionMessage('No route found for the URI "/".');
403
404
        $router->handle($request);
405
    }
406
407
    /**
408
     * @return void
409
     */
410
    public function testProcess() : void
411
    {
412
        $routes = [
413
            new Fixture\TestRoute(),
414
            new Fixture\TestRoute(),
415
            new Fixture\TestRoute(),
416
            new Fixture\TestRoute(),
417
            new Fixture\TestRoute(),
418
        ];
419
420
        $router = new Router();
421
        $router->addRoute(...$routes);
422
423
        $fallback = new Fixture\BlankRequestHandler();
424
425
        $router->process((new ServerRequestFactory)
426
            ->createServerRequest(
427
                $routes[2]->getMethods()[1],
428
                $routes[2]->getPath()
429
            ), $fallback);
430
431
        $this->assertTrue($routes[2]->getRequestHandler()->isRunned());
432
        $this->assertFalse($fallback->isRunned());
433
    }
434
435
    /**
436
     * @return void
437
     */
438
    public function testProcessForUnallowedMethod() : void
439
    {
440
        $routes = [
441
            new Fixture\TestRoute(),
442
            new Fixture\TestRoute(),
443
            new Fixture\TestRoute(),
444
        ];
445
446
        $router = new Router();
447
        $router->addRoute(...$routes);
448
449
        $request = (new ServerRequestFactory)
450
            ->createServerRequest('GET', '/');
451
452
        $fallback = new Fixture\BlankRequestHandler();
453
454
        $router->process($request, $fallback);
455
456
        $this->assertInstanceOf(
457
            MethodNotAllowedException::class,
458
            $fallback->getAttribute(Router::ATTR_NAME_FOR_ROUTING_ERROR)
459
        );
460
461
        $this->assertTrue($fallback->isRunned());
462
    }
463
464
    /**
465
     * @return void
466
     */
467
    public function testProcessForUndefinedRoute() : void
468
    {
469
        $routes = [
470
            new Fixture\TestRoute(),
471
            new Fixture\TestRoute(),
472
            new Fixture\TestRoute(),
473
        ];
474
475
        $router = new Router();
476
        $router->addRoute(...$routes);
477
478
        $request = (new ServerRequestFactory)
479
            ->createServerRequest($routes[0]->getMethods()[0], '/');
480
481
        $fallback = new Fixture\BlankRequestHandler();
482
483
        $router->process($request, $fallback);
484
485
        $this->assertInstanceOf(
486
            RouteNotFoundException::class,
487
            $fallback->getAttribute(Router::ATTR_NAME_FOR_ROUTING_ERROR)
488
        );
489
490
        $this->assertTrue($fallback->isRunned());
491
    }
492
}
493