Passed
Push — master ( 8844b9...9328af )
by Alexander
02:49 queued 01:34
created

GroupTest::testAddNestedMiddleware()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 20
c 2
b 0
f 0
nc 1
nop 0
dl 0
loc 27
rs 9.6
1
<?php
2
3
namespace Yiisoft\Router\Tests;
4
5
use Nyholm\Psr7\ServerRequest;
6
use Nyholm\Psr7\Response;
7
use PHPUnit\Framework\TestCase;
8
use Psr\Container\ContainerInterface;
9
use Psr\Http\Server\MiddlewareInterface;
10
use Psr\Http\Message\ResponseInterface;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Psr\Http\Server\RequestHandlerInterface;
13
use Yiisoft\Router\Middleware\Callback;
14
use Yiisoft\Router\Group;
15
use Yiisoft\Router\Route;
16
use Yiisoft\Router\RouteCollection;
17
use Yiisoft\Router\RouteCollectorInterface;
18
use Yiisoft\Router\Tests\Support\Container;
19
20
class GroupTest extends TestCase
21
{
22
    public function testAddRoute(): void
23
    {
24
        $listRoute = Route::get('/');
25
        $viewRoute = Route::get('/{id}');
26
27
        $group = Group::create();
28
        $group->addRoute($listRoute);
29
        $group->addRoute($viewRoute);
30
31
        $this->assertCount(2, $group->getItems());
32
        $this->assertSame($listRoute, $group->getItems()[0]);
33
        $this->assertSame($viewRoute, $group->getItems()[1]);
34
    }
35
36
    public function testAddMiddleware(): void
37
    {
38
        $group = Group::create();
39
40
        $middleware1 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
41
        $middleware2 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
42
43
        $group
44
            ->addMiddleware($middleware1)
45
            ->addMiddleware($middleware2);
46
47
        $this->assertCount(2, $group->getMiddlewares());
48
        $this->assertSame($middleware1, $group->getMiddlewares()[1]);
49
        $this->assertSame($middleware2, $group->getMiddlewares()[0]);
50
    }
51
52
    public function testAddNestedMiddleware(): void
53
    {
54
        $request = new ServerRequest('GET', '/outergroup/innergroup/test1');
55
56
        $middleware1 = new Callback(static function (ServerRequestInterface $request, RequestHandlerInterface $handler) {
57
            $request = $request->withAttribute('middleware', 'middleware1');
58
            return $handler->handle($request);
59
        }, $this->getContainer());
60
61
        $middleware2 = new Callback(static function (ServerRequestInterface $request) {
62
            return new Response(200, [], null, '1.1', implode($request->getAttributes()));
63
        }, $this->getContainer());
64
65
        $group = Group::create('/outergroup', [
66
            Group::create('/innergroup', [
67
                Route::get('/test1')->name('request1')
68
            ])->addMiddleware($middleware2),
69
        ])->addMiddleware($middleware1);
70
71
        $collector = Group::create();
72
        $collector->addGroup($group);
73
74
        $routeCollection = new RouteCollection($collector);
75
        $route = $routeCollection->getRoute('request1');
76
        $response = $route->process($request, $this->getRequestHandler());
77
        $this->assertSame(200, $response->getStatusCode());
78
        $this->assertSame('middleware1', $response->getReasonPhrase());
79
    }
80
81
    public function testGroupMiddlewareFullStackCalled(): void
82
    {
83
        $group = Group::create('/group', function (RouteCollectorInterface $r) {
84
            $r->addRoute(Route::get('/test1')->name('request1'));
85
        });
86
87
        $request = new ServerRequest('GET', '/group/test1');
88
        $middleware1 = new Callback(function (ServerRequestInterface $request, RequestHandlerInterface $handler) {
89
            $request = $request->withAttribute('middleware', 'middleware1');
90
            return $handler->handle($request);
91
        }, $this->getContainer());
92
        $middleware2 = new Callback(function (ServerRequestInterface $request) {
93
            return new Response(200, [], null, '1.1', implode($request->getAttributes()));
94
        }, $this->getContainer());
95
96
        $group->addMiddleware($middleware2)->addMiddleware($middleware1);
97
        $collector = Group::create();
98
        $collector->addGroup($group);
99
100
        $routeCollection = new RouteCollection($collector);
101
        $route = $routeCollection->getRoute('request1');
102
        $response = $route->process($request, $this->getRequestHandler());
103
        $this->assertSame(200, $response->getStatusCode());
104
        $this->assertSame('middleware1', $response->getReasonPhrase());
105
    }
106
107
    public function testGroupMiddlewareStackInterrupted(): void
108
    {
109
        $group = Group::create('/group', function (RouteCollectorInterface $r) {
110
            $r->addRoute(Route::get('/test1')->name('request1'));
111
        });
112
113
        $request = new ServerRequest('GET', '/group/test1');
114
        $middleware1 = new Callback(function () {
115
            return new Response(403);
116
        }, $this->getContainer());
117
        $middleware2 = new Callback(function () {
118
            return new Response(200);
119
        }, $this->getContainer());
120
121
        $group->addMiddleware($middleware2)->addMiddleware($middleware1);
122
        $collector = Group::create();
123
        $collector->addGroup($group);
124
125
        $routeCollection = new RouteCollection($collector);
126
        $route = $routeCollection->getRoute('request1');
127
        $response = $route->process($request, $this->getRequestHandler());
128
        $this->assertSame(403, $response->getStatusCode());
129
    }
130
131
    public function testAddGroup(): void
132
    {
133
        $logoutRoute = Route::post('/logout');
134
        $listRoute = Route::get('/');
135
        $viewRoute = Route::get('/{id}');
136
137
        $middleware1 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
138
        $middleware2 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
139
140
        $root = Group::create();
141
        $root->addGroup(Group::create('/api', static function (Group $group) use ($logoutRoute, $listRoute, $viewRoute, $middleware1, $middleware2) {
142
            $group->addRoute($logoutRoute);
143
            $group->addGroup(Group::create('/post', static function (Group $group) use ($listRoute, $viewRoute) {
144
                $group->addRoute($listRoute);
145
                $group->addRoute($viewRoute);
146
            }));
147
148
            $group->addMiddleware($middleware1);
149
            $group->addMiddleware($middleware2);
150
        }));
151
152
        $this->assertCount(1, $root->getItems());
153
        $api = $root->getItems()[0];
154
155
        $this->assertSame('/api', $api->getPrefix());
156
        $this->assertCount(2, $api->getItems());
157
        $this->assertSame($logoutRoute, $api->getItems()[0]);
158
159
        /** @var Group $postGroup */
160
        $postGroup = $api->getItems()[1];
161
        $this->assertInstanceOf(Group::class, $postGroup);
162
        $this->assertCount(2, $api->getMiddlewares());
163
        $this->assertSame($middleware1, $api->getMiddlewares()[1]);
164
        $this->assertSame($middleware2, $api->getMiddlewares()[0]);
165
166
        $this->assertSame('/post', $postGroup->getPrefix());
167
        $this->assertCount(2, $postGroup->getItems());
168
        $this->assertSame($listRoute, $postGroup->getItems()[0]);
169
        $this->assertSame($viewRoute, $postGroup->getItems()[1]);
170
        $this->assertEmpty($postGroup->getMiddlewares());
171
    }
172
173
    public function testAddGroupSecondWay(): void
174
    {
175
        $logoutRoute = Route::post('/logout');
176
        $listRoute = Route::get('/');
177
        $viewRoute = Route::get('/{id}');
178
179
        $middleware1 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
180
        $middleware2 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
181
182
        $root = Group::create(null, [
183
            Group::create('/api', [
184
                $logoutRoute,
185
                Group::create('/post', [
186
                    $listRoute,
187
                    $viewRoute
188
                ])
189
            ])->addMiddleware($middleware1)->addMiddleware($middleware2)
190
        ]);
191
192
        $this->assertCount(1, $root->getItems());
193
        $api = $root->getItems()[0];
194
195
        $this->assertSame('/api', $api->getPrefix());
196
        $this->assertCount(2, $api->getItems());
197
        $this->assertSame($logoutRoute, $api->getItems()[0]);
198
199
        /** @var Group $postGroup */
200
        $postGroup = $api->getItems()[1];
201
        $this->assertInstanceOf(Group::class, $postGroup);
202
        $this->assertCount(2, $api->getMiddlewares());
203
        $this->assertSame($middleware1, $api->getMiddlewares()[1]);
204
        $this->assertSame($middleware2, $api->getMiddlewares()[0]);
205
206
        $this->assertSame('/post', $postGroup->getPrefix());
207
        $this->assertCount(2, $postGroup->getItems());
208
        $this->assertSame($listRoute, $postGroup->getItems()[0]);
209
        $this->assertSame($viewRoute, $postGroup->getItems()[1]);
210
        $this->assertEmpty($postGroup->getMiddlewares());
211
    }
212
213
    public function testContainerInjected(): void
214
    {
215
        $container = $this->getContainer();
216
217
        $apiGroup = Group::create(
218
            '/api',
219
            static function (Group $group) {
220
                $group->addRoute(Route::get('/info')->name('api-info'));
221
                $group->addGroup(
222
                    Group::create(
223
                        '/v1',
224
                        static function (Group $group) {
225
                            $group->addRoute(Route::get('/user')->name('api-v1-user/index'));
226
                            $group->addRoute(Route::get('/user/{id}')->name('api-v1-user/view'));
227
                            $group->addGroup(
228
                                Group::create(
229
                                    '/news',
230
                                    static function (Group $group) {
231
                                        $group->addRoute(Route::get('/post')->name('api-v1-news-post/index'));
232
                                        $group->addRoute(Route::get('/post/{id}')->name('api-v1-news-post/view'));
233
                                    }
234
                                )
235
                            );
236
                            $group->addGroup(
237
                                Group::create(
238
                                    '/blog',
239
                                    static function (Group $group) {
240
                                        $group->addRoute(Route::get('/post')->name('api-v1-blog-post/index'));
241
                                        $group->addRoute(Route::get('/post/{id}')->name('api-v1-blog-post/view'));
242
                                    }
243
                                )
244
                            );
245
                            $group->addRoute(Route::get('/note')->name('api-v1-note/index'));
246
                            $group->addRoute(Route::get('/note/{id}')->name('api-v1-note/view'));
247
                        }
248
                    )
249
                );
250
                $group->addGroup(
251
                    Group::create(
252
                        '/v2',
253
                        static function (Group $group) {
254
                            $group->addRoute(Route::get('/user')->name('api-v2-user/index'));
255
                            $group->addRoute(Route::get('/user/{id}')->name('api-v2-user/view'));
256
                            $group->addGroup(
257
                                Group::create(
258
                                    '/news',
259
                                    static function (Group $group) {
260
                                        $group->addRoute(Route::get('/post')->name('api-v2-news-post/index'));
261
                                        $group->addRoute(Route::get('/post/{id}')->name('api-v2-news-post/view'));
262
                                    }
263
                                )
264
                            );
265
                            $group->addGroup(
266
                                Group::create(
267
                                    '/blog',
268
                                    static function (Group $group) {
269
                                        $group->addRoute(Route::get('/post')->name('api-v2-blog-post/index'));
270
                                        $group->addRoute(Route::get('/post/{id}')->name('api-v2-blog-post/view'));
271
                                    }
272
                                )
273
                            );
274
                            $group->addRoute(Route::get('/note')->name('api-v2-note/index'));
275
                            $group->addRoute(Route::get('/note/{id}')->name('api-v2-note/view'));
276
                        }
277
                    )
278
                );
279
            },
280
            $container
281
        );
282
283
        $items = $apiGroup->getItems();
284
285
        $this->assertAllRoutesAndGroupsHaveContainer($items);
286
    }
287
288
    private function getRequestHandler(): RequestHandlerInterface
289
    {
290
        return new class() implements RequestHandlerInterface {
291
            public function handle(ServerRequestInterface $request): ResponseInterface
292
            {
293
                return new Response(404);
294
            }
295
        };
296
    }
297
298
    private function getContainer(array $instances = []): ContainerInterface
299
    {
300
        return new Container($instances);
301
    }
302
303
    private function assertAllRoutesAndGroupsHaveContainer(array $items): void
304
    {
305
        $func = function ($item) use (&$func) {
306
            $this->assertTrue($item->hasContainer());
307
            if ($item instanceof Group) {
308
                $items = $item->getItems();
309
                array_walk($items, $func);
310
            }
311
        };
312
        array_walk($items, $func);
313
    }
314
}
315