1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
<?php
declare(strict_types=1);
namespace BrettParson\MiniRoute\Tests;
use ArrayObject;
use BrettParson\MiniRoute\Routing\RouteNotFoundException;
use BrettParson\MiniRoute\Routing\RouteRegistrationException;
use BrettParson\MiniRoute\Routing\Router;
use BrettParson\MiniRoute\Tests\Fixtures\CollidingController;
use BrettParson\MiniRoute\Tests\Fixtures\FakeController;
use BrettParson\MiniRoute\Tests\Fixtures\FakeMiddleware;
use BrettParson\MiniRoute\Tests\Fixtures\FakeResolver;
use BrettParson\MiniRoute\Tests\Fixtures\TestRequest;
use BrettParson\MiniRoute\Tests\Fixtures\TestResponse;
use PHPUnit\Framework\TestCase;
final class RouterTest extends TestCase
{
/**
* @return array{Router, FakeResolver, ArrayObject}
*/
private function makeRouter(): array
{
$resolver = new FakeResolver();
$resolver->bind(FakeController::class, new FakeController());
$log = new ArrayObject();
$resolver->bind(FakeMiddleware::class, new FakeMiddleware('m', $log));
return [new Router($resolver), $resolver, $log];
}
public function testDispatchesToController(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$response = $router->dispatch(new TestRequest('GET', '/entries'));
$this->assertSame(200, $response->status());
$this->assertSame('index', $response->body());
}
public function testInjectsRouteParameters(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$response = $router->dispatch(new TestRequest('GET', '/entries/hello-world'));
$this->assertSame('show:hello-world', $response->body());
}
public function testAppliesRouteMiddleware(): void
{
[$router, , $log] = $this->makeRouter();
$router->registerController(FakeController::class);
$router->dispatch(new TestRequest('POST', '/entries'));
$this->assertSame(['m'], $log->getArrayCopy());
}
public function testDuplicateRouteThrows(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$this->expectException(RouteRegistrationException::class);
$router->registerController(FakeController::class);
}
public function testNotFoundThrowsWithoutHandler(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$this->expectException(RouteNotFoundException::class);
$router->dispatch(new TestRequest('GET', '/missing'));
}
public function testNotFoundHandlerIsCalledWhenSet(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$router->setNotFoundHandler(static fn (): TestResponse => new TestResponse(404, 'custom-nf'));
$response = $router->dispatch(new TestRequest('GET', '/missing'));
$this->assertSame(404, $response->status());
$this->assertSame('custom-nf', $response->body());
}
public function testTrailingSlashIsNormalized(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$response = $router->dispatch(new TestRequest('GET', '/entries/'));
$this->assertSame('index', $response->body());
}
public function testMethodIsCaseInsensitive(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$response = $router->dispatch(new TestRequest('get', '/entries'));
$this->assertSame('index', $response->body());
}
public function testLeadingDoubleSlashDoesNotMatch(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$this->expectException(RouteNotFoundException::class);
$router->dispatch(new TestRequest('GET', '//entries'));
}
public function testPathsAreCaseSensitive(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$this->expectException(RouteNotFoundException::class);
$router->dispatch(new TestRequest('GET', '/Entries'));
}
public function testDuplicateRouteAcrossControllersThrows(): void
{
[$router] = $this->makeRouter();
$router->registerController(FakeController::class);
$this->expectException(RouteRegistrationException::class);
$router->registerController(CollidingController::class);
}
}
|