Passed
Push — master ( 70c68f...c76078 )
by Alexander
06:58
created

GroupTest::testAddGroupSecondWay()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 38
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 27
c 0
b 0
f 0
dl 0
loc 38
rs 9.488
cc 1
nc 1
nop 0
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 = new Group();
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 = new Group();
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 testGroupMiddlewareFullStackCalled(): void
53
    {
54
        $group = new Group('/group', function (RouteCollectorInterface $r) {
55
            $r->addRoute(Route::get('/test1')->name('request1'));
56
        });
57
58
        $request = new ServerRequest('GET', '/group/test1');
59
        $middleware1 = new Callback(function (ServerRequestInterface $request, RequestHandlerInterface $handler) {
60
            $request = $request->withAttribute('middleware', 'middleware1');
61
            return $handler->handle($request);
62
        }, $this->getContainer());
63
        $middleware2 = new Callback(function (ServerRequestInterface $request) {
64
            return new Response(200, [], null, '1.1', implode($request->getAttributes()));
65
        }, $this->getContainer());
66
67
        $group->addMiddleware($middleware2)->addMiddleware($middleware1);
68
69
        $routeCollection = new RouteCollection($group);
70
        $route = $routeCollection->getRoute('request1');
71
        $response = $route->process($request, $this->getRequestHandler());
72
        $this->assertSame(200, $response->getStatusCode());
73
        $this->assertSame('middleware1', $response->getReasonPhrase());
74
    }
75
76
    public function testGroupMiddlewareStackInterrupted(): void
77
    {
78
        $group = new Group('/group', function (RouteCollectorInterface $r) {
79
            $r->addRoute(Route::get('/test1')->name('request1'));
80
        });
81
82
        $request = new ServerRequest('GET', '/group/test1');
83
        $middleware1 = new Callback(function () {
84
            return new Response(403);
85
        }, $this->getContainer());
86
        $middleware2 = new Callback(function () {
87
            return new Response(200);
88
        }, $this->getContainer());
89
90
        $group->addMiddleware($middleware2)->addMiddleware($middleware1);
91
92
        $routeCollection = new RouteCollection($group);
93
        $route = $routeCollection->getRoute('request1');
94
        $response = $route->process($request, $this->getRequestHandler());
95
        $this->assertSame(403, $response->getStatusCode());
96
    }
97
98
    public function testAddGroup(): void
99
    {
100
        $logoutRoute = Route::post('/logout');
101
        $listRoute = Route::get('/');
102
        $viewRoute = Route::get('/{id}');
103
104
        $middleware1 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
105
        $middleware2 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
106
107
        $root = new Group();
108
        $root->addGroup(new Group('/api', static function (Group $group) use ($logoutRoute, $listRoute, $viewRoute, $middleware1, $middleware2) {
109
            $group->addRoute($logoutRoute);
110
            $group->addGroup(new Group('/post', static function (Group $group) use ($listRoute, $viewRoute) {
111
                $group->addRoute($listRoute);
112
                $group->addRoute($viewRoute);
113
            }));
114
115
            $group->addMiddleware($middleware1);
116
            $group->addMiddleware($middleware2);
117
        }));
118
119
        $this->assertCount(1, $root->getItems());
120
        $api = $root->getItems()[0];
121
122
        $this->assertSame('/api', $api->getPrefix());
123
        $this->assertCount(2, $api->getItems());
124
        $this->assertSame($logoutRoute, $api->getItems()[0]);
125
126
        /** @var Group $postGroup */
127
        $postGroup = $api->getItems()[1];
128
        $this->assertInstanceOf(Group::class, $postGroup);
129
        $this->assertCount(2, $api->getMiddlewares());
130
        $this->assertSame($middleware1, $api->getMiddlewares()[1]);
131
        $this->assertSame($middleware2, $api->getMiddlewares()[0]);
132
133
        $this->assertSame('/post', $postGroup->getPrefix());
134
        $this->assertCount(2, $postGroup->getItems());
135
        $this->assertSame($listRoute, $postGroup->getItems()[0]);
136
        $this->assertSame($viewRoute, $postGroup->getItems()[1]);
137
        $this->assertEmpty($postGroup->getMiddlewares());
138
    }
139
140
    public function testAddGroupSecondWay(): void
