Passed
Push — master ( 7fc855...fc8ef2 )
by Alexander
13:50
created

RouteTest   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 290
Duplicated Lines 0 %

Importance

Changes 15
Bugs 4 Features 0
Metric Value
eloc 110
c 15
b 4
f 0
dl 0
loc 290
rs 10
wmc 3
1
<?php
2
3
namespace Yiisoft\Router\Tests;
4
5
use Nyholm\Psr7\Response;
6
use Nyholm\Psr7\ServerRequest;
7
use PHPUnit\Framework\TestCase;
8
use Psr\Container\ContainerInterface;
9
use Psr\Http\Message\ResponseInterface;
10
use Psr\Http\Message\ServerRequestInterface;
11
use Psr\Http\Server\MiddlewareInterface;
12
use Psr\Http\Server\RequestHandlerInterface;
13
use Yiisoft\Http\Method;
14
use Yiisoft\Router\Tests\Support\Container;
15
use Yiisoft\Router\Tests\Support\TestController;
16
use Yiisoft\Router\Tests\Support\TestMiddleware;
17
use Yiisoft\Router\Route;
18
19
final class RouteTest extends TestCase
20
{
21
    public function testName(): void
22
    {
23
        $route = Route::get('/')->name('test.route');
24
25
        $this->assertSame('test.route', $route->getName());
26
    }
27
28
    public function testNameDefault(): void
29
    {
30
        $route = Route::get('/');
31
32
        $this->assertSame('GET /', $route->getName());
33
    }
34
35
    public function testMethods(): void
36
    {
37
        $route = Route::methods([Method::POST, Method::HEAD], '/');
38
39
        $this->assertSame([Method::POST, Method::HEAD], $route->getMethods());
40
    }
41
42
    public const PATCH = 'PATCH';
43
    public const HEAD = 'HEAD';
44
    public const OPTIONS = 'OPTIONS';
45
46
    public function testGetMethod(): void
47
    {
48
        $route = Route::get('/');
49
50
        $this->assertSame([Method::GET], $route->getMethods());
51
    }
52
53
    public function testPostMethod(): void
54
    {
55
        $route = Route::post('/');
56
57
        $this->assertSame([Method::POST], $route->getMethods());
58
    }
59
60
    public function testPutMethod(): void
61
    {
62
        $route = Route::put('/');
63
64
        $this->assertSame([Method::PUT], $route->getMethods());
65
    }
66
67
    public function testDeleteMethod(): void
68
    {
69
        $route = Route::delete('/');
70
71
        $this->assertSame([Method::DELETE], $route->getMethods());
72
    }
73
74
    public function testPatchMethod(): void
75
    {
76
        $route = Route::patch('/');
77
78
        $this->assertSame([Method::PATCH], $route->getMethods());
79
    }
80
81
    public function testHeadMethod(): void
82
    {
83
        $route = Route::head('/');
84
85
        $this->assertSame([Method::HEAD], $route->getMethods());
86
    }
87
88
    public function testOptionsMethod(): void
89
    {
90
        $route = Route::options('/');
91
92
        $this->assertSame([Method::OPTIONS], $route->getMethods());
93
    }
94
95
    public function testAnyMethod(): void
96
    {
97
        $route = Route::anyMethod('/');
98
99
        $this->assertSame(Method::ANY, $route->getMethods());
100
    }
101
102
    public function testPattern(): void
103
    {
104
        $route = Route::get('/test')->pattern('/test2');
105
106
        $this->assertSame('/test2', $route->getPattern());
107
    }
108
109
    public function testHost(): void
110
    {
111
        $route = Route::get('/')->host('https://yiiframework.com/');
112
113
        $this->assertSame('https://yiiframework.com', $route->getHost());
114
    }
115
116
    public function testDefaults(): void
117
    {
118
        $route = Route::get('/{language}')->defaults(['language' => 'en']);
119
120
        $this->assertSame(['language' => 'en'], $route->getDefaults());
121
    }
122
123
    public function testToString(): void
124
    {
125
        $route = Route::methods([Method::GET, Method::POST], '/')->name('test.route')->host('yiiframework.com');
126
127
        $this->assertSame('[test.route] GET,POST yiiframework.com/', (string)$route);
128
    }
129
130
    public function testToStringSimple(): void
131
    {
132
        $route = Route::get('/');
133
134
        $this->assertSame('GET /', (string)$route);
135
    }
136
137
    public function testInvalidMiddlewareMethod(): void
138
    {
139
        $this->expectException(\InvalidArgumentException::class);
140
        Route::get('/', new \stdClass());
141
    }
142
143
    public function testInvalidMiddlewareAdd(): void
144
    {
145
        $this->expectException(\InvalidArgumentException::class);
146
        Route::get('/')->addMiddleware(new \stdClass());
147
    }
148
149
    public function testAddMiddleware(): void
150
    {
151
        $container = $this->createMock(ContainerInterface::class);
152
        $request = new ServerRequest('GET', '/');
153
154
        $route = Route::get('/', null, $container)->addMiddleware(
155
            function () {
156
                return new Response(418);
157
            }
158
        );
159
160
        $response = $route->process($request, $this->getRequestHandler());
161
        $this->assertSame(418, $response->getStatusCode());
162
    }
163
164
    public function testAddCallableMiddleware(): void
165
    {
166
        $request = new ServerRequest('GET', '/');
167
168
        $route = Route::get('/', null, $this->getContainer())->addMiddleware(
169
            static function (): ResponseInterface {
170
                return (new Response())->withStatus(418);
171
            }
172
        );
173
174
        $response = $route->process($request, $this->getRequestHandler());
175
        $this->assertSame(418, $response->getStatusCode());
176
    }
177
178
    public function testAddCallableArrayMiddleware(): void
179
    {
180
        $request = new ServerRequest('GET', '/');
181
182
        $route = Route::get('/', null, $this->getContainer([TestController::class => new TestController()]))->addMiddleware([TestController::class, 'index']);
183
184
        $response = $route->process($request, $this->getRequestHandler());
185
        $this->assertSame(200, $response->getStatusCode());
186
    }
187
188
    public function testMiddlewareFullStackCalled(): void
189
    {
190
        $container = $this->getContainer();
191
        $request = new ServerRequest('GET', '/');
192
193
        $routeOne = Route::get('/', null, $container);
194
195
        $middleware1 = function (ServerRequestInterface $request, RequestHandlerInterface $handler) {
196
            $request = $request->withAttribute('middleware', 'middleware1');
197
            return $handler->handle($request);
198
        };
199
        $middleware2 = function (ServerRequestInterface $request) {
200
            return new Response(200, [], null, '1.1', implode($request->getAttributes()));
201
        };
202
203
        $routeOne = $routeOne->addMiddleware($middleware2)->addMiddleware($middleware1);
204
205
        $response = $routeOne->process($request, $this->getRequestHandler());
206
        $this->assertSame(200, $response->getStatusCode());
207
        $this->assertSame('middleware1', $response->getReasonPhrase());
208
    }
209
210
    public function testMiddlewareStackInterrupted(): void
211
    {
212
        $container = $this->getContainer();
213
        $request = new ServerRequest('GET', '/');
214
215
        $routeTwo = Route::get('/', null, $container);
216
217
        $middleware1 = function () {
218
            return new Response(403);
219
        };
220
        $middleware2 = function () {
221
            return new Response(200);
222
        };
223
224
        $routeTwo = $routeTwo->addMiddleware($middleware2)->addMiddleware($middleware1);
225
226
        $response = $routeTwo->process($request, $this->getRequestHandler());
227
        $this->assertSame(403, $response->getStatusCode());
228
    }
229
230
    public function testInvalidMiddlewareAddWrongStringLL(): void
231
    {
232
        $this->expectException(\InvalidArgumentException::class);
233
        Route::get('/', 'test');
234
    }
235
236
    public function testInvalidMiddlewareAddWrongStringClassLL(): void
237
    {
238
        $this->expectException(\InvalidArgumentException::class);
239
        $this->expectExceptionMessage('Parameter should be either PSR middleware class name or a callable.');
240
        Route::get('/', TestController::class);
241
    }
242
243
    public function testMiddlewareAddSuccessStringLL(): void
244
    {
245
        $route = Route::get('/', TestMiddleware::class, $this->getContainer());
246
        $this->assertInstanceOf(Route::class, $route);
247
    }
248
249
    public function testInvalidMiddlewareAddWrongArraySizeLL(): void
250
    {
251
        $this->expectException(\InvalidArgumentException::class);
252
        Route::get('/', ['test']);
253
    }
254
255
    public function testInvalidMiddlewareAddWrongArrayClassLL(): void
256
    {
257
        $this->expectException(\InvalidArgumentException::class);
258
        Route::get('/', ['class', 'test']);
259
    }
260
261
    public function testInvalidMiddlewareAddWrongArrayTypeLL(): void
262
    {
263
        $this->expectException(\InvalidArgumentException::class);
264
        Route::get('/', ['class' => TestController::class, 'index']);
265
    }
266
267
    public function testMiddlewareAddSuccessArrayLL(): void
268
    {
269
        $route = Route::get('/', [TestController::class, 'index'], $this->getContainer());
270
        $this->assertInstanceOf(Route::class, $route);
271
    }
272
273
    public function testMiddlewareCallSuccessArrayLL(): void
274
    {
275
        $request = new ServerRequest('GET', '/');
276
        $container = $this->getContainer([
277
            TestController::class => new TestController(),
278
        ]);
279
        $route = Route::get('/', [TestController::class, 'index'], $container);
280
        $response = $route->process($request, $this->getRequestHandler());
281
        $this->assertSame(200, $response->getStatusCode());
282
    }
283
284
    public function testMiddlewareCallSuccessArrayWithoutContainerLL(): void
285
    {
286
        $request = new ServerRequest('GET', '/');
287
        $container = $this->getContainer([
288
            TestController::class => new TestController(),
289
        ]);
290
        $route = Route::get('/', [TestController::class, 'index']);
291
        $route = $route->withContainer($container);
292
        $response = $route->process($request, $this->getRequestHandler());
293
        $this->assertSame(200, $response->getStatusCode());
294
    }
295
296
    private function getRequestHandler(): RequestHandlerInterface
297
    {
298
        return new class() implements RequestHandlerInterface {
299
            public function handle(ServerRequestInterface $request): ResponseInterface
300
            {
301
                return new Response(404);
302
            }
303
        };
304
    }
305
306
    private function getContainer(array $instances = []): ContainerInterface
307
    {
308
        return new Container($instances);
309
    }
310
}
311