Issues (101)

spec/Suite/Router.spec.php (70 issues)

1
<?php
2
declare(strict_types=1);
3
4
namespace Lead\Router\Spec\Suite;
5
6
use Kahlan\Plugin\Double;
7
use Lead\Router\Exception\RouteNotFoundException;
8
use Lead\Router\Exception\RouterException;
9
use Lead\Router\Router;
10
use Lead\Router\Route;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Psr\Http\Message\UriInterface;
13
14
describe("Router", function() {
15
16
    beforeEach(function() {
17
18
        $this->router = new Router();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
19
        $this->export = function($request) {
20
            return array_intersect_key($request, array_fill_keys(['path', 'method', 'host', 'scheme'], true));
21
        };
22
23
    });
24
25
    describe("->__construct()", function() {
26
27
        it("formats the basePath", function() {
28
29
            $router = new Router(['basePath' => '/']);
30
            expect($router->getBasePath())->toBe('');
31
32
        });
33
34
    });
35
36
    describe("->getBasePath()", function() {
37
38
        it("sets an empty basePath", function() {
39
40
            expect($this->router->setBasePath('/'))->toBe($this->router);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
41
            expect($this->router->getBasePath())->toBe('');
42
43
            expect($this->router->setBasePath(''))->toBe($this->router);
44
            expect($this->router->getBasePath())->toBe('');
45
46
        });
47
48
        it("adds an leading slash for non empty basePath", function() {
49
50
            expect($this->router->setBasePath('app'))->toBe($this->router);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
51
            expect($this->router->getBasePath())->toBe('/app');
52
53
            expect($this->router->setBasePath('/base'))->toBe($this->router);
54
            expect($this->router->getBasePath())->toBe('/base');
55
56
        });
57
58
    });
59
60
    describe("->bind()", function() {
61
62
        it("binds a named route", function() {
63
64
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
65
            $route = $r->bind('foo/bar', ['name' => 'foo'], function() { return 'hello'; });
66
            expect(isset($r['foo']))->toBe(true);
67
            expect($r['foo'])->toBe($route);
68
69
        });
70
71
        it("matches on methods", function() {
72
73
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
74
            $r->bind('foo/bar', ['methods' => ['POST', 'PUT']], function () {});
75
76
            $route = $r->route('foo/bar', 'POST');
77
            expect($route->getMethods())->toBe(['POST', 'PUT']);
78
79
            $route = $r->route('foo/bar', 'PUT');
80
            expect($route->getMethods())->toBe(['POST', 'PUT']);
81
82
            try {
83
                $route = $r->route('bar/foo', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
84
            } catch (RouteNotFoundException $e) {
85
                expect($e->getMessage())->toBe("No route found for `*:*:GET:/bar/foo`.");
86
            }
87
        });
88
89
        it("supports lowercase method names", function() {
90
91
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
92
            $r->bind('foo/bar', ['methods' => ['POST', 'PUT']], function () {});
93
94
            $route = $r->route('foo/bar', 'post');
95
            expect($route->getMethods())->toBe(['POST', 'PUT']);
96
97
            $route = $r->route('foo/bar', 'put');
98
            expect($route->getMethods())->toBe(['POST', 'PUT']);
99
100
            try {
101
                $route = $r->route('bar/foo', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
102
            } catch (RouteNotFoundException $e) {
103
                expect($e->getMessage())->toBe("No route found for `*:*:GET:/bar/foo`.");
104
            }
105
        });
106
107
        it("matches on same path different methods", function() {
108
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
109
            $r->bind('foo/bar', ['name' => 'foo', 'methods' => ['POST']], function () {});
110
            $r->bind('foo/bar', ['name' => 'bar', 'methods' => ['PUT']], function () {});
111
112
            $route = $r->route('foo/bar', 'POST');
113
            expect($route->name)->toBe('foo');
114
115
            $route = $r->route('foo/bar', 'PUT');
116
            expect($route->name)->toBe('bar');
117
        });
118
119
        it("throws an exception when the handler is not a closure", function() {
120
121
            $closure = function() {
122
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
123
                $r->bind('foo', 'substr');
124
            };
125
126
            expect($closure)->toThrow(new RouterException("The handler needs to be an instance of `Closure` or implements the `__invoke()` magic method."));
127
128
        });
129
130
        it("throws an exception when trying to use the `'method'` option", function() {
131
132
            $closure = function() {
133
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
134
                $r->bind('foo', ['method' => 'GET'], function() {});
135
            };
136
137
            expect($closure)->toThrow(new RouterException("Use the `'methods'` option to limit HTTP verbs on a route binding definition."));
138
139
        });
140
141
    });
142
143
    describe("->link()", function() {
144
145
        it("forwards router base path", function() {
146
147
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
148
            $r->basePath('app');
149
150
            $r->group(['host' => 'www.{domain}.com', 'scheme' => 'https'], function($r) {
151
                $r->bind('foo/{bar}', ['name' => 'foo'], function () {});
152
            });
153
154
            $link = $r->link('foo', [
155
                'bar'    => 'baz',
156
                'domain' => 'example'
157
            ], ['absolute' => true]);
158
            expect($link)->toBe('https://www.example.com/app/foo/baz');
159
160
        });
161
162
        it("maintains prefixes in nested routes", function() {
163
164
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
165
            $r->group('foo', ['name' => 'foz'], function($r) {
166
                $r->group('bar', ['name' => 'baz'], function($r) {
167
                    $r->bind('{var1}', ['name' => 'quz'], function () {});
168
                });
169
            });
170
171
            $link = $r->link('foz.baz.quz', ['var1' => 'hello']);
172
            expect($link)->toBe('/foo/bar/hello');
173
174
        });
175
176
        it("persists persisted parameters in a dispatching context", function() {
177
178
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
179
            $r->group('{locale:en|fr}', ['persist' => 'locale'], function($r) {
180
                $r->bind('{controller}/{action}[/{id}]', ['name' => 'controller'], function () {});
181
            });
182
183
            $r->route('fr/post/index');
184
            $link = $r->link('controller', [
185
                'controller' => 'post',
186
                'action'     => 'view',
187
                'id'         => 5
188
            ]);
189
            expect($link)->toBe('/fr/post/view/5');
190
191
            $r->route('en/post/index');
192
            $link = $r->link('controller', [
193
                'controller' => 'post',
194
                'action'     => 'view',
195
                'id'         => 5
196
            ]);
197
            expect($link)->toBe('/en/post/view/5');
198
199
        });
200
201
        it("overrides persisted parameters in a dispatching context", function() {
202
203
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
204
            $r->group('{locale:en|fr}', ['persist' => 'locale'], function($r) {
205
                $r->bind('{controller}/{action}[/{id}]', ['name' => 'controller'], function () {});
206
            });
207
208
            $r->route('fr/post/index');
209
210
            $link = $r->link('controller', [
211
                'locale'     => 'en',
212
                'controller' => 'post',
213
                'action'     => 'view',
214
                'id'         => 5
215
            ]);
216
            expect($link)->toBe('/en/post/view/5');
217
218
        });
219
220
        it("throws an exception when no route is found for a specified name", function() {
221
222
            $closure = function() {
223
                $this->router->link('not.binded.yet', []);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
224
            };
225
226
            expect($closure)->toThrow(new RouterException("No binded route defined for `'not.binded.yet'`, bind it first with `bind()`."));
227
228
        });
229
    });
230
231
    describe("->route()", function() {
232
233
        it("routes on a simple route", function() {
234
235
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
236
            $r->bind('foo/bar', function () {});
237
238
            $route = $r->route('foo/bar', 'GET');
239
            expect($this->export($route->request))->toEqual([
240
                'host'   => '*',
241
                'scheme' => '*',
242
                'method' => 'GET',
243
                'path'   => 'foo/bar'
244
            ]);
245
246
            try {
247
                $route = $r->route('bar/foo', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
248
            } catch (RouteNotFoundException $e) {
249
                expect($e->getMessage())->toBe("No route found for `*:*:GET:/bar/foo`.");
250
            }
251
        });
252
253
        it("routes on a named route", function() {
254
255
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
256
            $r->bind('foo/bar', ['name' => 'foo'], function () {});
257
258
            $route = $r->route('foo/bar', 'GET');
259
            expect($route->name)->toBe('foo');
260
261
            try {
262
                $route = $r->route('bar/foo', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
263
            } catch (RouteNotFoundException $e) {
264
                expect($e->getMessage())->toBe("No route found for `*:*:GET:/bar/foo`.");
265
            }
266
        });
267
268
        it("supports empty as index route", function() {
269
270
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
271
            $r->bind('', function () {});
272
273
            $route = $r->route('', 'GET');
274
            expect($this->export($route->request))->toEqual([
275
                'host'   => '*',
276
                'scheme' => '*',
277
                'method' => 'GET',
278
                'path'   => ''
279
            ]);
280
281
        });
282
283
        it("supports a slash as indes route", function() {
284
285
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
286
            $r->bind('/', function () {});
287
288
            $route = $r->route('', 'GET');
289
            expect($this->export($route->request))->toEqual([
290
                'host'   => '*',
291
                'scheme' => '*',
292
                'method' => 'GET',
293
                'path'   => ''
294
            ]);
295
296
        });
297
298
        it("supports route variables", function() {
299
300
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
301
            $r->get('foo/{param}', function() {});
302
303
            $route = $r->route('foo/bar', 'GET');
304
            expect($route->params)->toBe(['param' => 'bar']);
305
306
            try {
307
                $route = $r->route('bar/foo', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
308
            } catch (RouteNotFoundException $e) {
309
                expect($e->getMessage())->toBe("No route found for `*:*:GET:/bar/foo`.");
310
            }
311
        });
312
313
        it("supports constrained route variables", function() {
314
315
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
316
            $r->get('foo/{var1:\d+}', function() {});
317
318
            $route = $r->route('foo/25', 'GET');
319
            expect($route->params)->toBe(['var1' => '25']);
320
321
            try {
322
                $route = $r->route('foo/bar', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
323
            } catch (RouteNotFoundException $e) {
324
                expect($e->getMessage())->toBe("No route found for `*:*:GET:/foo/bar`.");
325
            }
326
        });
327
328
        it("supports optional segments with variables", function() {
329
330
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
331
            $r->get('foo[/{var1}]', function() {});
332
333
            $route = $r->route('foo', 'GET');
334
            expect($route->params)->toBe(['var1' => null]);
335
336
            $route = $r->route('foo/bar', 'GET');
337
            expect($route->params)->toBe(['var1' => 'bar']);
338
339
        });
340
341
        it("supports repeatable segments", function() {
342
343
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
344
            $r->get('foo[/:{var1}]*[/bar[/:{var2}]*]', function() {});
345
346
            $route = $r->route('foo', 'GET');
347
            expect($route->params)->toBe([
348
                'var1' => [],
349
                'var2' => []
350
            ]);
351
352
            $route = $r->route('foo/:bar', 'GET');
353
            expect($route->params)->toBe([
354
                'var1' => ['bar'],
355
                'var2' => []
356
            ]);
357
358
            $route = $r->route('foo/:bar/:baz/bar/:fuz', 'GET');
359
            expect($route->params)->toBe([
360
                'var1' => ['bar', 'baz'],
361
                'var2' => ['fuz']
362
            ]);
363
        });
364
365
        it("supports optional segments with custom variable regex", function() {
366
367
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
368
            $r->get('foo[/{var1:\d+}]', function() {});
369
370
            $route = $r->route('foo', 'GET');
371
            expect($route->params)->toBe(['var1' => null]);
372
373
            $route = $r->route('foo/25', 'GET');
374
            expect($route->params)->toBe(['var1' => '25']);
375
376
            try {
377
                $route = $r->route('foo/baz', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
378
            } catch (RouteNotFoundException $e) {
379
                expect($e->getMessage())->toBe("No route found for `*:*:GET:/foo/baz`.");
380
            }
381
        });
382
383
        it("supports multiple optional segments", function() {
384
385
            $patterns = [
386
                '/[{var1}[/{var2}]]'
387
            ];
388
389
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
390
391
            foreach ($patterns as $pattern) {
392
                $r->get($pattern, function() {});
393
394
                $route = $r->route('foo', 'GET');
395
                expect($route->params)->toBe(['var1' => 'foo', 'var2' => null]);
396
397
                $route = $r->route('foo/bar', 'GET');
398
                expect($route->params)->toBe(['var1' => 'foo', 'var2' => 'bar']);
399
400
                $r->clear();
401
402
            };
403
404
        });
405
406
        it("supports host variables", function() {
407
408
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
409
            $r->get('foo/{var1:\d+}', ['host' => 'foo.{domain}.bar'], function() {});
410
            $r->get('foo/{var1:\d+}', ['host' => 'foo.{domain}.baz'], function() {});
411
412
            $route = $r->route('foo/25', 'GET', 'foo.biz.bar');
413
            expect($route->getHost()->getPattern())->toBe('foo.{domain}.bar');
414
            expect($route->params)->toBe(['domain' => 'biz', 'var1' => '25']);
415
416
            $route = $r->route('foo/50', 'GET', 'foo.buz.baz');
417
            expect($route->getHost()->getPattern())->toBe('foo.{domain}.baz');
418
            expect($route->params)->toBe(['domain' => 'buz', 'var1' => '50']);
419
420
        });
421
422
        it("supports constrained host variables", function() {
423
424
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
425
            $r->get('foo/{var1:\d+}', ['host' => '{subdomain:foo}.{domain}.bar'], function() {});
426
427
            $route = $r->route('foo/25', 'GET', 'foo.biz.bar');
428
            expect($route->params)->toBe([ 'subdomain' => 'foo', 'domain' => 'biz', 'var1' => '25']);
429
430
            try {
431
                $route = $r->route('foo/bar', 'GET', 'foo.biz.bar');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
432
            } catch (RouteNotFoundException $e) {
433
                expect($e->getMessage())->toBe("No route found for `*:foo.biz.bar:GET:/foo/bar`.");
434
            }
435
        });
436
437
        it("supports absolute URL", function() {
438
439
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
440
            $r->get('foo/{var1:\d+}', ['host' => 'foo.{domain}.bar'], function() {});
441
            $r->get('foo/{var1:\d+}', ['host' => 'foo.{domain}.baz'], function() {});
442
443
            $route = $r->route('http://foo.biz.bar/foo/25', 'GET');
444
            expect($route->getHost()->getPattern())->toBe('foo.{domain}.bar');
445
            expect($route->params)->toBe(['domain' => 'biz', 'var1' => '25']);
446
447
            $route = $r->route('http://foo.buz.baz/foo/50', 'GET');
448
            expect($route->getHost()->getPattern())->toBe('foo.{domain}.baz');
449
            expect($route->params)->toBe(['domain' => 'buz', 'var1' => '50']);
450
451
        });
452
453
        it("supports RESTful routes", function() {
454
455
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
456
            $r->get('foo/bar', function () {});
457
            $r->head('foo/bar', function () {});
458
            $r->post('foo/bar', function () {});
459
            $r->put('foo/bar', function () {});
460
            $r->patch('foo/bar', function () {});
461
            $r->delete('foo/bar', function () {});
462
            $r->options('foo/bar', function () {});
463
464
            $methods = ['OPTIONS', 'DELETE', 'PATCH', 'PUT', 'POST', 'HEAD', 'GET'];
465
466
            $route = $r->route('foo/bar', 'GET');
467
            expect($route->getMethods())->toBe($methods);
468
469
            $route = $r->route('foo/bar', 'HEAD');
470
            expect($route->getMethods())->toBe($methods);
471
472
            $route = $r->route('foo/bar', 'POST');
473
            expect($route->getMethods())->toBe($methods);
474
475
            $route = $r->route('foo/bar', 'PUT');
476
            expect($route->getMethods())->toBe($methods);
477
478
            $route = $r->route('foo/bar', 'PATCH');
479
            expect($route->getMethods())->toBe($methods);
480
481
            $route = $r->route('foo/bar', 'DELETE');
482
            expect($route->getMethods())->toBe($methods);
483
484
            $route = $r->route('foo/bar', 'OPTIONS');
485
            expect($route->getMethods())->toBe($methods);
486
487
        });
488
489
        it("matches relationships based routes", function() {
490
491
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
492
            $r->get('[/{relations:[^/]+/[^/:][^/]*}]*/comment[/{id:[^/:][^/]*}][/:{action}]', function () {});
493
494
            $route = $r->route('blog/1/post/22/comment/:show', 'GET');
495
            expect($route->params)->toBe([
496
                'relations' => [
497
                    ['blog', '1'],
498
                    ['post', '22']
499
                ],
500
                'id' => null,
501
                'action' => 'show'
502
            ]);
503
504
        });
505
506
        it("dispatches HEAD requests on matching GET routes if the HEAD routes are missing", function() {
507
508
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
509
            $r->get('foo/bar', function () { return 'GET'; });
510
511
            $route = $r->route('foo/bar', 'HEAD');
512
            expect($route->getMethods())->toBe(['GET']);
513
514
        });
515
516
        it("dispatches HEAD requests on matching HEAD routes", function() {
517
518
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
519
520
            $r->head('foo/bar', function () { return 'HEAD'; });
521
            $r->get('foo/bar', function () { return 'GET'; });
522
523
            $route = $r->route('foo/bar', 'HEAD');
524
            expect($route->getMethods())->toBe(['GET', 'HEAD']);
525
526
        });
527
528
        it("supports requests as a list of arguments", function() {
529
530
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
531
            $r->bind('foo/bar', function () {});
532
533
            $route = $r->route('foo/bar', 'GET');
534
            expect($this->export($route->request))->toEqual([
535
                'scheme' => '*',
536
                'host'   => '*',
537
                'method' => 'GET',
538
                'path'   => 'foo/bar'
539
            ]);
540
541
        });
542
543
        it("supports requests as an object", function() {
544
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
545
            $r->bind('foo/bar', function () {});
546
547
            $request = Double::instance(['implements' => ServerRequestInterface::class]);
548
            $uri = Double::instance(['implements' => UriInterface::class]);
549
550
            allow($request)->toReceive('basePath')->andReturn('/');
551
            allow($uri)->toReceive('getScheme')->andReturn('http');
552
            allow($uri)->toReceive('getHost')->andReturn('');
553
            allow($uri)->toReceive('getPath')->andReturn('foo/bar');
554
            allow($request)->toReceive('getMethod')->andReturn('GET');
555
            allow($request)->toReceive('getUri')->andReturn($uri);
556
557
            $route = $r->route($request, 'GET');
558
            expect($route->request)->toBe($request);
559
560
        });
561
562
        it("supports requests as an array", function() {
563
564
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
565
            $r->bind('foo/bar', function () {});
566
567
            $route = $r->route(['path' =>'foo/bar'], 'GET');
568
            expect($this->export($route->request))->toEqual([
569
                'scheme' => '*',
570
                'host'   => '*',
571
                'method' => 'GET',
572
                'path'   => 'foo/bar'
573
            ]);
574
575
        });
576
577
    });
578
579
    describe("->group()", function() {
580
581
        it("supports nested named route", function() {
582
583
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
584
            $r->group('foo', ['name' => 'foz'], function($r) use (&$route) {
585
                $r->group('bar', ['name' => 'baz'], function($r) use (&$route) {
586
                    $route = $r->bind('{var1}', ['name' => 'quz'], function() {});
587
                });
588
            });
589
590
            expect(isset($r['foz.baz.quz']))->toBe(true);
591
            expect($r['foz.baz.quz'])->toBe($route);
592
593
        });
594
595
        it("returns a working scope", function() {
596
597
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
598
            $route = $r->group('foo', ['name' => 'foz'], function() {
599
            })->group('bar', ['name' => 'baz'], function() {
600
            })->bind('{var1}', ['name' => 'quz'], function() {});
601
602
            expect(isset($r['foz.baz.quz']))->toBe(true);
603
            expect($r['foz.baz.quz'])->toBe($route);
604
605
        });
606
607
        context("with a prefix contraint", function() {
608
609
            beforeEach(function() {
610
611
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
612
                $r->group('foo', function($r) {
613
                    $r->bind('{var1}', function () {});
614
                });
615
616
            });
617
618
            it("respects url's prefix constraint", function() {
619
620
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
621
                $route = $r->route('foo/bar');
622
                expect($route->params)->toBe(['var1'   => 'bar']);
623
624
            });
625
626
            it("throws an exception when the prefix does not match", function () {
627
628
                $closure = function () {
629
                    $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
630
                    $route = $r->route('bar/foo', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
631
                };
632
633
                expect($closure)->toThrow(new RouteNotFoundException("No route found for `*:*:GET:/bar/foo`."));
634
            });
635
        });
636
637
        context("with a prefix contraint and an optional parameter", function() {
638
639
            beforeEach(function() {
640
641
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
642
                $r->group('foo', function($r) {
643
                    $r->bind('[{var1}]', function () {});
644
                });
645
646
            });
647
648
            it("respects url's prefix constraint", function() {
649
650
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
651
                $route = $r->route('foo');
652
                expect($route->params)->toBe(['var1' => null]);
653
654
            });
655
656
            it("throws an exception when the prefix does not match", function () {
657
658
                $closure = function () {
659
                    $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
660
                    $route = $r->route('bar/foo', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
661
                };
662
663
                expect($closure)->toThrow(new RouteNotFoundException("No route found for `*:*:GET:/bar/foo`."));
664
            });
665
        });
666
667
        context("with a host constraint", function() {
668
669
            beforeEach(function() {
670
671
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
672
                $r->group('foo', ['host' => 'foo.{domain}.bar'], function($r) {
673
                    $r->group('bar', function($r) {
674
                        $r->bind('{var1}', function () {});
675
                    });
676
                });
677
678
            });
679
680
            it("respects url's host constraint", function() {
681
682
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
683
                $route = $r->route('http://foo.hello.bar/foo/bar/baz', 'GET');
684
                expect($route->params)->toBe([
685
                    'domain' => 'hello',
686
                    'var1'   => 'baz'
687
                ]);
688
689
            });
690
691
            it("throws an exception when the host does not match", function () {
692
693
                $closure = function () {
694
                    $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
695
                    $route = $r->route('http://bar.hello.foo/foo/bar/baz', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
696
                };
697
698
                expect($closure)->toThrow(new RouteNotFoundException("No route found for `http:bar.hello.foo:GET:/foo/bar/baz`."));
699
            });
700
        });
701
702
        context("with a scheme constraint", function() {
703
704
            beforeEach(function() {
705
706
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
707
                $r->group('foo', ['scheme' => 'http'], function($r) {
708
                    $r->group('bar', function($r) {
709
                        $r->bind('{var1}', function () {});
710
                    });
711
                });
712
713
            });
714
715
            it("respects url's scheme constraint", function() {
716
717
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
718
                $route = $r->route('http://domain.com/foo/bar/baz', 'GET');
719
                expect($route->params)->toBe([
720
                    'var1'   => 'baz'
721
                ]);
722
723
            });
724
725
            it("throws an exception when route is not found", function () {
726
727
                $closure = function () {
728
                    $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
729
                    $route = $r->route('https://domain.com/foo/bar/baz', 'GET');
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
730
                };
731
732
                expect($closure)->toThrow(new RouteNotFoundException("No route found for `https:domain.com:GET:/foo/bar/baz`."));
733
            });
734
        });
735
736
        it("concats namespace values", function() {
737
738
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
739
            $r->group('foo', ['namespace' => 'My'], function($r) {
740
                $r->group('bar', ['namespace' => 'Name'], function($r) {
741
                    $r->bind('{var1}', ['namespace' => 'Space'], function () {});
742
                });
743
            });
744
745
            $route = $r->route('foo/bar/baz', 'GET');
746
            expect($route->namespace)->toBe('My\Name\Space\\');
747
748
        });
749
750
        it("throws an exception when the handler is not a closure", function() {
751
752
            $closure = function() {
753
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
754
                $r->group('foo', 'substr');
755
            };
756
757
            expect($closure)->toThrow(new RouterException("The handler needs to be an instance of `Closure` or implements the `__invoke()` magic method."));
758
759
        });
760
761
    });
762
763
    describe("->middleware()", function() {
764
765
        it("returns global middleware", function() {
766
767
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
768
769
            $mw1 = function($request, $response, $next) {
770
                return '1' . $next() . '1';
771
            };
772
            $mw2 = function($request, $response, $next) {
773
                return '2' . $next() . '2';
774
            };
775
776
            $r->apply($mw1, $mw2);
777
778
            $next = function() { return ''; };
779
780
            $generator = $r->middleware();
781
782
            $actual2 = $generator->current();
783
            $generator->next();
784
            $actual1 = $generator->current();
785
786
            expect($actual2(null, null, $next))->toBe('22');
787
            expect($actual1(null, null, $next))->toBe('11');
788
789
        });
790
791
    });
792
793
    describe("->apply()", function() {
794
795
        it("applies middlewares globally", function() {
796
797
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
798
799
            $r->apply(function($request, $response, $next) {
800
                return '1' . $next() . '1';
801
            })->apply(function($request, $response, $next) {
802
                return '2' . $next() . '2';
803
            });
804
805
            $route = $r->bind('/foo/bar', function($route) {
0 ignored issues
show
The assignment to $route is dead and can be removed.
Loading history...
The parameter $route is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

805
            $route = $r->bind('/foo/bar', function(/** @scrutinizer ignore-unused */ $route) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
806
                return 'A';
807
            });
808
809
            $route = $r->route('foo/bar');
810
            $actual = $route->dispatch();
811
812
            expect($actual)->toBe('21A12');
813
814
        });
815
816
        it("applies middlewares globally and per groups", function() {
817
818
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
819
820
            $r->apply(function($request, $response, $next) {
821
                return '1' . $next() . '1';
822
            });
823
824
            $r->bind('foo/{foo}', ['name' => 'foo'], function () {
825
                return 'A';
826
            });
827
828
            $r->group('bar', function($r) {
829
                $r->bind('{bar}', ['name' => 'bar'], function () {
830
                    return 'A';
831
                });
832
            })->apply(function($request, $response, $next) {
833
                return '2' . $next() . '2';
834
            });
835
836
            $route = $r->route('foo/foo');
837
            $actual = $route->dispatch();
838
839
            expect($actual)->toBe('1A1');
840
841
            $route = $r->route('bar/bar');
842
            $actual = $route->dispatch();
843
844
            expect($actual)->toBe('21A12');
845
846
        });
847
848
    });
849
850
    describe("->strategy()", function() {
851
852
        it("sets a strategy", function() {
853
854
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
855
856
            $mystrategy = function($router) {
857
                $router->bind('foo/bar', function() {
858
                    return 'Hello World!';
859
                });
860
            };
861
862
            $r->strategy('mystrategy', $mystrategy);
863
            expect($r->strategy('mystrategy'))->toBe($mystrategy);
864
865
            $r->mystrategy();
866
            $route = $r->route('foo/bar');
867
            expect($route->getPattern())->toBe('/foo/bar');
868
869
        });
870
871
        it("unsets a strategy", function() {
872
873
            $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
874
875
            $mystrategy = function() {};
876
877
            $r->strategy('mystrategy', $mystrategy);
878
            expect($r->strategy('mystrategy'))->toBe($mystrategy);
879
880
            $r->strategy('mystrategy', false);
881
            expect($r->strategy('mystrategy'))->toBe(null);
882
883
        });
884
885
        it("throws an exception when the handler is not a closure", function() {
886
887
            $closure = function() {
888
                $r = $this->router;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
889
                $r->strategy('mystrategy', "substr");
890
            };
891
892
            expect($closure)->toThrow(new RouterException("The handler needs to be an instance of `Closure` or implements the `__invoke()` magic method."));
893
894
        });
895
896
    });
897
898
});
899