141
    {
142
        $logoutRoute = Route::post('/logout');
143
        $listRoute = Route::get('/');
144
        $viewRoute = Route::get('/{id}');
145
146
        $middleware1 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
147
        $middleware2 = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
148
149
        $root = Group::create(null, [
150
            Group::create('/api', [
151
                $logoutRoute,
152
                Group::create('/post', [
153
                    $listRoute,
154
                    $viewRoute
155
                ])
156
            ])->addMiddleware($middleware1)->addMiddleware($middleware2)
157
        ]);
158
159
        $this->assertCount(1, $root->getItems());
160
        $api = $root->getItems()[0];
161
162
        $this->assertSame('/api', $api->getPrefix());
163
        $this->assertCount(2, $api->getItems());
164
        $this->assertSame($logoutRoute, $api->getItems()[0]);
165
166
        /** @var Group $postGroup */
167
        $postGroup = $api->getItems()[1];
168
        $this->assertInstanceOf(Group::class, $postGroup);
169
        $this->assertCount(2, $api->getMiddlewares());
170
        $this->assertSame($middleware1, $api->getMiddlewares()[1]);
171
        $this->assertSame($middleware2, $api->getMiddlewares()[0]);
172
173
        $this->assertSame('/post', $postGroup->getPrefix());
174
        $this->assertCount(2, $postGroup->getItems());
175
        $this->assertSame($listRoute, $postGroup->getItems()[0]);
176
        $this->assertSame($viewRoute, $postGroup->getItems()[1]);
177
        $this->assertEmpty($postGroup->getMiddlewares());
178
    }
179
180
    public function testContainerInjected(): void
181
    {
182
        $container = $this->getContainer();
183
184
        $apiGroup = new Group(
185
            '/api', static function (Group $group) {
186
                $group->addRoute(Route::get('/info')->name('api-info'));
187
                $group->addGroup(
188
                new Group(
189
                    '/v1', static function (Group $group) {
190
                        $group->addRoute(Route::get('/user')->name('api-v1-user/index'));
191
                        $group->addRoute(Route::get('/user/{id}')->name('api-v1-user/view'));
192
                        $group->addGroup(
193
                        new Group(
194
                            '/news', static function (Group $group) {
195
                                $group->addRoute(Route::get('/post')->name('api-v1-news-post/index'));
196
                                $group->addRoute(Route::get('/post/{id}')->name('api-v1-news-post/view'));
197
                            }
198
                        )
199
                    );
200
                        $group->addGroup(
201
                        new Group(
202
                            '/blog', static function (Group $group) {
203
                                $group->addRoute(Route::get('/post')->name('api-v1-blog-post/index'));
204
                                $group->addRoute(Route::get('/post/{id}')->name('api-v1-blog-post/view'));
205
                            }
206
                        )
207
                    );
208
                        $group->addRoute(Route::get('/note')->name('api-v1-note/index'));
209
                        $group->addRoute(Route::get('/note/{id}')->name('api-v1-note/view'));
210
                    }
211
                )
212
            );
213
                $group->addGroup(
214
                new Group(
215
                    '/v2', static function (Group $group) {
216
                        $group->addRoute(Route::get('/user')->name('api-v2-user/index'));
217
                        $group->addRoute(Route::get('/user/{id}')->name('api-v2-user/view'));
218
                        $group->addGroup(
219
                        new Group(
220
                            '/news', static function (Group $group) {
221
                                $group->addRoute(Route::get('/post')->name('api-v2-news-post/index'));
222
                                $group->addRoute(Route::get('/post/{id}')->name('api-v2-news-post/view'));
223
                            }
224
                        )
225
                    );
226
                        $group->addGroup(
227
                        new Group(
228
                            '/blog', static function (Group $group) {
229
                                $group->addRoute(Route::get('/post')->name('api-v2-blog-post/index'));
230
                                $group->addRoute(Route::get('/post/{id}')->name('api-v2-blog-post/view'));
231
                            }
232
                        )
233
                    );
234
                        $group->addRoute(Route::get('/note')->name('api-v2-note/index'));
235
                        $group->addRoute(Route::get('/note/{id}')->name('api-v2-note/view'));
236
                    }
237
                )
238
            );
239
            }, $container
240
        );
241
242
        $items = $apiGroup->getItems();
243
244
        $this->assertAllRoutesAndGroupsHaveContainer($items);
245
    }
246
247
    private function getRequestHandler(): RequestHandlerInterface
248
    {
249
        return new class() implements RequestHandlerInterface {
250
            public function handle(ServerRequestInterface $request): ResponseInterface
251
            {
252
                return new Response(404);
253
            }
254
        };
255
    }
256
257
    private function getContainer(array $instances = []): ContainerInterface
258
    {
259
        return new Container($instances);
260
    }
261
262
    private function assertAllRoutesAndGroupsHaveContainer(array $items): void
263
    {
264
        $func = function ($item) use (&$func) {
265
            $this->assertTrue($item->hasContainer());
266
            if ($item instanceof Group) {
267
                $items = $item->getItems();
268
                array_walk($items, $func);
269
            }
270
        };
271
        array_walk($items, $func);
272
    }
273
}
274