Completed
Push — master ( e6c9d7...cc6bd7 )
by Grégoire
12:23
created

tests/Route/DefaultRouteGeneratorTest.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Tests\Route;
15
16
use PHPUnit\Framework\TestCase;
17
use Sonata\AdminBundle\Admin\AdminInterface;
18
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
19
use Sonata\AdminBundle\Route\DefaultRouteGenerator;
20
use Sonata\AdminBundle\Route\RouteCollection;
21
use Sonata\AdminBundle\Route\RoutesCache;
22
use Symfony\Component\HttpFoundation\ParameterBag;
23
use Symfony\Component\HttpFoundation\Request;
24
use Symfony\Component\Routing\RouterInterface;
25
26
class DefaultRouteGeneratorTest extends TestCase
27
{
28
    protected $cacheTempFolder;
29
30
    public function setUp(): void
31
    {
32
        $this->cacheTempFolder = sys_get_temp_dir().'/sonata_test_route';
33
34
        exec('rm -rf '.$this->cacheTempFolder);
35
    }
36
37
    public function testGenerate(): void
38
    {
39
        $router = $this->getMockForAbstractClass(RouterInterface::class);
40
        $router->expects($this->once())->method('generate')->willReturn('/foo/bar');
41
42
        $cache = new RoutesCache($this->cacheTempFolder, true);
43
44
        $generator = new DefaultRouteGenerator($router, $cache);
0 ignored issues
show
$router is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component\Routing\RouterInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
45
46
        $this->assertSame('/foo/bar', $generator->generate('foo_bar'));
47
    }
48
49
    /**
50
     * @dataProvider getGenerateUrlTests
51
     */
52
    public function testGenerateUrl($expected, $name, array $parameters): void
53
    {
54
        $childCollection = new RouteCollection('base.Code.Foo|base.Code.Bar', 'admin_acme_child', '/foo/', 'BundleName:ControllerName');
55
        $childCollection->add('bar');
56
57
        $collection = new RouteCollection('base.Code.Foo', 'admin_acme', '/', 'BundleName:ControllerName');
58
        $collection->add('foo');
59
        $collection->addCollection($childCollection);
60
61
        $admin = $this->getMockForAbstractClass(AdminInterface::class);
62
        $admin->expects($this->any())->method('isChild')->willReturn(false);
63
        $admin->expects($this->any())->method('getBaseCodeRoute')->willReturn('base.Code.Foo');
64
        $admin->expects($this->once())->method('hasParentFieldDescription')->willReturn(false);
65
        $admin->expects($this->once())->method('hasRequest')->willReturn(true);
66
        $admin->expects($this->any())->method('getUniqid')->willReturn('foo_uniqueid');
67
        $admin->expects($this->once())->method('getPersistentParameters')->willReturn(['abc' => 'a123', 'efg' => 'e456']);
68
        $admin->expects($this->any())->method('getRoutes')->willReturn($collection);
69
        $admin->expects($this->any())->method('getExtensions')->willReturn([]);
70
        $admin->expects($this->any())->method('getCode')->willReturn($name);
71
72
        $router = $this->getMockForAbstractClass(RouterInterface::class);
73
        $router->expects($this->once())
74
            ->method('generate')
75
            ->willReturnCallback(static function ($name, array $parameters = []) {
76
                $params = '';
77
                if (!empty($parameters)) {
78
                    $params .= '?'.http_build_query($parameters);
79
                }
80
81
                switch ($name) {
82
                    case 'admin_acme_foo':
83
                        return '/foo'.$params;
84
                    case 'admin_acme_child_bar':
85
                        return '/foo/bar'.$params;
86
                }
87
            });
88
89
        $cache = new RoutesCache($this->cacheTempFolder, true);
90
91
        $generator = new DefaultRouteGenerator($router, $cache);
0 ignored issues
show
$router is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component\Routing\RouterInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
92
93
        $this->assertSame($expected, $generator->generateUrl($admin, $name, $parameters));
94
    }
95
96
    public function getGenerateUrlTests()
97
    {
98
        return [
99
            ['/foo?abc=a123&efg=e456&default_param=default_val', 'foo', ['default_param' => 'default_val']],
100
            ['/foo/bar?abc=a123&efg=e456&default_param=default_val', 'base.Code.Bar.bar', ['default_param' => 'default_val']],
101
        ];
102
    }
103
104
    public function testGenerateUrlWithException(): void
105
    {
106
        $this->expectException(\RuntimeException::class, 'unable to find the route `base.Code.Route.foo`');
107
108
        $admin = $this->getMockForAbstractClass(AdminInterface::class);
109
        $admin->expects($this->any())->method('isChild')->willReturn(false);
110
        $admin->expects($this->any())->method('getBaseCodeRoute')->willReturn('base.Code.Route');
111
        $admin->expects($this->once())->method('hasParentFieldDescription')->willReturn(false);
112
        $admin->expects($this->once())->method('hasRequest')->willReturn(true);
113
        $admin->expects($this->once())->method('getPersistentParameters')->willReturn([]);
114
        $admin->expects($this->exactly(2))->method('getRoutes')->willReturn(new RouteCollection('base.Code.Route', 'baseRouteName', 'baseRoutePattern', 'BundleName:ControllerName'));
115
        $admin->expects($this->any())->method('getExtensions')->willReturn([]);
116
        $admin->expects($this->any())->method('getCode')->willReturn('Code');
117
118
        $router = $this->getMockForAbstractClass(RouterInterface::class);
119
120
        $cache = new RoutesCache($this->cacheTempFolder, true);
121
122
        $generator = new DefaultRouteGenerator($router, $cache);
0 ignored issues
show
$router is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component\Routing\RouterInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
123
        $generator->generateUrl($admin, 'foo', []);
124
    }
125
126
    /**
127
     * @dataProvider getGenerateUrlChildTests
128
     */
129
    public function testGenerateUrlChild($type, $expected, $name, array $parameters): void
130
    {
131
        $childCollection = new RouteCollection('base.Code.Parent|base.Code.Child', 'admin_acme_child', '/foo/', 'BundleName:ControllerName');
132
        $childCollection->add('bar');
133
134
        $collection = new RouteCollection('base.Code.Parent', 'admin_acme', '/', 'BundleName:ControllerName');
135
        $collection->add('foo');
136
        $collection->addCollection($childCollection);
137
138
        $admin = $this->getMockForAbstractClass(AdminInterface::class);
139
        $admin->expects($this->any())->method('isChild')->willReturn(true);
140
        $admin->expects($this->any())->method('getBaseCodeRoute')->willReturn('base.Code.Parent|base.Code.Child');
141
        $admin->expects($this->any())->method('getIdParameter')->willReturn('id');
142
        $admin->expects($this->any())->method('hasParentFieldDescription')->willReturn(false);
143
        $admin->expects($this->any())->method('hasRequest')->willReturn(true);
144
        $admin->expects($this->any())->method('getUniqid')->willReturn('foo_uniqueid');
145
        $admin->expects($this->any())->method('getPersistentParameters')->willReturn(['abc' => 'a123', 'efg' => 'e456']);
146
        $admin->expects($this->any())->method('getRoutes')->willReturn($childCollection);
147
        $admin->expects($this->any())->method('getExtensions')->willReturn([]);
148
149
        $parentAdmin = $this->getMockForAbstractClass(AdminInterface::class);
150
        $parentAdmin->expects($this->any())->method('getIdParameter')->willReturn('childId');
151
        $parentAdmin->expects($this->any())->method('getRoutes')->willReturn($collection);
152
        $parentAdmin->expects($this->any())->method('getBaseCodeRoute')->willReturn('base.Code.Parent');
153
        $parentAdmin->expects($this->any())->method('getExtensions')->willReturn([]);
154
        $parentAdmin->expects($this->any())->method('getCode')->willReturn($name);
155
156
        // no request attached in this test, so this will not be used
157
        $parentAdmin->expects($this->never())->method('getPersistentParameters')->willReturn(['from' => 'parent']);
158
159
        $request = $this->createMock(Request::class);
160
        $request->attributes = $this->createMock(ParameterBag::class);
161
        $request->attributes->expects($this->any())->method('has')->willReturn(true);
162
        $request->attributes->expects($this->any())
163
            ->method('get')
164
            ->willReturnCallback(static function ($key) {
165
                if ('childId' === $key) {
166
                    return '987654';
167
                }
168
            });
169
170
        $admin->expects($this->any())->method('getRequest')->willReturn($request);
171
        $admin->expects($this->any())->method('getParent')->willReturn($parentAdmin);
172
        $admin->expects($this->any())->method('getCode')->willReturn($name);
173
174
        $router = $this->getMockForAbstractClass(RouterInterface::class);
175
        $router->expects($this->once())
176
            ->method('generate')
177
            ->willReturnCallback(static function ($name, array $parameters = []) {
178
                $params = '';
179
                if (!empty($parameters)) {
180
                    $params .= '?'.http_build_query($parameters);
181
                }
182
183
                switch ($name) {
184
                    case 'admin_acme_foo':
185
                        return '/foo'.$params;
186
                    case 'admin_acme_child_bar':
187
                        return '/foo/bar'.$params;
188
                }
189
            });
190
191
        $cache = new RoutesCache($this->cacheTempFolder, true);
192
193
        $generator = new DefaultRouteGenerator($router, $cache);
0 ignored issues
show
$router is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component\Routing\RouterInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
194
195
        $this->assertSame($expected, $generator->generateUrl('child' === $type ? $admin : $parentAdmin, $name, $parameters));
196
    }
197
198
    public function getGenerateUrlChildTests()
199
    {
200
        return [
201
            ['parent', '/foo?id=123&default_param=default_val', 'foo', ['id' => 123, 'default_param' => 'default_val']],
202
            ['parent', '/foo/bar?id=123&default_param=default_val', 'base.Code.Child.bar', ['id' => 123, 'default_param' => 'default_val']],
203
            ['child', '/foo/bar?abc=a123&efg=e456&default_param=default_val&childId=987654', 'bar', ['id' => 123, 'default_param' => 'default_val']],
204
        ];
205
    }
206
207
    /**
208
     * @dataProvider getGenerateUrlParentFieldDescriptionTests
209
     */
210
    public function testGenerateUrlParentFieldDescription($expected, $name, array $parameters): void
211
    {
212
        $childCollection = new RouteCollection('base.Code.Parent|base.Code.Child', 'admin_acme_child', '/foo/', 'BundleName:ControllerName');
213
        $childCollection->add('bar');
214
215
        $collection = new RouteCollection('base.Code.Parent', 'admin_acme', '/', 'BundleName:ControllerName');
216
        $collection->add('foo');
217
        $collection->addCollection($childCollection);
218
219
        $admin = $this->getMockForAbstractClass(AdminInterface::class);
220
        $admin->expects($this->any())->method('isChild')->willReturn(false);
221
        $admin->expects($this->any())->method('getCode')->willReturn('base.Code.Parent');
222
        $admin->expects($this->any())->method('getBaseCodeRoute')->willReturn('base.Code.Parent');
223
        // embeded admin (not nested ...)
224
        $admin->expects($this->once())->method('hasParentFieldDescription')->willReturn(true);
225
        $admin->expects($this->once())->method('hasRequest')->willReturn(true);
226
        $admin->expects($this->any())->method('getUniqid')->willReturn('foo_uniqueid');
227
        $admin->expects($this->once())->method('getPersistentParameters')->willReturn(['abc' => 'a123', 'efg' => 'e456']);
228
        $admin->expects($this->any())->method('getExtensions')->willReturn([]);
229
        $admin->expects($this->any())->method('getRoutes')->willReturn($collection);
230
231
        $router = $this->getMockForAbstractClass(RouterInterface::class);
232
        $router->expects($this->once())
233
            ->method('generate')
234
            ->willReturnCallback(static function ($name, array $parameters = []) {
235
                $params = '';
236
                if (!empty($parameters)) {
237
                    $params .= '?'.http_build_query($parameters);
238
                }
239
240
                switch ($name) {
241
                    case 'admin_acme_foo':
242
                        return '/foo'.$params;
243
                    case 'admin_acme_child_bar':
244
                        return '/foo/bar'.$params;
245
                }
246
            });
247
248
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
249
        $fieldDescription->expects($this->once())->method('getOption')->willReturn([]);
250
251
        $parentAdmin = $this->getMockForAbstractClass(AdminInterface::class);
252
        $parentAdmin->expects($this->any())->method('getUniqid')->willReturn('parent_foo_uniqueid');
253
        $parentAdmin->expects($this->any())->method('getCode')->willReturn('parent_foo_code');
254
        $parentAdmin->expects($this->any())->method('getExtensions')->willReturn([]);
255
256
        $fieldDescription->expects($this->any())->method('getAdmin')->willReturn($parentAdmin);
257
        $admin->expects($this->any())->method('getParentFieldDescription')->willReturn($fieldDescription);
258
259
        $cache = new RoutesCache($this->cacheTempFolder, true);
260
261
        $generator = new DefaultRouteGenerator($router, $cache);
0 ignored issues
show
$router is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component\Routing\RouterInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
262
263
        $this->assertSame($expected, $generator->generateUrl($admin, $name, $parameters));
264
    }
265
266
    public function getGenerateUrlParentFieldDescriptionTests()
267
    {
268
        return [
269
            ['/foo?abc=a123&efg=e456&default_param=default_val&uniqid=foo_uniqueid&code=base.Code.Parent&pcode=parent_foo_code&puniqid=parent_foo_uniqueid', 'foo', ['default_param' => 'default_val']],
270
            // this second test does not make sense as we cannot have embeded admin with nested admin....
271
            ['/foo/bar?abc=a123&efg=e456&default_param=default_val&uniqid=foo_uniqueid&code=base.Code.Parent&pcode=parent_foo_code&puniqid=parent_foo_uniqueid', 'base.Code.Child.bar', ['default_param' => 'default_val']],
272
        ];
273
    }
274
275
    /**
276
     * @dataProvider getGenerateUrlLoadCacheTests
277
     */
278
    public function testGenerateUrlLoadCache($expected, $name, array $parameters): void
279
    {
280
        $childCollection = new RouteCollection('base.Code.Parent|base.Code.Child', 'admin_acme_child', '/foo', 'BundleName:ControllerName');
281
        $childCollection->add('bar');
282
283
        $collection = new RouteCollection('base.Code.Parent', 'admin_acme', '/', 'BundleName:ControllerName');
284
        $collection->add('foo');
285
        $collection->addCollection($childCollection);
286
287
        $standaloneCollection = new RouteCollection('base.Code.Child', 'admin_acme_child_standalone', '/', 'BundleName:ControllerName');
288
        $standaloneCollection->add('bar');
289
290
        $admin = $this->getMockForAbstractClass(AdminInterface::class);
291
        $admin->expects($this->any())->method('isChild')->willReturn(true);
292
        $admin->expects($this->any())->method('getCode')->willReturn('base.Code.Child');
293
        $admin->expects($this->any())->method('getBaseCodeRoute')->willReturn('base.Code.Parent|base.Code.Child');
294
        $admin->expects($this->any())->method('getIdParameter')->willReturn('id');
295
        $admin->expects($this->any())->method('hasParentFieldDescription')->willReturn(false);
296
        $admin->expects($this->any())->method('hasRequest')->willReturn(true);
297
        $admin->expects($this->any())->method('getUniqid')->willReturn('foo_uniqueid');
298
        $admin->expects($this->any())->method('getPersistentParameters')->willReturn(['abc' => 'a123', 'efg' => 'e456']);
299
        $admin->expects($this->any())->method('getRoutes')->willReturn($childCollection);
300
        $admin->expects($this->any())->method('getExtensions')->willReturn([]);
301
302
        $parentAdmin = $this->getMockForAbstractClass(AdminInterface::class);
303
        $parentAdmin->expects($this->any())->method('getIdParameter')->willReturn('childId');
304
        $parentAdmin->expects($this->any())->method('getRoutes')->willReturn($collection);
305
        $parentAdmin->expects($this->any())->method('getCode')->willReturn('base.Code.Parent');
306
        $parentAdmin->expects($this->any())->method('getExtensions')->willReturn([]);
307
308
        // no request attached in this test, so this will not be used
309
        $parentAdmin->expects($this->never())->method('getPersistentParameters')->willReturn(['from' => 'parent']);
310
311
        $request = $this->createMock(Request::class);
312
        $request->attributes = $this->createMock(ParameterBag::class);
313
        $request->attributes->expects($this->any())->method('has')->willReturn(true);
314
        $request->attributes->expects($this->any())
315
            ->method('get')
316
            ->willReturnCallback(static function ($key) {
317
                if ('childId' === $key) {
318
                    return '987654';
319
                }
320
            });
321
322
        $admin->expects($this->any())->method('getRequest')->willReturn($request);
323
        $admin->expects($this->any())->method('getParent')->willReturn($parentAdmin);
324
325
        $standaloneAdmin = $this->getMockForAbstractClass(AdminInterface::class);
326
        $standaloneAdmin->expects($this->any())->method('isChild')->willReturn(false);
327
        $standaloneAdmin->expects($this->any())->method('getBaseCodeRoute')->willReturn('base.Code.Child');
328
        $standaloneAdmin->expects($this->once())->method('hasParentFieldDescription')->willReturn(false);
329
        $standaloneAdmin->expects($this->once())->method('hasRequest')->willReturn(true);
330
        $standaloneAdmin->expects($this->any())->method('getUniqid')->willReturn('foo_uniqueid');
331
        $standaloneAdmin->expects($this->once())->method('getPersistentParameters')->willReturn(['abc' => 'a123', 'efg' => 'e456']);
332
        $standaloneAdmin->expects($this->any())->method('getRoutes')->willReturn($standaloneCollection);
333
        $standaloneAdmin->expects($this->any())->method('getExtensions')->willReturn([]);
334
        $standaloneAdmin->expects($this->any())->method('getCode')->willReturn('Code');
335
336
        $router = $this->getMockForAbstractClass(RouterInterface::class);
337
        $router->expects($this->exactly(2))
338
            ->method('generate')
339
            ->willReturnCallback(static function ($name, array $parameters = []) {
340
                $params = '';
341
                if (!empty($parameters)) {
342
                    $params .= '?'.http_build_query($parameters);
343
                }
344
345
                switch ($name) {
346
                    case 'admin_acme_child_bar':
347
                        return '/foo/bar'.$params;
348
                    case 'admin_acme_child_standalone_bar':
349
                        return '/bar'.$params;
350
                }
351
            });
352
353
        $cache = new RoutesCache($this->cacheTempFolder, true);
354
355
        $generator = new DefaultRouteGenerator($router, $cache);
356
357
        // Generate once to populate cache
358
        $generator->generateUrl($admin, 'bar', $parameters);
359
        $this->assertSame($expected, $generator->generateUrl($standaloneAdmin, $name, $parameters));
360
    }
361
362
    public function getGenerateUrlLoadCacheTests()
363
    {
364
        return [
365
            ['/bar?abc=a123&efg=e456&id=123&default_param=default_val', 'bar', ['id' => 123, 'default_param' => 'default_val']],
366
        ];
367
    }
368
}
369