Passed
Push — master ( a586e8...77a217 )
by Alexander
01:33
created

RouteTest.php$0 ➔ testAddCallableArrayMiddleware()   A

Complexity

Conditions 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
rs 9.9666
cc 1
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
        $controller = new TestController();
183
        $route = Route::get('/', null, $this->getContainer())->addMiddleware([$controller, 'index']);
184
185
        $response = $route->process($request, $this->getRequestHandler());
186
        $this->assertSame(200, $response->getStatusCode());
187
    }
188
189
    public function testMiddlewareFullStackCalled(): void
190
    {
191
        $container = $this->getContainer();
192
        $request = new ServerRequest('GET', '/');
193
194
        $routeOne = Route::get('/', null, $container);
195
196
        $middleware1 = function (ServerRequestInterface $request, RequestHandlerInterface $handler) {
197
            $request = $request->withAttribute('middleware', 'middleware1');
198
            return $handler->handle($request);
199
        };
200
        $middleware2 = function (ServerRequestInterface $request) {
201
            return new Response(200, [], null, '1.1', implode($request->getAttributes()));
202
        };
203
204
        $routeOne = $routeOne->addMiddleware($middleware2)->addMiddleware($middleware1);
205
206
        $response = $routeOne->process($request, $this->getRequestHandler());
207
        $this->assertSame(200, $response->getStatusCode());
208
        $this->assertSame('middleware1', $response->getReasonPhrase());
209
    }
210
211
    public function testMiddlewareStackInterrupted(): void
212
    {
213
        $container = $this->getContainer();
214
        $request = new ServerRequest('GET', '/');
215
216
        $routeTwo = Route::get('/', null, $container);
217
218
        $middleware1 = function () {
219
            return new Response(403);
220
        };
221
        $middleware2 = function () {
222
            return new Response(200);
223
        };
224
225
        $routeTwo = $routeTwo->addMiddleware($middleware2)->addMiddleware($middleware1);
226
227
        $response = $routeTwo->process($request, $this->getRequestHandler());
228
        $this->assertSame(403, $response->getStatusCode());
229
    }
230
231
    public function testInvalidMiddlewareAddWrongStringLL(): void
232
    {
233
        $this->expectException(\InvalidArgumentException::class);
234
        Route::get('/', 'test');
235
    }
236
237
    public function testInvalidMiddlewareAddWrongStringClassLL(): void
238
    {
239
        $this->expectException(\InvalidArgumentException::class);
240
        $this->expectExceptionMessage('Parameter should be either PSR middleware class name, handler action or a callable.');
241
        Route::get('/', TestController::class);
242
    }
243
244
    public function testMiddlewareAddSuccessStringLL(): void
245
    {
246
        $route = Route::get('/', TestMiddleware::class, $this->getContainer());
247
        $this->assertInstanceOf(Route::class, $route);
248
    }
249
250
    public function testInvalidMiddlewareAddWrongArraySizeLL(): void
251
    {
252
        $this->expectException(\InvalidArgumentException::class);
253
        Route::get('/', ['test']);
254
    }
255
256
    public function testInvalidMiddlewareAddWrongArrayClassLL(): void
257
    {
258
        $this->expectException(\InvalidArgumentException::class);
259
        Route::get('/', ['class', 'test']);
260
    }
261
262
    public function testInvalidMiddlewareAddWrongArrayTypeLL(): void
263
    {
264
        $this->expectException(\InvalidArgumentException::class);
265
        Route::get('/', ['class' => TestController::class, 'index']);
266
    }
267
268
    public function testMiddlewareAddSuccessArrayLL(): void
269
    {
270
        $route = Route::get('/', [TestController::class, 'index'], $this->getContainer());
271
        $this->assertInstanceOf(Route::class, $route);
272
    }
273
274
    public function testMiddlewareCallSuccessArrayLL(): void
275
    {
276
        $request = new ServerRequest('GET', '/');
277
        $container = $this->getContainer([
278
            TestController::class => new TestController(),
279
        ]);
280
        $route = Route::get('/', [TestController::class, 'index'], $container);
281
        $response = $route->process($request, $this->getRequestHandler());
282
        $this->assertSame(200, $response->getStatusCode());
283
    }
284
285
    public function testMiddlewareCallSuccessArrayWithoutContainerLL(): void
286
    {
287
        $request = new ServerRequest('GET', '/');
288
        $container = $this->getContainer([
289
            TestController::class => new TestController(),
290
        ]);
291
        $route = Route::get('/', [TestController::class, 'index']);
292
        $route = $route->withContainer($container);
293
        $response = $route->process($request, $this->getRequestHandler());
294
        $this->assertSame(200, $response->getStatusCode());
295
    }
296
297
    private function getRequestHandler(): RequestHandlerInterface
298
    {
299
        return new class() implements RequestHandlerInterface {
300
            public function handle(ServerRequestInterface $request): ResponseInterface
301
            {
302
                return new Response(404);
303
            }
304
        };
305
    }
306
307
    private function getContainer(array $instances = []): ContainerInterface
308
    {
309
        return new Container($instances);
310
    }
311
}
312